注:温湿度传感器AHT20数据手册.pdf
http://www.aosong.com/userfiles/files/AHT20%E4%BA%A7%E5%93%81%E8%A7%84%E6%A0%BC%E4%B9%A6(%E4%B8%AD%E6%96%87%E7%89%88)%20B1.pdf
一、分析AHT数据手册文档
(1).准备工作
1.新建工程。配置UART2
2.配置I2C1为I2C标准模式,并开启中断和DMA设置
3.设置工程参数为每个外设初始化生成头文件和源文件,而后生成代码。
(2).根据数据手册,编写AHT20驱动
数据手册中的传感器读取流程如下:
1.上电后要等待40ms,读取温湿度值之前, 首先要看状态字的校准使能位Bit[3]是否为 1(通过发送0x71可以获取一个字节的状态字),如果不为1,要发送0xBE命令(初始化),此命令参数 有两个字节, 第一个字节为0x08,第二个字节为0x00。2.直接发送 0xAC命令(触发测量),此命令参数有两个字节,第一个字节为 0x33,第二个字节为0x00。3.等待75ms待测量完成,忙状态Bit[7]为0,然后可以读取六个字节(发0X71即可以读取)。4.计算温湿度值
(3),关键代码
#include "aht20.h"
#define AHT20_ADDRESS 0x70
//AHT20初始化
void AHT20_Init(){
uint8_t readBuffer;
//1.工作前延迟40ms
HAL_Delay(40);
//2.从AHT20收取一个字节,判断第Bit[3]是否为1
HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS, &readBuffer, 1, HAL_MAX_DELAY);
//加上状态位后实际上要判断Bit[4]
if( (readBuffer & 0x08)== 0x00){
//如果不为1,要发送0xBE命令(初始化)
//发送0xBE命令(初始化),此命令参数有两个字节, 第一个字节为0x08,第二个字节为0x00。
uint8_t sendBuffer[3] ={0xBE,0x08,0x00};
HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY);
}
}
void AHT20_Read(float *O_Temperature,float* O_Humidity){
//输入触发命令和参数
uint8_t sendBuffer[3] ={0xAC,0x33,0x00};
HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY);
//等待75ms测量完成
HAL_Delay(75);
//读6个字节
uint8_t readBuffer[6];
HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS, readBuffer, 6, HAL_MAX_DELAY);
//其中第0个字节是状态位,需获取bit[7]判断设备是否空闲。为0则不再工作
if((readBuffer[0] & 0x80 )==0x00){
uint32_t tempdata = 0;
//湿度数据由20个bit位组成:第1个字节是湿度的高8位,第2个字节是湿度的次高8位.第3个字节的高4个bit位是湿度的低4位。
tempdata =((uint32_t)readBuffer[1] << 12 ) + ((uint32_t)readBuffer[2] <<4 ) +((uint32_t)readBuffer[3] >>4 );
//相对湿度计算
*O_Humidity = tempdata *1.0f /(1<<20);
//温度数据也由20个bit位组成。第3个字节的低4个bit位是温度的高4位,第4个字节是温度的次高8位,第5个字节是温度的低8位。
tempdata = (((uint32_t)readBuffer[3] & 0x0F ) <<16 ) +((uint32_t)readBuffer[4] <<8 ) + (uint32_t)readBuffer[5];
//转化成摄氏度
*O_Temperature= tempdata*200.0f /(1<<20)-50;
}
}
main.c 关键函数如下:
/* USER CODE BEGIN Includes */
#include "aht20.h"
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
AHT20_Init();
char message[50];
float temperature, humidity;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
AHT20_Read(&temperature, &humidity);
sprintf(message,"温度:%.1f °C,湿度: %.1f %% \r\n",temperature,humidity*100);
HAL_UART_Transmit(&huart2, message, 50, HAL_MAX_DELAY);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
注:起初 sprintf(message,"温度:%.1f °C,湿度: %.1f %% \r\n",temperature,humidity*100);会报不支持浮点数输出的错误。
二、基于状态机编程实现AHT20的中断程序
HAL_I2C_Master_Transmit_IT() // 采用中断模式发送HAL_I2C_Master_Transmit_DMA() //采用DMA模式发送HAL_I2C_Master_Receive_IT() // 采用中断模式接收
HAL_I2C_Master_Receive_DMA() // 采用DMA模式接收
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c); //主机发送完成回调函数
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c); //主机接收完成回调函数
- 在状态为0时,发送测温湿度的命令,并将状态值为1。此时要等待DMA或者中断函数处理完成
- 触发 IIC发送完成回调函数,则表示发送命令完成,将状态置为2
- 当状态为2时,等待75 ms,让AHT20测温湿度结束。而后发送接收AHT20测温湿度数据的命令,并将状态置为3.
- 触发 IIC接收完成回调函数,则表示数据接收完成,测试接收到的6字节数据就是温湿度数据。并将状态置为4
- 当状态为4时,解析接收到的6字节数据,并打印
三、中断程序主要代码
#include <aht20.h>
//AHT20设备地址
static uint8_t AHT20_ADDRESS=0x70;
//发送0xBE命令(初始化),此命令参数有两个字节, 第一个字节为0x08,第二个字节为0x00。
static uint8_t AHT20InitCmd[3]={0xBE,0x08,0x00} ;
//输入测量触发命令和参数
static uint8_t AHT20MeasureCmd[3]={0xAC,0x33,0x00};
static uint8_t AHT20readBuffer[6];
//AHT20初始化
void AHT20_Init(){
uint8_t readOneByte;
//1.工作前延迟40ms
HAL_Delay(40);
//2.从AHT20收取一个字节,判断第Bit[3]是否为1
HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS, &readOneByte, 1, HAL_MAX_DELAY);
//加上状态位后实际上要判断Bit[4]
if( (readOneByte & 0x08)== 0x00){
//如果不为1,要发送0xBE命令(初始化)
//发送0xBE命令(初始化),此命令参数有两个字节, 第一个字节为0x08,第二个字节为0x00。
HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, AHT20InitCmd, 3, HAL_MAX_DELAY);
}
}
//发送测量指令
void AHT20_Transmit(){
HAL_I2C_Master_Transmit_IT(&hi2c1, AHT20_ADDRESS, AHT20MeasureCmd, 3);
}
//接收测量数据到AHT20readBuffer
void AHT20_Receive(){
HAL_I2C_Master_Receive_IT(&hi2c1, AHT20_ADDRESS, AHT20readBuffer, 6);
}
//解析AHT20readBuffer输出O_Temperature和O_Humidity
void AHT20_Analysis(float *O_Temperature,float* O_Humidity){
//其中第0个字节是状态位,需获取bit[7]判断设备是否空闲。为0则不再工作
if((AHT20readBuffer[0] & 0x80 )==0x00){
uint32_t tempdata = 0;
//湿度数据由20个bit位组成:第1个字节是湿度的高8位,第2个字节是湿度的次高8位.第3个字节的高4个bit位是湿度的低4位。
tempdata =((uint32_t)AHT20readBuffer[1] << 12 ) + ((uint32_t)AHT20readBuffer[2] <<4 ) +((uint32_t)AHT20readBuffer[3] >>4 );
//相对湿度计算
*O_Humidity = tempdata *1.0f /(1<<20);
//温度数据也由20个bit位组成。第3个字节的低4个bit位是温度的高4位,第4个字节是温度的次高8位,第5个字节是温度的低8位。
tempdata = (((uint32_t)AHT20readBuffer[3] & 0x0F ) <<16 ) +((uint32_t)AHT20readBuffer[4] <<8 ) + (uint32_t)AHT20readBuffer[5];
//转化成摄氏度
*O_Temperature= tempdata*200.0f /(1<<20)-50;
}
}
main.c关键代码
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
//状态:0 初始状态,1正在发送测量指令 2测量指令发送完成 3 IIC读取ANT20数据中 4 读取完成
uint8_t aht20State =0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c){
if(hi2c == &hi2c1){
aht20State =2;
}
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c){
if(hi2c == &hi2c1){
aht20State =4;
}
}
/* USER CODE END 0 */
int main(void)
{
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
AHT20_Init();
char message[50];
float temperature, humidity;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(aht20State == 0){
//初始状态
//测量数据
AHT20_Transmit();
aht20State=1;
}else if(aht20State == 2){
HAL_Delay(75);
//读取数据
AHT20_Receive();
aht20State=3;
}else if(aht20State == 4){
//AHT20_
AHT20_Analysis(&temperature, &humidity);
sprintf(message,"温度:%.1f °C,湿度: %.1f %% ",temperature,humidity*100);
HAL_UART_Transmit(&huart2, (uint8_t *)message, strlen(message), HAL_MAX_DELAY);
HAL_Delay(1000);
aht20State= 0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
查看效果:波特律动 串口助手