IIC通信协议详解(以STM32F407控制0.96寸OLED显示屏代码+逻辑分析仪为例)

1.IIC通信协议介绍

IIC(Inter-Integrated Circuit)协议是一种同步串行通信接口,它采用半双工工作模式,也就是在同一时间只能进行单向的数据传输,要么发数据,要么接数据,不能既发又收。IIC总线由两条信号线组成:一条是数据线SDA(Serial Data Line),用于传输数据;另一条是时钟线SCL(Serial Clock Line),由主设备提供时钟信号,以确保所有连接到总线的设备同步进行数据交换,这个SCL就是控制同步的作用。

在I2C总线上,每个从设备都有一个唯一的地址,主设备通过发送这个地址来选择与其通信的从设备。由于支持多主控功能,多个具备主控能力的设备可以在同一总线上竞争控制权,并通过硬件仲裁机制避免冲突。

由于其物理接口简单且占用线路少,I2C被广泛应用于嵌入式系统和电子设备中,方便连接各种低速外设,例如常见的SHT30温湿度传感器、AT24C02存储器、0.96寸OLED显示屏等等。同时,I2C支持多种速度等级,分为如下几种,能满足不同应用环境对数据传输速率的需求。

IIC通信速度速率
标准模式100K/s
快速模式400K/s
高速模式3.4M/s

2.STM32F407与0.96寸OLED显示屏接线

STM32管脚0.96寸OLED显示屏管脚
VCC(3.3V或者5V)VCC
PD10SDA
PD11SCL
GNDGND

3.IIC通信协议时序图

3.1 IIC开始和停止

IIC的时序图随便从网上找一个,或者看IIC设备的Datasheet,翻到有IIC时序图模样的地方,下面这张图是0.96寸OLED屏幕的Datasheet截取的图。

从上图可以看出,IIC的开始和停止比较简单,开始条件就是SCL在高电平期间,SDA从高电平拉低为低电平,这里的拉低时间有要求,就是这个tstart至少要大于0.6us,也就是SCL由高变低后保持的时间;停止条件就是SCL在高电平期间,SDA从低电平拉高为高电平,这里的拉高时间有要求,就是这个tstop至少要大于0.6us,也就是SCL由低变高后保持的时间。

开始对应的代码如下:

从开始条件代码可以看出,主要分为四步:

3.1.1 设置SDA引脚为输出模式(开始)

SDA的引脚是接到了STM32F407的PD10上,配置代码如下:

从上图可以看出,首先要打开GPIOD的GPIO外设时钟,因为GPIOD是挂接在AHB1时钟上的,注意,STM32F1和STM32F4的外设挂接不一样,这个如果移植的话需要自己更改。然后配置引脚号、配置为输出模式、推挽输出、输出速率还有上拉电阻,最后初始化GPIOD端口

3.1.2  确保SDA和SCL为高电平(开始)

IIC总线在不传输数据的时候,也就是空闲状态下SCL和SDA是高电平状态,所以在开始之前要使得其为空闲状态,然后延时5us,确保其SCL和SDA已经成为高电平。

3.1.3 把SDA引脚从高电平拉低到低电平(开始)

根据IIC时序图的开始条件,在SCL高电平的期间,SDA由高电平拉低到低电平才是开始,在第二步的时候SCL和SDA已经变成了高电平,所以这一步拉低SDA,IIC就处于开始通信状态了。

3.1.4 再把SCL引脚拉低,表示准备通信(开始)

因为在SCL和SDA在空闲状态下是高电平,所以要把SCL从第二步的高电平拉低到低电平,表示已经开始了,可以进行通信传输数据了。

停止对应的代码如下:

从上图可以看出,IIC通信停止也是分四步

3.1.5 设置SDA引脚为输出模式(停止)

SDA的引脚是接到了STM32F407的PD10上,配置代码如下:

3.1.6  确保SDA和SCL为低电平(停止)

IIC总线想要停止传输的时候,是SCL在高电平期间,SCL由高拉低的过程。但是在停止前IIC在传输数据的,所以怎么能让SCL和SDA是高电平呢,那么就要自己写程序让它在停止前是高电平。

3.1.7 把SDA引脚从低电平拉低到高电平(停止)

根据IIC时序图的停止条件,在SCL高电平的期间,SDA由低电平拉高到高电平才是开始,在第二步的时候SCL和SDA已经变成了低电平,所以这一步拉高SDA,IIC就停止不再数据通信了。

3.1.8 再把SCL引脚拉低,表示准备通信(停止)

