显示学习5(基于树莓派Pico) -- 彩色LCD的驱动

一 环境搭建

使用的ST7715S驱动的1.8寸彩色屏,主控是我们熟悉的树莓派Pico。软件环境是micropython。连接是屏幕直接从Pico取3.3V的供电,然后总线用的SPI。

ST7735 PinPico Pin
VCC3.3V
GNDGND
SCL (SCK)GP10
SDA (MOSI)GP11
RES (RST)GP17
DC(A0)GP16
CSGP18

和下面这篇也算是姊妹篇,只是一个侧重SPI协议,一个侧重显示驱动。可以结合着一起看。

总线学习3--SPI-CSDN博客

驱动是来自:https://github.com/boochow/MicroPython-ST7735

所以这里主要还是学习大神的代码。

ST7735S的数据手册:ST7735S Datasheet, PDF - Alldatasheet

基本上所有的驱动开发工作,都是围绕着数据手册。对上层软件工程师来说,其实数据手册这个名字有点误导人,叫做接口文档一下就秒懂。。。移植的一般不用太怎么看这个,但是如果是从头做,或者是要改一下内容,就得自己慢慢啃这个200页的文档了。。。

二 启动

启动阶段的代码是这样的:

spi = SPI(2, baudrate=20000000, polarity=0, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12))
tft=TFT(spi,16,17,18)
tft.initr()
tft.rgb(True)
tft.fill(TFT.BLACK)

基本上就是TFT代码初始化,一个initr。

TFT Init

  def __init__( self, spi, aDC, aReset, aCS) :"""aLoc SPI pin location is either 1 for 'X' or 2 for 'Y'.aDC is the DC pin and aReset is the reset pin."""self._size = ScreenSizeself._offset = bytearray([0,0])self.rotate = 0                    #Vertical with top toward pins.self._rgb = True                   #color order of rgb.self.tfa = 0                       #top fixed areaself.bfa = 0                       #bottom fixed areaself.dc  = machine.Pin(aDC, machine.Pin.OUT, machine.Pin.PULL_DOWN)self.reset = machine.Pin(aReset, machine.Pin.OUT, machine.Pin.PULL_DOWN)self.cs = machine.Pin(aCS, machine.Pin.OUT, machine.Pin.PULL_DOWN)self.cs(1)self.spi = spiself.colorData = bytearray(2)self.windowLocData = bytearray(4)

这里就是很多PIN口设置,比较要注意的是offset,colorData,windowsLocData。

这里有个奇怪的点,self.colorData = bytearray(2)只用了2个byte,但是rgb不是要3个byte吗?查了一下,原来为了减少数据量,ST7735使用了RGB565,2个byte,如下:

在许多显示屏控制器(如ST7735)中,颜色数据通常使用16位格式而不是24位格式来表示颜色。这意味着每个像素的颜色由2个字节(16位)表示,而不是3个字节(24位)。这种16位颜色格式通常被称为RGB565格式。

RGB565 格式

在RGB565格式中,颜色数据按如下方式编码:

  • 5位用于红色(R),范围为0到31
  • 6位用于绿色(G),范围为0到63
  • 5位用于蓝色(B),范围为0到31

这种格式可以有效地将颜色压缩为16位,从而减少数据传输量,并且对许多嵌入式系统来说,这种压缩是非常重要的。

示例

假设你有一个颜色 (R, G, B),例如 (255, 0, 0)(纯红色),在RGB565格式中编码如下:

  • 红色:255 对应的5位表示为 11111(31)
  • 绿色:0 对应的6位表示为 000000(0)
  • 蓝色:0 对应的5位表示为 00000(0)

最终的16位值是:11111 000000 00000,即 0b1111100000000000 或十六进制的 0xF800

不过这样肯定会导致色彩数不足,显示效果没那么好了。。。

这里说一个题外话,作为一个游戏迷,看看一下以前的主机是怎么显示的:

