第五章 stm32 cubemx 软件I2C实验以及EEPROM的使用理论及实验过程
前言
本章将讲解stm32通讯协议中的IIC协议,利用cubeMX完成软件和硬件IIC的实现,并结合实验数据,给人更为深刻的体验。
我们结合IIC的具体协议和逻辑分析仪得到的具体实验数据理解IIC协议。
IIC概述
I2C通讯协议是由Phiilps公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要USART、CAN等通讯协议的外部收发设备,现在被广泛地使用在系统内多个集成电路(IC)间的通讯。
llC: Inter Integrated Circuit,集成电路总线,是一种同步串行半双工通信总线。其中同步说明这种通信方式需要时钟线;串行说明数据一位一位(一个字节8位即0000 0000)在一个数据线上朝一个方向发送;半双工说明一个时间只能进行接收或者发送;总线就是传输数据的通道,如果有多个设备想使用总线进行传输数据多个都需要挂载在总线上,注意在总线上可以有多个主机,多个从机;协议则是传输数据的规则,首先我们讲解该协议。
IIC物理层
如图所示,即位IIC的物理层,由图可明显看到所有的设备挂载在,两条l2C总线下,一条双向串行数据线(SDA)用来传递数据,一条串行时钟线(SCL)用于数据收发同步。总线通过上拉电阻接到电源。当I2C设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。
要点
- IIC总线协议是一个支持多设备的总线。在一个l2C通讯总线中,如图,可连接多个I2C通讯设备,支持多个通讯主机及多个通讯从机。
- 多个设备并不是指无限多个,连接到相同总线的IC数量要受到总线的最大电容400pF限制。
- 每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的通信。
- 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
- 具有三种传输模式:标准模式传输速率为100kbit/s ,快速模式为400kbit/s,高速模式3.4Mbit/s,但目前大多/2C设备尚不支持高速模式。
IIC协议层
I2C协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。接下来我们将逐个进行实验。
IIC读写概述
主机写入到从机的基本过程,如图所示。由主机发出起始信号表示开始通信,然后发送从机地址及数据传输方向,然后释放总线(总线上有上拉电阻,总线拉高即为释放总线)交给从机,得到从机应答ACK或非应答NACK,紧接着进行数据的接收或者数据传输的终止。
实验结果
结果如图所示。
接下来进行具体讲解,各个信号如何产生、代码实现、实验反馈。
起始、停止信号及代码
理论说明
如图所示
-
起始:当SCL线是高电平时,SDA线从高电平向低电平切换。
-
停止:当SCL是高电平时,SDA线由低电平向高电平切换。
代码实现
代码如下(示例):
void I2C_SCL_1()//SCL电平拉高
{
HAL_GPIO_WritePin(GPIO_PORT_I2C, I2C_SCL_PIN, GPIO_PIN_SET);
}
void I2C_SCL_0()
{
HAL_GPIO_WritePin(GPIO_PORT_I2C, I2C_SCL_PIN, GPIO_PIN_RESET);
}
void I2C_SDA_1()
{
HAL_GPIO_WritePin(GPIO_PORT_I2C, I2C_SDA_PIN, GPIO_PIN_SET);
}
void I2C_SDA_0()
{
HAL_GPIO_WritePin(GPIO_PORT_I2C, I2C_SDA_PIN, GPIO_PIN_RESET);
}
static void i2c_Delay(void)
{
uint8_t i;
for (i = 0; i < 10; i++);
}
void i2c_Start(void)
{
/* 当SCL线是高电平时,SDA线从高电平向低电平切换。*/
I2C_SDA_1();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_0();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
void i2c_Stop(void)
{
/* 当SCL是高电平时,SDA线由低电平向高电平切换 */
I2C_SDA_0();
I2C_SCL_1();
i2c_Delay();
I2C_SDA_1();
}
实验验证
数据有效性及代码
理论说明
如图所示
I2C使用SDA信号线来传输数据,使用SCL信号线进行数据同步。SDA数据线在SCL的每个时钟周期传输一位数据。
SCL为高电平的时候SDA表示的数据有效,即此时的SDA为高电平时表示数据“1”,为低电平时表示数据“0”。
当SCL为低电平时,SDA的数据无效,一般在这个时候SDA进行电平切换,为下一次表示数据做好准备。
代码实现
这个代码函数功能是读取一个字节的数据,利用for循环依次读取8位数据。
#define I2C_SDA_READ HAL_GPIO_ReadPin(GPIO_PORT_I2C, I2C_SDA_PIN)
uint8_t i2c_ReadByte(void)
{
uint8_t i;
uint8_t value;
value = 0;
for (i = 0; i < 8; i++)
{
value <<= 1;
I2C_SCL_1();
i2c_Delay();
if (I2C_SDA_READ)
{
value++;
}
I2C_SCL_0();
i2c_Delay();
}
return value;
}
这个代码函数功能是发送一个字节的数据,利用for循环依次发送8位数据。
void i2c_SendByte(uint8_t oneByte)
{
uint8_t i;
/* 数据由高位到低位依次发送 */
for (i = 0; i < 8; i++)
{
if (oneByte& 0x80)
{
I2C_SDA_1();//判断为1发送1
}
else
{
I2C_SDA_0();
}
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
if (i == 7)
{
I2C_SDA_1(); //发送完成后释放总线等待应答
}
oneByte<<= 1; /* 左移做下一次判断*/
i2c_Delay();
}
}
实验验证
响应ACK及代码
理论说明
I2C的数据和地址传输都带响应。响应包括“应答(ACK)”和“非应答(NACK)”两种信号。每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据。
应答信号:主机SCL拉高,读取从机SDA的电平,为低电平表示产生应答。应答信号为低电平时,规定为有效应答(ACK),表示已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),表示接收该字节失败。
传输时主机产生时钟,在第9个时钟时,数据发送端会释放SDA的控制权,由数据接收端控制SDA,若SDA为高电平,表示非应答信号(NACK),低电平表示应答信号(ACK)。
代码实现
该代码实现包括三个函数,第一个函数为产生应答信号,第二函数为产生非应答信号,第三个函数为判断应答。第一、二个函数如上述所示,第三个函数需要注意在读取ACK/NACK信号时先进行释放总线,即将SDA总线拉高交给其他需要响应的设备控制。
void i2c_Ack(void)
{
I2C_SDA_0();
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();//应答信号为低电平时,规定为有效应答(ACK)
I2C_SDA_1();
}
void i2c_NAck(void)
{
I2C_SDA_1();
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
I2C_SCL_0();
i2c_Delay();
}
uint8_t i2c_WaitAck(uint16_t timeout)
{
uint8_t re,ucErrTime=0;
I2C_SDA_1();//释放SDA总线
i2c_Delay();
I2C_SCL_1();
i2c_Delay();
while(I2C_SDA_READ)//等待ACK//NACK
{
re = 0;
ucErrTime++;
if(ucErrTime>timeout)
{
return re;
}
else re = 1;
}
I2C_SCL_0();
i2c_Delay();
return re;
}
实验验证
文章来源:https://www.toymoban.com/news/detail-812635.html
地址及数据方向
I2C总线上的每个设备都有自己的独立地址,主机发起通讯时,通过SDA信号线发送设备地址(SLAVE_ADDRESS)来查找从机。设备地址可以是7位或10位。
紧跟设备地址的一个数据位R/W用来表示数据传输方向,数据方向位为“1”时表示主机由从机读数据,该位为“0”时表示主机向从机写数据。
以EEPROM 24C01为例,其地址如图所示。
文章来源地址https://www.toymoban.com/news/detail-812635.html
到了这里,关于第五章 stm32 cubemx 软件I2C实验以及EEPROM的使用理论及实验过程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!