当前位置: 首页 > news >正文

海外推广渠道网站图片大小优化

海外推广渠道,网站图片大小优化,怎样建俄文网站,电白手机网站建设公司OLED#xff08;SSD306#xff09;移植全解-基于IIC 一#xff0c;什么是oled?二#xff0c;什么是IIC协议三#xff0c;IIC通信流程#xff1a;四#xff0c;针对SSD1306的IIC通信流程#xff08;结合芯片手册版#xff09;1#xff0c;主机发送起始信号2#xff… OLEDSSD306移植全解-基于IIC 一什么是oled?二什么是IIC协议三IIC通信流程四针对SSD1306的IIC通信流程结合芯片手册版1主机发送起始信号2从设备应答 ACK 或 NACK3主机发送控制字节4重复 START5STOP 五在 CubeMX 中配置 I²C 外设1Mode2ConfigurationParameter Settings1Master Feasures2Timing Configuration即 数字滤波器和模拟滤波器3Slave Features即从机特性 GPIO Settings 六HAL库IIC API1I2C_HandleTypeDef (句柄)和HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) 2HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)3HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)4HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout)七SSD1306驱动库1IIC通信层2亮灭控制与上电初始化3设置坐标和清屏4文本显示层5高级图形显示层 一什么是oled? 一种屏幕类型每个像素都能自己发光不需要背光 大小多为 128×32 或 128×64 像素像素就是屏幕上最小的发光点还有一种衡量大小的方式就是使用对角线长度表示例如128×32 和 128×64像素数分别对应对角线长0.91英寸 或 0.93 英寸 oled如何发光呢 首先其内部会有一个驱动芯片ssd1306 [media pointer“file-service://file-QsH4on2Cfai99p4uU4zGB4”] OLED 屏幕多为 128×32 或 128×64 像素像素就是屏幕上最小的发光点。那0.91和0.93是什么意思你说简单说STM32F4 通过 I²C 总线把「命令数据」发给 SSD1306SSD1306 再把对应的点阵内容显示到 OLED 屏幕上难道ssd1306是通过iic接收stm32f4的数据信号然后依据此数据想stm32一样控制io引脚电平去点亮像素点如果不是像stm32通过io引脚输出高低电平那是怎么点亮像素点的呢依据上面的原理图讲讲 这个驱动芯片并不是像STM32一样直接通过控制 GPIO 引脚来点亮像素点它通过iic协议接收STM32发过来的数据和命令SSD1306 会根据 DC 引脚的状态判断接收到的是命令还是数据。在写入控制命令时DC 设为低电平在写入像素数据时DC 设为高电平内部电路对这些数据进行解析然后将数据通过驱动电路输出到 OLED 屏幕上。 那么什么是命令Command 命令就是不会改变oled的显示内容就算说命令配置的不是屏幕而是ssd1306的寄存器如 打开显示、关闭显示。 设置显示的分辨率128x32 或 128x64。 设置显示起始地址或列地址。 什么又是数据Data呢 数据就是可以直接控制oled显示内容的数据控制像素的亮灭直接存储在显存中1字节数据1页中1个列的像素的亮灭 这里提到了页在OLED中什么叫页呢 以分辨率为128*64的oled为例128代表整个屏幕有128列像素点64代表整个屏幕有64行像素点页的划分就是每8行表示1个页那么整个屏幕就分为8个页。 如果我们在每个页中讨论1个页的列不是整个屏幕的列即8个像素就是一组由一个字节数据控制亮灭 STM32F4 向 SSD1306 发送特定的命令和显示数据你提到的命令和数据有什么区别和联系吗这些命令和数据有什么作用啊能不能举例说明你说ssd1306有自己的内存区域显存用于存储屏幕上所有像素的状态你提到的显存只是存储像素状态并没有说明ssd1306怎么通过显存数据控制像素的亮灭啊好像意思是说ssd1306通过iic接收stm32的命令和数据然后ssd1306去根据这些命令和数据改变自己的显存数据这个内部有一个 点阵矩阵每个像素点由电子方式控制。好像说明了像素点亮的原理但我还是不懂啊每个字节存储 8 位像素信息对于 128×32 分辨率显示内容被存储为 128 列 * 4 页。这又是什么意思啊一个oled屏幕不是有12864个像素点吗如果显存中的一字节存储8个像素点的状态那就需要12864/8 1024个字节也就是说ssd1306的显存只有1024B即1KB而你又说显示内容被存储为 128 列 * 4 页这个页是什么意思我记得32位是一个字啊这里怎么用页表示这里4页是代表一列的32个位吗还有你的这个举例我也不理解啊发送一个字节数据 0xFF 表示这一列的所有 8 个像素都被点亮而 0x00 则表示这一列的所有像素都熄灭0xFF应该表示2个字节吧怎么只表示了1列而且只有8个点即1字节呢 二什么是IIC协议 接下来我们该了解什么是IIC通信协议 I²CInter-Integrated Circuit, 发音“eye-squared-see”是一种串行总线协议。由飞利浦公司现恩智浦半导体开发的串行通信总线广泛应用于连接微控制器和低速外围设备。 什么是低速外围设备呢 举几个低速外围设备的例子 传感器比如温度传感器、湿度传感器、光传感器等 显示屏例如 OLED 显示屏 RTC实时时钟用于保持时间的模块 EEPROM电可擦可编程只读存储器 按键、开关、LED 灯等简单接口设备 对应按键和LED使用IIC驱动见很少见但不是没有例如MCP23017 是一个 I²C 控制的 GPIO 扩展器芯片可以用来控制多个 LED 灯的亮灭。 它只有两根线 SCL时钟线告诉对方“我开始传/收数据了每一个时钟脉冲传/收一个 bit”。 SDA数据线真正传输数据的线每个时钟周期上或下会放置一个数据位0 或 1 主机/从机 STM32F4 配置成 I²C 主机由它来产生时钟脉冲。 SSD1306 芯片作为 I²C 从机等待主机发命令或数据。 I²C 地址 SSD1306 常见硬件地址通常是 0x3C有的模块也可能用 0x3D。这个地址是写死在 OLED 板子上的跳线或者由焊盘决定。 地址的作用就是让STM32找到ssd1306 核心特点 1支持多主机多从机架构最多128个设备使用7位寻址 什么叫做多主机呢 就是多个主机可以共享同一总线但是只有一个主机可以在某一时刻控制总线如何实现多台主机的发送冲突呢如果两个主机同时尝试发送数据时较低的电平会“获胜”另一方的发送被停止从而避免了冲突。 注意虽然支持多主机但在实际应用中多主机模式不常用。大多数情况下我们看到的都是一个主机控制多个从机的结构。 多从机的7位地址是什么? 如果我们使用一个主机控制多个从机那么为了方便主机向特定的从机发送数据我们为每个从机设备设置了唯一的一个地址这个地址用7位数据表示那么最多可以设置27128个从机设备范围是从 0x00 到 0x7F其实有些地址会被保留使用实际上小于128 2通信速率灵活标准模式100kHz快速模式400kHz等 我们知道在串口通信中使用波特率来表示每秒传输的数据位数而在IIC通信当中我们使用比特每秒bps表示每秒传输的位数这里也可以用Hz表示在这里1bps 1Hz 为了适应不同的设备需求不同的数据传输速度我们的IIC支持多种通信速度 标准模式100 kHz低速传感器、简单的控制设备、温度传感器、RTC实时时钟模块 快速模式400 kHz显示屏 高速模式3.4 MHz 图像传感器、 高速数据采集 超高速模式5 MHz某些高速视频采集系统 3内置硬件应答机制确保可靠传输 什么是IIC的应答机制呢 就是接收方不管有没有接收到数据都要发送应答信号/非应答信号给发送方接收方可以是主机也可以是从机 应答信号ACK接收方成功接收到数据并准备好继续接收下一个字节时发送 低电平0表示应答。 非应答信号NACK接收方没有成功接收到数据或者接收完所有数据后不再接收时发送 高电平1表示没有应答 4起始和停止条件 I²C通信使用特殊的总线状态表示通信的开始和结束。起始条件(START)是在SCL高电平时SDA从高变为低停止条件(STOP)是在SCL高电平时SDA从低变为高。这两种条件定义了一个完整通信帧的边界 三IIC通信流程 前面介绍了IIC协议的基础知识那么在一个完整的IIC通信过程中IIC的两条总线会经历什么呢 1IIC的两条线SCL和SDA默认处于高电平的状态 2当某一个主机想访问某个从设备时会发送起始信号SCL保持高电平SDA从高电平变为低电平此时其他主设备不能访问总线所有的从设备都进入准备接收接下来的地址数据 补充此时总线进入“忙碌Busy”状态其他主机检测到 SDA 被拉低时就知道总线已被占用。不过如果在多主机场景下可能出现同时两个主机几乎同时发起 START此时会进行总线仲裁Arbitration。 若两个主机都在同一个时钟周期尝试拉低 SDA不同主机对 SDA 的读写一致时继续若出现冲突则掉线的主机会自动放弃从而保证一个主机获得总线控制权 3主设备发送7位或10位从设备地址紧跟一个读/写控制位表示接下来是读还是写构成8个位即1字节所有从设备接收并比对此地址仅地址匹配的从设备继续参与后续通信。 补充对于 10 位地址寻址需要发送两次地址字节第一字节包含前两位“11110”、接着高 2 位地址和 R/W0第二字节才是真正的低 8 位地址详细流程略微复杂但大方向与 7 位寻址相似。 4如果总线上存在匹配地址的从设备从机会将SDA线拉低一个时钟周期发送ACK如果不存在匹配的从设备SDA线保持高电平NACK 在发送完 8 位地址R/W之后主机会释放 SDA进入第 9 个时钟周期。此时若有从设备应答 从机就在第 9 个时钟上拉低 SDA表示 ACK否则 SDA 处于高电平表示 NACK 如果出现 NACK主机常见做法就是发出 STOP 条件中断本次传输然后视情况重试或放弃。 5地址确认后主设备和从设备开始根据之前的读/写位进行数据交换。数据以8位字节为单位传输每个字节后必须有一个应答位 6当完成一次数据交换后主机还想发送其他数据为避免了其他主设备在操作中途获取总线控制权主设备可以发送新的起始条件SCL高SDA由高变低不需要停止再开始 重复 START 用于在一次事务Transaction中先进行写地址/写数据再切换为读数据或反之而不释放总线。例如先给某个寄存器写入要读的起始地址然后立刻发 Re-START再执行读操作。这避免了总线空闲期间其他主机介入的可能。 7通信结束于停止条件SCL保持高电平SDA从低电平变为高电平。这一转换表明主设备释放总线将总线状态恢复为空闲。停止条件后任何主设备都可以通过发送起始条件获取总线控制权。 四针对SSD1306的IIC通信流程结合芯片手册版 1主机发送起始信号 主设备将 7 位从设备地址 R/W 位构成一个“字节”传给总线 7位从设备地址哪里来呢 看芯片手册The device will respond to the slave address following by the slave address bit (“SA0” bit) and the read/write select bit (“R/W#” bit) with the following byte format, b7 b6 b5 b4 b3 b2 b1 b0 011110 SA0 R/W#.” D/C# pin acts as SA0这里是说ssd1306的从地址是011110 SA0 R/W当SA0为低电平时7为地址为0111100即0x3c这也是默认的地址如果想改变可以的这里有一个地址拓展位SA0将这个引脚改为高电平则7位地址就变成了0111101即0x3d 实际上主机发送的起始信号是8个位组成1字节这第8个位哪里不是只有7位地址吗 我们的0x3c和0x3d会左移一位将第8位留给R/WR/W 为 0 表示“下面我要写数据给你”R/W 为 1 表示“我想从你那里读数据”。 2从设备应答 ACK 或 NACK 主机发送完起始信号之后会在第 9 个时钟周期会先松开 SDA恢复到高电平 看总线上有没有某个从机把 SDA 拉低从机拉低 SDA 就表示向主机发送ACK即应答信号表示从机接收到了地址数据准备被读/被写 如果主机发现SDA没有被拉低而是SDA在第9个时钟周期一直保持高电平就表示从机发送了NACK即非应答信号于是主机通常会放弃这次尝试发 STOP停止 参考手册After the transmission of the slave address, an acknowledgement signal will be generated after receiving one byte … The acknowledge bit is defined as the SDA line is pulled down during the HIGH period of the acknowledgement related clock pulse.” “If there is no ACK, the master usually sends a STOP condition to terminate the current communication attempt 3主机发送控制字节 对于步骤 5发送控制字节Co D/C#及后续数据或命令我连什么是控制字节都不知道啊Co 位Continuity bit决定本次 I²C 传输里是否还会接着再发“下一个控制字节”这又是什么意思啊如果会再发控制字节会怎么样不发又会怎么样你说D/C# 位Data/Command bit决定下面真正的“8 位”是命令Command还是显示数据Data即写入显存这里的下面的8位又是在哪里啊问题又来了Co和D/C是什么时候发送的在起始信号之后命令/数据信号之前用 “0x00” 作为“单字节命令”的控制字节用 “0x40” 作为“写数据到显存”的控制字节这里0x00是控制字节又提到了控制字节我还是不理解单字节命令又是什么东西0x40是写数据到显存的控制字节这里我感觉控制字节是命令啊他们是什么关系主机在收到 ACK 之后紧接着发0x00控制字节表示“下一个字节当命令”。然后发命令。例如0xA8 设置 Multiplex Ratio后面再跟一个参数字节比如 0x1F 表示 32 行面板。这里我好像理解了什么是控制字节和命令控制字节0x00是在每个命令之前都要发送的表示下面要发送命令但是你这里又提出了设置0xa8的参数要发送0x1F我看你的代码里面也是在0x00之后发送0x1f难道0x1f也是命令?为什么没有紧跟着0xa8呢现在我还是不理解Co位和D/C位对应在0x00和0x40的哪些位置显示之前通常都要先用一系列命令设置好“内存地址模式”Page 模式 / Horizontal 模式 / Vertical 模式、“页面起始地址”、“列起始地址”“列结束地址”……以便告诉 SSD1306 后面连续发来的显存数据要怎么往 GDDRAM 里放这一步怎么实现我是小白什么都不懂啊 什么是“控制字节”前面的iic通信流程里面没有讲啊 我们知道主机会发送起始信号地址读/写然后会发送命令操作ssd1306寄存器和数据操作屏幕但是其实在发送数据之前主机还会向ssd1306发送控制字节就仅仅8个位这个“控制字节”本身不算是命令或数据他有两个功能 1告诉ssd1306接下来发的下一个字节是命令Command还是要写到显存里的数据Data 2告诉ssd1306以后还会不会再发另一个控制字节。 这个控制字节是怎么组成的呢 Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0CoD/C#000000 Co位和D/C#的作用 Bit7CoContinuity即连续性 如果 Co 0表示“我只发这一个控制字节不紧跟另一个控制字节”。 就是说下一个字节是数据/命令不是控制字节了但是当发送完数据/命令主机仍然可以发送0x00控制字节只是两个控制字节不能连续发送 如果 Co 1表示“我这次发完这个控制字节后还会接着发下一个控制字节 Bit6D/C#DataCommand即数据/命令 如果 D/C# 0表示“接下来的字节要被 SSD1306 当作命令Command来执行”。 如果 D/C# 1表示“接下来的字节要被 SSD1306 当作数据Data写入显存 GDDRAM”。 Bit5…Bit06 位都必须填 0。 这里我们先举一个发送命令的例子 首先明确0xA8是命令Set Multiplex Ratio0x1F 是命令 0xA8 的参数也属于命令 我们主机想要发送这两个命令给从机它会这么发送呢 1发送0x00表示下一个是命令 20xA8表示Set Multiplex Ratio但是这个命令还需要一个参数 30x00又一个控制字节因为 0xA8 还有参数要发 40x1F是命令 0xA8 的参数属于命令范畴 注意0x1F 不是新的“命令”它只是“命令 0xA8 的参数”但它也仍然是通过控制字节 0x00 告诉 SSD1306下一个字节 (0x1F) 是命令相关的数据 这里0xA8是一个多字节命令就是除了命令本身还有配套的参数0x1F这种命令发送时时它自己和参数前面都要发送0x00不能只发送一个0x00然后两者紧接着发送 如果是单字节命令就不需要考虑这些直接发送0x00然后在将自己发出去就行了 再举一个发送数据的例子 首先我们在MCU即STM32中定义一个空间uint8_t buffer[512]这有512个字节刚好覆盖128*64分辨率的oled的所有像素点 接下来通过iic通信将这512个字节发送到屏幕上 10x40表示接下来主机要发送数据到显存 GDDRAM 2buffer[0] 3buffer[1] … 4buffer[512]发送完最后一个字节 参考手册After the transmission of the slave address, either the control byte or the data byte may be sent across the SDA. A control byte mainly consists of Co and D/C# bits following by six 0’s … If the D/C# bit is set to logic 1, it defines the following data byte as data which will be stored at the GDDRAM. The GDDRAM column address pointer will be increased by one automatically after each data write. 到了这里相信你已经理解了控制字节的作用就是控制发送命令和数据但是在发送数据之前我们会发送命令给ssd1306而不是直接发送数据我因为我们要对ssd1306的寄存器进行配置具体包括内存地址模式页面地址列地址 下面结合前面的知识我们一个一个进行配置: 1内存地址模式设置此模式的命令是0x20 此命令的参数是 0x00 → Horizontal 模式 0x01 → Vertical 模式 0x02 → Page 模式 这三个模式的区别是什么呢 Page 模式每次写完 1 列就保持在当前页不动需要你手动再发命令才换下一列或者换下一页。 Vertical 模式写完一个字节后会自动把 “页指针”1从 Page0 跳到 Page1到页末就翻回到起始页同时 “列指针”1。 Horizontal 模式写完一个字节后会自动把 “列指针”1从 Column0 跳到 Column1到列末就翻回起始列同时 “页指针”1。 代码示例 // 发控制字节告诉它我接下来要发命令 send_I2C(0x00); // 发命令本身Set Memory Addressing Mode send_I2C(0x20);// 因为这条命令还要跟一个参数所以再发控制字节 send_I2C(0x00); // 发参数0x02 → Page 模式 send_I2C(0x02); 2页面起始地址 在 Page 模式下显存被分成若干“页”前面我们知道8行为1页128*32的分辨率就分成了4页每一页对应的命令是 Page0 → 0xB0 Page1 → 0xB1 Page2 → 0xB2 Page3 → 0xB3 发送对应的命令就表示以这一页的开头作为起始地址例如 send_I2C(0x00); // 控制字节准备发命令 send_I2C(0xB1); // 命令Page1 发完这条命令SSD1306 内部就把“当前页指针”切到 Page1。接下来再发 0x40 数据就会把数据写入 Page1 这一行的 128 列里。 3列地址 我们知道1页有8行128列前面我们通过命令设置了写入哪一个页Page1接下来通过命令就可以设置写入这个页Page1的哪一个列这个命令分为两部分列低地址命令和列高地址命令 列低地址命令0x00~0x0F分别表示写入第0 ~ 15列 列高地址命令0x10~0x17即0001 0000 ~ 0001 0111结合列低地址命令表示第16 ~ 127列这里每加1代表加16列因为列低地址命令代表低4位这个代表高3位 发送命令时列高地址命令和列低地址命令要一起发送组成一个完整的地址 列低地址命令 0x00 0x0F (N 0x0F) 列高地址命令 0x10 0x17 0x10 | ((N 4) 0x07) 例如我要写在第66列就发送0x01和0x14 send I2C 0x01 //发送低4位 send I2C 0x14 //发送高4位 结合起来就是4*16266列 还不明白就自己思考反正我理解了 其实就相当于ssd1306里面有两个8位的寄存器列高寄存器0001 0xxx和列低寄存器0000 xxxx可以看到列低寄存器在0000 0000 ~ 0000 1111里面变化共16种可能而列高寄存器在0001 0000 ~ 0001 0111里面变化列低寄存器变化16位列高寄存器就变化1位所以总共就有8*16 128种可能对应屏幕的128列每次发送命令时需要两个一起发送组成对应的列号 4重复 START 什么是“重复 START” I²C 允许在不发 STOP释放总线的情况下再发起另一次 START 条件。这样做的好处是 总线不中断其他主机没法趁你 STOP 之后插队。 可以在同一次事务里先写命令、再读状态或数据 参考手册If the master device needs to transmit more data, it can issue a Repeated START condition (SCL HIGH, SDA: HIGH→LOW) without issuing a STOP. This avoids other masters from taking control of the bus in the middle of the operation. 在ssd1306中的用法是先通过 PAGE 模式写入一部分显存再 Re-START切换到 Horizontal 模式写下一部分。所以无需在两个不同事务间 STOP再重新 START。 为什么都是些数据我们先通过pqge模式写再通过 Horizontal 写呢 回顾前面这2种模式的区别pqge模式可以选择写的位置而且写完后指针不加1而Horizontal 写完后指针加1 这就导致2种模式有自己的用处Page 模式负责把起始指针“精准定位”到某一页某一列定位后切换到 Horizontal 模式一口气写后面要填的 N 列数据 5STOP 通知所有从机“本次通信搞完了可以释放总线” 把 SDA 和 SCL 都拉回到空闲状态都 HIGH让下一个想用总线的主机知道“现在可以发起新的 START”。 参考手册The write mode will be finished when a stop condition is applied. The stop condition is … established by pulling the SDA from LOW to HIGH while the SCL stays HIGH 五在 CubeMX 中配置 I²C 外设 1Mode Disable禁用 I2C 外设。如果选择该选项对应的IIC引脚就是普通的GPIO引脚 I2C表示 I2C 外设工作在 I²C 通信模式STM32 可以作为主机 (Master) 或从机 (Slave)。 当我们需要主机和和从机设备通信时需要选择此模式 SMBus-Alert-mode、SMBus-two-wire-Interface系统管理总线模式是 I2C 的一个变种具有更严格的时序和协议要求例如超时检测、PEC (Packet Error Checking) 等。通常用于电源管理或特定的传感器。 2Configuration Clock Speed 为 100kHz 是 SSD1306 的推荐设置完全满足其需求避免了较高频率带来的不必要的噪声问题,为什么说这是推荐设置从哪里看到呢我是小白不懂这些这个配置在图中属于Master Feasures,这个配置一般在芯片手册的哪一个地方啊如果我要开发其他的IIC芯片这一项该怎么选择看芯片手册的哪里你总结一下常见的IIC芯片 对应这一项该选择什么Master Feasures这一项的含义是什么呢这个好像是针对主机即STM32CubeMX而言的设置的速度有什么有呢这是IIC通信的速度吗Timing Configuration Coefficient of Digital Filter 设置为 0这个数字滤波器用于抑制干扰信号通常对于 I2C 协议默认设置即可不需要修改。 Analog Filter 设置为 Enabled这个模拟滤波器会启用 I2C 总线上的模拟过滤功能默认启用即可。这里的数字滤波器是干什么的有什么用具体讲讲我是小白芯片参考手册里面有Timing Configuration的相关信息吗Slave Features这是针对从机的配置吗Clock No Stretch Mode 设置为 Disabled这是控制 I²C 总线时钟拉伸功能的选项。由于 SSD1306 使用的是标准的 7 位地址 I²C 协议因此可以保持禁用。什么是总线拉伸功能为什么说7位地址就要保持禁用在芯片手册里面能找到相关信息吗Primary Address Length selection 设置为 7-bit这表明你正在使用 7 位地址。SSD1306 使用的是 7 位地址例如 0x3C因此这一选项保持为 7 位是正确的。这里的Primary 代表什么特殊含义吗这个能在芯片手册里面找到吗Dual Address Acknowledged 设置为 DisabledSSD1306 只有一个地址不需要支持双地址。因此禁用此选项是正确的。这里为什么又出现了双地址什么是双地址我是嵌入式小白没有见过啊能不能举一些例子对于IIC芯片手册一般在哪里能够找到地址信息啊在哪里能够找到有无双地址的信息啊Primary slave address 设置为 0这表示主设备地址的设置。你不需要修改这个主机通信时会使用从设备的地址。你说这个是主地址的设置这个选项有什么应用场景吗在芯片手册里面的哪里有相关的信息General Call address detection 设置为 Disabled不启用通用调用地址检测。对于 SSD1306这个选项可以禁用确保通信时只针对你设置的从设备地址。这里通用地址检查又是什么东西啊我是小白不懂啊这里配置选项一般在芯片手册的哪里啊 Parameter Settings 1Master Feasures 这里有两个选项 IIC Speed Mode I2C 时钟速度 IIC Clock Speed(Hz)IIC Speed Mode可以选择 Standard Mode 和 Fast Mode 如果选择前者那么下面的IIC Clock Speed最大可以设置为100 000如果选择Fast Mode 高速模式则IIC Clock Speed最大可以设置为400 000 IIC Clock Speed是我们期望的频率但是系统时钟输入到IIC的频率通过APB1总线的频率不等于IIC Clock Speed还需要CCRClock Control Register这个分频器将IIC总线上的频率分频为我们期望的频率为什么一定是分频呢因为在我们选择IIC Clock Speed时手册就要求 I2CCLK APB1总线频率高于我们选择IIC Clock Speed I2CCLK 至少是 Standard Mode 频率的 2 倍Fast Mode 频率的 3 倍 其实还有第三个选项Fast Mode Plus: 最高速率 1 MHz但是这个需要外设和 GPIO 都支持 FMPFast Mode Plus特性 对应SSD1306而言选择100 000 Hz的速度就足够了 当我们选择 Fast Mode 时还可以设置 Clock Duty Cycle - Fast Mode快速模式占空比 这里有两个选项 DUTYCYCLE_2: 低电平时间是高电平时间的 2 倍。这是推荐和常用的设置。 DUTYCYCLE_16_9: 低电平时间是高电平时间的 16/9 倍。在某些特定从设备或总线条件下可能需要。 我们选择DUTYCYCLE_2即可 2Timing Configuration即 数字滤波器和模拟滤波器 Coefficient of Digital Filter 数字滤波器它处理的是 I²C 总线上的 数据只有当总线噪声较大时才需要考虑启用它。 Analog Filter 模拟滤波器它帮助滤除噪声源确保 I2C 数据和时钟信号不受干扰。SSD1306 的 I²C 通信中通常会保持启用模拟滤波器来提高可靠性。 在 STM32 中默认 启用模拟滤波器这是因为 模拟信号更容易受到干扰明明IIC总线上的信号是数字信号哪里来的模拟信号呢其实在IIC总线的数字信号之前是模拟信号模拟滤波器用来在 I²C 总线的数字信号传输之前 处理这些噪声 3Slave Features即从机特性 这些选项主要用于配置 I2C 总线的从设备功能而不涉及主设备 STM32 的配置 Primary Addressing Length selection主要寻址模式 可以选择7/10这个选项只影响HAL库函数HAL_I2C_Master_Transmit 的地址参数处理如果从机既有7位地址又有10位地址HAL_I2C_Master_Transmit函数可以自动根据传入的参数进行处理 Clock No Stretch Mode I²C 总线的一些从设备可能会在数据传输时“拉伸”时钟线表示它还在处理数据 Primary Address Length selection选择主地址长度 在 I²C 通信中SSD1306 的从设备地址通常是 0x3C这就是 7 位地址 Primary Slave Address本机地址 1 直接输入地址值 注意: 这里输入的是 7 位地址本身不需要左移或添加读写位 Dual Address Acknowledged即确认双地址 对于某些 I²C 设备它们支持“双地址模式”允许它们同时使用两个地址进行通信。对于 SSD1306由于它只需要一个地址因此禁用此选项。 如果使能该选项CubeMX就会多出一个从地址本机地址2 General Call Address Detection 广播呼叫地址检测 之前说过7位地址最多不一定支持128个设备还有些地址被保留了0x00就是被保留的地址即广播呼叫地址 当主机向此地址发送信息时使能此项的从机会响应发往0x00地址的信息 Clock Stretching时钟延长 只有在确定主机不支持时钟延长或追求极低延迟且能保证从机处理速度的情况下才考虑禁用。 GPIO Settings GPIO Output level: 无需配置 此项表示GPIO输出的高低电平因为我们使用的是硬件IIC总线的电平由外设控制不需要我们手动设置GPIO电平软件IIC所以不需要勾选此项 什么是软件iic 用普通GPIO口通过软件程序控制GPIO的电平变化来模拟I2C的时序和协议 什么是硬件iic? 主机和从机的的IIC模块自动完成IIC通信不需要我们手动配置GPIO电平 对于GPIO Output level在硬件IIC模式时就算我们配置了此项也没有用因为I2C模块自动驱动引脚你手动设置电平是无效的配置会被硬件覆盖或忽略。 GPIO mode: Alternate Function Open Drain Alternate Function: 将引脚功能配置为连接到 I2C 外设而不是通用输入输出。 Open Drain (开漏): 允许多个设备连接到同一总线。设备只能将线拉低不能主动推高。高电平由外部上拉电阻提供。 GPIO Pull-up/Pull-down: Pull-up 或 No pull-up and no pull-down I2C 协议要求 SCL 和 SDA 必须有上拉电阻。 选项: Pull-up: 启用 STM32 内部自带的弱上拉电阻 (通常 30kΩ - 50kΩ)。仅适用于低速 (100kHz) 且总线负载很小 (设备少、线短) 的情况。 No pull-up and no pull-down: 推荐 禁用内部上拉。此时必须在 PCB 上为 SCL 和 SDA 各添加一个外部上拉电阻。 这是最可靠的做法允许根据总线速度和电容选择合适的电阻值。 外部上拉电阻选择: 典型值在 1.5kΩ 到 10kΩ 之间。常用 4.7kΩ (适用于 100kHz/400kHz中等负载)。更高速率或更大总线电容需要更小的上拉电阻 (如 2.2kΩ, 1.8kΩ)。具体计算需参考 I2C 规范和总线电容。 Maximum output speed: High 或 Very High 为确保信号边沿足够陡峭以满足 I2C 时序要求尤其是在 Fast Mode 或更高速度下应选择较高的 GPIO 输出速度 User Label: (可选) 为引脚添加自定义标签 六HAL库IIC API 1I2C_HandleTypeDef (句柄)和HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) 句柄就是包含了iic的所有配置信息这个初始化代码是CubeMX自动生成的举个例子 void MX_I2C1_Init(void) {/* USER CODE BEGIN I2C1_Init 0 *//* USER CODE END I2C1_Init 0 *//* USER CODE BEGIN I2C1_Init 1 *//* USER CODE END I2C1_Init 1 */hi2c1.Instance I2C1;hi2c1.Init.ClockSpeed 400000;hi2c1.Init.DutyCycle I2C_DUTYCYCLE_2;hi2c1.Init.OwnAddress1 0;hi2c1.Init.AddressingMode I2C_ADDRESSINGMODE_7BIT;hi2c1.Init.DualAddressMode I2C_DUALADDRESS_DISABLE;hi2c1.Init.OwnAddress2 0;hi2c1.Init.GeneralCallMode I2C_GENERALCALL_DISABLE;hi2c1.Init.NoStretchMode I2C_NOSTRETCH_DISABLE;if (HAL_I2C_Init(hi2c1) ! HAL_OK){Error_Handler();}/** Configure Analogue filter*/if (HAL_I2CEx_ConfigAnalogFilter(hi2c1, I2C_ANALOGFILTER_ENABLE) ! HAL_OK){Error_Handler();}/** Configure Digital filter*/if (HAL_I2CEx_ConfigDigitalFilter(hi2c1, 0) ! HAL_OK){Error_Handler();}/* USER CODE BEGIN I2C1_Init 2 *//* USER CODE END I2C1_Init 2 */}首先我们要知道iic初始化的目的是配置硬件iic按照什么规则工作针对的是MCU本身不是和哪个设备通信 设置通信速度 hi2c1.Init.ClockSpeed 400000; 设置通信时钟线的占空比 hi2c1.Init.DutyCycle I2C_DUTYCYCLE_2; 设置MCU自己作为从机时的地址 hi2c1.Init.OwnAddress1 0; hi2c1.Init.AddressingMode I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 0; 禁用广播呼叫功能 hi2c1.Init.GeneralCallMode I2C_GENERALCALL_DISABLE; 当MCU作为从机时将不响应地址为0x00的广播指令 允许时钟延展(更可靠通信) I2C_NOSTRETCH_DISABLE; 配置数字滤波和模拟滤波 // 模拟滤波器(消除电气噪声) if (HAL_I2CEx_ConfigAnalogFilter(hi2c1, I2C_ANALOGFILTER_ENABLE) ! HAL_OK) { Error_Handler(); } // 数字滤波器(设为0表示不额外过滤) if (HAL_I2CEx_ConfigDigitalFilter(hi2c1, 0) ! HAL_OK) { Error_Handler(); } 2HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) 有两个关键参数 DevAddress:即设备地址 注意是那7位地址左移一位后加上读写位后得到的8位地址 pData: 传入我们要写的数据 3HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) Mem_Write实际上是对Master_Transmit的封装 就多了一个MemAddress即内存地址 为什么叫内存地址我也不知道实际上就是控制字节 0x00表示将数据写到寄存器即写命令 0x40表示将数据写到显存即写数据 4HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout) 在初始化 OLED 之前可以调用此函数来确认 OLED 模块是否正确连接并且 I2C 通信正常。有助于调试硬件连接问题 七SSD1306驱动库 HAL_Delay(100); // 上电稳定 for(i0;isizeof(initcmd1);i)OLED_Write_cmd(initcmd1[i]); OLED_Clear(); // 防止上电随机 RAM OLED_Set_Position(0,0); // 光标归零 接下来详细介绍一下这个ssd1306驱动库以至于我们可以将它移植到sh1106上面 1IIC通信层 OLED_Write_cmd和OLED_Write_data这两个函数其实就是对前面讲的IIC的API的再次封装 void OLED_Write_cmd(uint8_t cmd) {HAL_I2C_Mem_Write(hi2c1, OLED_ADDRESS, 0x00, I2C_MEMADD_SIZE_8BIT, cmd, 1, 0x100); }void OLED_Write_data(uint8_t data) {HAL_I2C_Mem_Write(hi2c1, OLED_ADDRESS, 0x40, I2C_MEMADD_SIZE_8BIT, data, 1, 0x100); } 竟然HAL库都已经有IIC发送数据的专用API了为什么我们还有再次封装它呢? 调用OLED_Write_cmd比直接调用HAL函数更清晰我们直接在封装后的函数写入命令就行不用在发送控制字节 2亮灭控制与上电初始化 初始化命令initcmd1数组 uint8_t initcmd1[] {0xAE, //display off0xD5, 0x80, //Set Display Clock Divide Ratio/Oscillator Frequency0xA8, 0x1F, //set multiplex Ratio //128*32 // 0xA8, 0x3F, //set multiplex Ratio //128*640xD3, 0x00, //display offset0x40, //set display start line0x8d, 0x14, //set charge pump0xa1, //set segment remap0xc8, //set com output scan direction // 0xda, 0x12, //set com pins hardware configuration //128*640xda, 0x00, //set com pins hardware configuration //128*320x81, 0x80, //set contrast control0xd9, 0x1f, //set pre-charge period0xdb, 0x40, //set vcom deselect level0xa4, //Set Entire Display On/Off0xaf, //set display on }; 这些命令来自于哪里ssd1306的12832与12864分辨率的初始化命令有什么区别 如果我要移植到sh1106上面需要修改什么 上电初始化函数 void OLED_Init(void) {HAL_Delay(100);uint8_t i;for (i 0; i sizeof(initcmd1); i){OLED_Write_cmd(initcmd1[i]); //display off}OLED_Clear();OLED_Set_Position(0, 0); } 这里为什么要HAL_Delay?明明我才上电为什么要清屏OLED_Set_Position有什么用 HAL_Delay(100)确保OLED完全上电后再发送命令 清屏确保显示从干净状态开始避免上电时显示残留内容 OLED_Set_Position(0,0)将光标设置到初始位置准备显示内容 3设置坐标和清屏 OLED_Set_Position设置光标位置(x,y) OLED_Clear清屏 OLED_Allfill全屏填充白色 /*** OLED fill function, after using the function 0.91 inch oled screen into full white **/ void OLED_Allfill(void) {uint8_t i, j;for (i 0; i 4; i) //根据分辨率修改总页数{OLED_Write_cmd(0xb0 i); //决定写白几页OLED_Write_cmd(0x00);OLED_Write_cmd(0x10);for (j 0; j 128; j){OLED_Write_data(0xFF);}} }/*** brief Set coordinates* param x: X position, range 0 - 127 Because our OLED screen resolution is 128*32, so the horizontal is 128 pixels* param y: Y position, range 0 - 3 Because the vertical pixels are positioned in pages, each page has 8 pixels, so there are 4 pages **/ void OLED_Set_Position(uint8_t x, uint8_t y) //把“写数据指针”移动到 列 x、页 y {OLED_Write_cmd(0xb0 y); //决定哪一页写白OLED_Write_cmd(((x 0xf0) 4) | 0x10); //列地址“高四位”OLED_Write_cmd((x 0x0f) | 0x00); //列地址“低四位” }/*** Clear Screen Function* Fill each row and column with 0 **/ void OLED_Clear(void) {uint8_t i, n;for (i 0; i 8; i){OLED_Write_cmd(0xb0 i); //决定消除几页OLED_Write_cmd(0x00);OLED_Write_cmd(0x10);for (n 0; n 128; n){OLED_Write_data(0);}} }这里的清屏和覆盖全屏操作中的命令0xb0i0x01是什么含义 0xb0i设置页地址(0-7)每页8像素高 0x00和0x10设置列地址的低4位和高4位 不是说在发送命令之前都要先发送0x00吗为什么在0xb0i之前没有呢? OLED_Write_cmd函数已经通过参数0x00指明了这是命令而非数据 这里的设置坐标的函数逻辑是什么啊 4文本显示层 字符显示OLED_ShowChar (支持8x6和8x16字体) 字符串显示OLED_ShowStr 数字显示OLED_ShowNum和OLED_ShowFloat 5高级图形显示层 中文显示OLED_ShowHanzi(16x16)和OLED_ShowHzbig(32x32) 图片显示OLED_ShowPic 这里的文本显示层和图像显示层怎么使用啊 下面是我使用显示字符串的代码 int Oled_Printf(uint8_t x, uint8_t y, const char *format, ...) {char buffer[128]; // 缓冲区大小根据需要调整va_list arg;int len;va_start(arg, format);len vsnprintf(buffer, sizeof(buffer), format, arg);va_end(arg);OLED_ShowStr(x, y, buffer, 8); // 将 buffer 转为 uint8_t*为什么不是char//8F6*8一行写满跳一页 16F8*16像素一行写满跳两页return len;}下面的函数没有介绍啊 /*** brief OLED pow function* param m - base* param n - exponent* return result */ static uint32_t OLED_Pow(uint8_t a, uint8_t n) {uint32_t result 1;while (n--){result * a;}return result; }这是一个辅助函数计算a的n次方。在OLED_ShowNum函数中用于从整数中提取各个位的数字。例如计算10^3用于提取千位数字
http://www.pierceye.com/news/704286/