主机名颜色格式用法色彩数
FC红色R 2位| 绿色G 2位| 蓝色B 2位64
MDRGB333红色R 3位| 绿色G 3位| 蓝色B 3位512
SFCRGB555红色R 5位| 绿色G 5位| 蓝色B 5位32768
GBARGB565红色R 5位| 绿色G 6位| 蓝色B 5位65536
PSRGB555红色R 5位| 绿色G 5位| 蓝色B 5位32768
PS2RGB888红色R 8位| 绿色G 8位| 蓝色B 8位16,777,216
PS5RGB10A2红色R 10位| 绿色G 10位| 蓝色B 10位| Alpha 4位超过10亿

屏幕初始化

 def initr( self ) :'''Initialize a red tab version.'''self._reset()self._writecommand(TFT.SWRESET)              #Software reset.time.sleep_us(150)self._writecommand(TFT.SLPOUT)               #out of sleep mode.time.sleep_us(500)data3 = bytearray([0x01, 0x2C, 0x2D])       #fastest refresh, 6 lines front, 3 lines back.self._writecommand(TFT.FRMCTR1)              #Frame rate control.self._writedata(data3)self._writecommand(TFT.FRMCTR2)              #Frame rate control.self._writedata(data3)data6 = bytearray([0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d])self._writecommand(TFT.FRMCTR3)              #Frame rate control.self._writedata(data6)time.sleep_us(10)data1 = bytearray(1)self._writecommand(TFT.INVCTR)               #Display inversion controldata1[0] = 0x07                             #Line inversion.self._writedata(data1)self._writecommand(TFT.PWCTR1)               #Power controldata3[0] = 0xA2data3[1] = 0x02data3[2] = 0x84self._writedata(data3)self._writecommand(TFT.PWCTR2)               #Power controldata1[0] = 0xC5   #VGH = 14.7V, VGL = -7.35Vself._writedata(data1)data2 = bytearray(2)self._writecommand(TFT.PWCTR3)               #Power controldata2[0] = 0x0A   #Opamp current smalldata2[1] = 0x00   #Boost frequencyself._writedata(data2)self._writecommand(TFT.PWCTR4)               #Power controldata2[0] = 0x8A   #Opamp current smalldata2[1] = 0x2A   #Boost frequencyself._writedata(data2)self._writecommand(TFT.PWCTR5)               #Power controldata2[0] = 0x8A   #Opamp current smalldata2[1] = 0xEE   #Boost frequencyself._writedata(data2)self._writecommand(TFT.VMCTR1)               #Power controldata1[0] = 0x0Eself._writedata(data1)self._writecommand(TFT.INVOFF)self._writecommand(TFT.MADCTL)               #Power controldata1[0] = 0xC8self._writedata(data1)self._writecommand(TFT.COLMOD)data1[0] = 0x05self._writedata(data1)self._writecommand(TFT.CASET)                #Column address set.self.windowLocData[0] = 0x00self.windowLocData[1] = 0x00self.windowLocData[2] = 0x00self.windowLocData[3] = self._size[0] - 1self._writedata(self.windowLocData)self._writecommand(TFT.RASET)                #Row address set.self.windowLocData[3] = self._size[1] - 1self._writedata(self.windowLocData)dataGMCTRP = bytearray([0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f,0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10])self._writecommand(TFT.GMCTRP1)self._writedata(dataGMCTRP)dataGMCTRN = bytearray([0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30,0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10])self._writecommand(TFT.GMCTRN1)self._writedata(dataGMCTRN)time.sleep_us(10)self._writecommand(TFT.DISPON)time.sleep_us(100)self._writecommand(TFT.NORON)                #Normal display on.time.sleep_us(10)self.cs(1)

这个就是一系列SPI命令的组合。这部分一般是来自厂家或者自己去数据手册翻。。这哥们注释写的还不错,可以看到主要就是电源的设置。之后就是行列和颜色的设置,这里有个特别点的。就是命令和数据的不同。另外除了initr,还有三个初始化函数initb,initb2和initg,整体大同小异。以后有空再看吧。

  #@micropython.nativedef _writecommand( self, aCommand ) :'''Write given command to the device.'''self.dc(0)self.cs(0)self.spi.write(bytearray([aCommand]))self.cs(1)#@micropython.nativedef _writedata( self, aData ) :'''Write given data to the device.  This may beeither a single int or a bytearray of values.'''self.dc(1)self.cs(0)self.spi.write(aData)self.cs(1)

