STM32 —— 读取 AHT20 数据到 OLED 屏幕
STM32 —— 读取 AHT20 数据到 OLED 屏幕
实验目的
理解OLED屏显和汉字点阵编码原理,使用STM32F103的SPI或IIC接口实现以下功能:
显示AHT20的温度和湿度
实验原理
实验原理可以参考我的前面几篇博客:
由于这里同时涉及到温度采集和 OLED 流动显示,所以这里采用 UCOS III 系统移植进行
HAL 库方法
CubeMX 项目配置
RCC 配置
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122103027050-349903670.png)
SYS 配置
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122103204151-1395957157.png)
SPI1 配置
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122103313974-221239876.png)
I2C 配置
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122103332111-72317182.png)
时钟配置
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122103353231-352486118.png)
引脚配置
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122103735273-1012200290.png)
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122104102247-361434267.png)
代码设计
我们在前面的博客中已将介绍了如何使用并修改好了对应的外设驱动代码,这里我们直接调用就行,而且我们不需要单独设计其他代码,只是将前面我们读取传感器和写屏幕的代码结合起来:
添加驱动代码源文件:
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122232515620-630509695.png)
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122232526451-1782611852.png)
引用对应头文件:
#include "stm32f1xx_hal.h"
#include "includes.h"
#include "stdbool.h"
#include "oled.h"
#include "bmp.h"
#include "gui.h"
#include "AHT20.h"
由于需要在 OLED 屏幕上显示温湿度,所以这里需要定义相关变量,并将温湿度转为 string 字符串格式再进行输出
//用于LED显示的温度和湿度
uint32_t CT_data[2]={0,0}; // 设置读取温度的参数
volatile int c1,t1;
uint8_t temp[10];
uint8_t hum[10];
void getData(){ // 读取温度并转为字符串格式便于 OLED 进行显示
//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倍)
//转为字符串易于显示
temp[0]=t1/100+'0';
temp[1]=(t1/10)%10+'0';
temp[2]='.';
temp[3]=t1%10+'0';
temp[4]='\0';
hum[0]=c1/100+'0';
hum[1]=(c1/10)%10+'0';
hum[2]='.';
hum[3]=c1%10+'0';
hum[4]=32;
hum[5]='%';
hum[6]='\0';
}
main.c 源码
这里直接给出 main.c 源代码:
int main(void)
{
/* USER CODE BEGIN 1 */
/* 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_I2C1_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */
OLED_Init(); // OLED 初始化
HAL_Delay(500);
/***********************************************************************************/
/**///①刚上电,产品芯片内部就绪需要时间,延时100~500ms,建议500ms
/***********************************************************************************/
AHT20_Init(); // AHT20 初始化
HAL_Delay(500);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// 获取温度
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET); // 使用 PC13 引脚上的板载小灯泡进行测试——小灯泡亮
AHT20_Read_CTdata_crc(CT_data); //经过CRC校验,读取AHT20的温度和湿度数据 推荐每隔大于1S读一次
c1 = CT_data[0]*1000/1024/1024; //计算得到湿度值c1(放大了10倍)
t1 = CT_data[1]*2000/1024/1024-500;//计算得到温度值t1(放大了10倍)
// 屏幕显示
OLED_Clear(0); // 清空屏幕
OLED_WR_Byte(0x2E,OLED_CMD); //关闭滚动
OLED_WR_Byte(0x27,OLED_CMD); //水平向左或者右滚动 26/27
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节
OLED_WR_Byte(0x00,OLED_CMD); //起始页 0
OLED_WR_Byte(0x07,OLED_CMD); //滚动时间间隔
OLED_WR_Byte(0x02,OLED_CMD); //终止页 2,即全屏
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节
OLED_WR_Byte(0xFF,OLED_CMD); //虚拟字节
GUI_ShowString(40,0,(uint8_t *)"ppqppl",16,1);
OLED_WR_Byte(0x2F,OLED_CMD); //开启滚动
getData(); // 获取温湿度
//显示温度
GUI_ShowCHinese(15,28,16,"温度",1);
GUI_ShowString(47,28,":",16,1);
GUI_ShowString(62,28,temp,16,1);
GUI_ShowCHinese(96,28,16,(uint8_t)"℃",1);
//显示湿度
GUI_ShowCHinese(15,48,16,"湿度",1);
GUI_ShowString(47,48,":",16,1);
GUI_ShowString(62,48,hum,16,1);
HAL_Delay(6200);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
其他细节可以去前两篇博客中查看
标准库方法
标准库与 HAL 库类似,需要先初始化对应的外设和引脚之后对外设进行调用即可,这里给出标准库中 main.c 源文件中代码:
#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"
#include "AHT20-21_DEMO_V1_3.h"
//存放温度和湿度
uint32_t CT_data[2]={0,0};
//湿度和温度
volatile int c1,t1;
//用于LED显示的温度和湿度
u8 temp[10];
u8 hum[10];
//初始化PC13用于测试
void GPIOC13_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_ResetBits(GPIOC,GPIO_Pin_13);
}
//初始化以及前期准备
void Init(void);
//读取温湿度
void getData(void);
//显示温湿度
void showData(void);
int main(void)
{
//初始化
Init();
while(1){
/* //获取数据
getData();
//显示数据
showData();*/
//开启滚动
OLED_WR_Byte(0x2F,OLED_CMD);
//延时
Delay_1ms(6200);
//OLED_Clear(0);
}
}
//初始化以及前期准备
void Init(void){
//初始化PC12
GPIOC13_Init();
//延时函数初始化
delay_init();
//初始化OLED
OLED_Init();
//清屏(全黑)
OLED_Clear(0);
//开机显示信息
GUI_ShowString(40,0,"ppqppl",16,1);
GUI_ShowString(20,24,"631907060520",16,1);
GUI_ShowCHinese(40,48,16,"欢迎你",1);
Delay_1ms(1000);
AHT20_Init();
/***********************************************************************************/
/**///①刚上电,产品芯片内部就绪需要时间,延时100~500ms,建议500ms
/***********************************************************************************/
Delay_1ms(1000);
OLED_Clear(0);
OLED_WR_Byte(0x2E,OLED_CMD); //关闭滚动
OLED_WR_Byte(0x27,OLED_CMD); //水平向左或者右滚动 26/27
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节
OLED_WR_Byte(0x00,OLED_CMD); //起始页 0
OLED_WR_Byte(0x07,OLED_CMD); //滚动时间间隔
OLED_WR_Byte(0x07,OLED_CMD); //终止页 2
OLED_WR_Byte(0x00,OLED_CMD); //虚拟字节
OLED_WR_Byte(0xFF,OLED_CMD); //虚拟字节
// 诗句
GUI_ShowCHinese(10,24,16,"春有百花秋有月",1);
OLED_WR_Byte(0x2F,OLED_CMD); //开启滚动
}
//读取温湿度
void getData(){
//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倍)
//转为字符串易于显示
temp[0]=t1/100+'0';
temp[1]=(t1/10)%10+'0';
temp[2]='.';
temp[3]=t1%10+'0';
temp[4]='\0';
hum[0]=c1/100+'0';
hum[1]=(c1/10)%10+'0';
hum[2]='.';
hum[3]=c1%10+'0';
hum[4]=32;
hum[5]='%';
hum[6]='\0';
}
//显示温湿度
void showData(){
//显示温度
GUI_ShowCHinese(15,28,16,"温度",1);
GUI_ShowString(47,28,":",16,1);
GUI_ShowString(62,28,temp,16,1);
GUI_ShowCHinese(96,28,16,"℃",1);
//显示湿度
GUI_ShowCHinese(15,48,16,"湿度",1);
GUI_ShowString(47,48,":",16,1);
GUI_ShowString(62,48,hum,16,1);
}
运行测试
接线示例
HAL 库接线
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122142755156-1360815295.jpg)
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122142750523-643336347.jpg)
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221120012440435-758138043.jpg)
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122142746722-1856981970.jpg)
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122142743125-1229920619.jpg)
标准库接线
接线方法与 HAL 库相同,仅引脚不同
运行结果
HAL 库运行结果
![](https://img2022.cnblogs.com/blog/2829072/202211/2829072-20221122234110271-843494109.gif)
运行结果与 HAL 库相同
结果分析
已经实现成功将我们需要的数据显示在 OLED 屏幕上,说明我们设计的代码没有问题
错误解决方法
这里容易出现的报错和前面在写 OLED 屏幕和读取 AHT20 传感器是相同,稍加注意就不会出现问题