上篇已经描述了单总线的优缺点,以及单总线传输机制和程序的编写。接下来这篇需要来讲解IIC。先简单列举采用IIC的设备,如温湿度传感器SHT20,陀螺仪MPU6050,液晶显示屏oled,存储芯片24C02等等。
二、IIC
IIC为I2C Bus的简称,也叫集成电路总线。I2C串行总线上一般有两根信号线,一根双向数据线SDA,一根时钟线SCL。I2C设备通常可以挂载多个,将I2C设备的串行数据SDA接在总线的SDA上,各设备的时钟线SCL接到总线的SCL上。绝大多数I2C设备都有一个固话的地址,只有线上传输的地址等于设备地址时,设备才会响应主机信号。主设备在很多时间都是控制SCL线的,而从设备一般只会拉低SCL用来延长总线的时钟周期信号。
接下来都以SHT2x(SHT20,SHT21等)为例,该传感器体积很小,采用DFN的封装,且可达到14bit精度。
与传感器的通讯。
1、首先通过其数据手册可以发现,所有的该传感器的I2C地址都一致(1000000)。
2、此传感器在上电之后需要至多15ms的等待时间将传感器达到空闲状态。
3、每次传输都以Start状态为开始,以Stop状态为结束。
开始传输状态,当SCL为高电平时,SDA由高电平转换为低电平。由主机控制,指示从机传输开始。
停止传输状态,当SCL为高电平时,SDA由低电平转换为高电平。由主机控制,指示从机传输结束。
程序部分:
- void IIC_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure; //先使能外设IO PORTC时钟
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- IIC_SCL=1;
- IIC_SDA=1;
- }
- //产生IIC起始信号
- void IIC_Start(void)
- {
- SDA_OUT(); //sda线输出
- IIC_SDA=1;
- IIC_SCL=1;
- delay_us(4);
- IIC_SDA=0;//START:when CLK is high,DATA change form high to low
- delay_us(4);
- IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
- delay_us(4);
- }
- //产生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(4);
- IIC_SCL=1;
- delay_us(1);
- IIC_SDA=1;//发送I2C总线结束信号
- delay_us(4);
- }
4、启动传输之后,先将I2C设备地址(7位)以及SDA的方向位(1位,读为1,写为0)发送。在第八个SCL时钟的下降沿时,
从机通过拉低SDA引脚,指示传感器数据传输正常,即ACK位。SHT2X工作模式分为主机模式和非主机模式,可以通过单片机
改变传感器的工作模式。方法如下,
①主机模式下,在传感器测量过程中,SCL线被封锁。即单片机不能操作SCL线,单片机便不能对传感器传输数据。
②非主机模式下,当传感器在执行测量任务时,SCL线仍保持开放状态,可由单片机操作。
非主机模式下,传输方式如图。图中灰色部分由SHT2X控制。
由于测量的最大分辨率为14bit,所以第二字节的SDA上的后两位(bit43和bit44),用来表示传输的信息,
bit43表示测量的类型(0表示温度,1表示湿度)。
程序源码:
- float SHT2x_GetTempPoll(void)
- {
- float TEMP;
- u8 ack, tmp1, tmp2;
- u16 ST;
- u16 i=0;
- IIC_Start(); //发送IIC开始信号
- IIC_Send_Byte(I2C_ADR_W); //IIC发送一个字节
- ack = IIC_Wait_Ack();
- IIC_Send_Byte(TRIG_TEMP_MEASUREMENT_POLL);
- ack = IIC_Wait_Ack();
- do {
- delay_ms(100);
- IIC_Start(); //发送IIC开始信号
- IIC_Send_Byte(I2C_ADR_R);
- i++;
- ack = IIC_Wait_Ack();
- if(i==1000)break;
- } while(ack!=0);
- tmp1 = IIC_Read_Byte(1);
- tmp2 = IIC_Read_Byte(1);
- IIC_Read_Byte(0);
- IIC_Stop();
- ST = (tmp1 << 8) | (tmp2 << 0);
- ST &= ~0x0003;
- TEMP = ((float)ST * 0.00268127) - 46.85;
- return (TEMP);
- }
- float SHT2x_GetHumiPoll(void)
- {
- float HUMI;
- u8 ack, tmp1, tmp2;
- u16 SRH;
- u16 i=0;
- IIC_Start(); //发送IIC开始信号
- IIC_Send_Byte(I2C_ADR_W); //IIC发送一个字节
- ack = IIC_Wait_Ack();
- IIC_Send_Byte(TRIG_HUMI_MEASUREMENT_POLL);
- ack = IIC_Wait_Ack();
- do {
- delay_ms(100);
- IIC_Start(); //发送IIC开始信号
- IIC_Send_Byte(I2C_ADR_R);
- i++;
- ack = IIC_Wait_Ack();
- if(i==100)break;
- } while(ack!=0);
- tmp1 = IIC_Read_Byte(1);
- tmp2 = IIC_Read_Byte(1);
- IIC_Read_Byte(0);
- IIC_Stop();
- SRH = (tmp1 << 8) | (tmp2 << 0);
- SRH &= ~0x0003;
- HUMI = ((float)SRH * 0.00190735) - 6;
- return (HUMI);
- }
5、软复位
该命令用于无需关闭和再次打开电源的情况下,重新启动传感器系统。接收到这个命令之后, 传感器系统开始重新初始化,并恢复默认设置状态。
- u8 SHT2x_SoftReset(void) //SHT20软件复位
- {
- u8 err=0;
- IIC_Start();
- IIC_Send_Byte(0x80);
- err = IIC_Wait_Ack();
- IIC_Send_Byte(0xFE);
- err = IIC_Wait_Ack();
- IIC_Stop();
- return err;
- }