用逻辑分析仪来看,发送命令和数据区别就是dc那条线。拉低就是命令,拉高就是数据。从之前的图来看,第三行就是dc。也就是开始有一些命令,后面就全是数据了。

命令都是8位为一组,也就是一个byte。像这样的INVOFF = 0x20。

rgb主要是设置屏幕格式,是RGB色彩还是BGR色彩,这里要用bytearray转成字节码。

  def _setMADCTL( self ) :'''Set screen rotation and RGB/BGR format.'''self._writecommand(TFT.MADCTL)rgb = TFTRGB if self._rgb else TFTBGRself._writedata(bytearray([TFTRotations[self.rotate] | rgb]))

fill则是初始化屏幕颜色,直接是绘制整个屏幕矩形这样。

三 图形库的封装

初始完屏幕之后,后面主要就是发送各种数据,做各种图形的操作了,为了方便上层操作,做了很多封装,基本上分以下几类。

1 底层接口封装

def _vscrolladdr(self, addr) :
def _setColor( self, aColor ) :
def _draw( self, aPixels ) :
def _setwindowpoint( self, aPos ) :
def _setwindowloc( self, aPos0, aPos1 ) :

def _writecommand( self, aCommand ) :
def _writedata( self, aData ) :
def _pushcolor( self, aColor ) :
def _setMADCTL( self ) :
def _reset( self ) :

都是以_为开始的函数。这里面_writecommand,_writedata更底层一些。然后所有的图形操作都分成了点和面(包含线条)。

点就是_setwindowpoint,_pushcolor组合。第一个封装的都是self._writecommand(TFT.CASET),_writecommand(TFT.RASET),_writecommand(TFT.RAMWR)这几个SPI的接口。_pushcolor则是直接用SPI数据口将色彩信息传上去,没有使用命令。

面就是_setwindowloc,_setColor和_draw组合。SPI接口和上面差不多一样。

2 上层接口封装

def rotation( self, aRot )
def pixel( self, aPos, aColor ) :
def text( self, aPos, aString, aColor, aFont, aSize = 1, nowrap = False ) :
def char( self, aPos, aChar, aColor, aFont, aSizes ) :
def line( self, aStart, aEnd, aColor ) :
def vline( self, aStart, aLen, aColor ) :
def hline( self, aStart, aLen, aColor ) :
def rect( self, aStart, aSize, aColor ) :
def fillrect( self, aStart, aSize, aColor ) :
def circle( self, aPos, aRadius, aColor ) :
def fillcircle( self, aPos, aRadius, aColor ) :
def fill( self, aColor = BLACK ) :
def image( self, x0, y0, x1, y1, data ) :
def setvscroll(self, tfa, bfa) :
def vscroll(self, value) :

简单整理一下,大概是这么几类,画图形,比如circle,画线,文字,操作点。这些都比较上层了,直接调用封装的底层接口,和硬件没啥关系,搞软件的人瞅一眼就能懂了。

四 示例分析

下面可以具体看一两个。

这个是画垂直线。

例1 Vline

这个就是画一条垂直线。

  def vline( self, aStart, aLen, aColor ) :'''Draw a vertical line from aStart for aLen. aLen may be negative.'''start = (clamp(aStart[0], 0, self._size[0]), clamp(aStart[1], 0, self._size[1]))stop = (start[0], clamp(start[1] + aLen, 0, self._size[1]))#Make sure smallest y 1st.if (stop[1] < start[1]):start, stop = stop, startself._setwindowloc(start, stop)self._setColor(aColor)self._draw(aLen)

前面主要是对线的处理,判断位置,有没有出界等等。后面调用了三个下层一些的接口来处理。

Setwindowloc

  def _setwindowloc( self, aPos0, aPos1 ) :'''Set a rectangular area for drawing a color to.'''self._writecommand(TFT.CASET)            #Column address set.self.windowLocData[0] = self._offset[0]self.windowLocData[1] = self._offset[0] + int(aPos0[0])self.windowLocData[2] = self._offset[0]self.windowLocData[3] = self._offset[0] + int(aPos1[0])self._writedata(self.windowLocData)self._writecommand(TFT.RASET)            #Row address set.self.windowLocData[0] = self._offset[1]self.windowLocData[1] = self._offset[1] + int(aPos0[1])self.windowLocData[2] = self._offset[1]self.windowLocData[3] = self._offset[1] + int(aPos1[1])self._writedata(self.windowLocData)self._writecommand(TFT.RAMWR)            #Write to RAM.

