一.I2C总线
#1.I2C总线的电气连接
描述通信总线的方式:
同步 全双工 串行
异步 半双工 并行(速度快,占的资源多,8的倍数条线)
单工
I2C总线(同步 半双工 串行总线)支持多主多从的模式;一般情况使用的是一主多从的应用。一般有上拉电阻。
两条线:
数据线(SDA):
时钟线(SCL):
典型I2C总线图
2.I2C时序
2.1 START和STOP条件
启动信号:SCL为高电平的时候,SDA负跳变。
结束信号:SCL为高电平的时候,SDA正跳变。
Start/Stop Condition of I2C-BUS
2.1.1起始信号代码
void I2C_Start(void)
{
I2C_SDA_High(); //SDA=1
I2C_SCL_High(); //SCL=1
I2C_Delay();
I2C_SDA_Low();
I2C_Delay();
I2C_SCL_Low();
I2C_Delay();
}
2.1.2停止信号代码
void I2C_Stop(void)
{
I2C_SDA_Low();
I2C_SCL_High();
I2C_Delay();
I2C_SDA_High();
I2C_Delay();
}
2.2主从设备读写条件
2.2.1主从设备读写操作
(1)主设备往从设备写数据
写数据时序图
(2)主设备从从设备中读数据
读数据时序图
写:MCU在数据总线上的数据稳定之后,检测边沿信号(上升沿)写数据到器件;
读:MCU发出边沿信号(下降沿)告诉器件发送数据,检测到边沿信号之后,器件更新数据,等待稳定之后MCU读取数据
字节中每一位的传输都需要一个时钟周期;
发送一个字节
CPU向I2C总线设备发送一个字节(8bit)数据
u8 I2C_SendByte(uint8_t Byte)
{
uint8_t i;
/* 先发送高位字节 */
for(i = 0 ; i < 8 ; i++)
{
if(Byte & 0x80)
{
I2C_SDA_High();
}
else
{
I2C_SDA_Low();
}
I2C_Delay();
I2C_SCL_High();
I2C_Delay();
I2C_SCL_Low();
I2C_Delay();
if(i == 7)
{
I2C_SDA_High(); /* 释放SDA总线 */
}
Byte <<= 1; /* 左移一位 */
I2C_Delay();
}
}
读取一个字节
CPU从I2C总线设备上读取一个字节(8bit数据)
u8 I2C_ReadByte(void)
{
uint8_t i;
uint8_t value;
/* 先读取最高位即bit7 */
value = 0;
for(i = 0 ; i < 8 ; i++)
{
value <<= 1;
I2C_SCL_High();
I2C_Delay();
if(I2C_SDA_READ())
{
value++;
}
I2C_SCL_Low();
I2C_Delay();
}
return value;
}
CPU产生一个ACK信号
void I2C_Ack(void)
{
I2C_SDA_Low();
I2C_Delay();
I2C_SCL_High();
I2C_Delay();
I2C_SCL_Low();
I2C_Delay();
I2C_SDA_High();
}
参考博文:https://blog.youkuaiyun.com/weixin_42229404/article/details/81514457
https://blog.youkuaiyun.com/JoggingPig/article/details/107522737
https://blog.youkuaiyun.com/stephenbruce/article/details/116449974