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

news2025/1/12 3:43:19

一、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 */
     
     //初始化AHT20
     AHT20_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.coloradmin.cn/o/1854398.html

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

相关文章

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

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

虚拟机空间满了怎么办?

只剩143.8MB 1. 清理不必要的文件和软件 首先尝试清理系统中的不必要文件和软件&#xff0c;以释放一些空间。 清理包缓存 sudo apt-get clean sudo apt-get autoclean sudo apt-get autoremove 查找大文件 使用以下命令查找系统中的大文件&#xff0c;并删除不必要的文…

Altera的JTAG电路下载模块为何上下拉电阻,不可不知的秘密

一、FPGA背景信息 当前的FPGA市场上有国际和国产两大体系&#xff0c;国际排名&#xff0c;一直很稳定&#xff0c;国际上前三名Xilinx、Altera、Lattice&#xff0c;国内FPG厂商也在填补空白&#xff0c;低端、中低端市场上发力&#xff0c;替代潮流已在兴起&#xff0c;目前…

视频监控平台:支持交通部行业标准JT/T905协议(即:出租汽车服务管理信息系统)的源代码的函数和功能介绍及分享

目录 一、视频监控平台介绍 &#xff08;一&#xff09;概述 &#xff08;二&#xff09;视频接入能力介绍 &#xff08;三&#xff09;功能介绍 二、JT/T905协议介绍 &#xff08;一&#xff09;概述 &#xff08;二&#xff09;主要内容 1、设备要求 2、业务功能要求…

leetcode 130被围绕的区域

思路 一个区域不能被围绕是这个区域有部分在边界 可以循环边界&#xff0c;找边界的区域&#xff08;利用深搜&#xff09;&#xff0c;这些都不能被围绕&#xff0c;其余的&#xff0c;能被围绕&#xff0c;应该从"O"变为”X“ 代码 static boolean[][] hasGo;/…

【python】python基于akshare企业财务数据对比分析可视化(源码+数据集+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

江协科技51单片机学习- p14 调试LCD1602显示屏

前言&#xff1a; 本文是根据哔哩哔哩网站上“江协科技51单片机”视频的学习笔记&#xff0c;在这里会记录下江协科技51单片机开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了江协科技51单片机教学视频和链接中的内容。 引用&#xff1a; 51单片机入门教程-2…

Java8 --- Gradle7.4整合IDEA

目录 一、Gradle整合IDEA 1.1、Groovy安装 1.1.1、配置环境变量 ​编辑 1.2、创建项目 ​编辑 1.3、Groovy基本语法 1.3.1、基本语法 1.3.2、引号 1.3.3、语句结构 1.3.4、数据类型 1.3.5、集合操作 1.4、使用Gradle创建普通Java工程 1.5、使用Gradle创建Java ss…

Linux内核开发-编写一个内核模块

0.前言 上一章&#xff08;点击返回上一章&#xff09;已经完成了将ubuntu原始内核替换成了自己编好的内核。本章开始编写一个内核模块。 1.内核模块 1.1 什么是内核模块 Linux内核模块可独立于内核之外进行编译&#xff0c;可以在内核运行时动态加载、卸载。内核模块以.ko…

C语言| 数组元素的删除

同数组元素的插入差不多。 数组元素的插入&#xff0c;是先移动要插入元素位置后面的所有元素&#xff0c;再插入新元素&#xff0c;长度1。 C语言| 数组的插入-CSDN博客 数组元素的删除&#xff0c;是先删除元素&#xff0c;再把后面的元素往前移动一位&#xff0c;而本程序…

Adobe XD最新2023资源百度云盘下载(附教程)

如大家所了解的&#xff0c;Adobe XD是一种基于矢量的UI和UX设计工具&#xff0c;可用于设计从智能手表应用程序到成熟网站的任何内容&#xff0c;功能非常强大且操作便捷。目前最新已推出2023版本。 Adobe XD解决了Photoshop和其他图形应用程序无法解决的两个主要问题&#xf…

数据库理论大题与编译原理大题(笔记)

目录 数据库&#xff08;求最小函数依赖&#xff09; 数据库&#xff08;求属性集的闭包和候选码&#xff09; 编译原理&#xff08;NFA ——> DFA&#xff09; 编译原理&#xff08;识别文法的活前缀 DFA 和 LR(0) 分析表&#xff09; 哈哈&#xff01;这是本人作者才…

2024.06.23 刷题日记

〇、前言 今天重点刷了回溯&#xff0c;以及常见的题目。 46. 全排列 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3…

[stm32]温湿度采集与OLED显示

一、I2C总线协议 I2C&#xff08;Inter-integrated circuit &#xff09;是一种允许从不同的芯片或电路与不同的主芯片通信的协议。它仅用于短距离通信&#xff0c;是一种用于两个或多个设备之间进行数据传输的串行总线技术&#xff0c;它可以让你在微处理器、传感器、存储器、…

【Flink metric】Flink指标系统的系统性知识:以便我们实现特性化数据的指标监控与分析

文章目录 一. Registering metrics&#xff1a;向flink注册新自己的metrics1. 注册metrics2. Metric types:指标类型2.1. Counter2.2. Gauge2.3. Histogram(ing)4. Meter 二. Scope:指标作用域1. User Scope2. System Scope ing3. User Variables 三. Reporter ing四. System m…

[图解]《分析模式》漫谈08-反射·Taylor Swift

1 00:00:02,200 --> 00:00:06,070 今天我们延续昨天的话题&#xff0c;反射 2 00:00:06,770 --> 00:00:08,580 后面多了一个Taylor Swift 3 00:00:08,590 --> 00:00:11,810 跟这有什么关系 4 00:00:12,390 --> 00:00:14,740 是这样&#xff0c;昨天我发了视频之…

SCI一区级 | Matlab实现BO-Transformer-LSTM多变量时间序列预测

SCI一区级 | Matlab实现BO-Transformer-LSTM多变量时间序列预测 目录 SCI一区级 | Matlab实现BO-Transformer-LSTM多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【SCI一区级】Matlab实现BO-Transformer-LSTM多变量时间序列预测&#xff0c;贝叶斯…

Java项目:基于SSM框架实现的精品酒销售管理系统分前后台【ssm+B/S架构+源码+数据库+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的精品酒销售管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功…

基于动力学的六自由度机器人阻抗恒力跟踪控制

1.整个代码的控制流程图如下&#xff1a; 2.正逆运动学计算 略 3.动力学模型 采用拉格朗日法计算机械臂的动力学模型&#xff0c;其输入的是机械臂的关节角度、角速度和角加速度&#xff1b;其中M、C、G本别是计算的惯性力、科式力和重力项&#xff0c;相关部分如下&#xf…

【2024德国留学】签证被拒的十种原因.....

目录 2024德国留学签证被拒的常见原因 一、德语水平不足 二、录取考试未通过 三、签证申请中的其他问题 一、选择适合自己的签证类型 二、准备面签材料 1. 确认预约邮件 2. 签证申请表 3. 自备3张证件照 4. 护照原件和复印件 5. 动机信 6. 个人简历 7. 学历证及其…