这个就是设置要绘图的区域。居然还要调用硬件接口去设置,觉得有点略奇怪。。。

然后是setcolor

  def _setColor( self, aColor ) :self.colorData[0] = aColor >> 8self.colorData[1] = aColorself.buf = bytes(self.colorData) * 32

这个基本上都是软件操作。

最后就是draw,这个也是显示接口老熟人了,不管什么屏,最后都有这个接口。

#   @micropython.nativedef _draw( self, aPixels ) :'''Send given color to the device aPixels times.'''self.dc(1)self.cs(0)for i in range(aPixels//32):self.spi.write(self.buf)rest = (int(aPixels) % 32)if rest > 0:buf2 = bytes(self.colorData) * restself.spi.write(buf2)self.cs(1)

这里就是绘制颜色,将指定的区域设置成需要的颜色。

从这里可以看到,彩色屏幕就是基本上就是围绕色彩来处理的。就是两个步骤,指定区域,指定色彩。。。

例2 circle

知道了这个原理,那么矩形框应该就是很简单的了。圆形该怎么处理呢?

#   @micropython.nativedef circle( self, aPos, aRadius, aColor ) :'''Draw a hollow circle with the given radius and color with aPos as center.'''self.colorData[0] = aColor >> 8self.colorData[1] = aColorxend = int(0.7071 * aRadius) + 1rsq = aRadius * aRadiusfor x in range(xend) :y = int(sqrt(rsq - x * x))xp = aPos[0] + xyp = aPos[1] + yxn = aPos[0] - xyn = aPos[1] - yxyp = aPos[0] + yyxp = aPos[1] + xxyn = aPos[0] - yyxn = aPos[1] - xself._setwindowpoint((xp, yp))self._writedata(self.colorData)self._setwindowpoint((xp, yn))self._writedata(self.colorData)self._setwindowpoint((xn, yp))self._writedata(self.colorData)self._setwindowpoint((xn, yn))self._writedata(self.colorData)self._setwindowpoint((xyp, yxp))self._writedata(self.colorData)self._setwindowpoint((xyp, yxn))self._writedata(self.colorData)self._setwindowpoint((xyn, yxp))self._writedata(self.colorData)self._setwindowpoint((xyn, yxn))self._writedata(self.colorData)#   @micropython.nativedef fillcircle( self, aPos, aRadius, aColor ) :'''Draw a filled circle with given radius and color with aPos as center'''rsq = aRadius * aRadiusfor x in range(aRadius) :y = int(sqrt(rsq - x * x))y0 = aPos[1] - yey = y0 + y * 2y0 = clamp(y0, 0, self._size[1])ln = abs(ey - y0) + 1;self.vline((aPos[0] + x, y0), ln, aColor)self.vline((aPos[0] - x, y0), ln, aColor)

可以看到,圆形的处理会慢上几个数量级。首先,画空心圆是按照点来处理的。实心圆则是变成线条来处理。要增加几十上百倍的self._writecommand(TFT.CASET),self._writecommand(TFT.RASET)调用。

例3 图片

最后再看看图片:

f=open('test128x160.bmp', 'rb')
if f.read(2) == b'BM':  #headerdummy = f.read(8) #file size(4), creator bytes(4)offset = int.from_bytes(f.read(4), 'little')hdrsize = int.from_bytes(f.read(4), 'little')width = int.from_bytes(f.read(4), 'little')height = int.from_bytes(f.read(4), 'little')if int.from_bytes(f.read(2), 'little') == 1: #planes must be 1depth = int.from_bytes(f.read(2), 'little')if depth == 24 and int.from_bytes(f.read(4), 'little') == 0:#compress method == uncompressedprint("Image size:", width, "x", height)rowsize = (width * 3 + 3) & ~3if height < 0:height = -heightflip = Falseelse:flip = Truew, h = width, heightif w > 128: w = 128if h > 160: h = 160tft._setwindowloc((0,0),(w - 1,h - 1))for row in range(h):if flip:pos = offset + (height - 1 - row) * rowsizeelse:pos = offset + row * rowsizeif f.tell() != pos:dummy = f.seek(pos)for col in range(w):bgr = f.read(3)tft._pushcolor(TFTColor(bgr[2],bgr[1],bgr[0]))

