基于I2C协议的AHT20温湿度传感器的数据采集

一、I2C总线通信协议

软件I2C

        软件I2C,也称为模拟I2C或bit-bang I2C,是一种通过微控制器的通用输入输出(GPIO)引脚来模拟I2C总线通信的方式。它不依赖于专门的硬件I2C接口,而是通过编程控制GPIO引脚的电平状态来实现I2C协议的数据传输。在软件I2C中,通常需要两个GPIO引脚:一个是SCL(时钟线),另一个是SDA(数据线)。通过精确地控制这两个引脚上的电压变化,可以发送和接收数据。

硬件I2C

        硬件I2C是一种利用微控制器或其他设备上的专用硬件模块来进行I2C通信的方法。这种硬件模块内置了I2C协议的逻辑,能够自动处理时钟信号(SCL)和数据线(SDA)的操作,从而允许微控制器以更高效和可靠的方式与其他I2C兼容设备通信。

二、AHT20芯片

        了解AHT20芯片的相关信息,具体信息请到官方下载对应产品介绍文档。
        资料链接:http://www.aosong.com/class-36.html        
        官方代码使用的是PB14,PB15引脚需要修改对应的引脚才可以正常使用。

下图为AHT20芯片的典型电路(芯片正面有孔)。

三、工程配置

        要求:每隔2秒钟采集一次温湿度数据,显示到OLED上,同时通过串口发送到上位机的“串口助手”软件。
        首先进入CubeMX新疆工程,选择STM32F103C8T6芯片。

1.RCC配置。

2.SYS配置。

3.TIM1配置。

4.UASART串口配置。

5.I2C1配置(用于AHT20)。

6..I2C2配置(用于u8g2)。

7.时钟树配置。

8.代码配置。

四、代码修改

首先参考作者上篇文章进行u8g2的基础配置,以及字模的获取。
STM32—U8g2图形库练习

然后在usart.c文件中添加如下代码(添加头文件#include "stdio.h")。

 /* USER CODE BEGIN 1 */int fputc(int ch,FILE *f){HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xffff);return ch;}/* USER CODE END 1 */

