关于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_vcc
    self.height  = 32 if height == 32 else 64
    
    self.pages   = int(self.height / 8) 
    self.columns  = 128
    self.i2c = pyb.I2C(1)
    self.i2c.init(pyb.I2C.MASTER, baudrate=400000) # 400kHz
    self.devid = i2c_devid

    self.offset = 1
    self.cbuffer = bytearray(2)
    self.cbuffer[0] = CTL_CMD

  def clear(self):
    self.buffer = bytearray(self.offset + self.pages * self.columns)
    if self.offset == 1:
      self.buffer[0] = CTL_DAT
  def 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_number
      pixel_offset = char_offset + char_column * size + point_row
      return self.columns - pixel_offset

    def pixel_y(char_row, point_column):
      char_offset = y + char_row * size
      return char_offset + point_column

    def 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=5
      for char_row in range(font.rows)#rows=8
      for 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_number
      pixel_offset = char_offset + char_column * size + point_row
      # return self.columns - pixel_offset
      return pixel_offset    *************************************************************
    def pixel_y(char_row, point_column):
      #char_offset = y + char_row * size
      #另一种布局,修改一下坐标
      #原来的布局
      # char_offset=y+char_row*size
      char_offset = y + (font.rows - 1 - char_row) * size***************************
      #y垂直方向不设置间隔
      # return char_offset + point_column
      return  char_offset + point_column

    def pixel_mask(char, char_column, char_row):
      char_index_offset = ord(char) * font.cols
      return font.bytes[char_index_offset + char_column] >> char_row & 0x1

    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)
      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_number
        pixel_offset =char_offset+char_column * size + point_row
        #y垂直方向不设置间隔
        # return char_offset + point_column
        return  pixel_offset
    def pixel_x( char_row , point_column):
        #行的距离域(128->64)偏移从(5->8)s
          char_offset = x +  char_row * size
          # return self.columns - pixel_offset
          return char_offset + point_column    
    def pixel_mask(char, char_column, char_row):
        char_index_offset = ord(char) * font.cols
        return font.bytes[char_index_offset + char_column] >> char_row & 0x1
    pixels = ((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:  # 如果当前像素为1
                rotated_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-38
      if 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.height

      for 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_x
    y = start_y

    while 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_byte
    self.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)  # 无垂直偏移

就先记录到这里。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Chromium form表单post提交过程分析c++

form表单get提交参考之前文章Chromium 前端form表单提交过程分析c-CSDN博客 一、表单post提交测试例子&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>菜鸟教程(runoob.com)</title> </head&…

【火山引擎】AIGC图像风格化 | 风格实践 | PYTHON

目录 1 准备工作 2 实践 代码 效果图 1 准备工作 ① 服务开通 确保已开通需要访问的服务。您可前往火山引擎控制台,在左侧菜单中选择或在顶部搜索栏中搜索需要使用的服务,进入服务控制台内完成开通流程。

TWS蓝牙耳机发展史

目录 1&#xff1a;人类历史第一副耳机 2&#xff1a;第一台手持式耳机 3&#xff1a;第一台头戴式耳机 4&#xff1a;第一台动圈式耳机 5&#xff1a;第一台立体声耳机 6&#xff1a;第一台压耳式耳机 7&#xff1a;随身听 8&#xff1a;商用降噪耳机 9&#xff1a;i…

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

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

《献给阿尔吉侬的花束》

这是看过的错别字最多的一本书&#xff0c;错别字多并不是这本书的缺点&#xff0c;反而是一个亮点。全书以“近步抱告”的形式讲述了想变“聪明”的查理的故事。很治愈&#xff0c;也很虐心。聪明有聪明的代价&#xff0c;看到的感受到的越多&#xff0c;需要强大的内心去承受…

LeetCode 精选 75 回顾

目录 一、数组 / 字符串 1.交替合并字符串 &#xff08;简单&#xff09; 2.字符串的最大公因子 &#xff08;简单&#xff09; 3.拥有最多糖果的孩子&#xff08;简单&#xff09; 4.种花问题&#xff08;简单&#xff09; 5.反转字符串中的元音字母&#xff08;简单&a…

高性能 JSON 处理:为何选择 Fastjson?

一、关于Fastjson 1.1 简介 Fastjson 是由阿里巴巴集团开发的一个高性能的 JSON 处理库&#xff0c;它支持 Java 对象与 JSON 字符串之间的互相转换。Fastjson 自 2011 年发布以来&#xff0c;以其卓越的性能和丰富的功能在 Java 社区中获得了广泛的应用。 Alibaba Fastjson:…

RabbitMQ系列学习笔记(九)--路由模式

文章目录 一、路由模式原理二、多重绑定三、路由模式实战1、消费者代码2、生产者代码3、运行结果分析 本文参考 尚硅谷RabbitMQ教程丨快速掌握MQ消息中间件rabbitmq RabbitMQ 详解 Centos7环境安装Erlang、RabbitMQ详细过程(配图) 一、路由模式原理 使用发布订阅模式时&#x…

C++ -string -常见用法5

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【C】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 文章目录 &#x1f4a1;前言&#x1f4a1;非成员函数1.operator1.1函数原型1.2使用1.3注意 2.relational operators3.swap4.operator>>5.operator<<6.operator<…

Javascript算法(滑块窗口、螺旋矩阵)

滑块窗口 JS滑块窗口算法&#xff0c;即滑动窗口算法&#xff08;Sliding Window&#xff09;&#xff0c;在JavaScript中的应用场景主要集中在处理字符串和数组等数据结构中的子串或子数组问题。这种算法通过维护一个窗口&#xff0c;并移动窗口的两个边界&#xff08;左右指…

Linux命令进阶·vi\vim编辑器详细命令介绍

目录 1. 什么是 vim&#xff1f; 2. vi\vim 模式介绍 2.1 命令模式&#xff08;Command mode&#xff09; 2.2 输入模式&#xff08;Insert mode&#xff09; 2.3 底线命令模式&#xff08;Last line mode&#xff09; 3. vi\vim 的使用 4. 命令介绍 1. 什么是 …

微信小程序-自定义组件

文章目录 微信小程序-自定义组件概述创建和使用数据、方法和属性slot 插槽默认插槽具名插槽 组件样式注意项样式隔离 数据监听组件间通信父传子子传父获取子组件实例 生命周期组件的生命周期组件所在页面的生命周期App、Page与Component生命周期对比冷启动保留当前页面和关闭当…

诺奖印证产业方向,AI先行者晶泰科技开拓黄金赛道

2024年诺贝尔奖揭晓的各奖项中&#xff0c;AI领域无疑成为“最大赢家”。 从诺贝尔物理学奖被授予两名AI科学家&#xff0c;到诺贝尔化学奖表彰三位科学家“用人工智能&#xff08;AI&#xff09;破译蛋白质的密码”&#xff0c;本届诺贝尔奖“含AI量”之高引起市场热议。 值…

如何将 Elasticsearch 与流行的 Ruby 工具结合使用

作者&#xff1a;来自 Elastic Fernando Briano 了解如何将 Elasticsearch 与一些流行的 Ruby 库一起使用。 在这篇博文中&#xff0c;我们将介绍如何将 Elasticsearch 与一些流行的 Ruby 工具结合使用。我们将实现 Ruby 客户端 “入门”指南 中介绍的常用 API。如果你点击该链…

【从零开发Mybatis】引入XNode和XPathParser

引言 在上文&#xff0c;我们发现直接使用 DOM库去解析XML 配置文件&#xff0c;非常复杂&#xff0c;也很不方便&#xff0c;需要编写大量的重复代码来处理 XML 文件的读取和解析&#xff0c;代码可读性以及可维护性相当差&#xff0c;使用起来非常不灵活。 因此&#xff0c…

深度学习:对评论信息的情感分析,建立模型,自动识别评论信息的情绪状态完整代码实现

评论 思考&#xff1a;向模型中传递数据时&#xff0c;需要提前处理好数据 1、目标&#xff1a;将评论内容转换为词向量。 2、每个词/字转换为词向量长度(维度)200 3、每一次传入的词/字的个数是否就是评论的长度? 应该是固定长度&#xff0c;每次传入数据与图像相似…

DIY我的世界磁力方块

引子 小朋友喜欢我的世界&#xff0c;就像当年我那代对俄罗斯方块的执着&#xff0c;考虑电子游戏伤眼睛&#xff0c;所以最近开始给小朋友买磁力方块。 一个将近1元多的价格&#xff0c;催生我DIY的念头。 正文 Freecad图&#xff0c;A,B,C,D处 放磁铁 5.14g 材料费 最后的成…

Axure中继器单选、多选和重置

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 课程主题&#xff1a;Axure中继器单选、多选和重置 主要内容&#xff1a;根据查询条件&#xff0c;通过单选、多选和重置&#xff0c;从中继器中得到数据 应用场景&…

DockerCompose快速部署Java项目、nginx前端和mysql数据库到centos虚拟机

简介&#xff1a;整理自&#xff1a;SpringCloud微服务开发与实战&#xff0c;java黑马商城项目微服务实战开发&#xff08;涵盖MybatisPlus、Docker、MQ、ES、Redis高级等&#xff09;课程的飞书文档。 DockerCompose介绍 大家可以看到&#xff0c;我们部署一个简单的java项…

stm32实现esp8266连接到TCP服务器(二)未完

1.2 连接到TCP Server 1.2.1 使用网络助手&#xff0c;设立TCP服务器 ​ 编辑 1.2.2 连接服务器 ATCIPSTART"TCP","192.168.1.18",8080 //指令&#xff0c;注意双引号逗号都要半角(英文)输入 CONNECT //结果&#xff1a;成功 OK //结果&#xff1a;成功 …