可以看到,这个函数其实分成两部分。

首先是解析BMP文件格式,主要是长和宽。

然后按照长宽逐个点遍历去处理,首先读取BMP的bgr信息,bgr = f.read(3),然后调用接口将颜色一个一个的写进去。tft._pushcolor(TFTColor(bgr[2],bgr[1],bgr[0]))。

这边也顺带介绍一下BGR格式。

BGR颜色模型,全称为Blue-Green-Red,是一种颜色编码方式,常用于计算机图形学和数字图像处理中。BGR颜色模型是RGB颜色模型的一个变种,主要区别在于颜色通道的顺序。在RGB模型中,颜色由红(Red)、绿(Green)、蓝(Blue)三个颜色通道的组合来表示,而在BGR模型中,则是按照蓝、绿、红的顺序来编码颜色。

以下是BGR颜色模型的一些关键点:

1. **通道顺序**:BGR中的每个像素由三个8位(1字节)的整数表示,分别是蓝色(Blue)、绿色(Green)和红色(Red)的强度值。这三个值通常以BGR的顺序存储。

2. **颜色深度**:BGR通常用于24位颜色深度的图像,即每个像素使用3个字节来存储颜色信息。

3. **位操作**:在BGR编码中,一个像素的颜色可以通过位操作来获取和设置。例如,如果有一个32位整数存储了一个BGR颜色值,可以通过位移和掩码操作来提取每个颜色通道的值。

4. **应用领域**:BGR颜色模型在某些图像处理库和硬件接口中较为常见,比如OpenCV库在处理图像时默认使用BGR颜色空间。

5. **转换为RGB**:如果需要将BGR颜色转换为RGB颜色,只需交换第一个和最后一个字节的值即可。

6. **示例**:假设有一个BGR颜色值为`0x00BBGGRR`,其中`BB`是蓝色分量的16进制表示,`GG`是绿色分量,`RR`是红色分量。转换为RGB颜色值就是`0xRRGGBB`。

7. **编程实现**:在编程中,BGR颜色通常表示为一个整数,例如在Python中,可以使用以下方式表示BGR颜色:

```python
bgr_color = 0x00BBGGRR
```

8. **颜色空间转换**:在图像处理中,可能需要在不同的颜色空间之间转换,如从BGR转换到HSV或LAB颜色空间,以适应特定的视觉处理或图像分析任务。

BGR颜色模型的使用主要是由于某些技术或历史原因,在特定的库或硬件中采用,而在大多数通用的图形和图像处理标准中,RGB模型更为常见。

这里再说一个小话题。BMP的色彩存储是RGB888,我们知道这个屏是RGB565。应该怎么转换呢?

#@micropython.native
def TFTColor( aR, aG, aB ) :'''Create a 16 bit rgb value from the given R,G,B from 0-255.This assumes rgb 565 layout and will be incorrect for bgr.'''return ((aR & 0xF8) << 8) | ((aG & 0xFC) << 3) | (aB >> 3)

RGB是三个颜色,每个颜色用0到FF来表示,不同的值表示不同的色彩强度。以红色为例,如果要压缩到5位应该怎么做呢?
r5 = (r * 31) // 255
假如色彩值是100,那么算出来大概是12.15,保留整数就是12。
这里代码怎么做的呢?直接扔掉低三位。
100的二进制是110 0100,扔掉低三位就是1100,换算成10进制就是12。明显移位的方法效率高得多。

位操作可以看这篇:C的位操作-CSDN博客

五 小结

从上面可以看出,显示驱动主要就是两个部分。

1 显示屏的初始化。设置PIN脚,然后直接就是一串SPI命令,找厂商要就行了。

2 屏幕SPI命令的封装。从ST7735的SPI命令来看,其实就是两个接口。要绘制哪里?要绘制成什么颜色?就这两个接口,然后所有的上层接口,都是围绕这两个接口的封装。画图,画线,画圆,显示图片,颜色有时候要转换成屏要的2个byte格式,让上层更方便使用。

