[STM32C0] 【STM32C092RC 测评】AHT10 温湿度 OLED 显示

[复制链接]
 楼主| 无垠的广袤 发表于 2025-5-20 01:58 | 显示全部楼层 |阅读模式
<

【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)

实物连接

oled_aht10_display.jpg

工程代码

aht10.haht10.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 显示温湿度

oled_aht10_display.gif

同时串口打印温湿度数据

oled_aht10_print.gif

总结

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

您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

67

帖子

0

粉丝

27

主题

67

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部