main.c文件修改

 #include "main.h"#include "dma.h"#include "i2c.h"#include "tim.h"#include "usart.h"#include "gpio.h"#include "u8g2.h"​/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes */#include<stdio.h>/* USER CODE END Includes */​/* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD */​//温static const unsigned char  wen[] ={0x00,0x00,0xC4,0x1F,0x48,0x10,0x48,0x10,0xC1,0x1F,0x42,0x10,0x42,0x10,0xC8,0x1F,0x08,0x00,0xE4,0x3F,0x27,0x25,0x24,0x25,0x24,0x25,0x24,0x25,0xF4,0x7F,0x00,0x00};​//湿static const unsigned char  shi[] ={0x00,0x00,0xE4,0x1F,0x28,0x10,0x28,0x10,0xE1,0x1F,0x22,0x10,0x22,0x10,0xE8,0x1F,0x88,0x04,0x84,0x04,0x97,0x24,0xA4,0x14,0xC4,0x0C,0x84,0x04,0xF4,0x7F,0x00,0x00};​//度 static const unsigned char  du[] ={0x80,0x00,0x00,0x01,0xFC,0x7F,0x44,0x04,0x44,0x04,0xFC,0x3F,0x44,0x04,0x44,0x04,0xC4,0x07,0x04,0x00,0xF4,0x0F,0x24,0x08,0x42,0x04,0x82,0x03,0x61,0x0C,0x1C,0x70};​//待 static const unsigned char  dai[]={0x10,0x02,0x10,0x02,0x08,0x02,0xC4,0x3F,0x12,0x02,0x10,0x02,0xE8,0x7F,0x0C,0x08,0x0A,0x08,0xE9,0x7F,0x08,0x08,0x48,0x08,0x88,0x08,0x88,0x08,0x08,0x0A,0x08,0x04};​//检 static const unsigned char  jian[]={0x08,0x02,0x08,0x02,0x08,0x05,0x08,0x05,0xBF,0x08,0x48,0x10,0xAC,0x6F,0x1C,0x00,0x2A,0x11,0x0A,0x12,0x49,0x12,0x88,0x0A,0x88,0x08,0x08,0x04,0xE8,0x7F,0x08,0x00};​//测 static const unsigned char  che[]={0x00,0x20,0xE4,0x23,0x28,0x22,0x28,0x2A,0xA1,0x2A,0xA2,0x2A,0xA2,0x2A,0xA8,0x2A,0xA8,0x2A,0xA4,0x2A,0xA7,0x2A,0x84,0x20,0x44,0x21,0x44,0x22,0x24,0x28,0x10,0x10};​/* USER CODE END PTD */​/* Private define ------------------------------------------------------------*//* USER CODE BEGIN PD */​/* USER CODE END PD */​/* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PM */​/* USER CODE END PM */​/* Private variables ---------------------------------------------------------*/​/* USER CODE BEGIN PV */​/* USER CODE END PV */​/* Private function prototypes -----------------------------------------------*/void SystemClock_Config(void);/* USER CODE BEGIN PFP */​/* USER CODE END PFP */​/* Private user code ---------------------------------------------------------*//* USER CODE BEGIN 0 */​void oled_write(int temperature,int humidity){​char t[5]; // 创建一个足够大的字符数组来存储转换后的数字char h[5];double t1=( double)temperature;double h1=(double)humidity;sprintf(t, "%.2f",t1/10 ); // 使用sprintf将int变量转换为字符串sprintf(h, "%.2f",h1/10);u8g2_t u8g2;u8g2Init(&u8g2);  u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2,u8g2_font_ncenB12_tf);//设置字体格式u8g2_DrawXBMP(&u8g2,16,0,16,16,wen);//(参数顺序依次是,结构体、x、y、字宽、字高、储存要显示的字点阵的数组)u8g2_DrawXBMP(&u8g2,32,0,16,16,du);u8g2_DrawStr(&u8g2,48,16,":");u8g2_DrawXBMP(&u8g2,16,32,16,16,shi);u8g2_DrawXBMP(&u8g2,32,32,16,16,du);u8g2_DrawStr(&u8g2,48,48,":");u8g2_DrawUTF8(&u8g2,55,16,t);u8g2_DrawUTF8(&u8g2,55,48,h);u8g2_SendBuffer(&u8g2);}void oled_write_init(){u8g2_t u8g2;u8g2Init(&u8g2);  u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2,u8g2_font_ncenB12_tf);//设置字体格式u8g2_DrawXBMP(&u8g2,16,0,16,16,wen);//(参数顺序依次是,结构体、x、y、字宽、字高、储存要显示的字点阵的数组)u8g2_DrawXBMP(&u8g2,32,0,16,16,du);u8g2_DrawStr(&u8g2,48,16,":");u8g2_DrawXBMP(&u8g2,16,32,16,16,shi);u8g2_DrawXBMP(&u8g2,32,32,16,16,du);u8g2_DrawStr(&u8g2,48,48,":");u8g2_DrawXBMP(&u8g2,58,0,16,16,dai);u8g2_DrawXBMP(&u8g2,74,0,16,16,jian);u8g2_DrawXBMP(&u8g2,90,0,16,16,che);u8g2_DrawXBMP(&u8g2,58,32,16,16,dai);u8g2_DrawXBMP(&u8g2,74,32,16,16,jian);u8g2_DrawXBMP(&u8g2,90,32,16,16,che);u8g2_SendBuffer(&u8g2);}​/* USER CODE END 0 */​/*** @brief  The application entry point.* @retval int*/int main(void){​/* USER CODE BEGIN 1 */uint32_t CT_data[2]={0,0};volatile int  c1,t1;Delay_1ms(500);/* USER CODE END 1 */​/* MCU Configuration--------------------------------------------------------*/​/* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();​/* USER CODE BEGIN Init */​/* USER CODE END Init */​/* Configure the system clock */SystemClock_Config();​/* USER CODE BEGIN SysInit */​/* USER CODE END SysInit */​/* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();MX_I2C1_Init();MX_TIM1_Init();MX_I2C2_Init();/* USER CODE BEGIN 2 *///初始化AHT20AHT20_Init();Delay_1ms(500);u8g2_t u8g2;u8g2Init(&u8g2);/* USER CODE END 2 */​/* Infinite loop *//* USER CODE BEGIN WHILE */oled_write_init();while (1){/* USER CODE END WHILE */​AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次//AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据 ​c1 = CT_data[0]*1000/1024/1024;  //计算得到湿度值c1(放大了10倍)t1 = CT_data[1]*2000/1024/1024-500;//计算得到温度值t1(放大了10倍)printf("正在检测");for(int i=0;i<10;i++){HAL_Delay(100);printf(".");}printf("\r\n");HAL_Delay(1000);printf("温度:%d%d.%d",t1/100,(t1/10)%10,t1%10);printf("湿度:%d%d.%d",c1/100,(c1/10)%10,c1%10);printf("\r\n");printf("等待");for(int i=0;i<10;i++){HAL_Delay(100);printf(".");}printf("\r\n");HAL_Delay(1000);oled_write(t1,c1);/* USER CODE BEGIN 3 */}/* USER CODE END 3 */}​

