关于SSD1306的OLED的显示的研究

文章目录

      • 函数作用
      • 参数解释
      • 嵌套函数分析
      • 主代码分析
      • 逻辑流程
      • 总结
    • 难点的解析:
      • 生成器的主要逻辑分解:
      • 每次生成的元组 `(pixel_x, pixel_y, pixel_mask)`:
      • 生成器的整体流程
      • 举例
      • 总结
    • 反转后的文本绘制
    • 竖直布局
    • 有问题的旋转
    • 180度旋转
    • 坐标轴
    • 绘制矩形
    • 绘制曲线(正弦波)
    • 控制命令
    • 屏幕的滚动

本文从内存的显示,缓存的读写来进行研究

class SSD1306(object):def __init__(self, pinout, height=32, external_vcc=True, i2c_devid=DEVID):self.external_vcc = external_vccself.height  = 32 if height == 32 else 64self.pages   = int(self.height / 8) self.columns  = 128self.i2c = pyb.I2C(1)self.i2c.init(pyb.I2C.MASTER, baudrate=400000) # 400kHzself.devid = i2c_devidself.offset = 1self.cbuffer = bytearray(2)self.cbuffer[0] = CTL_CMDdef clear(self):self.buffer = bytearray(self.offset + self.pages * self.columns)if self.offset == 1:self.buffer[0] = CTL_DATdef display(self):self.write_command(COLUMNADDR)self.write_command(0)self.write_command(self.columns - 1)self.write_command(PAGEADDR)self.write_command(0)self.write_command(self.pages - 1)if self.offset == 1:self.i2c.send(self.buffer, addr=self.devid, timeout=5000)else:self.dc.high()self.spi.send(self.buffer)def set_pixel(self, x, y, state):index = x + (int(y / 8) * self.columns)if state:self.buffer[self.offset + index] |= (1 << (y & 7))else:self.buffer[self.offset + index] &= ~(1 << (y & 7))

对于这段代码,我们可以知道,OLED设置了两个缓冲区,一个是命令缓冲区cbuffer ,一个是buffer数据缓冲区。
在读写数据前,我们要使用clear函数,来创建缓冲区,

self.buffer = bytearray(self.offset + self.pages * self.columns)

我们来粗略的计算一下这个buffer。

8*128+1 =1025

绘制字体的代码,需要

# 计算真实的x坐标,怎么计算
#初始位置x,第几个字符*放缩尺寸*字符的列数,space * char_number间隔
char_offset = x + char_number * size * font.cols + space * char_number
#像素的偏移,除了char_offset,还有字符内部是第几列(这个是x的偏移乘以放缩尺寸),Point_row是尺寸增加的额外补全点
pixel_offset = char_offset + char_column * size + point_row
#计算出最后的坐标,使用128减之后,代表return 128 - pixel_offset
 def draw_text(self, x, y, string, size=1, space=1):def pixel_x(char_number, char_column, point_row):char_offset = x + char_number * size * font.cols + space * char_numberpixel_offset = char_offset + char_column * size + point_rowreturn self.columns - pixel_offsetdef pixel_y(char_row, point_column):char_offset = y + char_row * sizereturn char_offset + point_columndef pixel_mask(char, char_column, char_row):char_index_offset = ord(char) * font.cols#取到对应的font.py数组return font.bytes[char_index_offset + char_column] >> char_row & 0x1# 0x1 是二进制的 00000001。& 运算符是位与运算符,它的作用是从字节的最低位提取出那一位的值(0 或 1)。# & 0x1 操作确保我们只关注字节的最低位,判断这一位是 1(点亮)还是 0(不点亮)。pixels = ((pixel_x(char_number, char_column, point_row),#(第几个字母,字母列定位,生成多个(尺寸的点))放大尺寸pixel_y(char_row, point_column),#pixel_mask(char, char_column, char_row))for char_number, char in enumerate(string)for char_column in range(font.cols)#cols=5for char_row in range(font.rows)#rows=8for point_column in range(size)for point_row in range(1, size + 1))for pixel in pixels:self.set_pixel(*pixel)

在这里插入图片描述

这个 draw_text 函数的作用是在 OLED 显示屏上显示文本。它通过将文本字符串中的每个字符逐个绘制到显示屏上,模拟了字符的像素显示效果。以下是对该函数的详细分析:

函数作用

draw_text 负责将字符串中的每个字符逐个绘制到 OLED 显示屏上。它根据字符的大小、间距以及具体的像素位置,计算出每个字符应该显示的像素位置,并调用 set_pixel 来设置相应的像素点。

参数解释

  • x:文本的起始 x 坐标,表示文本在屏幕的水平位置。
  • y:文本的起始 y 坐标,表示文本在屏幕的垂直位置。
  • string:要显示的字符串。
  • size:字符的大小缩放比例,默认为 1,表示原始大小。
  • space:字符之间的间隔,默认为 1。

嵌套函数分析

  1. pixel_x

    • 计算当前字符的像素 x 坐标。
    • 参数:
      • char_number: 当前字符在字符串中的位置。
      • char_column: 当前字符的列位置(表示字符的某一列像素)。
      • point_row: 字符点阵的某一行的像素。
    • 公式解释:
      • char_offset: 基于 x 坐标和字符的编号、大小、间距,计算当前字符的偏移量。
      • pixel_offset: 计算字符在列方向上的像素偏移量。self.columns 用来确保不超出显示屏的宽度。
  2. pixel_y

    • 计算当前字符的像素 y 坐标。
    • 参数:
      • char_row: 当前字符在点阵中的行数。
      • point_column: 点阵某一列的像素点。
    • 公式解释:
      • char_offset: 基于 y 坐标和字符的行数、大小,计算字符在垂直方向的偏移量。
      • 最终返回的是这个字符的像素点在显示屏中的 y 坐标。
  3. pixel_mask

    • 获取当前字符在某一行某一列的像素点是亮(1)还是灭(0)。
    • 参数:
      • char: 当前字符。
      • char_column: 当前字符的列位置。
      • char_row: 当前字符的行位置。
    • 通过 ord(char) 获取字符的 ASCII 编码,然后从字体数组中找到该字符的位图信息,具体到每一个像素点。

主代码分析

  • pixels = (...)

    • 这是一个生成器表达式,它遍历字符串中的每个字符,逐行逐列地处理字符的每个像素点。每个字符由 font.cols 列和 font.rows 行组成。
    • 它遍历每个字符的所有像素点,并调用上面定义的 pixel_x, pixel_y, pixel_mask 来确定每个像素点的 x 和 y 坐标,以及它是否点亮(通过 pixel_mask 函数)。
    • 该生成器最终生成一个包含了所有像素信息的三元组 (pixel_x, pixel_y, pixel_mask),并将其保存为 pixels
  • for pixel in pixels:

    • 遍历生成的所有像素点,并调用 self.set_pixel() 来设置 OLED 显示屏上相应位置的像素点。
    • self.set_pixel(*pixel):将 pixel 作为位置参数解包,传入 set_pixel(),从而在 OLED 上设置对应的像素。

逻辑流程

  1. 遍历字符串:函数首先遍历传入的字符串 string,并对每个字符进行处理。
  2. 逐列处理字符像素:每个字符由多个列组成,每列包含多个像素点。通过 char_columnchar_row 逐个遍历字符的点阵。
  3. 获取像素信息:通过 pixel_xpixel_ypixel_mask 获取字符中每个像素点的位置和状态(亮或灭)。
  4. 绘制到显示屏:通过 self.set_pixel() 将每个像素点绘制到 OLED 显示屏上。

总结

draw_text 函数的主要目的是在 OLED 显示屏上绘制文本字符串。它通过遍历每个字符的像素点阵信息,将字符的像素映射到显示屏的相应位置,并通过设置像素来显示文本内容。

如果需要在显示屏上显示不同大小、不同间隔的文本,或者需要精确控制字符在屏幕上的位置,可以通过修改 sizespace 参数来实现。

难点的解析:

生成器的代码:
这个生成器表达式 pixels = (...) 是一个复杂的多重循环,它遍历了字符串中的每个字符、字符的每个列、每列的每一行、行中的每一个像素点,然后计算出每个像素点的 x 坐标、y 坐标,以及该像素点是否点亮(通过 pixel_mask 函数决定)。

生成器的主要逻辑分解:

这个生成器由多个嵌套的 for 循环构成。它的执行过程可以分为以下几个步骤:

  1. for char_number, char in enumerate(string)
  • 这是最外层的循环,遍历字符串 string 中的每个字符。
  • char_number:字符在字符串中的索引,用于计算字符在屏幕上的横向位置。
  • char:当前字符。
  1. for char_column in range(font.cols)
  • 这是第二层循环,遍历当前字符在字体点阵中的列。font.cols 是字符的列数(即字符的宽度,以像素为单位),通常一个字符在点阵字体中是 5 列。
  • char_column:当前列的索引,用于计算字符点阵中的列像素。
  1. for char_row in range(font.rows)
  • 这是第三层循环,遍历当前列中字符的行。font.rows 是字符的行数(即字符的高度,以像素为单位),通常一个字符在点阵字体中有 8 行。
  • char_row:当前行的索引,用于计算字符点阵中的行像素。
  1. for point_column in range(size)

    • 这是第四层循环,用于处理字符放大(缩放)时的列像素扩展。size 是字符的缩放大小,range(size) 表示在 x 轴上重复 size 次,以模拟字符的放大效果。
    • point_column:缩放列的索引,用于实现字符的宽度放大。
  2. for point_row in range(1, size + 1)

  • 这是第五层循环,类似于 point_column,用于处理字符放大时的行像素扩展。在 y 轴上重复 size 次,以实现字符的高度放大。
  • point_row:缩放行的索引,用于实现字符的高度放大。

每次生成的元组 (pixel_x, pixel_y, pixel_mask)

这三个值是通过每层循环计算出来的,它们表示当前像素点的 x 坐标、y 坐标和该像素点是否点亮的状态。每次生成一个这样的三元组,传递给 set_pixel() 方法,来在屏幕上绘制这个像素点。

  • pixel_x(char_number, char_column, point_row)
    通过字符的索引 char_number 和当前列索引 char_column,结合字符缩放后的列索引 point_row 计算出这个像素点在屏幕上的 x 坐标。

  • pixel_y(char_row, point_column)
    通过字符的行索引 char_row 和缩放后的行索引 point_column 计算出这个像素点在屏幕上的 y 坐标。

  • pixel_mask(char, char_column, char_row)
    通过字符的 ASCII 值 char 以及字符点阵中的行列位置来确定这个像素点是否需要点亮(返回 1)或不点亮(返回 0)。

生成器的整体流程

假设我们有一个字符串 "A",字体点阵为 5 列 8 行,size = 2,那么生成器的执行流程大致如下:

  1. for char_number, char in enumerate("A")

    • 遍历字符串 "A" 中的字符,当前字符是 "A"char_number = 0
  2. for char_column in range(font.cols)

    • 遍历 "A" 的点阵列,假设 "A" 是 5 列字符,这个循环会从 0 遍历到 4
  3. for char_row in range(font.rows)

    • 遍历 "A" 每列的点阵行,假设 "A" 是 8 行字符,这个循环会从 0 遍历到 7
  4. for point_column in range(size)

    • 假设 size = 2,表示字符需要放大 2 倍,这里会重复每列两次。
  5. for point_row in range(1, size + 1)

    • 同样地,字符的每一行也会放大 2 倍,行像素重复 2 次。

举例

假设 "A" 的点阵如下(5x8 字符):

01110
10001
10001
11111
10001
10001
10001
10001

生成器会依次生成 "A" 的每个像素点的坐标和亮度信息。通过缩放,每个原始像素点都会被放大 2 倍,从而使 "A" 的像素图显示更大。

总结

这个生成器的作用是通过多重嵌套循环遍历字符串中的每个字符,并处理字符的点阵像素信息。在考虑字符的大小缩放和位置偏移的基础上,生成对应的屏幕坐标和像素状态,最后通过 set_pixel() 绘制到 OLED 显示屏上。

一个例子:

