I2C通信原理及程序详细讲解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
I2C 通信:
起始条件:SCL为高电平,SDA电平从高变低,这一变化即完成了通信的起始条件。
起始条件和数据通信间,通常会有延时要求具体的指标见设备说明。
数据传输阶段:一字节需要9个时钟周期;且每一位需要一个时钟周期;如上图所示,ADDRESS为目标设备的地址,R/ w为通信的的方向位;"1"时表示读,即后续的数据由目标设备发出,主机进行接收;"0"时表示写,即后续的数据由主机发出目标设备进行接收。
当ACK信号为"0"时,说明接收成功;为"1"时,说明接收失败。
每个字节的传输都是由高位(MSB)到低位(LSB)依次进行传输。
在数据通信过程中,总是由数据接收方发出ACK信号。
终止阶段:当主机完成数据通信,并终止本次传输时会发出终止信号。当SCL 是高电平时,SDA电平由低变高,这个变化意味着传输终止。注:每个时钟周期的高电平期间,SDA的数据状态达到稳定。
下面给出了模拟I2C总线进行读写的伪代码,用以说明如何使用GPIO 实现I2C通信:
int i2c_start() /* I2C起始条件*/
{
//初始化GPIO口
set_gpio_direction(SDA, OUTP); //设置SDA方向为输出
set_gpio_direction (SCL, OUTP); //设置SCL方向为输出
set_gpio_value(SDA, 1); //设置SDA为高电平
set_gpio_value(SCL, 1); //设置SCL为高电平
delay(); //延时
//起始条件
set_gpio_value(SDA, 0); //SCL为高电平时,SDA由高变低delay(); //适当延时
}
void i2c_stop() /* I2C终止条件*/
{
set_gpio_value(SCL, 1);
set_gpio_direction(SDA, OUTP);
set_gpio_value(SDA, 0);
delay();
set_gpio_value(SDA, 1); //SCL高电平时,SDA由低变高
}
/* I2C读取ACK信号(写数据时使用)返回值:0表示ACK信号有效;非0表示ACK信号无效*/
unsigned char i2c_read_ack()
{
unsigned char r;
set_gpio_direction(SDA, INP); //设置SDA方向为输入
set_gpio_value(SCL,0); // SCL变低
r = get_gpio_value(SDA); //读取ACK信号
delay();
set_gpio_value(SCL,1); // SCL变高
delay();
return r;
}
/* I2C发出ACK信号(读数据时使用) */
int i2c_send_ack()
{
set_gpio_direction(SDA, OUTP); //设置SDA方向为输出
set_gpio_value(SCL,0); // SCL变低
set_gpio_value(SDA, 0); //发出ACK信号
delay();
set_gpio_value(SCL,1); // SCL变高
delay();
}
void i2c_write_byte(unsigned char b) /* I2C字节写*/
{
int i;
set_gpio_direction(SDA, OUTP); //设置SDA方向为输出
for (i=7; i>=0; i--)
{
set_gpio_value(SCL, 0); // SCL变低
delay();
set_gpio_value(SDA, b & (1<
delay();
}
i2c_read_ack(); //检查目标设备的ACK信号}
/* I2C字节读*/
unsigned char i2c_read_byte()
{
int i;
unsigned char r = 0;
set_gpio_direction(SDA, INP); //设置SDA方向为输入
for (i=7; i>=0; i--)
{
set_gpio_value(SCL, 0); // SCL变低
delay();
r = (r <<1) | get_gpio_value(SDA); //高位到低位依次数据读取set_gpio_value(SCL, 1); // SCL变高
delay();
}
i2c_send_ack(); //向目标设备发送ACK信号return r;
}
/* I2C读操作addr:目标设备地址buf:读缓冲区len:读入字节的长度*/
void i2c_read(unsigned char addr, unsigned char* buf, int len)
{
int i;
unsigned char t;
i2c_start(); //起始条件,开始数据通信//发送地址和数据读写方向
t = (addr << 1) | 1; //低位为1,表示读数据
i2c_write_byte(t);
//读入数据
for (i=0; i buf[i] = i2c_read_byte();