因为在SCL和SDA在空闲状态下是高电平,所以要把SCL从第二步的低电平拉低到高电平,表示结束本次通信了,为下一次通信做准备。

3.1.9 逻辑分析仪的使用和捕捉IIC开始波形

3.1.9.1 逻辑分析仪介绍

逻辑分析仪是一种用于捕获和分析数字信号的工具,它在数字电路调试和验证过程中非常有用。具体用途包括:信号捕获时序分析、协议分析、故障排除、数据验证、性能分析。

逻辑分析仪是数字电路设计和调试过程中不可或缺的工具,能够显著提高工程师的工作效率和设计质量。

我使用的是KingST LA1010的逻辑分析仪,300块钱左右,对于嵌入式基本的调试分析够用了。本次分析IIC波形,逻辑分析仪的CH0和CH1通道分别接入SDA和SCL,一定要把逻辑分析仪的GND和板子的GND连一起,实现共地,不然信号是没有参考的。逻辑分析仪连接好后另一端的USB端插入电脑上的USB,然后根据商家提供的驱动包在电脑上安装好驱动,然后通过电脑的:此电脑->管理->设备管理器->通用串行总线控制器查看逻辑分析仪是否被电脑识别到。

这一步没问题后,就可以打开逻辑分析仪的上位机软件(也是商家提供的)

从上图的左下角可以看到:设备已连接。表示驱动已经安装好,逻辑分析仪和电脑上位机通讯正常。重点在左上角的三个设置:

齿轮图标(设置通道)逻辑分析仪最多支持16个通道(CH0-CH15)
采样深度采样深度是指逻辑分析仪在一次捕获过程中能够存储的采样点的数量。采样深度越大,逻辑分析仪能够记录的信号变化时间段就越长。
采样频率采样频率是指逻辑分析仪每秒钟对被测信号进行采样的次数。采样频率越高,逻辑分析仪捕捉信号变化的精度就越高。对于数字信号,根据奈奎斯特采样定理:采样频率应该至少是信号频率的两倍以上,才能准确捕捉信号的变化。
3.1.9.2 IIC通信传输数据时间计算

本次采用的IIC通信协议的0.96寸OLED屏幕是100KHz速率的,所以采样频率理论上是200KHz就可以,但是实际中使用为了保证采样准确,一般都放大十倍,所以我用的是10MHz采样频率。那么IIC实际在传输过程中的一次数据传输要多长时间呢?这个其实是可以理论计算出来的,计算方法如下:

要计算I2C在100kHz频率下一次传输数据所需的时间,需要考虑I2C传输的具体内容和协议细节。I2C传输包括起始条件、地址字节、数据字节、应答位,以及停止条件。

开始和停止条件所需要的时间这些条件通常是非常短暂的,根据时序图,只有0.6us,可以忽略不计。
地址字节I2C的地址字节通常为7位地址+1位读/写位,总计8位。
数据字节每个数据字节为8位。
应答位每个字节传输后有1位的应答位(ACK/NACK)

I2C频率为100kHz,即时钟周期为10微秒(us)。计算每个步骤所需的时间:

  • 起始条件:忽略不计
  • 地址字节:8位 × 10微秒/位 = 80微秒
  • 应答位:1位 × 10微秒/位 = 10微秒
  • 数据字节:8位 × 10微秒/位 = 80微秒
  • 应答位:1位 × 10微秒/位 = 10微秒
  • 停止条件:忽略不计

将所有步骤的时间相加,得到一次基本I2C传输的总时间: 80微秒(地址字节)+10微秒(应答位)+80微秒(数据字节)+10微秒(应答位)=180微秒。因此,在100kHz频率下,一次传输一个数据字节(包括地址字节和应答位)大约需要180微秒。如果传输多个数据字节,则每增加一个数据字节会增加90微秒(80微秒数据字节 + 10微秒应答位)。

采样深度我选择了10MSa,这个MSa单位是“兆采样点”的意思,也就是一次捕捉到1000000个采样点,10MSa就是可以捕捉10000000个采样点。逻辑分析仪的记录时间计算公式:

记录时间=采样深度/采样频率=10000000/10000000=1S。

3.1.9.3 IIC开始波形逻辑分析仪捕捉

逻辑分析仪自带解析器,可以解析常用的IIC/SPI/CAN/UART等通信协议,设置如下图所示。

设置好后就可以看到设置的通道0为SDA,通道1为SCL,和我们实际的接入电路板的是一样,还是那句话,一定要记得共地。