对了,这个驱动是基于python的,很多地方都确实慢的出奇,真要堪用,还是得上C/C++。

好了,基本上就是这么回事,驱动很难吗?好像也不太难。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/394214.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【HarmonyOS NEXT星河版开发学习】小型测试案例01-今日头条置顶练习

个人主页→VON 收录专栏→鸿蒙开发小型案例总结​​​​​ 基础语法部分会发布于github 和 gitee上面 ​ 前言 本系列可能是博客首发&#xff0c;鸿蒙开发星河版是一个全新的版本&#xff0c;由于参考视频较少鸿蒙开发不被重视导致csdn上面并没有全套的学习路线&#xff0c;…

第20周:Pytorch文本分类入门

目录 前言 一、前期准备 1.1 环境安装导入包 1.2 加载数据 1.3 构建词典 1.4 生成数据批次和迭代器 二、准备模型 2.1 定义模型 2.2 定义示例 2.3 定义训练函数与评估函数 三、训练模型 3.1 拆分数据集并运行模型 3.2 使用测试数据集评估模型 总结 前言 &#x1…

【JUC】03-CompletableFuture使用

1. CompletableFuture CompletableFuture可以进行回调通知、创建异步任务、多个任务前后依赖可以组合处理、对计算速度选最快。  CompletableFuture提供了一种类似于观察者模式的通知方式&#xff0c;可以在任务完成后通知监听方。 CompletableFuture实例化用CompletableFutur…

【弱网】模拟弱网环境

fiddler工具 调整上传/下载速率 打开fiddler脚本工具&#xff0c;在上方状态栏选择 Rules -> Customize Rules…&#xff0c;打开ScriptEditor编辑器 修改上传/下载速率&#xff0c;实现模拟指定弱网环境 计算公示&#xff1a;[1/(上或下行速率/8)] x 1000 网络上行下载2G2…

【Hive】学习笔记

Hive学习笔记 【一】Hive入门【1】什么是Hive【2】Hive的优缺点&#xff08;1&#xff09;优点&#xff08;2&#xff09;缺点 【3】Hive架构原理&#xff08;1&#xff09;用户接口&#xff1a;Client&#xff08;2&#xff09;元数据&#xff1a;Metastore&#xff08;3&…

相机标定——小孔成像、相机模型与坐标系

小孔成像 用一个带有小孔的板遮挡在墙体与物之间&#xff0c;墙体上就会形成物的倒影&#xff0c;我们把这样的现象叫小孔成像。 用一个带有小孔的板遮挡在墙体与物之间&#xff0c;墙体上就会形成物的倒影&#xff0c;我们把这样的现象叫小孔成像。前后移动中间的板&#xff…

Docker 常规安装简介

Docker常规安装简介 欢迎关注我的B站&#xff1a;https://space.bilibili.com/379384819 1. 安装mysql 1.1 docker hub上面查找mysql镜像 网址&#xff1a; https://hub.docker.com/_/mysql 1.2 从docker hub上&#xff08;阿里云加速器&#xff09;拉取mysql镜像到本地标…

Redis远程字典服务器(0)——分布式系统

目录 一&#xff0c;关于Redis 二&#xff0c;分布式系统 2.1 关于分布式 2.2 理解数据库分离 2.3 理解负载均衡 2.4 数据库读写分离 2.5 引入缓存 2.6 数据库分库分表 2.7 微服务 四&#xff0c;补充 五&#xff0c;总结 一&#xff0c;关于Redis MySQL是在磁盘中存…

分类预测 | Matlab实现PSO-XGBoost粒子群算法优化XGBoost的多特征分类预测

分类预测 | Matlab实现PSO-XGBoost粒子群算法优化XGBoost的多特征分类预测 目录 分类预测 | Matlab实现PSO-XGBoost粒子群算法优化XGBoost的多特征分类预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现PSO-XGBoost粒子群算法优化XGBoost的多特征分类预测&a…

英特尔:“芯”痛巨头

