STM32模拟IIC协议
一:IIC通信接口的历史
IIC(Inter-Integrated Circuit)其实总的一个名称就是IICBUS,所以在中文上叫做集成电路总线,它是一种串行通信总线,可以实现一主多从。由飞利浦公司在1980年为了让主板、嵌入式系统用以了连接周围设备发展而来。
二:IIC通信接口的特点
1.双线制:一根SCL(时钟同步线);一根SDA(数据传输线)
2.半双工通信:从上图我们可以看到,IIC通信只有一根数据线SDA,所以IIC通信是半双工的
3.同步通信:有同步时钟线SCL,通信双方严格按照通信协议,SDA在通信双方初步同步后在SCL下按位传输数据
4.通信为主从机模式:支持一主多从模式,但是通信的SCL是一直由主机来控制的,IIC通信只能由主机先发起,不能由从机先发起通信。
5.从属设备地址:因为支持一主多从的模式,所以IIC总线中主机在通信中为了找到具体要通信的从机,主机需要知道该从机的设备地址,比如说我们上图的0XA1和0XA2,但是我们要注意,从机的设备地址是在出厂的时候厂家已经设定好了。主机不需要设备地址
IIC从设备地址的说明:
一 :设备地址般由7bit组成,在IIC通信时,将其左移一位,将最低位作为读写位。
比如:0xA1(1010 0001),实际使用过程中应该是0XA1<<1 = 0X42(0100 0010),这里默认为写模式。
二 :读写位:
因为IIC是半双工通信接口,所以在主机开始于从机通信前,主机需要告诉从机此次通信是谁作为发送端,谁作为接收端。其中最低位控制读还是写。
0:表示写模式—主机作为发送端
1:表示读模式—主机作为接收端
以我们上图的一个地址(0XA1)作为例子:
(0xA1)<<1|0x00 ==0x42-----主机为发送端(写模式)
(0xA1)<<1|0x01 ==0x43-----主机为接收端(读模式)
设备地址的作用:确保在IIC通信中主机可以找到从机,从而达到一主多从的功能
二:IIC通信的时序图(非常重要)
一:数据位有效性规定:
I2C总线通过上拉电阻接正电源。当总线空闲时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。
I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低时钟开始数据传输
for(t=0;t<8;t++)
{
delay_us(2);
IIC_SDA=(txd&0x80)>>7; //将发送的数据置到最低位
txd<<=1;
delay_us(3); //对TEA5767这三个延时都是必须的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
起始和终止信号SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
IIC_SDA=1;
IIC_SCL=1;
//保证IIC处于空闲状态
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4); //看时序图
IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(5);
IIC_SCL=1;
delay_us(5);
IIC_SDA=1;//发送I2C总线结束信号
}
应答和非应答:IIC 总线协议规定,每传送一个字节数据(即8个bit)后,第9为一个应答信号以确定数据传送是否被对方收到。应答信号由接受设备产生,在SCL为高电平期间,接受设备将SDA拉低为低电平,表示数据传输正确,产生应答。
//产生ACK应答
void IIC_Ack(void)
{
IIC_SDA=0;
SDA_OUT();
IIC_SCL=1;
delay_us(4);
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
}
//不产生ACK应答
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}