根据时序图,IIC的开始条件就是SCL在高电平期间,SDA由高电平变为低电平,这样才能使得IIC开始,这个也是触发逻辑分析仪捕捉IIC信号的开始。

上面的绿色三角标就是开始捕捉信号按钮,红色的正方形图标就是停止捕捉信号的按钮,点击开启捕捉信号按钮后,会出现等待触发的字样,这个时候手去按一下STM32电路板的复位按键,IIC就开始传输数据了(前提是按照前面的步骤将STM332HE10.96寸OLED屏幕接好,然后逻辑分析仪的CH0和CH1接入SDA和SCL,GND接GND)。 

通过鼠标滑轮可以放大缩小波形,我们选取开始信号波形分析。

从上图可以看到,开始阶段黄绿白三个框选,对应我们开始的代码里四步中的2.3.4,在SDA高电平期间,SDA由低变高,并且通过时间标尺A1-A2,SDA在高电平期间持续了5.3us,代码里调用了 Delay_us(5);   基本一致。

3.2 IIC通信数据传输

IIC的开始和停止只是控制起始条件,真正的数据传输才是最重要的。IIC数据传输时序图如下图所示。

从图中可以看到IIC的数据传输相对于开始和停止位比较复杂,但是仔细分析不是很难,只是看起来传输的内容多一些。

3.2.1 第一个字节(地址字节)

首先发送7位停止位+1位读写位作为第一个字节,这个字节是从机地址字节,地址字节的前6个位是固定的,就是0111 10,第7位是SA0,一般设置为0,第8位是读写字节,也就是主机向从机读还是写,既然是发送给从机的数据,肯定是写数据,所以写的话是W,就是0,所以第一个字节地址字节的8个位组合起来就是:0111 1000,换算成十六进制就是0x78(也可以写做78h);

3.2.2 第二个字节(命令字节)

IIC数据传输的第二个字节是命令字节,主机发送命令给从机,从机才知道主机要干啥,是要让他执行什么动作的意思,第二个字节的第1个CO位的意思就是如果设置这个CO位是0,那么后面发送的第三个字节的内容就全都是数据内容,不会有其他内容,一般都设置为0,第2个D/C位是设置本字节的内容是数据还是命令,如果是数据则为1,如果是命令则为0,后面全填0就行了。所以如果这个字节是命令字节,八位组合起来就是:0000 0000,换算成十六进制就是0x00(也可以写做00h)。

3.2.3 第三个字节(数据字节)

IIC数据传输的第三个字节是数据字节,主机发送完第二个字节的命令给从机后,从机才知道主机要传输数据了。第三个字节和第二个字节基本一致,只是D/C位不一样,如果是发送的数据则为1,所以八位组合起来就是:0100 0000,换算成十六进制就是0x40(也可以写做40h)。

3.2.4 应答位

从图中可以看到每个字节传输完成后都会有个ACK应答位,应答位是从机发送给主机的,当从机接收到主机发过来的一个字节的数据或者命令后,要返回一个应答位给主机,记住,这个时候主机就要去判断从机返回来的是不是应答位,应答位是只有1个位的数据,而不是一个字节,所以主机只需要判断这一个位是否为低电平或者高电平,规定低电平(0)为应答位,高电平(1)为非应答位

3.2.5 对应代码

写命令函数。

写数据函数

写命令函数和写数据函数都调用了OLED_Write_IIC_Byte()函数,这个函数的作用是写一个字节的数据,因为IIC数据传输是以字节为单位传输的,代码如下:

这个函数主要分3步:

1.先将IIC设置为输出模式,也就是主机输出数据给从机,写数据给从机

2.在SCL和SDA都在低电平状态下才能够传输数据,因为SDA和SCL都在高电平期间是空闲状态,此时不能传输数据。如下图所示,把SCL和SDA都拉低,表示要传输数据了。