cols = 5
rows = 8
bytes = [0x00, 0x00, 0x00, 0x00, 0x00,0x3E, 0x5B, 0x4F, 0x5B, 0x3E,

0x是一个八位的数,就是一列。每一行,就是一个字符的表示。
0x3E -> 00111110
0x5B -> 01011011
0x4F -> 01001111
0x5B -> 01011011
0x3E -> 00111110

00111110 -> ******
01011011 -> * ** **
01001111 -> * ****
01011011 -> * ** **
00111110 -> ******

如上图表示。所以每个字符都是这样保存和取用的。

反转后的文本绘制

修改过上下翻转的字符绘制:

在这里插入图片描述

#可以修改一下函数名
# draw_text_normal()def draw_text(self, x, y, string, size=1, space=1):def pixel_x(char_number, char_column, point_row):char_offset = x + char_number * size * font.cols + space * char_numberpixel_offset = char_offset + char_column * size + point_row# return self.columns - pixel_offsetreturn pixel_offset    *************************************************************def pixel_y(char_row, point_column):#char_offset = y + char_row * size#另一种布局,修改一下坐标#原来的布局# char_offset=y+char_row*sizechar_offset = y + (font.rows - 1 - char_row) * size***************************#y垂直方向不设置间隔# return char_offset + point_columnreturn  char_offset + point_columndef pixel_mask(char, char_column, char_row):char_index_offset = ord(char) * font.colsreturn font.bytes[char_index_offset + char_column] >> char_row & 0x1pixels = ( (pixel_x(char_number, char_column, point_row),pixel_y(char_row, point_column),pixel_mask(char, char_column, char_row))for char_number, char in enumerate(string)for char_column in range(font.cols)for char_row in range(font.rows)for point_column in range(size)for point_row in range(1, size + 1))for pixel in pixels:self.set_pixel(*pixel)

修改了星标这两个地方。

竖直布局

为了实现竖直布局的书写,我们的屏幕从(128,64)->(64,128)

在这里插入图片描述
我们不需要修改mask的部分,只需要把,求y和x的逻辑进行交换就可以。
在这里插入图片描述

def draw_ylayout(self, x, y, string, size=1, space=1):def pixel_y(char_number,char_column, point_row):char_offset = y + char_number * size * font.cols+space * char_numberpixel_offset =char_offset+char_column * size + point_row#y垂直方向不设置间隔# return char_offset + point_columnreturn  pixel_offsetdef pixel_x( char_row , point_column):#行的距离域(128->64)偏移从(5->8)schar_offset = x +  char_row * size# return self.columns - pixel_offsetreturn char_offset + point_column    def pixel_mask(char, char_column, char_row):char_index_offset = ord(char) * font.colsreturn font.bytes[char_index_offset + char_column] >> char_row & 0x1pixels = ((pixel_x(char_row, point_column),pixel_y(char_number, char_column, point_row),pixel_mask(char, char_column, char_row))for char_number, char in enumerate(string)for char_column in range(font.cols)for char_row in range(font.rows)for point_column in range(1, size + 1)for point_row in range(size))for pixel in pixels:self.set_pixel(*pixel)

本来本文尝试实现90度旋转,但是因为最终需要的模式不同,非方阵,矩阵的旋转很容易出现溢出。尝试了几个生成的代码,没有比较满意的。
下面这个应该有错,但现在不想探索了。

有问题的旋转

def rotate_buffer(self):# 旋转后的缓冲区rotated_buffer = bytearray(1025)  # 保留控制字节rotated_buffer[0] = self.buffer[0]  # 保留控制字节for x in range(128):for y in range(64):# 计算原缓冲区中的位置original_index = 1 + (x * 8) + (y // 8)original_bit = (self.buffer[original_index] >> (y % 8)) & 0x01# 计算旋转后的位置new_x = y  # 90度旋转,新列new_y = 127 - x  # 反转行# 计算新缓冲区中的位置new_index = 1 + (new_x * 8) + (new_y // 8)if original_bit:  # 如果当前像素为1rotated_buffer[new_index] |= (1 << (new_y % 8))# 用旋转后的缓冲区替换原缓冲区self.buffer = rotated_buffer

180度旋转

旋转180度的反转代码是好用的。

def rotate_180(self):# 创建一个新的缓冲区来存储反转后的内容new_buffer = bytearray(self.offset + self.pages * self.columns)# 复制控制字节new_buffer[0] = self.buffer[0]# 反转每个字节和行的顺序for page in range(self.pages):  # 这里 pages 是 8,因为屏幕高度为 64 像素for column in range(self.columns):  # 这里 columns 是 128# 计算反转后的索引original_index = 1 + page * self.columns + column  # 原始索引new_index = 1 + (self.pages - 1 - page) * self.columns + (self.columns - 1 - column)  # 新索引# 将字节反转并赋值到新的缓冲区new_buffer[new_index] = self.buffer[original_index] ^ 0xFF  # 反转字节# 更新原始缓冲区self.buffer = new_buffer

代码并不难,但是旋转感觉自己绕来绕去,以后要多写文档,理清楚思路。180旋转直接就可以替代反转后的文本绘制

额外的绘制函数坐标轴。

坐标轴

绘制了正方向,设置了一下角度,按照原来的。
可调参数不多,需要进一步调整。

def draw_axes(self, origin_x=None, origin_y= None, length_x=None, length_y=None):# 绘制 X 轴if origin_x is None:origin_x = self.columns-38if origin_y is None:origin_y = self.height-10# 默认 X 轴长度为屏幕宽度if length_x is None:length_x = self.columns# 默认 Y 轴长度为屏幕高度if length_y is None:length_y = self.heightfor x in range(1, origin_x):self.set_pixel(x, origin_y, 1)# 绘制 Y 轴for y in range(origin_y, origin_y - length_y, -1):self.set_pixel(origin_x, y, 1)#绘制单位self.draw_text(110,56,"X/s")self.draw_text(1, 1, "Y/d")#绘制横的三角self.draw_triangle(0,54,5,1)self.draw_triangle(90, 0, 5, 0)#绘制竖的三角#是线,不是填充的。def draw_triangle(self, x, y, size=2,direction=1):
#认为是横的三角if 1 == direction:for i in range(1, size + 1):self.set_pixel(x + i, y, 1)self.set_pixel(x + i, y - i, 1)self.set_pixel(x + i, y + i, 1) else:#认为是竖的三角for i in range(1, size + 1):self.set_pixel(x, y + i, 1)self.set_pixel(x - i, y + i, 1)self.set_pixel(x + i, y + i, 1)

绘制矩形

  def draw_rectangle(self, x, y, width, height, filled=True):"""绘制一个方块或矩形:param x: 方块左上角的 X 坐标:param y: 方块左上角的 Y 坐标:param width: 方块的宽度:param height: 方块的高度:param filled: 是否填充方块(True 为填充,False 为仅绘制边框)"""# 绘制填充的方块if filled:for i in range(x, x + width):for j in range(y, y + height):self.set_pixel(i, j, 1)else:# 绘制空心方块(仅边框)# 上边框for i in range(x, x + width):self.set_pixel(i, y, 1)# 下边框for i in range(x, x + width):self.set_pixel(i, y + height - 1, 1)# 左边框for j in range(y, y + height):self.set_pixel(x, j, 1)# 右边框for j in range(y, y + height):self.set_pixel(x + width - 1, j, 1)# 显示绘制的方块self.display()

可以利用这个来绘制直方图。

绘制曲线(正弦波)

import math#记得添加这个库def draw_curve(self, start_x=98, start_y=32, step=-1):#可绘制的区域x[98,0],y[54,0]数越大,绘制的是越小,或者说越早的值# """# 从 x = 98 处开始动态绘制曲线,x 递减到 0 时重新更新显示器并从新开始绘制。# :param start_x: 起始 x 坐标,默认为 98# :param start_y: 起始 y 坐标,默认为屏幕中间# :param step: 每次 x 变化的步长,默认为 -1(向左绘制)# """x = start_xy = start_ywhile x >= 0:# 根据某个逻辑更新 y 值(这里示例使用正弦函数进行动态曲线绘制)y = int(32 + 10 * math.sin(x / 10))# 绘制当前像素self.set_pixel(x, y, 1)# 更新 x 值x += step# 如果 x 达到 0,刷新显示器并清空屏幕if x < 0:# 刷新显示内容self.display()# 清空显示屏以重新绘制曲线self.clear()#绘制坐标轴self.draw_axes()# 重新设置 x 为 98,重新开始绘制曲线x = 98# 显示绘制的点self.display()

控制命令

  def poweron(self):if self.offset == 1:pyb.delay(10)else:self.res.high()pyb.delay(1)self.res.low()pyb.delay(10)self.res.high()pyb.delay(10)def poweroff(self):self.write_command(DISPLAYOFF)def contrast(self, contrast):self.write_command(SETCONTRAST)self.write_command(contrast)

屏幕的滚动

  def write_command(self, command_byte):self.cbuffer[1] = command_byteself.i2c.send(self.cbuffer, addr=self.devid, timeout=5000)
  def setup_scroll(self):# Step 1: 停止任何正在进行的滚动self.write_command(DEACTIVATE_SCROLL)# Step 2: 设置水平滚动,从右向左滚动self.write_command(LEFT_HORIZONTAL_SCROLL)  # 左水平滚动self.write_command(0x00)  # 虚拟字节self.write_command(0x00)  # 起始页地址 (0表示第1页)self.write_command(0x00)  # 设置滚动速度,0x00 是较快滚动self.write_command(0x07)  # 结束页地址 (7表示第8页)self.write_command(0x00)  # 无垂直偏移self.write_command(0xFF)  # 无垂直偏移

就先记录到这里。

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

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

相关文章

SVM(支持向量机)

SVM&#xff08;支持向量机&#xff09; 引言 支持向量机(Support Vector Machine,SVM)&#xff0c;可以用来解答二分类问题。支持向量(Support Vector)&#xff1a;把划分数据的决策边界叫做超平面&#xff0c;点到超平面的距离叫做间隔。在SVM中&#xff0c;距离超平面最近…

【配色网站分享】

个人比较喜欢收藏一些好看的插画、UI设计图和配色&#xff0c;于是有了此篇&#xff0c;推荐一些配色网站&#xff0c;希望能对自己和大家有些帮助。 1.uiGradients 一个主打渐变风网站&#xff0c;还可以直接复制颜色。 左上角的“show all gradients”可以查看一些预设的渐…

upload-labs靶场Pass-02

upload-labs靶场Pass-02 分析源码 $is_upload false; $msg null; if (isset($_POST[submit])) {if (file_exists(UPLOAD_PATH)) {if (($_FILES[upload_file][type] image/jpeg) || ($_FILES[upload_file][type] image/png) || ($_FILES[upload_file][type] image/gif)) …

搭建Golang gRPC环境:protoc、protoc-gen-go 和 protoc-gen-go-grpc 工具安装教程

参考文章&#xff1a; 安装protoc、protoc-gen-go、protoc-gen-go-grpc-CSDN博客 一、简单介绍 本文开发环境&#xff0c;均为 windows 环境&#xff0c;mac 环境其实也类似 ~ ① 编译proto文件&#xff0c;相关插件 简单介绍&#xff1a; protoc 是编译器&#xff0c;用于将…

excel 表格中url转图片

待处理的单元格通过如下公式获取目标格式&#xff1a; "<table><img src"&A4&" height20></table>" 然后下拉后获取多列的单元格转换结果&#xff0c; 然后将这些转换后的结果拷贝到纯文本文档中&#xff0c; 然后再将纯文本…

音乐播放器-0.专栏介绍​

1.简介 本专栏使用Qt QWidget作为显示界面&#xff0c;你将会学习到以下内容&#xff1a; 1.大量ui美化的实例。 2.各种复杂ui布局。 3.常见显示效果实现。 4.大量QSS实例。 5.Qt音频播放&#xff0c;音乐歌词文件加载&#xff0c;展示。 6.播放器界面换肤。 相信学习了本专栏…

【Qt】Qt的介绍——Qt的概念、使用Qt Creator新建项目、运行Qt项目、纯代码方式、可视化操作、认识对象模型(对象树)

文章目录 Qt1. Qt的概念2. 使用Qt Creator新建项目3. 运行Qt项目3.1 纯代码方式实现3.2 可视化操作实现 4. 认识对象模型&#xff08;对象树&#xff09; Qt 1. Qt的概念 Qt 是一个跨平台的 C 图形用户界面应用程序开发框架。它是软件开发者提供的用于界面开发的程序框架&#…

Mysql(5)—函数

一、关于函数 1.1 简介 MySQL提供了许多内置的函数以帮助用户进行数据操作和分析。这些函数可以分为几类&#xff0c;包括聚合函数、字符串函数、数值函数、日期和时间函数、控制流函数等。 ​ ‍ 1.2 发展 早期版本&#xff08;MySQL 3.x 和 4.x&#xff09; : MySQL 最初…

无人机之三维航迹规划篇

一、基本原理 飞行环境建模&#xff1a;在三维航迹规划中&#xff0c;首先需要对飞行环境进行建模。这包括对地形、障碍物、气象等因素进行准确的测量和分析&#xff0c;以获得可行的飞行路径。 飞行任务需求分析&#xff1a;根据无人机的任务需求&#xff0c;确定航迹规划的…

Java最全面试题->计算机基础面试题->计算机网络面试题

计算机网络 下边是我自己整理的面试题&#xff0c;基本已经很全面了&#xff0c;想要的可以私信我&#xff0c;我会不定期去更新思维导图 哪里不会点哪里 1.说一下TCP/IP四层模型 TCP/IP协议是美国国防部高级计划研究局为实现ARPANET互联网而开发的。 网络接口层&#xff…

现代物流管理:SpringBoot技术突破

3系统分析 3.1可行性分析 通过对本智能物流管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本智能物流管理系统采用SSM框架&#xff0c;JAVA作为开发语…

【云从】九、CDN加速

文章目录 1、CDN基本概念2、CDN加速3、云CDN 1、CDN基本概念 源站&#xff1a;用户稳定运行的业务应用服务器 静态内容&#xff1a;用户多次访问某一资源&#xff0c;响应返回的数据都是相同的内容 例如:图片、视频、软件安装包、安卓 apk 安装包、压缩包文件等动态内容&…

【数据结构】栈和队列经典题目

目录 1.有效的括号【链接】 代码实现 2.用队列实现栈【链接】 代码实现 3.用栈实现队列 ​编辑 代码实现 4.循环队列&#xff08;数组实现&#xff09;【链接】 代码实现 1.有效的括号【链接】 题目描述&#xff1a; 给定一个只包括 (&#xff0c;)&#xff0c;{&…

Mycat 详细介绍及入门实战,解决数据库性能问题

一、基本原理 1、数据分片 &#xff08;1&#xff09;、水平分片 Mycat 将一个大表的数据按照一定的规则拆分成多个小表&#xff0c;分布在不同的数据库节点上。例如&#xff0c;可以根据某个字段的值进行哈希取模&#xff0c;将数据均匀的分布到不同的节点上。 这样做的好处…

数据结构7——二叉树的顺序结构以及堆的实现

在上篇文章数据结构6——树与二叉树中&#xff0c;我们了解了树和二叉树的概念&#xff0c;接着上篇文章&#xff0c;在本篇文章中我们学习二叉树顺序结构的实现。 目录 1. 二叉树的顺序存储结构 2. 堆的概念及结构 1. 堆的概念 2. 堆的结构 3. 堆的实现 1. 堆节点 2. 交…

R语言实现logistic回归曲线绘制

方式一&#xff1a;编制函数 x<-rnorm(10000)#设置随机种子 #编写绘图函数代码快 f <- function(x){y 1/(1 exp(-x))plot(x,y)}#sigmoid函数 f(x)​ 方式二&#xff1a;Sigmoid函数代码 x<-rnorm(10000)#设置随机种子 #编写绘图函数代码块 #y<-1/(1exp(-x)) y&…

数据结构-复杂度

复杂度 1.数据结构1.1算法 2.算法效率2.1复杂度的概念 3.时间复杂度3.1大O渐进表示法3.2时间复杂度计算示例3.2.1 示例13.2.2 示例23.2.3 示例33.2.4 示例43.2.5 示例5&#xff1a;3.2.6 示例63.2.7 示例7 4.空间复杂度4.1.1 示例14.1.2 示例2 5.常见复杂度对比6.复杂度算法题6…

【重学 MySQL】六十七、解锁检查约束,守护数据完整性

【重学 MySQL】六十七、解锁检查约束&#xff0c;守护数据完整性 检查约束的基本概念检查约束的语法检查约束的使用场景注意事项示例 在MySQL中&#xff0c;检查约束&#xff08;CHECK&#xff09;是一种用于确保表中数据满足特定条件的约束。 检查约束的基本概念 检查约束用…

考研前所学c语言02(2024/10/16)

1.一个十进制的数转化为二进制的就是不断除二取余&#xff0c;得到的余数从下到上取 比如123&#xff1a; 结果为&#xff1a; 同理其他的十进制转八进制&#xff0c;十六进制就除八&#xff0c;除十六即可 再比如123转十六进制&#xff1a; 因为余数是11&#xff0c;十六进…

【JavaEE初阶】深入理解网络编程—使用UDP协议API实现回显服务器

前言 &#x1f31f;&#x1f31f;本期讲解关于TCP/UDP协议的原理理解~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不…