作为使用目前嵌入式设备使用最多的协议之一,I2C和SPI都是要研究透的。在我使用的开发板上,SPI协议集成了,只需要使用3个GPIO引脚即可。但I2C协议没有集成,还得自己写I2C的时序驱动,I2C的时序图大家可以百度到,专门的协议文档也有。关于时序图我会贴到博客里。
1. I2C串行总线的组成与工作原理
a. 组成:2根双向信息线,一根数据线SDA,一根时钟线SCL
b. I2C总线上多个器件的挂接(注意,每个器件都有唯一的地址)
c. 数据的通讯方式
主从方式。主机负责主动联系从机,从机被动回应主机(上图里I2C设备都是从机)
2. 工作方式:I2C总线通过上拉电阻接正电源,当总线空闲时,2根线均为高电平,各期件的SDA及SCL都是“线与”关系[单一器件输出低电平,整条总线的信号都拉低,I2C总线上的器件都可以读取到,主从机通讯就是这种机制]
3. 数据位的有效性规定(规定就是没有理由)
SCL处于高电平期间,这时对数据进行操作,数据线上的数据必须保持稳定。只有SCL处于低电平期间,SDA状态才能变化
4. I2C字节的传送与应答
每一位字节必须保持8位长度。数据传送时,先传送最高位MSB, 每一个被传送的字节最后必须跟随一个应答位(及一帧9位,应答位要用于说明一个字节已经传完,I2C总线重新置空闲态)
5. 时序协议的驱动的理解要逻辑性良好(这点是对各个应答信号时序的理解与编程)
4个基本时序信号:起始信号, 终止信号, 应答“0”, 应答“1”。(注意,一定要严格按照时序图来编写程序,延时也有严格的要求)
void I2C_Start() /*起始信号*/
{
I2C_SDA_OUT(); /*先SDA输出模式,主机MCU负责主动联系从机,所以MCU是输出*/
I2C_SDA_H;
I2C_SCL_H;
delay_us(5);
I2C_SDA_L;
delay_us(6);
I2C_SCL_L;
}
void I2C_Stop() /*终止信号*/
{
I2C_SDA_OUT(); /*先SDA输出模式,同理主机也负责切断与从机的通讯*/
I2C_SCL_L;
I2C_SDA_L;
I2C_SCL_H;
delay_us(6);
I2C_SDA_H;
delay_us(6);
}
void I2C_Ack() /*主机应答*/
{
I2C_SCL_L;
I2C_SDA_OUT(); /*SDA输出,主机应答函数,从机器件自然内置相应的应答函数*/
I2C_SDA_L;
delay_us(2);
I2C_SCL_H;
delay_us(5);
I2C_SCL_L; /*SDA在“0”时,SCL保持高电平则作为读状态*/
}
void I2C_NAck() /*主机非应答*/
{
I2C_SCL_L;
I2C_SDA_OUT(); /*SDA输出*/
I2C_SDA_H;
delay_us(2);
I2C_SCL_H;
delay_us(5);
I2C_SCL_L; /*同理*/
}