文章目录[隐藏]
一、前言
IIC通信作为单片机经常使用的通信协议,有着十分重要的地位,我们经常使用IIC通信驱动各种外设。IIC在使用上有软件IIC与硬件IIC。
软件IIC是指用单片机的两个引脚模拟出来的IIC,通过程序控制引脚状态。
硬件IIC是指芯片上的IIC外设,有专门的电路与控制寄存器,对应引脚也是专用的。
硬件IIC的效率要远高于软件IIC,但引脚固定且数量有限,软件IIC不受引脚限制。
本章我们使用软件IIC。
二、IIC总线介绍
I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。
I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。
三、IIC物理层
IIC通信的连接方式:
说明:
- SCL总线是时钟线,由主设备提供。SDA总线是数据线,用于数据的传输。
- 总线上同一时间只能由一个主设备使用,当多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
- 每个连接到总线的从设备都有一个独立的地址,主设备可以利用这个地址进行不同设备之间的访问。
- IIC通信属于半双工通信,同一时间的设备只能接收数据或者发射数据。(因为只有一根数据线)
- 总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,由上拉电阻把总线拉成高电平。
- 常见两种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s 。
- 连接设备数量受最大电容400pF的限制。
四、IIC协议层
1、通信大致流程:
- 主设备首先发射一个起始信号,开始通信。
- 然后,主设备会发射需要通信的某一个从设备的地址。
- 当对应地址的从设备接收到地址信号后会返回一个应答信号,当主设备接收到应答信号时,开始进行数据传输。
- 每当 接收或者发送 数据都会 接收或者发送 一个应答信号,当不需要传输数据时,需要提供一个非应答信号,结束数据传输。
- 数据传输完毕时,主设备会发射一个停止信号结束通信。
2、传输过程
(1)主机向从机发送数据:
(2)主机读取从设备的数据:
(3)主机在发送数据过程中,转为读取数据。
S:起始信号, 0:写数据, 1:读数据, A:应答信号, A非:非应答信号, P:停止信号
数据传输一帧数据有8位,地址的数据一般为7位加上1位读写位,正好一帧数据。(10位的地址一般检测头7位)
3、信号要求
(1)起始和停止信号
(2)应答与非应答信号
(3)数据有效性规定
数据电平变化必须在SCL为低电平的时候。
五、使用C语言实现IIC
根据信号要求,可以用C语言写出对应传输程序。
1、起始信号与停止信号
(1)起始信号
/*************************************************
*函数名: IIC_start
*函数功能: IIC起始信号
*输入: 无
*返回值: 无
**************************************************/
void IIC_start()
{
IIC_OUT(); //SDA变为输出状态
SCL = 1;
SDA_out = 1;
Delay_us(5);
SDA_out = 0;
Delay_us(5);
}
(2)终止信号
/*************************************************
*函数名: IIC_end
*函数功能: IIC停止信号
*输入: 无
*返回值: 无
**************************************************/
void IIC_end()
{
IIC_OUT(); //SDA变为输出状态
SCL = 0;
SDA_out = 1;
SDA_out = 0;
Delay_us(5);
SDA_out = 1;
Delay_us(5);
}
2、应答信号、非应答信号与等待应答信号
(1)应答信号
/*************************************************
*函数名: IIC_ACK
*函数功能: IIC主机发出应答信号
*输入: 无
*返回值: 无
**************************************************/
void IIC_ACK()
{
IIC_OUT(); //SDA变为输出状态
SCL = 0;
SDA_out = 0;
Delay_us(2);
SCL = 1;
Delay_us(5);
SCL = 0;
}
(2)非应答信号
/*************************************************
*函数名: IIC_NACK
*函数功能: IIC主机发出非应答信号
*输入: 无
*返回值: 无
**************************************************/
void IIC_NACK()
{
IIC_OUT(); //SDA变为输出状态
SCL = 0;
SDA_out = 1;
Delay_us(2);
SCL = 1;
Delay_us(5);
SCL = 0;
}
(3)等待应答信号
/*************************************************
*函数名: IIC_Wait_ACK
*函数功能: 主机等待应答信号
*输入: 无
*返回值: 1:接收到应答信号,0:非应答或者未接收到应答信号
**************************************************/
u8 IIC_Wait_ACK()
{
u8 i;
IIC_IN(); //SDA变为输入状态
SCL = 1;
while(SDA_in)
{
i++;
if(i > 250)
{
IIC_end();
return 0;
}
}
SCL=0;
return 1;
}
3、发送一个字节数据与接收一个字节的数据
(1)发送一个字节数据
/*************************************************
*函数名: IIC_Write_byte
*函数功能: IIC写一个字节函数
*输入: bit:写入的数据
*返回值: 无
**************************************************/
void IIC_Write_byte(u8 bit)
{
u8 i;
IIC_OUT(); //SDA变为输出状态
SCL = 0;
for(i = 0;i < 8;i++)
{
if(bit & 0x80)
SDA_out = 1;
else
SDA_out = 0;
bit <<= 1;
Delay_us(2);
SCL = 1;
Delay_us(2);
SCL = 0;
Delay_us(2);
}
}
(2)接收一个字节的数据
/*************************************************
*函数名: IIC_Read_byte
*函数功能: IIC读取一个字节的数据
*输入: ACK:1-接收后给应答信号,0-接收后给非应答信号
*返回值: BIt:读取的值
**************************************************/
u8 IIC_Read_byte(u8 ACK)
{
u8 i,Bit;
IIC_IN(); //SCL变为输入状态
for(i = 0;i < 8;i++) //判断最高位,0x80 = 1000 0000
{
SCL = 0;
Delay_us(2);
SCL = 1;
Bit <<= 1;
if(SDA_in)
Bit++;
}
if(ACK)
IIC_ACK();
else
IIC_NACK();
return Bit;
}
六、设备间使用IIC的大致流程
1、发送数据
- 主机发送起始信号
- 主机发送从机地址+写信号
- 主机接收到应答信号,发送从设备写入数据的地址
- 主机接收到应答信号,主机开始发送数据,每发送一字节数据,都要接收一次应答信号。
- 数据发送完毕,主机发送停止信号,通信结束。
2、接收数据
- 主机发送起始信号
- 主机发送从机地址+读信号
- 主机接收到应答信号,发送从设备读取数据的地址
- 主机接收到应答信号,从设备开始发送数据,主机每接送一字节数据,都要发送一次应答信号。
- 主机不在想接收数据时,发送非应答信号,,结束数据传输。
- 主机发送停止信号,通信结束。
到这里就结束啦!
版权声明:本文为CSDN博主「修成真」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_51447215/article/details/121778136
暂无评论