通信协议讲解一 I2C 通讯协议简介应用及模拟
一,原理和通讯过程
IIC是主从通信方式,依靠SCL,SDA即时钟线和数据线进行通讯,因此可以看出IIC采用同步传输方式,由于其SDA数据线可进行双向通讯,但同一时刻仅能实现单向通讯,被称为半双工通讯。
IIC通讯时,非工作状态时,应保持数据线和时钟线上为高电平,因此,我们默认通过上拉电阻将其电平抬高。同样的,当我们配置主机接口时,需要将主机接口配置为开漏输出模式,此时需要设置为上拉模式。网上也有配置为推挽输出输入,关于这两者的区别,我会放在文章最末端讲解。
IIC协议规定,数据线的电平转换只能在时钟线为高电平时进行,起始信号和停止信号除外。下面我们详细讲一下上述过程:
当主机想要从从机获取信号时,我们以温度传感器为例:
mcu想要获取当前温度时,通过IIC向从机广播温度传感器名字(地址),这时,如果温度传感器听到有主机呼唤自己,会在收到后紧接发出一个应答信号ACK,告诉主机我在这里。此时温度传感器处于待命状态,等待主机进一步指令,当主机收到应答,表明呼唤成功,此时主机发送要读取的指定寄存器地址,当温度寄传感器收到指令,再次发出应答,此时主机待命,准备接受数据,温度传感器将寄存器内容发送到IIC通信线上由主机接收,接受完成,主机发送停止信号,结束对IIC通信线的占用,完成一次IIC读取操作。
另外需要说明的是,当主机发送地址时是7位地址位,加一位读写位,读写为为0时,主机向从机写入,为1时,主机读取从机寄存器。++
起始信号和终止信号:
信号转换需要在SCL为低电平时进行:
一次传输过程其实包含9个字节,7字节地址+1字节读写指示位组成8字节,以及1字节从机应答位。
总体而言,IIC通信时的流程如下:
对于esp32而言,实现IIC通信较为简单:
步骤如下:
设置IIC时钟和数据引脚,配置时钟频率,配置主从模式。
//定义端口号,用于区分不同IIC线,ESP有两个IIC驱动
i2c_port_t i2c_port_num = I2C_NUM_0;
//配置IIC引脚
#define iic_scl_io GPIO_NUM_0
#define iic_sda_io GPIO_NUM_1
//枚举读写地址,从数值意义上说,主机写入数据时,读写位为0,故枚举时应将写地址放在第一位。
enum{
add_write=0x78,
add_read
}ADD;
//设置发送指令集,个人根据从机进行填充,用于发送相关指令。
uint8_t tx_data[10]={
1,2,3,4,5,6,7,8,9,10};
//接收从机数据
uint8_t rx_data[10];
void iic_init()
{
//IIC配置结构体
配置为主机模式下的,开漏上拉模式
i2c_config_t iic_1 ={
.mode = I2C_MODE_MASTER,
.scl_io_num = iic_scl_io,
.sda_io_num = iic_sda_io,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ
};
//初始化配置结构体
i2c_param_config(i2c_port_num,&iic_1);
//安装IIC驱动
i2c_driver_install(i2c_port_num,I2C_MODE_MASTER,0,0