五、实验结果

六、总结

        本次STM32编程练习结合了串口通信、AHT20的温湿度检测和u8g2的oled显示,让我学到了很多。

七、参考资料

stm32通过I2C接口实现温湿度(AHT20)的采集

I2C总线通信协议及实操stm32通过I2C实现温湿度(AHT20)采集 

STM32F103基于I2C协议的AHT20温湿度传感器的数据采集(HAL库,提供源码)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/32801.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快去复习吧+++常用算法及参考算法 递推法++穷举法++排序(冒泡、选择)++查找(顺序、折半)++字符串处理++方程求根++无穷级数求和

接上&#xff1a;常用算法及参考算法 &#xff08;1&#xff09;累加 &#xff08;2&#xff09;累乘 &#xff08;3&#xff09;素数 &#xff08;4&#xff09;最大公约数 &#xff08;5&#xff09;最值问题 &#xff08;6&#xff09;迭代法 常用算法及参考算法 7. 递推法…

如何解决Mac电脑不显示以.开头的文件?

Mac电脑默认是不显示以.开头的文件的&#xff0c;今天我一个朋友第一次编译一个vite的项目时&#xff0c;编译成功后发现API的网址都是http://localhost:48080开头&#xff0c;然后跟我吐槽说这个项目有毛病吧&#xff1f;我心想这明显就是没有设置VITE_BASE_URL啊&#xff1f;…

Vue-观察器(watch)的定义方式引发组件初始值没有渲染成功问题(已解决)

问题描述&#xff1a;在测试环境发现一个问题&#xff0c;打开一张表单的时候&#xff0c;所有字段都成功赋上了值&#xff0c;唯独一个人员组件的值&#xff08;出差人员&#xff09;没有带出&#xff0c;而接口返回的数据是正常的&#xff0c;也就是说不是后端接口的问题&…

JVM专题七:JVM垃圾回收机制

JVM专题六&#xff1a;JVM的内存模型中&#xff0c;我们介绍了JVM内存主要分哪些区域&#xff0c;这些区域分别是干什么的&#xff0c;同时也举了个例子&#xff0c;在运行过程种各个区域数据是怎样流转的。细心的小伙伴可能发现一个问题&#xff0c;在介绍完方法弹栈以后就没有…

指令微调数据集构建方法

指令微调&#xff08;Instruction Tuning&#xff09;&#xff0c;是指使用自然语言形式的数据对预训练后的大语言模型进行参数微调&#xff0c;在一些文章中也称为有监督微调&#xff08;Supervised Fine-tuning&#xff0c;SFT&#xff09;或多任务提示训练&#xff08;Multi…

go语言:两协程并发交替打印数字和字母(代码逐行注释)

要求&#xff1a; 并发两协程交替打印数字和字母。一个协程打印数字&#xff0c;一个协程打印字母。 输出&#xff1a; 12AB34CD56EF78GH910IJ1112KL1314MN1516OP1718QR1920ST2122UV2324WX2526YZ2728 思路&#xff1a; 两个 channel 控制两个协程进行交替打印。sync.WaitG…

CARLA自动驾驶模拟器基础

CARLA 使用服务器-客户端架构运行&#xff0c;其中 CARLA 服务器运行模拟并由客户端向其发送指令。客户端代码使用 API 与服务器进行通信。要使用 Python API&#xff0c;您必须通过 PIP 安装该模块&#xff1a; pip3 install carla-simulator # Python 3World and client 客…

【Android面试八股文】你能说一说View中onTouch、onTouchEvent和onClick的执行顺序吗?

