资讯详情

【51单片机快速入门指南】4.2: SSD1306 OLED屏(0.96寸、1.3寸)的I2C控制详解

目录

  • 硬知识
    • SSD1306简介
    • I2C 接口
      • 从机地址位(SA0)
      • I2C 总线写数据
      • 命令解码器
    • 晶振电路和显示时间发生器
    • 复位
    • 图形显示数据RAM (GDDRAM)
    • 命令表
      • 基本命令表
        • 详细说明部分指令
          • 为 BANK0 设置对比度控制(81)h)
          • 所有显示打开(A4h/A5h)
          • 设置正常/反相显示(A6h、A7h)
          • 设置显示关,打开(AEh、AFh)
      • 滚屏命令
        • 详细说明部分指令
          • 水平滚动设置(26h 27h)
          • 连续垂直和水平滚动设置(29h 2Ah)
          • 关闭滚动(2Eh)
          • 激活滚动(2Fh)
          • 设置垂直滚动区域(A3h)
      • 地址设置命令表
        • 部分指令详解
          • 将低列开始地址设置为页面地址模式h~0Fh)
          • 将高列开始地址设置为页面地址模式h~1Fh)
          • 设置内存地址模式(20h)
          • 设置列地址(21h)
          • 设置页面地址(22h)
          • 设置页面开始地址作为页面寻址模式(B0h~B7h)
      • 硬件配置命令表(面板分辨率与布局相关)
        • 详细说明部分指令
          • 设置显示开始行(40h~7Fh)
          • 设置 Segment 重映射(A0h/A1h)
          • 设置复用率(A8h)
          • 设置 COM 输出扫描方向(C0h、C8h)
          • 设置显示偏移(D3h)
          • 设置 COM 引脚硬件配置(DAh)
      • 命令表设置时钟和驱动方案
        • 详细说明部分指令
          • 设置显示时钟频率、振荡器频率(D5h)
          • 设置重充电周期(D9h A[7:0])
          • 设置 Vcomh 取消选择水平(DBh A[6:4])
          • NOP(E3h)
  • 示例程序
    • oled.c
    • oled.h
    • oledfont.h
    • 测试程序
    • 实验现象

普中51-单核-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0


2022/1/12 重制,统一SPI版和I2C版本的代码

硬知识

摘自SSD1306-OLED驱动芯片中文手册 神秘的排版

SSD1306简介

SSD1306 是一个单片 CMOS OLED/PLED 驱动芯片,可驱动有机/聚合发光二极管点阵图形显示系统。 128 segments 和 64 Commons 组成。该芯片专为共阴极 OLED 面板设计。 SSD1306 对比度控制器嵌入显示器 RAM 和晶振,从而降低了外部设备和功耗。 256级亮度控制。发送数据/命令有三个接口:6800/80000 串口,I2C 接口或 SPI 接口。

I2C 接口

从机地址位(SA0)