3.然后开始按位去写这个数据。因为1个字节是8位,所以要一位一位发,比如数据0xD2,二进制为1101 0010,那么发送顺序是1->1->0->1->0->0->1->0,先发最左边的1,那么i=0,1&1还是1,<<(7-i)就是<<7,也就是把1&1后的结果1左移7位,然后跳出for循环,把SCL拉高,因为只有在SCL高电平期间才能把数据发出去,此时才是发数据,发完后再把SCL拉低,目的是修改数据,因为第一个位都发完了,主机要修改第二个数据,要么为0要么为1,当然根据本例子第二个数据要修改为1,为的是发送第二位的数据;同理,第二个要发的就是左边第二位的1,此时i=2,1&1还是1,<<(7-i)就是<<6,也就是把1&1后的结果1左移6位,然后跳出for循环,把SCL拉高,把数据发出去,此时才是发数据,发完后再把SCL拉低,为的是发送第三位的数据;第三个要发的就是左边第三位的0,此时i=3,0&1还是1,<<(7-i)就是<<5,也就是把0&1后的结果0左移5位,然后跳出for循环,把SCL拉高,把数据发出去,此时才是发数据,发完后再把SCL拉低,为的是发送第四位的数据。以此类推把8个位的数据全部发完,也就是发完一个字节的数据。

为了达到有数据发数据,有命令发命令的目的,将写数据函数和写命令函数合二为一,形成了下面的函数,如下面代码所示,达到了有数据发数据,有命令发命令的目的。

举个发命令的例子,下面的代码就是OLED的一些常见的命令操作,比如发送0xAE就是关闭显示,就是利用了有有数据发数据,有命令发命令的函数OLED_WR_Byte()。OLED_CMD在.h文件中宏定义为0,所以OLED_WR_Byte(0xAE,OLED_CMD);就相当于OLED_WR_Byte(0xAE,1);

那么此时就是发命令0xAE。

举个发数据的例子,下面的OLED_WR_Byte(0,OLED_DATA),就是利用了有有数据发数据,有命令发命令的函数OLED_WR_Byte(),OLED_DATA在.h文件中宏定义为1,所以OLED_WR_Byte(0,OLED_DATA)就相当于OLED_WR_Byte(0,0),也就是发送数据0,目的是清楚屏幕,给屏幕全写0。

3.2.6 IIC通信数据传输波形逻辑分析仪捕捉。

上图就是捕捉到的发送地址字节的波形,从图中黄色框内可以看出SDA通道一共有9个点,每两个点之间就是一个数据位,也就是有8个位的数据传输,因为传输有延迟,所以看起来对其比较难。这8个位对应的SDA通道的电平是低电平->高电平->高电平->高电平->高电平->低电平->低电平->低电平,二进制数字就是0111 1000,换算成十六进制就是0x78(78h),这就是发送了从机地址为0x78,与我们的代码一致,同时可以看到图里右侧是逻辑分析仪自动解析出来的地址,也是0x78。

在第9个点结束后,就是ACK位,根据时序图,ACK位是在SCL高电平期间,SDA低电平是ACK应答位,如果SDA是高电平,则不应答,注意,这里的应答指的是主机发送地址给从机设备,从机地址为0x78的设备应答主机,证明你找的就是我。

3.2.6.1 IIC通信数据捕捉传输命令的波形

接着看传输命令的波形。我们代码里有个0xAE指令,是关闭OLED显示屏的指令,如果忘了请看3.2.5小节里的代码分析,我们以这个命令为例子解析逻辑分析仪捕捉到的这个命令波形。

上图可以看到,SDA波形是高电平->低电平->高电平->低电平->高电平->高电平->高电平->低电平,二进制数字就是1010 1110,换算成十六进制就是0xAE(AEh),这就是发送了0xAE指令,OLED关闭显示屏的指令,然后第九位发送了ACK。

3.2.6.2 IIC通信数据捕捉传输数据的波形

我用OLED显示屏显示了五个汉字:胖虎最可爱。这五个汉字需要通过取字模的软件去生成一个十六进制组成的数组,这个方法网上很多,自行百度。我取出的汉字字模数组如下所示。

逻辑分析仪捕捉到的传输数据波形如下图所示。只看第一个汉字:胖。这个汉字数组的前几位可以对照一下图里的右下角,数据传输完全正确,并且每次发数据之前都要先发开始,然后发设备地址0x78,再发写数据命令0x40,再发对应的数据,并且每个字节都有ACK回应。

