IIC通信协议
两条总线:串行数据总线(SDA)和串行时钟总线(SCL)
真正的多主机总线连接到相同总线的ic数量只受到总线的最大电容400pF限制。
串行8位双向数据在标准模式下可达100K bit/s
快速模式400K bit/s,高速模式下3.4Mbit/s.
数据有效性规定:
IIC总线在进行数据传输时,SCL在高电平区间,SDA上的电平必须保持稳定
SDA的数据的高或者低电平状态只有在SCL线的时钟信号是低电平时才能改变。
起始和停止条件:
起始:SCL高电平时,SDA由高电平向低电平切换。
停止:SCL高电平时,SDA由低电平向高电平切换。
每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。如果一段时间内没有收到从机的应答信号,则自动认为从机已正确接收到数据。
这种通信协议的要求是很精确的,一点点不对都可能导致在实际工程中无法读取数据
1、开始信号:处理器让SCL时钟保持高电平,然后让SDA数据信号由高变低就表示一个开始信号。同时IIC总线上的设备检测到这个开始信号它就知道处理器要发送数据了。停止信号:处理器让SCL时钟保持高电平,然后让SDA数据信号由低变高就表示一个停止信号。同时IIC总线上的设备检测到这个停止信号它就知道处理器已经结束了数据传输.
2、SDA上传输的数据必须在SCL为高电平期间保持稳定:因为外接IIC设备在SCL为高电平的期间采集数据方知SDA是高或低电平。SDA上的数据只能在SCL为低电平期间翻转变化。
3、处理器把数据发给外接IIC设备,如何知道IIC设备数据已经收到呢?就需要外接IIC设备回应一个信号给处理器。处理器发完8bit数据后就不再驱动总线了(SDA引脚变输入),而SDA和SDL硬件设计时都有上拉电阻,所以这时候SDA变成高电平。那么在第8个数据位,如果外接IIC设备能收到信号的话接着在第9个周期把SDA拉低,那么处理器检测到SDA拉低就能知道外接IIC设备数据已经收到。IIC数据从最高位开始传输。
void iic_init(void)//初始化
{
SCL = 1;
dalay_us();
SDA = 1;
dalay_us();
}
// 起始信号,时钟高,数据高变低
void start(void)
{
SDA = 1;
delay_us();
SCL = 1;
dalay_us();
SDA = 0;
delay_us();
SCL = 0; //钳住I2C总线,准备发送或接收数据
}
//停止信号
void stop(void)
{
SDA = 0;
delay_us();
SCL = 0;
delay_us();
SCL = 1;
delay_us();
SDA = 1;
delay_us();
}
//写一个字节
void iic_write_byte(unsigned char _byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
SDA = _byte&0X80; //先写高位
delay_us();
SCL = 1;
delay_us();
SCL = 0;
//下降沿采集数据
dalay_us();
_byte = _byte<<1;
}
SDA = 1;//发送完毕后,释放数据线,检测从机应答
iic_wait_ack();//等待应答
}
//读字节,也是先读取的是高位,需要左移
读取数据
unsigned char iic_read_byte(void)
{
unsigned char i = 0;
unsigned char read_byte = 0;
SDA = 1; //先确保主机释放SDA
delay_us();
for(i = 0;i<8;i++)
{
SCL = 1;
read_byte = (read_byte<<1)|SDA ;
delay_us();
SCL = 0; //拉低,采集数据
delay_us();
}
return read_byte;
}