I2C与AHT20温湿度传感器
嵌入式领域另一种常见的通信IIC通信,并用其与AHT20传感器进行交互,获取房间的温度与湿度。
I2C有一条用于传递数据的数据线称为SDA(Serial Data),另一条是用于提供同步时钟脉冲的时钟线SCL(Serical clock)。SDA可以双向通信,但同一时刻只允许一段发送信号。
而串口的两根数据线TX-RX 和 RX-TX 为全双工通信,可以同时进行双向通信。
为了避免冲突,I2C采用了主从模式,一台为主机,另一台(或多台)为从机
只能由主机发起通信,从机才能根据主机的指令回复相应的信息。一问一答
或者与多台从机交互
这种总线协议,只需要在发送数据时带有目标地址的数据,相应地址的设备才会回应,其他设备则选择性“失聪”
IIC 采用同步通信,第二根线,SCL 保证
在而串口采用异步通信,没有SCL线,通信的双方都是基于各自的时钟,好处是比较便捷,其缺点就是通信的双方必须保证各自的系统时钟系统是精确的。若一方有问题,就会不知所云。
I2C1上有两个传感器:AHT20以及OLED
点击可查看具体过程
开始编码
1.新建文件
取名iic,将USART2打开用于串口接收数据,在图形界面 Connectivity -> I2C1 -> 配置为标准的I2C模式 参数保持默认
Project mange -> Code Generator (代码生成器) -> 勾选 Generate peripheral initializationxxxx of ‘.c/.h’ filesXXX 为每一个外设生成一对.c/.h文件 就可以在其他文件中include 相应的头文件,就能拿到huart2 或者 hi2c1这类外设操作句柄了
保存后,代码多生成了
2.自定义AHT20的.c/.h文件
在aht20.h中
#include "i2c.h"
在aht20.c中
#include "aht20.h"
就可以引用串口,I2C的相关变量。
根据温湿度手册初始化AHT20
1.上电后需要等待40ms
2.先向ATH20发送0x71 , aht20回返回1字节的状态信息。并判断此状态信息的第三位是否为1,是1才进行后面的操作,如果不是,则要发送0xBE命令(初始化),此命令参数有两个字节,第一个字节为0x08,第二个字节为0x00
- 0x71 是AHT20作为IIC从机的地址 AHT20_ADDRESS
IIC通信一般使用7位地址码,但发送时都是发送一字节即,8位,所以规定从机地址要向左移一位,左边补0还是1,则取决于如果主机发起通信的目的是为了设置(写)从机 那这一位为0,如果发起通信的目的是为了从从机读取数据,那这一位则为1,HAL对于0x70还是0x71的设置,相关函数会自动帮我们处理。一般默认说0
AHT20的地址码为0111000,但需要发送的数据地址为0x70
I2C通信指令:
I2C接收函数
HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS , &readBuffer, 3, HAL_MAX_DELAY);
参数说明
1.外设操作句柄的指针
2.读取的从机地址
3.用于接收数据的地址
4.读取的长度
5.设置超时时间。
I2C发送函数
HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS , &readBuffer, 3, HAL_MAX_DELAY);
参数说明:
1.外设操作句柄的指针
2.发送到的从机地址
3.发送的数据指针
4.发送的长度
5.设置超时时间。
根据说明
在aht20.c中编写代码
#include"aht20.h"
#define AHT20_ADDRESS 0x70
void AHT20_Init(){
uint8_t readBuffer;
HAL_Delay(40); //①
HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS , &readBuffer, 1 , HAL_MAX_DELAY); //②
if ((readBuffer & 0x08) == 0x00) { //③
uint8_t sendBuffer[3] = { 0xBE , 0x08 , 0x00 }; //④
HAL_I2C_Master_Transmit(&hi2c, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY); //④
}
}
void AHT20_Read(float *Temperature, float *Humidty){ //读取温湿度并返回
uint8_t sendBuffer[3] = {0xAC,0x33,0x00}; //①
HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY); //②
HAL_Delay(75); //③
uint8_t readBuffer[6];
HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS , readBuffer, 6 , HAL_MAX_DELAY); //⑤
if( (readBuffer[0] & 0x80 ) == 0x00) {
//计算
uint32_t data = 0;
data = ((uint32_t)readBuffer[3]>>4)+((uint32_t)readBuffer[2] << 4) + ((uint32_t)readBuffer[1]<<12);
*Humidty = data * 100.0f / (1<<20);
data = (((uint32_t)readBuffer[3] & 0x0f )<<16 ) + ((uint32_t)readBuffer[4] << 8) + ((uint32_t)readBuffer[5]);
*Temperature = data * 200.0f/(1<<20) - 50;
}
温湿度拼接以及计算公式
接着在aht20.h中声明
void AHT20_Init();
void AHT20_Read(float *Temperature,float *Humidity);
在main.c中:
#include "aht20.h"
#include "stdio.h"
#include "string.h"
//其他代码
//||||||
//其他代码
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
AHT20_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
float temperature;
float humidity;
AHT20_Read(&temperature, &humidity);
char message[50];
sprintf(message,"温度:%.1f\t 湿度:%.1f%%\t\r",temperature,humidity);
HAL_UART_Transmit(&huart2, (uint8_t *)message, strlen(message), HAL_MAX_DELAY);
HAL_Delay(1000);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
接着在串口助手中查看
自此就完成了使用I2C与AHT20之间的通信发送并读取了温湿度相关信息。