【STM32C092RC 测评】AHT10 温湿度 OLED 显示
本文介绍了 Nucleo-STM32C092 开发板通过硬件 IIC 与 AHT10 和 OLED 通信,采集环境温湿度、串口打印并实时显示在 OLED 的项目设计,制成 DIY 温湿度计。
项目方案
- 使用 STM32CubeMX 创建工程,配置 IIC 和 UART;
- STM32CubeIDE 代码编译和工程调试、固件上传;
- 实现基于 AHT10 传感器的环境温湿度的数据采集、串口打印和 OLED 实时显示。
工程创建
使用 STM32CubeMX 快速创建工程。
-
打开 STM32CubeMX
软件,新建 ST 板卡工程,搜索 NUCLEO-C092RC
选中目标板卡,开始工程,选择默认外设配置(注意不使用 BSP 板级支持包);
-
时钟配置:采用默认设置,系统时钟频率 12MHz;
-
Pinout & Configuration
标签下选择 Connectivity
- 使能 USART2
- 选择 Asynchronous
异步通信模式;
-
Pinout & Configuration
标签下选择 I2C1
- 使能 I2C1
- 注意到 GPIO 对应 PA9 (SCL) 和 PA10 (SDA);
-
Pinout & Configuration
标签下选择 I2C2
- 使能 I2C2
- 注意到 GPIO 对应 PA7 (SCL) 和 PA6 (SDA);
这里可以仅开启一个 IIC 实现复用。
-
配置完成后,进入 Project Manager
标签栏,进行项目命名、保存路径设置、编译器选择等操作;
-
点击 Generate Code
按钮,使用 STM32CubeIDE 或 Keil 打开目标工程;
-
编译工程,0 error, 0 warning
.
硬件连接
AHT10
AHT10 引脚 |
NUCLEO-C092RC 引脚 |
VCC |
3.3V |
GND |
GND |
SDA |
PA10 (I2C1_SDA) |
SCL |
PA9 (I2C1_SCL) |
OLED
OLED 引脚 |
NUCLEO-C092RC 引脚 |
GND |
GND |
VCC |
3.3V |
SCL |
PA10 (I2C2_SCL) |
SDA |
PA9 (I2C2_SDA) |
实物连接