4.获取源码方式

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用STM32F103C8T6硬件IIC控制4针0.96OLED显示屏时,我们需要了解IIC总线的基本原理和OLED显示屏的接口及控制方式。 IIC总线是一种串行通信协议,它由两根信号线组成,分别是时钟线(SCL)和数据线(SDA)。IIC通信中,数据从一个设备流向另一个设备,通过设备地址进行寻址和选择。而OLED显示屏则是一种可以直接输出图像的静电显示器件,需要通过IIC总线进行控制。 通常,我们会使用STM32F103C8T6的GPIO引脚连接OLED显示屏的时钟线和数据线。在程序中,我们需要设置STM32F103C8T6的GPIO引脚为IIC模式,并且按照IIC协议的流程来进行数据的发送和接收。对于不同的OLED显示屏,其IIC地址可能不一样,我们需要在程序中进行指定。 在显示实际内容时,我们可以通过对OLED显示屏内部的寄存器进行设置来显示所需的图像和文字。需要注意的是,OLED显示屏控制方式和寄存器的设置可能与其他显示屏不同,我们需要查阅相关的资料才能正确地进行设置。 通过STM32F103C8T6硬件IIC控制4针0.96OLED显示屏,我们可以实现对各种图像和文字内容的显示,是嵌入式开发中常用的一种显示方式。 ### 回答2: 首先,stm32f103c8t6是一款运行速度快、性能稳定的工业级微控制器。该微控制器内置硬件IIC接口,可直接用于控制OLED显示屏0.96OLED显示屏通常具有128x64的分辨率,并且有四个引脚:电源、地、SCL和SDA。连接硬件IIC接口和OLED显示屏的时候,需要将SCL引脚连接到stm32f103c8t6的PB6引脚,将SDA引脚连接到stm32f103c8t6的PB7引脚。 对于代码编写,我们可以使用STM32CubeMX和Keil uVision等工具来生成初始化代码,具体步骤如下: 1. 在STM32CubeMX中选择对应的微控制器型号和工程,然后进入"Pinout & Configuration"页面,找到PB6和PB7引脚,将其配置为I2C1_SCL和I2C1_SDA。 2. 进入"Project Manager"页面,在Code Generator一栏中选择"Generate peripheral initialization as a pair of '.c/.h' files per peripheral",然后点击"Generate Code"按钮。 3. 在Keil uVision中创建一个新工程,将CubeMX生成的.c和.h文件添加到工程中。然后在main函数中调用HAL_I2C_Init函数初始化IIC接口,并使用oled_init函数初始化OLED屏。 4. 编写显示函数,例如oled_show_char等,通过IIC接口向OLED屏发送显示数据即可。 需要注意的是,OLED屏显存为8页,每页包含8个字节,因此需要在显示函数中进行相应的位移计算,以保证数据正确展示在OLED屏上。 综上所述,stm32f103c8t6硬件IIC控制0.96OLED显示屏的方式比较简单,只需以下几个步骤:连接SCL和SDA引脚、生成初始化代码、初始化IIC接口和OLED屏、编写显示函数,并处理相关的位移计算。 ### 回答3: STM32F103C8T6是一种强大的微控制器,也是目前广泛应用于嵌入式系统中的芯片之一。它拥有强大的处理器能力和大量的电子模块,并且可以方便地进行编程,具有广泛的应用领域。而硬件IIC控制的4针0.96OLED显示屏则是智能硬件设备中非常重要的一部分,可以用于显示各种数据、文本和图形等。 在将STM32F103C8T6微控制器连接到4针0.96OLED显示屏之前,我们需要了解一些基本知识。其中,硬件IIC (Inter-Integrated Circuit)是一种用于实现芯片之间通信的协议,它可以实现高速和双向传输。硬件IIC总线有两个线路:SDA和SCL,其中SDA是数据线,而SCL是时钟线。因此,在使用IIC控制4针0.96OLED显示屏时,需要将SDA和SCL引脚连接到相应的STM32F103C8T6引脚上。 为了开始使用硬件IIC控制4针0.96OLED显示屏,我们需要在STM32F103C8T6上初始化IIC控制器并打开IIC通讯。在初步准备工作完成后,我们可以开始使用C语言程序将相应的数据传输到OLED显示屏上,以便实现图形和文本输出等功能。OLED显示屏有两种驱动方式:点阵和字符。每种驱动方式都有其自己的优势和劣势。 点阵驱动方式发送的数据可能更加精细和清晰,而字符驱动方式可以输出文本等更具分析性的数据。因此,在使用硬件IIC控制4针0.96OLED显示屏时,需要选择适当的驱动方式来实现所需的功能。 除此之外,硬件IIC控制4针0.96OLED显示屏还涉及到电源管理、数据缓存和错误检测等方面的操作,需要进行适当的设置和调整。只有在正确的设置和调整下才能实现良好的显示效果。 总而言之,硬件IIC控制4针0.96OLED显示屏STM32F103C8T6上的应用是非常重要的,需要熟悉IIC协议、OLED显示屏驱动和字符集库等相关技术知识,并进行适当的调整和设置才能实现理想的显示效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值