STM32:AHT20温湿度传感器驱动程序开发

2023-11-02 08:04

本文主要是介绍STM32:AHT20温湿度传感器驱动程序开发,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

注:温湿度传感器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.计算温湿度值
1.第一条的意思是,开机后,要等待40ms才能够与AHT20通信。因此在AHT20建立通信前要等待40ms。而后0x71地址实际上AHT20作为IIC从机的地址。按照AHT20手册,在启动传输后,随后传输的 II C首字节包括 7位的 I I C设备地址0x38。因为IIC通信一般使用7为地址码,但是读写数据都是一个字节一个字节的读写。0x38的七位二进制为0111000。规定从机地址要左一位。多出来的第八位就是读写位。IIC协议规定,如果主机发起通信的目的是为了写从机,那么读写位是0,此时AHT20的地址是01110000,即0x70.如果主机发起通信的目的是为了读从机传入的数据,那么读写位就是1。此时AHT20的地址是0x71。对于第8位的读写设置,HAL库已经帮我们封装好了,所以不用特意去操作。用户只当作AHT20的地址是0x70就行。
2.直接发送信息,略
3.等待75ms后,读取6个字节数据,里面包含了状态信息,湿度信息,和温度信息。其中第0个字节是状态位,需获取bit[7]判断设备是否空闲。而后,湿度数据由20个bit位组成:第1个字节是湿度的高8位,第2个字节是湿度的次高8位.第3个字节的高4个bit位是湿度的低4位。温度数据也由20个bit位组成。第3个字节的低4个bit位是温度的高4位,第4个字节是温度的次高8位,第5个字节是温度的低8位。
4.解析完温度、湿度数据后,进行计算

(3),关键代码

aht.h声明函数, aht.c函数定义如下

#include "aht20.h"
#define AHT20_ADDRESS 0x70
//AHT20初始化
void AHT20_Init(){uint8_t readBuffer;//1.工作前延迟40msHAL_Delay(40);//2.从AHT20收取一个字节,判断第Bit[3]是否为1HAL_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);会报不支持浮点数输出的错误。

菜单栏Project ->properties解决

二、基于状态机编程实现AHT20的中断程序

上面一节实现的是AHT20的轮询模式。发送HAL_I2C_Master_Transmit ,接收HAL_I2C_Master_Receive都会阻塞主程序,待完全执行完发送/接收内容时程序才会执行下一步操作。而在中断或DMA模式下,发送和接收消息不会阻塞主程序,那么就有可能发生还没接收完数据就对温度、湿度变量进行计算,造成脏读。
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); //主机接收完成回调函数

所谓状态机编程实际上类似与设计模式中的状态模式类型,把AHT20的通信流程拆分开来。每个状态标识分别对应着自己的处理逻辑,并且指明下一个的状态。
        
改造上述代码。
1).保持AHT20初始化不变
2).拆分温度、湿度发送/接收/计算模块
  • 在状态为0时,发送测温湿度的命令,并将状态值为1。此时要等待DMA或者中断函数处理完成
  • 触发 IIC发送完成回调函数,则表示发送命令完成,将状态置为2
  • 当状态为2时,等待75 ms,让AHT20测温湿度结束。而后发送接收AHT20测温湿度数据的命令,并将状态置为3.
  • 触发 IIC接收完成回调函数,则表示数据接收完成,测试接收到的6字节数据就是温湿度数据。并将状态置为4
  • 当状态为4时,解析接收到的6字节数据,并打印
这样就完成了中断/DMA的测量温湿度数据的案例

三、中断程序主要代码

aht.h声明函数, aht.c函数定义如下
#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.工作前延迟40msHAL_Delay(40);//2.从AHT20收取一个字节,判断第Bit[3]是否为1HAL_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 */
}

查看效果:波特律动 串口助手

        

这篇关于STM32:AHT20温湿度传感器驱动程序开发的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/329235

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

v0.dev快速开发

探索v0.dev:次世代开发者之利器 今之技艺日新月异,开发者之工具亦随之进步不辍。v0.dev者,新兴之开发者利器也,迅速引起众多开发者之瞩目。本文将引汝探究v0.dev之基本功能与优势,助汝速速上手,提升开发之效率。 何谓v0.dev? v0.dev者,现代化之开发者工具也,旨在简化并加速软件开发之过程。其集多种功能于一体,助开发者高效编写、测试及部署代码。无论汝为前端开发者、后端开发者

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2