从全球芯片巨头到“芯”痛巨头&#xff0c; 英特尔 到底经历了什么&#xff1f; 今天券商中国说英特尔在QDII基金上这么多年&#xff0c;一直就没能进入主流持仓中&#xff0c;最后一只试探性持仓英特尔的QDII也已在今年3月末砍仓了&#xff0c; 这一砍还让这只QDII完美躲过…

医得快医疗服务交易服务平台/基于微信小程序的药品销售系统

获取源码联系方式请查看文章结尾&#x1f345; 摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而…

【中间件】Redis从入门到精通-黑马点评综合实战

文章目录 一&#xff1a;Redis基础1.Redis是什么2.初识Redis3.Redis的数据结构A.通用命令B.String类型C.Key的层级格式D.Hash类型E.List类型F.Set类型G.SortedSet类型 二&#xff1a;Redis的Java客户端1.JedisA.引入依赖B.建立连接C.测试JedisD.释放资源 2.Jedis连接池3.Spring…

如何通过GD32 MCU内部ADC参考电压通道提高采样精度?

ADC采样精度受很多因素影响&#xff0c;比如电源波动、参考电压波动、输入信号波动等&#xff0c;GD32 MCU内部提供了一个参考电压通道&#xff0c;理论上可以优化由于电源和参考电压较大波动引入的采样误差。 如下图所示&#xff0c;GD32F303 ADC内部17通道为VREFINT参考电压…

密码学基础-为什么使用真随机数(True Random Number Generators)

密码学基础-为什么使用真随机数&#xff08;True Random Number Generators&#xff09; 概述 随机的意义很重要&#xff0c;就像你的银行密码如果是亲朋好友的生日&#xff0c;结婚纪念日&#xff08;可预测的&#xff09;&#xff0c;那么就容易被人测试出来&#xff1b;而…

从零开始学习性能测试

学习目标 理解性能测试定义、目的理解常见性能测试策略理解性能指标理解性能测试方法学习性能测试工具 什么是性能测试 测试中的非功能测试其实范围比较广&#xff0c;性能、稳定性、安全性等都可以放进这个范畴。非功能测试&#xff0c;一般比功能测试门槛高些&#xff0c;多数…

深入理解计算机系统 CSAPP lab:bomb

实验资源下载地址&#xff1a;csapp.cs.cmu.edu/3e/labs.html 请先查看writeup 解压后 当我们运行bomb时,发现该程序要求我们输入行,如果输入错误,程序就会返回BOOM!!!提示我们失败了. 所以我们的目标是输入正确的行.以解开bomb程序. 实验前先详细阅读bomb.c //bomb.c /*****…

计算机系统基础(一)

开始复习了软考软件设计师还有考研复习了&#xff0c;这个重合部分比较大&#xff0c;开始学习打卡&#xff0c;基础最重要&#xff0c;直接看书又多又杂&#xff0c;重点理不出来&#xff0c;学习记录。 计算机系统基础 冯诺依曼体系结构奠定了计算机的基础结构。五个部分组成…

认识Modbus RTU与Modbus TCP

&#xff08;选自成都纵横智控-Modbus RTU与Modbus TCP协议区别详解 &#xff09; Modbus RTU 和 Modbus TCP 是两种常用的工业通信协议&#xff0c;用于连接电子设备&#xff0c;但它们在多方面有所不同。以下是它们的详细比较&#xff1a; Modbus RTU 协议类型&#xff1a; …

Flink 实时数仓(九)【DWS 层搭建(三)交易域汇总表创建】

前言 今天立秋&#xff0c;任务是完成 DWS 剩余的表&#xff0c;不知道今天能不能做完&#xff0c;欲速则不达&#xff0c;学不完就明天继续&#xff0c;尽量搞懂每一个需求&#xff1b; 1、交易域下单各窗口汇总表 任务&#xff1a;从 Kafka 订单明细主题读取数据&#xff0…

SpringBoot中使用过滤器filter

过滤器Filter 在 Java 中&#xff0c;Filter&#xff08;过滤器&#xff09;是一种用于对请求进行预处理和后处理的机制。 工作原理&#xff1a; 当一个请求到达服务器时&#xff0c;会先经过一系列配置好的过滤器。过滤器可以检查请求的参数、头信息、请求体等内容&#xf…