一、I2C总线协议
I2C总线是一种双向的同步串行总线,它支持设备之间的短距离通信,经常用于处理器和一些外围设备之间的接口通信。I2C总线的标准通信速率是100Kbps,快速模式是400Kbps,高速模式支持3.4Mbps。I2C总线支持多设备的通信,而且各个设备之间的SCL和SDA线都是线与关系。I2C总线上扩展的器件的数量主要由电容负载来决定,其负载能力为400pF。I2C总线具有极低的电流消耗。
1. 物理层
I2C总线物理层由两根线组成:串行时钟线SCL、串行数据线SDA。由于这两根线都是开漏输出结构,因此必须都接上拉电阻到高电平,因此当总线处于空闲状态时,两根线都处于高电平状态。下图为I2C总线的物理层示意图。
2. 协议层
I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的设备地址。通常的我们将CPU模块作为主设备,而挂接在总线上的其他设备作为从设备。I2C总线上的主设备与从设备之间以8字节为单位进行双向数据传输,并且每个单位后还须跟着一位ACK位。其中数据在SCL处于低电平时被放到SDA数据线上,在SCL处于高电平时进行数据的采样。
I2C总线的传输时序包括:开始条件、地址帧、数据帧、停止条件、重复开始条件。
-
开始条件:标识传输正式开始,当SCL处于高电平时,SDA由高电平变为低电平。这样所有Slave设备都会知道传输已经开始。
-
地址帧:地址帧总是在一次通信的最开始出现,通常包括7位的设备地址(MSB)和最后1位的读写控制位(1表示读,0表示写)。接下来是1位的NACK/ACK,当这8位地址发送完成后,Slave设备获得SDA的控制权,此时Slave设备应该在第9个时钟脉冲之前回复一个ACK(将SDA拉低)以表示数据接收正常,否则表示数据接受失败,控制权交由Master设备处理。
-
数据帧:在地址帧发送之后,就可以开始传送数据了。每个数据帧8位,数据帧的数量可以是任意的,直到产生停止条件。每一个8位数据传输完成之后,接收方就需要回复一个ACK/NACK。
-
停止条件:当所有数据都发送完成时,当SCL处于高电平时,SDA由低电平变为高电平。除了开始条件和停止条件,在正常的数据传输过程中,当SCL处于高电平时,SDA上的值不能变化,否则会意外产生停止条件。
-
重复开始条件:有时Master设备需要在一次通信中进行多次消息交换(例如切换读写操作等),并且不希望其他Master设备干扰,这时可以使用重复开始条件。再一次通信中,Master设备可以产生多次开始条件来完成多次信息交换,最后在产生一个停止条件结束整个通信过程。
二、AHT20采集温湿度数据
AHT20芯片数据如下:
http://www.aosong.com/class-36.html
主要代码:
芯片的使用
void read_AHT20_once(void)
{
delay_ms(10);
reset_AHT20();//重置AHT20芯片
delay_ms(10);
init_AHT20();//初始化AHT20芯片
delay_ms(10);
startMeasure_AHT20();//开始测试AHT20芯片
delay_ms(80);
read_AHT20();//读取AHT20采集的到的数据
delay_ms(5);
}
读取数据
void read_AHT20(void)
{
uint8_t i;
for(i=0; i<6; i++)
{
readByte[i]=0;
}
I2C_Start();//I2C启动
I2C_WriteByte(0x71);//I2C写数据
ack_status = Receive_ACK();//收到的应答信息
readByte[0]= I2C_ReadByte();//I2C读取数据
Send_ACK();//发送应答信息
readByte[1]= I2C_ReadByte();
Send_ACK();
readByte[2]= I2C_ReadByte();
Send_ACK();
readByte[3]= I2C_ReadByte();
Send_ACK();
readByte[4]= I2C_ReadByte();
Send_ACK();
readByte[5]= I2C_ReadByte();
SendNot_Ack();
//Send_ACK();
I2C_Stop();//I2C停止函数
//判断读取到的第一个字节是不是0x08,0x08是该芯片读取流程中规定的,如果读取过程没有问题,就对读到的数据进行相应的处理
if( (readByte[0] & 0x68) == 0x08 )
{
H1 = readByte[1];
H1 = (H1<<8) | readByte[2];
H1 = (H1<<8) | readByte[3];
H1 = H1>>4;
H1 = (H1*1000)/1024/1024;
T1 = readByte[3];
T1 = T1 & 0x0000000F;
T1 = (T1<<8) | readByte[4];
T1 = (T1<<8) | readByte[5];
T1 = (T1*2000)/1024/1024 - 500;
AHT20_OutData[0] = (H1>>8) & 0x000000FF;
AHT20_OutData[1] = H1 & 0x000000FF;
AHT20_OutData[2] = (T1>>8) & 0x000000FF;
AHT20_OutData[3] = T1 & 0x000000FF;
}
else
{
AHT20_OutData[0] = 0xFF;
AHT20_OutData[1] = 0xFF;
AHT20_OutData[2] = 0xFF;
AHT20_OutData[3] = 0xFF;
printf("读取失败!!!");
}
printf("\r\n");
//根据AHT20芯片中,温度和湿度的计算公式,得到最终的结果,通过串口显示
printf("温度:%d%d.%d",T1/100,(T1/10)%10,T1%10);
printf("湿度:%d%d.%d",H1/100,(H1/10)%10,H1%10);
printf("\r\n");
}
stm32f103与AHT20连接:
stm32f103 | AHT20 |
---|---|
5V | VCC |
GND | GND |
B6 | SCL |
B7 | SDA |
运行结果:
三、总结
使用AHT20测试温湿度十分方便。