SSD1306 在发送或接收任何信息之前,必须识别从机地址。设备将响应从机地址 跟随机地址(SA0 位)和读写选择位(R/W#位),格式如下: 在这里插入图片描述 SA0 位置为从机地址提供了一个位置扩展。) 或 ) 都可以做为 SSD1306 从机地址。D/C#引脚作为 SA0 用于选择从机地址。R/W#用于决定 I2C 总线接口的操作模式。 R/W# = 1,读模式。R/W# = 0 写模式

I2C 总线写数据

I2C 总线接口为设备提供编写数据和命令的接口。 I2C 请参考下图: I2C 的写模式

  1. 主机设备通过启动条件初始化数据通信。启动条件的定义显示在下图中。启动条件将通过 SDA 从高拉低而 SCL 保持高建立。
  2. 以起始条件为标志的从机地址。 SSD1306,从机地址可以是b0111100”或 “b0111101”通过改变 SA0 到 LOW 或 HIGH(D/C 引脚作为 SA0)。
  3. 通过设置来建立写作模式 R/W#为到逻辑 0 实现的。
  4. 接收到字节数据后,响应位信号将发生,包括从机地址和 R/W#位。可以参考下面的应答位信号的图示。应答位的定义是在应答位相关的时钟脉冲的高周期中把 SDA 线拉低。
  5. 从机地址传输后,控制字节或数据字节开始通过 SDA 传输。控制字节主要由 CO 和 D/C#位后加六个 0 组成的。 a) 如果 CO 为设为逻辑 后面传输的信息只包含数据字节。 b) D/C 如果位置决定了下一个数据字节是作为命令还是数据。 D/C#位设为0,下一个数据 就是命令。如果 D/C#位设为 1,下一个数据就是数据,将会存在 GDDRAM 中。GDDRAM 列地址指针将会在每次数据写之后自动加 1.
  6. 应答位将会在接收到每个控制字节或数据字节之后发生
  7. 写模式会在用了停止条件之后结束。停止条件:将 SDA 从低拉高,而 SCL 保持高。

请注意数据位的传输是有限制的 8. 数据位,在每个 SCL 脉冲阶段传输,必须在时钟脉冲高周期内保持稳定状态。可以参考 下面的图示。除了开始或停止条件,数据线只能在 SCL 为 LOW 的时候转换状态。 9. SDA 和 SCL 都必须接外接上拉电阻

命令解码器

       这个模块决定了输入数据被解读为数据还是命令。数据的解读是基于 D/C#引脚的输入。如果 D/C#引脚是高,D[7:0]就被解读为写到图像显示数据 RAM(GDDRAM)中的显示数据。        如果是低,D[7:0]的输入就被解读为一个命令。然后数据输入就会被解码并写到相关的命令寄存器中。

晶振电路和显示时间发生器

       这是一个片上低功耗 RC 震荡电路。操作时钟(CLK)可以由内部震荡器或外部 CL 引脚生成。        这个选择是通过 CLS 引脚完成的。当 CLS 引脚拉高,内部振荡器开启,CL 应该保留开启。将CLS 拉低可以静止内部振荡器,外部时钟必须连接到 CL 引脚上。当选择了内部振荡器之后,输出频率 Fosc 可以通过命令 D5h A[7:4]修改。        用于显示时钟发生器的显示时钟(DCLK)是源于 CLK 的。分频因子“D”可以通过命令 D5h 编程,范围为 1 到 16 DCLK = Fosc/D 显示的帧率是由下面的公式决定 D 代表时钟分频。由 D5h A[3:0]设置。范围是 1 到 16 K 是每行显示时钟的数量。值的计算如下: K = 相 1 周期 + 相 2 周期 + BANK0 脉冲宽度 = 2 + 2 + 50 = 54 在上电重启时 Number of Multiplex ratio 通过 command A8h 设置。上电重启值为 63 。 Fosc 是振荡器频率,可以通过命令 D5h A[7:4]修改。值越大频率越大。

复位

当 RES# 输入为 LOW 时,芯片初始化为下面的状态:

  1. 显示关
  2. 128 * 64 显示模式
  3. 正常的 segment 和显示数据列地址和行地址映射(SEG0 映射到 address 00h,COM0 映射到 address 00h)
  4. 在串口中清除移位寄存器数据
  5. 显示开始行设置为显示 RAM 地址 0
  6. 列地址计数设为 0
  7. 正常扫描 COM 输出方向
  8. 对比度控制寄存器设为 7Fh
  9. 正常显示模式(等同于 A4h 命令)

图形显示数据RAM (GDDRAM)

       GDDRAM是一个位映射的静态RAM,保存要显示的位模式。RAM的大小为128x64位,内存分为8个页面,从PAGEO到PAGE7,用于单色128x64点阵显示,如图8-13所示        当一个数据字节写到 GDDRAM 中,所有当前列的同一页的行图像数据都会被被填充(比如,被列地址指针指向的整列(8 位)都会被填充)。数据位 D0 写到顶行,而数据位 D7 写到底行,如下图所示。        为了灵活性,segment 和 common 上的重映射都可以通过软件选择。        对于显示的垂直移动,一个内部的寄存器保存了显示开始行可以用来设置控制 RAM 数据部分来映射显示(命令 D3h)。

命令表

基本命令表

部分指令详解

为 BANK0 设置对比度控制(81h)

       这个命令用来设置显示的对比度,该芯片有 256 级对比度,从 00h 到 FFh。屏显输出电流随着对比度增大而增大。

全部显示开启(A4h/A5h)

       A4h 命令打开显示,输出依据 GDDRAM 中的内容。        如果使用 A5h 命令,然后再使用 A4h 命令,显示就会重覆盖为 GDDRAM 的内容。        换句话说,A4h 命令从整体显示开启状态覆盖显示。        A5h 命令轻质整体显示状态位开启,不管显示数据 RAM 中的内容。

设置正常/反相显示(A6h、A7h)

       这个命令将显示设置成正常或反相模式。在正常模式 1 就是开,而在反相模式下 1 就是关

设置显示关、开(AEh、AFh)

       这个单字节命令用来打开或关闭 OLED 面板的显示。        当显示是 ON,通过设置主机配置命令选择的电路会打开;        当显示为 OFF 时,这些电路会关闭,segment 和 common 输出将处于高阻状态。这些命令设置显示的状态在开关之间切换:

滚屏命令

部分指令详解

水平滚动设置(26h 27h)

       这个命令是由五个连续字节来设置水平滚动参数和决定滚动开始页,结束页和滚动速度的。在声明这个命令前,水平滚动必须用命令(2Eh)关闭,否则,RAM 中的内容可能被损坏。SSD1306 水平滚动是为 128 列滚动设计的。下面的两张插图演示了滚动的效果:

持续垂直和水平滚动设置(29h 2Ah)

       这是一个由六个连续字节组成的命令,用来设置持续水平滚动参数和决定滚动开始页,结束页,滚动速度和垂直滚动偏移的。        命令 29h、2Ah 中的字节 B[2:0],C[2:0]和 D[2:0]用来设置持续水平滚动。字节 E[5:0]用来设置持续垂直滚动的偏移量。所有这些字节一起设置持续倾斜(垂直+水平)滚动。如果垂直滚动偏移字节 E[5:0]设为 0,那么效果就只是水平滚动。        在发布此命令前必须用命令(2Eh)关闭滚动。否则,RAM 内容会损坏。下面的插图展示了滚动效果:

关闭滚动(2Eh)

       这个命令停止滚动的动作。在发布命令 2Eh 来关闭滚动动作之后,RAM 内容需要重写。

激活滚动(2Fh)

       这个命令开始滚动的懂做,并且只有在声明了滚动设置参数之后使用。只对最后的设置命令有效 下面的命令在滚动激活后是禁止的:

  1. RAM 访问(数据读写)
  2. 改变水平滚动设置参数
设置垂直滚动区域(A3h)

       这个命令由三个连续的字节组成用来设置垂直滚动区域。对于持续垂直滚动功能(命令 29h 2Ah),垂直滚动的行数可以设置的更小或等于最大复用率。

地址设置命令表

部分指令详解

设置低列开始地址作为页地址模式(00h~0Fh)
设置高列开始地址作为页地址模式(10h~1Fh)
设置内存地址模式(20h)

       SSD1306 中有三种不同的内存地址模式:页地址模式,水平地址模式,垂直地址模式。这个命令将内存地址模式设置成这三种中的一种。在这里 COL 的意思是图形显示数据 RAM 列。        在页地址模式下,在显示 RAM 读写之后,列地址指针自动加一。如果列地址指针达到了列的结束地址,列地址指针重置为列开始地址并且也地址指针不会改变。用户需要设置新的页和列地址来访问下一页 RAM 内从。页地址模式下 PAGE 和列地址指针的移动模式参考下图 在正常显示数据 RAM 读或写和页地址模式,要求使用下面的步骤来定义开始 RAM 访问的位置:

  1. 通过命令 B0h 到 B7h 来设置目标显示位置的页开始地址
  2. 通过 00h~0Fh 来设置低开始列地址的指针
  3. 通过命令 10h~1Fh 来设置高开始列地址

       比如说,如果页地址设置为 B2h,低列地址是 03h 高列地址为 00h,那么就意味着开始列是PAGE2 的 SEG3.RAM 访问指针的位置如下图所示。输出数据字节将写到 RAM 列 3 的位置。        在水平寻址模式下,当显示 RAM 被读写之后,列地址指针自动加一。如果列地址指针达到列的结束地址,列地址指针重置为列的开始地址,并且页地址指针自动加 1。水平寻址模式下页和列地址的移动顺序如下图所示。当列地址和页地址都达到了结束地址,指针重设为列地址和页地址的开始地址。        在垂直寻址模式下,当显示 RAM 被读写之后,页地址指针自动加一。如果页地址达到了页的结束地址,页地址自动重置为页的开始地址,列地址自动加一。页地址和列地址的移动顺序如下图所示。当列地址和页地址都达到结束地址后,指针自动重置为开始地址。        在正常显示 RAM 读或写,水平/垂直寻址模式下,要求用下面的步骤来定义 RAM 访问指针位置:

  1. 用 21h 命令设置目标显示位置的列的开始和结束地址;
  2. 用命令 22h 设置目标显示位置的页的开始和结束地址
设置列地址(21h)

       这个三字节命令指定了显示数据 RAM 列开始地址和结束地址。这个命令也会设置列地址指针到列开始地址。这个指针用于定义当前读写的显示数据 RAM 列地址。如果用 20h 命令开启了水平寻址命令,在完成读写一个列数据之后,该指针就会自动指向下一列地址。当什么时候列地址指针完成了访问列结束地址,它就会返回到列开始地址,和行地址增加到下一行。

设置页地址(22h)

       这个三字节的命令指定了显示数据 RAM 页的开始和结束地址。这个命令同时也设置了页地址指针到页开始地址。这个指针用来定义在图像显示数据 RAM 中当前读写的地址。如果当前是垂直寻址模式,在读写完一页数据之后,会自动增加到下一页地址。当页地址指针完成访问结束页地址之后,会重置到开始页地址。        下面的插图展示了列和页地址指针的移动方式:列开始地址设置为 2,列结束地址设置为125,页开始地址设置为 1,页结束地址设置为 6;通过命令 20h 使能水平地址增加模式。在这个案例中,图形显示数据 RAM 可访问的地址就只有从列 2 到列 125,页 1 到页 6。另外,列地址指针被设为 2 页地址指针被设为 1.在完成读写数据中的一个像素后,列地址自动加 1 到下一个 RAM 位置进行下一次读写操作。当列地址指针完成访问结束列地址 125 之后,重新回到列 2,页地址自动加 1。当结束页 6 和结束列 125RAM 位置被访问过之后,页地址设回 1,列地址设回 2。

设置页开始地址作为页寻址模式(B0h~B7h)

硬件配置(面板分辨率和版面相关)命令表

部分指令详解

设置显示开始行(40h~7Fh)

       这个命令设置显示开始行寄存器来决定显示 RAM 的开始地址,通过选择 0 到 63 的值。当值为 0 是,RAM 行 0 映射到 COM0,当值为 1 时,RAM 行 1 映射到 COM0,以此类推。

设置 Segment 重映射(A0h/A1h)

       这个命令修改显示数据列地址和 segment 驱动器之间的映射,允许在 OLED 模块设置上的灵活性。        这个命令只影响后续的数据输出。早已存储在 GDDRAM 中的数据不会改变。

设置复用率(A8h)

       这个命令转换默认的 63 复用模式到任何复用率,范围从 16 到 63。输出 pads COM0~COM63将会转换为相关的 COM 信号。

设置 COM 输出扫描方向(C0h、C8h)
设置显示偏移(D3h)

       这是一个两字节的命令。第二个命令指定显示映射的开始行到 COM0 和 COM63 中的一个(假设 COM0 是显示的开始行,那么显示开始寄存器就等于 0)。        比如为了将 COM16 向 COM0 方向移动 16 行,第二个字节六位数据就应该写成 010000b。为了向相反方向移动 16 行,这个六位数据就应该是 64‐16,所谓第二个字节应该是 100000b。        下面两个表展示了命令 C0h/C8h 和 D3h 的设置效果

设置 COM 引脚硬件配置(DAh)

这个命令设置 COM 信号引脚配置来匹配 OLED 面板硬件层。下面的表展示了不同条件下的COM 引脚配置(复用率为 64)

时钟和驱动方案设置命令表

部分指令详解

设置显示时钟分频率、振荡器频率(D5h)

这个命令由两个功能组成:        设置分频率从 CLK 来生成 DCLK(display clock)。这个分频率的范围为 1 到 16,重置值为 1.请参考上表,获取 DCLK 和 CLK 关系的更多细节        如果 CLS 引脚置高编程后的振荡器频率 Fosc 就是 CLK 的源。这个 4 位的值设置 16种不同的频率,默认设置为 1000b。

设置重充电周期(D9h A[7:0])

       这个命令用于设置充充电周期的时间长度。间隔以计算 DCLK 的数量,重置值为 2DCLK。

设置 Vcomh 取消选择水平(DBh A[6:4])

       这个命令调整 V C O M H V_{COMH} VCOMH​ 调节器输出

NOP(E3h)

       空指令

示例程序

       软件I2C程序见【51单片机快速入门指南】4: 软件 I2C        见【51单片机快速入门指南】1:基础知识和工程创建

       由以上知识可知,SSD1306的7位地址可为0x3c、0x3d。最后一位由硬件决定。        如下图可见,我的屏幕的地址为0x3c(0x78 = 0x3c << 1)

oled.c

#include "oled.h"
#include "./Soft_I2C/Soft_I2C.h"
#include "oledfont.h"
#include <stdlib.h>

void delay_ms(uint16_t ms);

//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127

#if OLED_BUFFER_MODE

uint8_t OLED_GRAM[Max_Row / 8][Max_Column] = { 
        0};

#endif

/************************************************************************** Function: Refresh the OLED screen Input : none Output : none 函数功能:刷新OLED屏幕 入口参数:无 返回 值:无 **************************************************************************/
void OLED_Refresh_Gram(void)
{ 
        
#if OLED_BUFFER_MODE
    uint16_t i;
    OLED_Set_Pos(0, 128);
    for (i = 0; i < Max_Row / 8 * Max_Column; i++)
    { 
        
        OLED_WR_Byte(OLED_GRAM[0][i], OLED_DATA);
    }
#endif
}

/** * @brief 向SSD1306写入一个字节 * @param dat:要写入的数据/命令 cmd:数据/命令标志 0,表示命令;1,表示数据; * @retval None */
void OLED_WR_Byte(uint8_t dat, uint8_t cmd)
{ 
        
	if (cmd)
		i2c_mem_write(OLED_ADDRESS, OLED_WriteData_Addr, &dat, 1);
	else
		i2c_mem_write(OLED_ADDRESS, OLED_WriteCom_Addr, &dat, 1);
}

/************************************************************************** Function: Set the coordinates (position) displayed on the screen. Input : x, y: starting point coordinates Output : none 函数功能:设置汉字在屏幕上显示的坐标(位置) 入口参数: x,y :起点坐标 返回 值:无 **************************************************************************/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{ 
        
    OLED_WR_Byte(0xb0 + y, OLED_CMD);
    OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
    OLED_WR_Byte((x & 0x0f), OLED_CMD);
}

/** * @brief 开启OLED显示 * @param None * @retval None */
void OLED_Display_On(void)
{ 
        
    OLED_WR_Byte(0X8D, OLED_CMD);  //SET DCDC命令
    OLED_WR_Byte(0X14, OLED_CMD);  //DCDC ON
    OLED_WR_Byte(0XAF, OLED_CMD);  //DISPLAY ON
}

/** * @brief 关闭OLED显示 * @param None * @retval None */
void OLED_Display_Off(void)
{ 
        
    OLED_WR_Byte(0X8D, OLED_CMD);  //SET DCDC命令
    OLED_WR_Byte(0X10, OLED_CMD);  //DCDC OFF
    OLED_WR_Byte(0XAE, OLED_CMD);  //DISPLAY OFF
}

/** * @brief 清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样 * @param None * @retval None */
void OLED_Clear(void)
{ 
        
#if OLED_BUFFER_MODE
    uint16_t i;
    for (i = 0; i < Max_Row / 8 * Max_Column; i++)
    { 
        
        OLED_GRAM[0][i] = 0;
    }
    OLED_Refresh_Gram(); //Update the display //更新显示
#else
    uint8_t i, n;
    for (i = 0; i<8; i++)
    { 
        
        OLED_WR_Byte(0xb0 + i, OLED_CMD);    //设置页地址(0~7)
        OLED_WR_Byte(0x00, OLED_CMD);      //设置显示位置—列低地址
        OLED_WR_Byte(0x10, OLED_CMD);      //设置显示位置—列高地址
        for (n = 0; n<Max_Column; n++)
            OLED_WR_Byte(0, OLED_DATA);
    }//更新显示
#endif
}

/** * @brief 在指定位置显示一个字符,包括部分字符 * @param x:0~127 y:0~63 Is_Reverse:1,反白显示 0,正常显示 charSize:选择字体 16/6 * @retval None */
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t charSize, uint8_t Is_Reverse)
{ 
        
    uint8_t i = 0;
    chr -= ' ';	//得到偏移后的值
    if (x > Max_Column - 1)
    { 
        
        x = 0;
        y = y + 2;
    }
#if OLED_BUFFER_MODE
    if(charSize == 16)
    { 
        
		for(i = 0; i < 8; i++)
		{ 
        
			OLED_GRAM[y][x+i] = Is_Reverse == 0?F8X16[chr][i]:~F8X16[chr][i];
			OLED_GRAM[y+1][x+i] = Is_Reverse == 0?F8X16[chr][i+8]:~F8X16[chr][i+8];
		}
    }
    else if(charSize == 6)
    { 
        
		for(i=0; i<6; i++)
		{ 
        
			OLED_GRAM[y][x+i] = Is_Reverse == 0?F8X6[chr][i]:~F8X6[chr][i];
		}
    }
#else
    if (charSize == 16)
    { 
        
        OLED_Set_Pos(x, y);
        for (i = 0; i<8; i++)
            OLED_WR_Byte(Is_Reverse == 0?F8X16[chr][i]:~F8X16[chr][i], OLED_DATA);
        OLED_Set_Pos(x, y + 1);
        for (i = 0; i<8; i++)
            OLED_WR_Byte(Is_Reverse == 0?F8X16[chr][i + 8]:~F8X16[chr][i + 8], OLED_DATA);
    }
    else if(charSize == 6)
    { 
        
        OLED_Set_Pos(x, y);
        for (i = 0; i<6; i++)
            OLED_WR_Byte(Is_Reverse == 0?F8X6[chr][i]:~F8X6[chr][i], OLED_DATA);
    }
#endif
}