相关文章:

  • 成都眉山网站建设平台兼职网站开发
  • 化妆品网站的建设 论文php技术的网站开发
  • 女人与黑狗做视频网站网站seo关键词排名
  • ps制作个人网站营销软文怎么写
  • 建立网站的方案南京小程序开发网站建设
  • 类似淘宝的网站怎么做的产品推广会议流程
  • 写作网站的文风软件开发的基本过程
  • 做胃镜多少钱那好天津津门网站a顺德高端网站
  • 网站升级维护中 模板用ps怎么做网站背景
  • 免费商城网站建设建设银行企业网站首页
  • 北京哪家网站建设公司比较好帝国cms怎么做网站地图
  • 做网站制作外包数据可视化
  • 专注大连网站建设青海项目信息网
  • 网站开发开题报告范文可以做免费的网站吗
  • 淄博网站备案wordpress代码实现下载
  • 网站做全景做的好看的网站
  • 宜春专业的企业网站建设公司网站建设待遇怎样
  • 苏州企业网站建设制作服务在线培训平台
  • 成都创建公司网站wordpress的多说美化
  • 企业网站建设的方案书用织梦做模板网站
  • 馆陶做网站容桂低价网站建设
  • 帮一个企业做网站流程免费做app的软件有哪些
  • 河间哪里有做网站的wordpress禁用修正版
  • 网站建设对网络营销的影响做网站的怎么挣钱
  • 个人备案的网站涉及到资金抖音代运营服务达不到退费标准
  • 做网站投放广告湘潭学校网站建设 磐石网络第一
  • 营销手机网站目前专业做水果的网站有哪些
  • 莆田仿站定制模板建站网站设计应该考虑的重要因素
  • 简述网站制作过程企业网络推广网站建设
  • 外贸营销网站建设介绍wordpress分库技术