一、IIC 协议总体概述
IIC总线,是飞利浦推出的一种串行总线,是具备多主机系统所需的包括总线仲裁、高低速
兼容的高性能 同步 串行总线。
IIC总线的硬件,是由一根数据线 SDA ,一根时钟线 L SCL 构成。不同的器件,都是并联接在这两条线上。通过不同的硬件地址来识别通信对象。
IIC总线 必须 都接 上拉电阻接到电源 VCC ,电阻大小要根据设备实际测量。总线空闲时候, SDA和 和 L SCL 都是高电平。当其中一个设备拉低总线,整条线就全是低电平,器件与器件之间是“与”逻辑关系。
IIC 总线可能会有 多个主机进行互相控制多个从机,多个主机通信就会出现仲裁的情况。
我们单片机主要是单主机通信,多主机仲裁的问题本文不再概述。
IIC 协议,是在同一根 A SDA 线上进行双向通信,属于半双工类。IIC协议首先是发送从机硬件地址,然后发送命令,再发送数据/ / 寄存器编号 或者 读取数据。IIC 协议可以多字节连续读写数据。
二、协议规则
1. 协议的数据有效性
规定,必须是在 SCL 的低电平期间,才能改变 SDA 的电平状态。SCL 高电平期间 SDA 线必须是稳定的,否则会错误的识别成 起始信号 或者 停止信号。
2.协议的起始信号、停止信号
SCL 高电平 期间,SDA 下降沿 是起始信号,之后就是总线忙碌,比如发送设备唯一地址。
SCL 高电平 期间,SDA 上升沿 是终止信号。之后是总线的空闲。起始信号和终止信号,都是主机发送。
3.协议的通讯格式
IIC协议,起始信号之后,可以连续传输多个字节。然后以停止信号结束这一帧数据的传是输。第一字节是 7位硬件地址 + 如 传输方向控制位。地址是根据硬件配置的,比如 AT24C02的地址是 4位固定+3 位接地,可以挂8个相同的 2 AT24C02 芯片。只有地址匹配的设备,才会处理总线上的数。
4.协议的字节格式
IIC 协议,每个字节必须是 K 8 + ACK 位。字节是先传输高位后传输低位。标准IIC协议是每位 4 微秒以上。但是有些器件是兼容各种速度的。应答信号是接收端接收数据后,把 SDA 拉低。告诉发送端已经接收完毕。非应答信号是接收端未能拉低,或者单片机读取数据的最后一个字节不需要应答。
三、协议的数据读写三种方式
1.协议单向发送数据
比如显示设备,一般情况下我们只需要写入数据,传输过程如下:
2.协议发送地址后立即读取数据
比如传感器设备,一般情况下我们只需要读出数据,传输过程如下:
3.协议先 指 定寄存器地址,再读取该寄存器的数据
比如存储芯片,一般情况下我们要先制定存储地址,再读取数据。传输过程如下:
四、程序实现
void IIC_Start()
{
SDA_GPIO=1;
SCL_GPIO=1;
IIC_Delay();
SDA_GPIO=0;
IIC_Delay();
SCL_GPIO=0;
IIC_Delay();
}//*/
void IIC_Stop()
{
SDA_GPIO=0;
SCL_GPIO=1;
IIC_Delay();
SDA_GPIO=1;
IIC_Delay();
}
void IIC_Write_Byte(u8 IIC_Byte)
{
u8 i;
SCL_GPIO=0;
SDA_GPIO=1;
for(i=0;i<8;i++)
{
SDA_GPIO=(bit)(IIC_Byte&0x80);
IIC_Byte<<=1;
IIC_Delay();
SCL_GPIO=1;
IIC_Delay();
SCL_GPIO=0;
IIC_Delay();
}
}u8 IIC_Read_Byte()
{
u8 i,Value;
SCL_GPIO=0;
SDA_GPIO=1;
for(i=0;i<8;i++)
{
Value=(Value<<1)|SDA_GPIO;
IIC_Delay();
SCL_GPIO=1;
IIC_Delay();
SCL_GPIO=0;
IIC_Delay();
}
return Value;
}
u8 IIC_Read_Ack()
{
u8 ack=1,i=0;
SCL_GPIO=1;
IIC_Delay();
while((ack)&&(i<5))
{
ack=SDA_GPIO;
i++;
}
SCL_GPIO=0;
return ack;
}void IIC_Write_Ack(bit ack)
{
SDA_GPIO=ack;
IIC_Delay();
SCL_GPIO=1;
IIC_Delay();
SCL_GPIO=0;
IIC_Delay();
SDA_GPIO=1;
IIC_Delay();
}
void OLED_Write_fixed_Buffer()
{
OLED_Display_Symbol_Ser(0,0,'<','-');
OLED_Display_Symbol_Ser(0,1,'<','<');
OLED_Display_Chines_Ser(0,2,48);
OLED_Display_Symbol_Ser(0,3,'b','i');
OLED_Display_Symbol_Ser(0,4,'u','b');
OLED_Display_Symbol_Ser(0,5,'i','u');
OLED_Display_Symbol_Ser(0,6,'>','-');
OLED_Display_Symbol_Ser(0,7,'>','>');
OLED_Display_Symbol_Ser(0,0,'<','-');
OLED_Display_Symbol_Ser(0,1,'<','<');
/***************³¬Éù²¨********************/
OLED_Display_Chines_Ser(2,0,0);
OLED_Display_Chines_Ser(2,1,2);
OLED_Display_Chines_Ser(2,2,4);
OLED_Display_Symbol_Ser(2,3,' ',':');
OLED_Display_Symbol_Ser(2,6,'m','m');
/***************ζÈ********************/
OLED_Display_Chines_Ser(4,0,54);
OLED_Display_Chines_Ser(4,1,56);
OLED_Display_Symbol_Ser(4,3,' ',':');
OLED_Display_Chines_Ser(4,6,58);
}
void main()
{
IIC_Init();
OLED_Init();
while(1)
{
}
}