/** * @brief m^n函数 * @param None * @retval None */
uint32_t oled_pow(uint8_t m, uint8_t n)
{ 
        
    uint32_t result = 1;
    while (n--)result *= m;
    return result;
}

/** * @brief 显示2个数字 * @param x,y :起点坐标 * len :数字的位数,即显示几位有效数字 * Size:字体大小 * mode:模式 0,填充模式;1,叠加模式 * num:数值(0~4294967295); * @retval None */
void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t Size, uint8_t Is_Reverse)
{ 
        
    uint8_t t, temp;
    uint8_t enshow = 0;
    for (t = 0; t < len; t++)
    { 
        
        temp = (num / oled_pow(10, len - t - 1)) % 10;
        if (enshow == 0 && t < (len - 1))
        { 
        
            if (temp == 0)
            { 
        
                OLED_ShowChar(x + 8 * t, y, ' ', Size, Is_Reverse);
                continue;
            }
            else
                enshow = 1;

        }
        OLED_ShowChar(x + 8 * t, y, temp + '0', Size, Is_Reverse);
    }
}

/** * @brief 显示一个字符号串 * @param * @retval None */
void OLED_ShowString(uint8_t x, uint8_t y, char *chr, uint8_t charSize, uint8_t Is_Reverse)
{ 
        
    uint8_t j = 0;
    while (chr[j] != '\0')
    { 
        
        OLED_ShowChar(x, y, chr[j], charSize, Is_Reverse);
        x += 8;
        if (x>120)
        { 
        
            x = 0;
            y += 2;
        }
        j++;
    }
}

/** * @brief 显示汉字 * @param * @retval None */
void OLED_ShowChinese(uint8_t x, uint8_t y, uint8_t no, uint8_t Is_Reverse)
{ 
        
    uint8_t i;
#if OLED_BUFFER_MODE
    for (i = 0; i < 16; i++)
    { 
        
		OLED_GRAM[y][x+i] = Is_Reverse == 0?Hzk[2 * no] 

标签: 连接器xf3h

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台