文章目录 一、View中onTouch、onTouchEvent和onClick的执行顺序1.1 分析dispatchTouchEvent()1.1.1 执行顺序1.1.2 代码示例1.1.3 总结一、View中onTouch、onTouchEvent和onClick的执行顺序 要了解 onTouch()、onTouchEvent() 和 onClick() 方法的执行顺序,我们需要深入分析 …

React18中各种Hooks用法总结( 内附案例讲解)

React中各种Hooks用法总结 内附案例讲解 一、useState useState 是一个 React Hook&#xff0c;它允许你向组件添加一个 状态变量。 import React, { FC, memo, useState } from react import { MainContainer } from ./style interface IProps {children?: React.ReactNo…

FRP内网穿透及多级代理的使用

目录 0、前言 1、场景介绍 2、环境准备 2.1 下载frp 2.2 配置一台VPS 2.3 socks5客户端 2.5 网络环境准备 3、Frp设置 3.1 一层代理 3.1 二层代理 4、Frp总结 0、前言 FRP是比较老牌的也是比较流行的反向代理、内网穿透软件。FRP用途和使用场景可以看官方文档&#xff0c;…

JavaScript 预编译与执行机制解析

在深入探讨JavaScript预编译与执行机制之前&#xff0c;我们首先需要明确几个基本概念&#xff1a;声明提升、函数执行上下文、全局执行上下文以及调用栈。这些概念共同构成了JavaScript运行时环境的核心组成部分&#xff0c;对于理解代码的执行流程至关重要。本文将围绕这些核…

美团携手HarmonyOS SDK,开启便捷生活新篇章

华为开发者大会&#xff08;HDC 2024&#xff09;于6月21日在东莞松山湖拉开序幕&#xff0c;通过一系列精彩纷呈的主题演讲、峰会、专题论坛和互动体验&#xff0c;为开发者们带来了一场知识与技术的盛宴。6月23日&#xff0c;《HarmonyOS开放能力&#xff0c;使能应用原生易用…

如何在Java中实现数据加密与解密?

如何在Java中实现数据加密与解密&#xff1f; 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何在Java中实现数据加密与解密&#xff0c;这是保…

24-6-23-读书笔记(七)-《文稿拾零》豪尔赫·路易斯·博尔赫斯(第三辑)

文章目录 《文稿拾零》阅读笔记记录总结 《文稿拾零》 《文稿拾零》超厚的一本书&#xff08;570&#xff09;&#xff0c;看得时间比较长&#xff0c;这本书是作者零散时间写的一些关于文学性质的笔记&#xff0c;读起来还是比较无趣的&#xff0c;非常零散&#xff0c;虽然有…

C++系列-String(二)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” #define _CRT_SECURE_NO_WARNINGS #include<string> #include<iostream> #include<list> #include<algorithm> using namespace std; void test_string…

【Android面试八股文】如果 onTouchEvent()方法返回false,onClick()方法还会执行么?

文章目录 一、onTouchEvent 返回 false 的情况二、示例场景分析三、结论在 Android 中,拦截事件通常指阻止事件继续传递或者消费事件,以防止它继续触发其他后续事件(比如 onClick())。 在 onTouchEvent() 方法中,如果返回 false,表示当前 View 没有处理该事件,Android …

Java启动jar设置内存分配详解

在微服务架构越来越盛行的情况下&#xff0c;我们通常一个系统都会拆成很多个小的服务&#xff0c;但是最终部署的时候又因为没有那么多服务器只能把多个服务部署在同一台服务器上&#xff0c;这个时候问题就来了&#xff0c;服务器内存不够&#xff0c;这个时候我们就需要对每…

Spring响应式编程之Reactor操作符

操作符 操作符Processo<T,R>&#xff08;1&#xff09;创建操作符&#xff08;2&#xff09;转换操作符&#xff08;3&#xff09;组合操作符&#xff08;4&#xff09;条件操作符&#xff08;5&#xff09;错误处理操作符 操作符Processo<T,R> 操作符并不是响应式…

【Python机器学习实战】 | 基于线性回归以及支持向量机对汽车MPG与自重进行回归预测

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

【Android面试八股文】请你描述一下JVM的内存模型

文章目录 JVM内存模型1. 方法区(Method Area)运行时常量池(Runtime Constant Pool)2. 堆(Heap)3. 栈(Stack)4. 本地方法栈(Native Method Stack)5. 程序计数器(Program Counter Register)6. 直接内存(Direct Memory)JVM内存溢出的情况Java的口号是: “Write onc…