工程代码
aht10.h
和 aht10.c
的代码详见帖子:【STM32C092RC 测评】AHT10 温湿度串口打印 .
oled.h
#ifndef __OLED_H__
#define __OLED_H__
#include "stm32c0xx_hal.h"
#define OLED_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define GPIOx_OLED_PORT GPIOB
#define OLED_SCK_PIN GPIO_PIN_6
#define OLED_SCK_ON() HAL_GPIO_WritePin(GPIOx_OLED_PORT, OLED_SCK_PIN, GPIO_PIN_SET)
#define OLED_SCK_OFF() HAL_GPIO_WritePin(GPIOx_OLED_PORT, OLED_SCK_PIN, GPIO_PIN_RESET)
#define OLED_SCK_TOGGLE() HAL_GPIO_TogglePin(GPIOx_OLED_PORT, OLED_SCK_PIN)
#define OLED_SDA_PIN GPIO_PIN_7
#define OLED_SDA_ON() HAL_GPIO_WritePin(GPIOx_OLED_PORT, OLED_SDA_PIN, GPIO_PIN_SET)
#define OLED_SDA_OFF() HAL_GPIO_WritePin(GPIOx_OLED_PORT, OLED_SDA_PIN, GPIO_PIN_RESET)
#define OLED_SDA_TOGGLE() HAL_GPIO_TogglePin(GPIOx_OLED_PORT, OLED_SDA_PIN)
void WriteCmd(void);
void OLED_WR_CMD(uint8_t cmd);
void OLED_WR_DATA(uint8_t data);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Set_Pos(uint8_t x, uint8_t y);
void OLED_On(void);
void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2, uint8_t Color_Turn);
void OLED_ShowDecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn);
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size, uint8_t Color_Turn);
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size, uint8_t Color_Turn);
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no, uint8_t Color_Turn);
void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn);
void OLED_DrawGIF(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t k, int m, unsigned char GIF[][m]);
void OLED_HorizontalShift(uint8_t direction);
void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end);
void OLED_VerticalAndHorizontalShift(uint8_t direction);
void OLED_DisplayMode(uint8_t mode);
void OLED_IntensityControl(uint8_t intensity);
void OLED_ClearLinePart(uint8_t line, uint8_t start, uint8_t end);
#endif
oled.c
/*
* ======================
* ref: https://blog.csdn.net/m0_46295154/article/details/139970968
* ======================
*/
#include "oled.h"
#include "i2c.h"
#include "oledfont.h"
uint8_t CMD_Data[]={
0xAE, 0x00, 0x10, 0x40, 0xB0, 0x81, 0xFF, 0xA1, 0xA6, 0xA8, 0x3F,
0xC8, 0xD3, 0x00, 0xD5, 0x80, 0xD8, 0x05, 0xD9, 0xF1, 0xDA, 0x12,
0xD8, 0x30, 0x8D, 0x14, 0xAF}; //初始化命令
void WriteCmd(void)
{
uint8_t i = 0;
for(i=0; i<27; i++)
{
HAL_I2C_Mem_Write(&hi2c2 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,CMD_Data+i,1,0x100);
}
}
/**
* @function: void OLED_WR_CMD(uint8_t cmd)
* @description: 向设备写控制命令
* @param {uint8_t} cmd 芯片手册规定的命令
* [@return](home.php?mod=space&uid=266161) {*}
*/
void OLED_WR_CMD(uint8_t cmd)
{
HAL_I2C_Mem_Write(&hi2c2 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100);
}
/**
* @function: void OLED_WR_DATA(uint8_t data)
* @description: 向设备写控制数据
* @param {uint8_t} data 数据
* @return {*}
*/
void OLED_WR_DATA(uint8_t data)
{
HAL_I2C_Mem_Write(&hi2c2 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&data,1,0x100);
}
/**
* @function: void OLED_Init(void)
* @description: OLED初始化
* @return {*}
*/
void OLED_Init(void)
{
HAL_Delay(200);
WriteCmd();
}
/**
* @function: OLED_Clear(void)
* @description: 清屏,整个屏幕的像素点都是关闭的
* @return {*}
*/
void OLED_Clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i);
OLED_WR_CMD (0x00);
OLED_WR_CMD (0x10);
for(n=0;n<132;n++)
OLED_WR_DATA(0);
}
}
/**
* @function: void OLED_Display_On(void)
* @description: 更新显示
* @return {*}
*/
void OLED_Display_On(void)
{
OLED_WR_CMD(0X8D); //SET DCDC命令
OLED_WR_CMD(0X14); //DCDC ON
OLED_WR_CMD(0XAF); //DISPLAY ON
}
/**
* @function: void OLED_Display_Off(void)
* @description: 关闭OLED显示
* @return {*}
*/
void OLED_Display_Off(void)
{
OLED_WR_CMD(0X8D); //SET DCDC命令
OLED_WR_CMD(0X10); //DCDC OFF
OLED_WR_CMD(0XAE); //DISPLAY OFF
}
/**
* @function: void OLED_Set_Pos(uint8_t x, uint8_t y)
* @description: 坐标设置
* @param {uint8_t} x,y
* @return {*}
*/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_WR_CMD(0xb0+y);
OLED_WR_CMD(((x&0xf0)>>4)|0x10);
OLED_WR_CMD(x&0x0f);
}
/**
* @function: void OLED_On(void)
* @description: 更新显示
* @return {*}
*/
void OLED_On(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i); //设置页地址(0~7)
OLED_WR_CMD(0x00); //设置显示位置—列低地址
OLED_WR_CMD(0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
OLED_WR_DATA(1);
} //更新显示
}
/**
* @function: unsigned int oled_pow(uint8_t m,uint8_t n)
* @description: m^n函数
* @param {uint8_t} m,n
* @return {unsigned int} result
*/
unsigned int oled_pow(uint8_t m,uint8_t n)
{
unsigned int result=1;
while(n--)result*=m;
return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:模式 0,填充模式;1,叠加模式
//num:数值(0~4294967295);
void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2, uint8_t Color_Turn)
{
uint8_t t,temp;
uint8_t enshow=0;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2, Color_Turn);
continue;
}
else
enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2, Color_Turn);
}
}
/**
* @function: void OLED_Showdecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn)
* @description: 显示正负浮点数
* @param {uint8_t} x待显示的数字起始横坐标,x:0~126
* @param {uint8_t} y待显示的数字起始纵坐标, y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {float} num:输入的浮点型数据
* @param {uint8_t } z_ len:整数部分的位数
* @param {uint8_t } f_len: 小数部分的位数
* @param {uint8_t} size2:输入的数据大小,选择 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowDecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn)
{
uint8_t t,temp,i=0;//i为负数标志位
uint8_t enshow;
int z_temp,f_temp;
if(num<0)
{
z_len+=1;
i=1;
num=-num;
}
z_temp=(int)num;
//整数部分
for(t=0;t<z_len;t++)
{
temp=(z_temp/oled_pow(10,z_len-t-1))%10;
if(enshow==0 && t<(z_len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2, Color_Turn);
continue;
}
else
enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2, Color_Turn);
}
//小数点
OLED_ShowChar(x+(size2/2)*(z_len),y,'.',size2, Color_Turn);
f_temp=(int)((num-z_temp)*(oled_pow(10,f_len)));
//小数部分
for(t=0;t<f_len;t++)
{
temp=(f_temp/oled_pow(10,f_len-t-1))%10;
OLED_ShowChar(x+(size2/2)*(t+z_len)+5,y,temp+'0',size2, Color_Turn);
}
if(i==1)//如果为负,就将最前的一位赋值‘-’
{
OLED_ShowChar(x,y,'-',size2, Color_Turn);
i=0;
}
}
/**
* @function: void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t Char_Size,uint8_t Color_Turn)
* @description: 在OLED12864特定位置开始显示一个字符
* @param {uint8_t} x字符开始显示的横坐标 0~127
* @param {uint8_t} y字符开始显示的纵坐标 0~63
* @param {uint8_t} chr待显示的字符
* @param {uint8_t} Char_Size待显示字符的字体大小,选择字体 16/12
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size, uint8_t Color_Turn)
{
unsigned char c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x>128-1){x=0;y=y+2;}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F8X16[c*16+i]);
else
OLED_WR_DATA(F8X16[c*16+i]);
}
//OLED_WR_DATA(F8X16[c*16+i]);
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F8X16[c*16+i+8]);
else
OLED_WR_DATA(F8X16[c*16+i+8]);
}
//OLED_WR_DATA(F8X16[c*16+i+8]);
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F6x8[c][i]);
else
OLED_WR_DATA(F6x8[c][i]);
}
//OLED_WR_DATA(F6x8[c][i]);
}
}
/**
* @function: void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_tChar_Size, uint8_t Color_Turn)
* @description: 在OLED12864特定位置开始显示字符串
* @param {uint8_t} x待显示字符串的开始横坐标x:0~127
* @param {uint8_t} y待显示字符串的开始纵坐标 y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {uint8_t} *chr待显示的字符串
* @param {uint8_t} Char_Size待显示字符串的字体大小,选择字体 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr,uint8_t Char_Size, uint8_t Color_Turn)
{
uint8_t j=0;
while (chr[j]!='\0')
{
OLED_ShowChar(x,y,chr[j],Char_Size, Color_Turn);
if (Char_Size ==12) //6X8的字体列加6,显示下一个字符
x += 6;
else //8X16的字体列加8,显示下一个字符
x += 8;
if (x > 122 && Char_Size==12) //TextSize6x8如果一行不够显示了,从下一行继续显示
{
x = 0;
y++;
}
if (x > 120 && Char_Size== 16) //TextSize8x16如果一行不够显示了,从下一行继续显示
{
x = 0;
y+=2;
}
j++;
}
}
/**
* @function: void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no, uint8_t Color_Turn)
* @description: 在OLED特定位置开始显示16X16汉字
* @param {uint8_t} x待显示的汉字起始横坐标x: 0~112,两列汉字之间需要间隔16
* @param {uint8_t} y待显示的汉字起始纵坐标 y: 0~6 , 两行汉字之间需要间隔2
* @param {uint8_t} no待显示的汉字编号
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no, uint8_t Color_Turn)
{
uint8_t t=0;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
if (Color_Turn)
OLED_WR_DATA(~Hzk[2*no][t]); //显示汉字的上半部分
else
OLED_WR_DATA(Hzk[2*no][t]); //显示汉字的上半部分
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
if (Color_Turn)
OLED_WR_DATA(~Hzk[2*no+1][t]); //显示汉字的上半部分
else
OLED_WR_DATA(Hzk[2*no+1][t]);//显示汉字的上半部分
}
}
/**
* @function: void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn)
* @description: 在OLED特定区域显示BMP图片
* @param {uint8_t} x0图像开始显示横坐标 x0:0~127
* @param {uint8_t} y0图像开始显示纵坐标 y0:0~7
* @param {uint8_t} x1图像结束显示横坐标 x1:1~128
* @param {uint8_t} y1图像结束显示纵坐标 y1:1~8
* @param {uint8_t} *BMP待显示的图像数据
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn)
{
uint32_t j = 0;
uint8_t x = 0, y = 0;
if(y1%8==0)
y = y1/8;
else
y = y1/8 + 1;
for(y=y0;y<y1;y++)
{
OLED_Set_Pos(x0,y);
for(x=x0;x<x1;x++)
{
if (Color_Turn)
OLED_WR_DATA(~BMP[j++]);//显示反相图片
else
OLED_WR_DATA(BMP[j++]);//显示图片
}
}
}
/*
@brief 显示动图
@param x0:起始列地址
y0:起始页地址
x1:终止列地址
y1:终止页地址
k: 帧个数
m: 单帧数组大小
BMP[][m]:存放动图代码的数组
@retval 无
*/
void OLED_DrawGIF(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t k, int m, unsigned char GIF[][m])
{
unsigned int j=0; //定义变量
unsigned char x,y,i; //定义变量
if(y1%8==0) y=y1/8; //判断终止页是否为8的整数倍
else y=y1/8+1;
for (i=0;i<k;i++) //从第一帧开始画
{
j = 0;
for(y=y0;y<y1;y++) //从起始页开始,画到终止页
{
OLED_Set_Pos(x0,y);//在页的起始列开始画
for(x=x0;x<x1;x++) //画x1 - x0 列
{
OLED_WR_DATA(GIF[i][j++]); //画图片的点
}
}
}
}
/**
* @function: void OLED_HorizontalShift(uint8_t direction)
* @description: 屏幕内容水平全屏滚动播放
* @param {uint8_t} direction LEFT 0x27 RIGHT 0x26
* @return {*}
*/
void OLED_HorizontalShift(uint8_t direction)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0x00);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频
// 0x00-5帧, 0x01-64帧, 0x02-128帧, 0x03-256帧, 0x04-3帧, 0x05-4帧, 0x06-25帧, 0x07-2帧,
OLED_WR_CMD(0x07);//设置结束页地址
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end)
* @description: 屏幕部分内容水平滚动播放
* @param {uint8_t} direction LEFT 0x27 RIGHT 0x26
* @param {uint8_t} start 开始页地址 0x00~0x07
* @param {uint8_t} end 结束页地址 0x01~0x07
* @return {*}
*/
void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(start);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频,0x07即滚动速度2帧
OLED_WR_CMD(end);//设置结束页地址
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_VerticalAndHorizontalShift(uint8_t direction)
* @description: 屏幕内容垂直水平全屏滚动播放
* @param {uint8_t} direction 右上滚动 0x29
* 左上滚动 0x2A
* @return {*}
*/
void OLED_VerticalAndHorizontalShift(uint8_t direction)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x01);//虚拟字节设置
OLED_WR_CMD(0x00);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频,即滚动速度
OLED_WR_CMD(0x07);//设置结束页地址
OLED_WR_CMD(0x01);//垂直滚动偏移量
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_DisplayMode(uint8_t mode)
* @description: 屏幕内容取反显示
* @param {uint8_t} direction ON 0xA7 ,
* OFF 0xA6 默认此模式,设置像素点亮
* @return {*}
*/
void OLED_DisplayMode(uint8_t mode)
{
OLED_WR_CMD(mode);
}
/**
* @function: void OLED_IntensityControl(uint8_t intensity)
* @description: 屏幕亮度调节
* @param {uint8_t} intensity 0x00~0xFF,RESET=0x7F
* @return {*}
*/
void OLED_IntensityControl(uint8_t intensity)
{
OLED_WR_CMD(0x81);
OLED_WR_CMD(intensity);
}
/**
* [@brief](home.php?mod=space&uid=247401) 清除OLED上指定行的部分内容
* @param line: 行号(0-7)
* @param start: 起始列(0-127)
* @param end: 结束列(0-127)
* @retval None
*/
void OLED_ClearLinePart(uint8_t line, uint8_t start, uint8_t end)
{
uint8_t i;
// 参数检查
if(line > 7) return;
if(start > end) { uint8_t tmp = start; start = end; end = tmp; }
if(start > 127) start = 127;
if(end > 127) end = 127;
OLED_Set_Pos(start, line);
for(i = start; i <= end; i++) {
OLED_WR_DATA(0x00);
}
}
main.c
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
#include "aht10.h"
#include "oled.h"
/* USER CODE END Includes */
void SystemClock_Config(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_I2C2_Init();
MX_USART2_UART_Init();
if(AHT10_Init() != 0)
{
HAL_UART_Transmit(&huart2, (uint8_t*)"AHT11 Init Failed!\r\n", 19, 100);
while(1);
}
char msg[64];
float temp, humi;
OLED_Init();
OLED_Clear();
OLED_ShowString(0,0,"Temperature:",16,1);
OLED_ShowString(100,2,"C",16,0);
OLED_ShowString(0,4,"Humidity:",16,1);
OLED_ShowString(100,6,"%",16,0);
while (1)
{
uint8_t ret = AHT10_ReadData(&temp, &humi);
if(ret == 0)
{
sprintf(msg, "Temp: %.1f C, Humi: %.1f %%\r\n", temp, humi);
OLED_ClearLinePart(2, 45, 99);
OLED_ClearLinePart(3, 45, 99);
OLED_ShowDecimal(45,2,temp,2,2,16,0);
OLED_ClearLinePart(6, 45, 99);
OLED_ClearLinePart(7, 45, 99);
OLED_ShowDecimal(45,6,humi,2,2,16,0);
}
else
{
sprintf(msg, "Error: %d\r\n", ret);
}
HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 100);
HAL_Delay(500);
}
/* USER CODE END 3 */
}
编译程序,连接开发板并运行程序,可实现固件上传和程序自动执行。
效果演示
OLED 显示温湿度

同时串口打印温湿度数据

总结
本文介绍了 Nucleo-STM32C092 开发板通过硬件 IIC 与 AHT10 和 OLED 通信,采集环境温湿度、串口打印并实时显示在 OLED 的项目设计,实现了 DIY 温湿度计。这项工作为相关产品的开发和设计提供了参考。