feat: 添加AHT30温湿度传感器驱动及显示功能

实现AHT30温湿度传感器的I2C驱动
新增传感器任务定期读取数据
优化LCD显示界面,增加温湿度显示
添加I2C硬件和软件扫描功能
修复I2C引脚配置问题
This commit is contained in:
2026-02-23 23:00:00 +08:00
parent f5077adbe7
commit 43a5042c9e
7 changed files with 862 additions and 8 deletions

View File

@@ -0,0 +1,580 @@
/**
******************************************************************************
* @file bsp_aht30.c
* @brief AHT30温湿度传感器驱动实现
******************************************************************************
* @attention
* AHT30是一种高精度、低功耗的温湿度传感器支持I2C通信协议
******************************************************************************
*/
#include "bsp_aht30.h"
#include "cmsis_os.h"
#include "elog.h"
#include "i2c.h"
#include <string.h>
/* ================= 全局变量 ================= */
// AHT30设备实例
static AHT30_HandleTypeDef aht30_device = {0};
/* ================= 私有函数声明 ================= */
/**
* @brief I2C写命令
* @param cmd 命令数组
* @param len 命令长度
* @retval 1=成功, 0=失败
*/
static uint8_t AHT30_WriteCommand(uint8_t *cmd, uint8_t len);
/**
* @brief I2C读取数据
* @param data 数据缓冲区
* @param len 数据长度
* @retval 1=成功, 0=失败
*/
static uint8_t AHT30_ReadBytes(uint8_t *data, uint16_t len);
/**
* @brief 复位寄存器LibDriver标准方法
* @param addr 寄存器地址
* @retval 1=成功, 0=失败
*/
static uint8_t AHT30_ResetRegister(uint8_t addr);
/* ================= 私有函数实现 ================= */
/**
* @brief I2C写命令
*/
static uint8_t AHT30_WriteCommand(uint8_t *cmd, uint8_t len) {
if (HAL_I2C_Master_Transmit(aht30_device.hi2c,
(AHT30_I2C_ADDR << 1),
cmd, len, 500) == HAL_OK) {
return 1;
}
elog_e(AHT30_TAG, "I2C写命令失败, 地址: 0x%02X", AHT30_I2C_ADDR);
return 0;
}
/**
* @brief I2C读取数据
*/
static uint8_t AHT30_ReadBytes(uint8_t *data, uint16_t len) {
if (HAL_I2C_Master_Receive(aht30_device.hi2c,
(AHT30_I2C_ADDR << 1),
data, len, 500) == HAL_OK) {
return 1;
}
elog_e(AHT30_TAG, "I2C读取数据失败, 地址: 0x%02X", AHT30_I2C_ADDR);
return 0;
}
/* ================= 公共函数实现 ================= */
/**
* @brief 初始化AHT30传感器
*/
uint8_t AHT30_Init(I2C_HandleTypeDef *hi2c) {
if (!hi2c) {
elog_e(AHT30_TAG, "I2C句柄为空");
return 0;
}
memset(&aht30_device, 0, sizeof(AHT30_HandleTypeDef));
aht30_device.hi2c = hi2c;
elog_d(AHT30_TAG, "开始初始化AHT30传感器");
// 等待传感器上电稳定
osDelay(50);
// 读取初始状态
uint8_t status;
if (AHT30_ReadBytes(&status, 1)) {
elog_d(AHT30_TAG, "AHT30初始状态: 0x%02X", status);
}
// 检查校准使能位,如果未启用则执行复位校准
if ((status & 0x18) != 0x18) {
elog_w(AHT30_TAG, "AHT30未校准执行复位校准");
if (!AHT30_ResetRegister(0x1B)) {
elog_e(AHT30_TAG, "复位寄存器0x1B失败");
return 0;
}
if (!AHT30_ResetRegister(0x1C)) {
elog_e(AHT30_TAG, "复位寄存器0x1C失败");
return 0;
}
if (!AHT30_ResetRegister(0x1E)) {
elog_e(AHT30_TAG, "复位寄存器0x1E失败");
return 0;
}
}
osDelay(10);
aht30_device.initialized = 1;
elog_i(AHT30_TAG, "AHT30初始化成功");
return 1;
}
/**
* @brief 软复位AHT30传感器
*/
uint8_t AHT30_Reset(void) {
uint8_t cmd = AHT30_CMD_RESET;
if (!AHT30_WriteCommand(&cmd, 1)) {
elog_e(AHT30_TAG, "复位命令发送失败");
return 0;
}
// 等待复位完成
osDelay(20);
return 1;
}
/**
* @brief 复位寄存器LibDriver标准方法
*/
static uint8_t AHT30_ResetRegister(uint8_t addr) {
uint8_t buf[3];
uint8_t regs[3];
buf[0] = addr;
buf[1] = 0x00;
buf[2] = 0x00;
if (!AHT30_WriteCommand(buf, 3)) {
elog_e(AHT30_TAG, "写入地址0x%02X失败", addr);
return 0;
}
osDelay(5);
if (!AHT30_ReadBytes(regs, 3)) {
elog_e(AHT30_TAG, "读取寄存器失败");
return 0;
}
osDelay(10);
buf[0] = 0xB0 | addr;
buf[1] = regs[1];
buf[2] = regs[2];
if (!AHT30_WriteCommand(buf, 3)) {
elog_e(AHT30_TAG, "恢复寄存器失败");
return 0;
}
return 1;
}
/**
* @brief 校准AHT30传感器
*/
uint8_t AHT30_Calibrate(void) {
uint8_t cmd[3] = {AHT30_CMD_CALIBRATE, 0x08, 0x00};
if (!AHT30_WriteCommand(cmd, 3)) {
elog_e(AHT30_TAG, "校准命令发送失败");
return 0;
}
// 等待校准完成
osDelay(300);
// 读取校准状态
uint8_t status;
if (AHT30_ReadBytes(&status, 1)) {
if (status & 0x08) {
return 1;
} else {
elog_e(AHT30_TAG, "AHT30校准失败状态: 0x%02X", status);
return 0;
}
}
elog_e(AHT30_TAG, "无法读取校准状态");
return 0;
}
/**
* @brief 读取AHT30温湿度数据
*/
uint8_t AHT30_ReadData(AHT30_Data_t *data) {
uint8_t cmd[3] = {AHT30_CMD_MEASURE, 0x33, 0x00};
uint8_t recv[7] = {0};
if (!data) {
elog_e(AHT30_TAG, "数据指针为空");
return 0;
}
// 发送测量命令
if (!AHT30_WriteCommand(cmd, 3)) {
elog_e(AHT30_TAG, "测量命令发送失败");
return 0;
}
// 等待测量完成
osDelay(AHT30_MEASUREMENT_DELAY);
// 读取测量数据
if (!AHT30_ReadBytes(recv, 7)) {
elog_e(AHT30_TAG, "测量数据读取失败");
return 0;
}
// CRC校验
uint8_t crc = AHT30_CRC8(&recv[0], 6);
if (crc != recv[6]) {
elog_e(AHT30_TAG, "CRC校验失败计算值: 0x%02X, 接收值: 0x%02X", crc, recv[6]);
return 0;
}
// 检查状态位
if (recv[0] & 0x80) {
elog_e(AHT30_TAG, "设备忙");
return 0;
}
if (!(recv[0] & 0x08)) {
elog_e(AHT30_TAG, "数据无效");
return 0;
}
// 解析湿度数据 (20位)
uint32_t hum_raw = ((uint32_t)recv[1] << 12) |
((uint32_t)recv[2] << 4) |
(recv[3] >> 4);
data->humidity = (float)hum_raw / 1048576.0f * 100.0f;
// 解析温度数据 (20位)
uint32_t temp_raw = ((uint32_t)(recv[3] & 0x0F) << 16) |
((uint32_t)recv[4] << 8) |
recv[5];
data->temperature = (float)temp_raw / 1048576.0f * 200.0f - 50.0f;
data->valid = 1;
data->timestamp = osKernelGetTickCount();
// 更新设备缓存
memcpy(&aht30_device.data, data, sizeof(AHT30_Data_t));
return 1;
}
/**
* @brief 获取最新的温湿度数据
*/
AHT30_Data_t* AHT30_GetData(void) {
return &aht30_device.data;
}
/**
* @brief 检查AHT30是否已初始化
*/
uint8_t AHT30_IsInitialized(void) {
return aht30_device.initialized;
}
/**
* @brief 扫描I2C设备
*/
void AHT30_ScanI2C(I2C_HandleTypeDef *hi2c) {
if (!hi2c) {
elog_e(AHT30_TAG, "I2C句柄为空");
return;
}
elog_i(AHT30_TAG, "开始扫描I2C设备...");
elog_i(AHT30_TAG, "I2C句柄: 0x%p", (void*)hi2c);
// 检查GPIO状态
GPIO_PinState scl = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6);
GPIO_PinState sda = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);
elog_i(AHT30_TAG, "GPIO状态 - SCL(PB6): %d, SDA(PB7): %d", scl, sda);
if (scl == GPIO_PIN_RESET && sda == GPIO_PIN_RESET) {
elog_w(AHT30_TAG, "警告: SCL和SDA都是低电平可能被短路");
}
uint8_t found_count = 0;
for (uint8_t addr = 1; addr < 128; addr++) {
HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(hi2c, addr << 1, 3, 100);
if (status == HAL_OK) {
elog_i(AHT30_TAG, "发现I2C设备: 0x%02X (8位: 0x%02X)", addr, addr << 1);
found_count++;
}
}
if (found_count == 0) {
elog_w(AHT30_TAG, "未发现任何I2C设备请检查:");
elog_w(AHT30_TAG, " 1. 硬件连接 (SCL->PB6, SDA->PB7)");
elog_w(AHT30_TAG, " 2. 电源供电 (VCC->3.3V, GND->GND)");
elog_w(AHT30_TAG, " 3. 上拉电阻 (4.7kΩ 到 3.3V)");
elog_w(AHT30_TAG, " 4. I2C地址是否正确");
} else {
elog_i(AHT30_TAG, "共发现 %d 个I2C设备", found_count);
}
}
/**
* @brief 软件I2C扫描备用方案
*/
void AHT30_ScanI2C_Soft(void) {
elog_i(AHT30_TAG, "使用软件I2C扫描...");
// 配置为输出模式(推挽输出)
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// 设置为高电平
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
uint8_t found_count = 0;
// 简单软件I2C扫描
for (uint8_t addr = 0; addr < 128; addr++) {
// 开始条件
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
osDelay(1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
osDelay(1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
osDelay(1);
// 发送地址
for (uint8_t i = 0; i < 8; i++) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
if (addr & (0x80 >> i)) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
}
osDelay(1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
osDelay(1);
}
// 读取ACK
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
osDelay(1);
// 切换SDA为输入
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_PinState ack = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
osDelay(1);
// 恢复SDA为输出
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// 停止条件
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET);
osDelay(1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
osDelay(1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);
osDelay(1);
if (ack == GPIO_PIN_RESET) {
elog_i(AHT30_TAG, "软件I2C发现设备: 0x%02X", addr);
found_count++;
}
}
elog_i(AHT30_TAG, "软件I2C扫描完成发现 %d 个设备", found_count);
// 恢复I2C模式
MX_I2C1_Init();
}
/**
* @brief AHT30 CRC8校验
*/
uint8_t AHT30_CRC8(uint8_t *data, uint8_t len) {
uint8_t i;
uint8_t byte;
uint8_t crc = 0xFF;
for (byte = 0; byte < len; byte++) {
crc ^= data[byte];
for (i = 8; i > 0; --i) {
if ((crc & 0x80) != 0) {
crc = (crc << 1) ^ 0x31;
} else {
crc = crc << 1;
}
}
}
return crc;
}
/**
* @brief 读取AHT30状态
*/
uint8_t AHT30_GetStatus(uint8_t *status) {
if (!status) {
elog_e(AHT30_TAG, "状态指针为空");
return 0;
}
if (!AHT30_ReadBytes(status, 1)) {
elog_e(AHT30_TAG, "读取状态失败");
return 0;
}
return 1;
}
/**
* @brief 仅读取温度数据
*/
uint8_t AHT30_ReadTemperature(float *temperature) {
uint8_t cmd[3] = {AHT30_CMD_MEASURE, 0x33, 0x00};
uint8_t recv[7] = {0};
uint32_t temp_raw;
if (!temperature) {
elog_e(AHT30_TAG, "温度指针为空");
return 0;
}
if (!AHT30_WriteCommand(cmd, 3)) {
elog_e(AHT30_TAG, "测量命令发送失败");
return 0;
}
osDelay(AHT30_MEASUREMENT_DELAY);
if (!AHT30_ReadBytes(recv, 7)) {
elog_e(AHT30_TAG, "测量数据读取失败");
return 0;
}
if (recv[0] & AHT30_STATUS_BUSY) {
elog_e(AHT30_TAG, "设备忙");
return 0;
}
if (AHT30_CRC8(recv, 6) != recv[6]) {
elog_e(AHT30_TAG, "CRC校验失败");
return 0;
}
temp_raw = ((uint32_t)recv[3] << 16) |
((uint32_t)recv[4] << 8) |
(uint32_t)recv[5];
temp_raw = temp_raw & 0xFFFFF;
*temperature = (float)temp_raw / 1048576.0f * 200.0f - 50.0f;
return 1;
}
/**
* @brief 仅读取湿度数据
*/
uint8_t AHT30_ReadHumidity(float *humidity) {
uint8_t cmd[3] = {AHT30_CMD_MEASURE, 0x33, 0x00};
uint8_t recv[7] = {0};
uint32_t hum_raw;
if (!humidity) {
elog_e(AHT30_TAG, "湿度指针为空");
return 0;
}
if (!AHT30_WriteCommand(cmd, 3)) {
elog_e(AHT30_TAG, "测量命令发送失败");
return 0;
}
osDelay(AHT30_MEASUREMENT_DELAY);
if (!AHT30_ReadBytes(recv, 7)) {
elog_e(AHT30_TAG, "测量数据读取失败");
return 0;
}
if (recv[0] & AHT30_STATUS_BUSY) {
elog_e(AHT30_TAG, "设备忙");
return 0;
}
if (AHT30_CRC8(recv, 6) != recv[6]) {
elog_e(AHT30_TAG, "CRC校验失败");
return 0;
}
hum_raw = ((uint32_t)recv[1] << 16) |
((uint32_t)recv[2] << 8) |
(uint32_t)recv[3];
hum_raw = hum_raw >> 4;
*humidity = (float)hum_raw / 1048576.0f * 100.0f;
return 1;
}
/**
* @brief 写寄存器(扩展功能)
*/
uint8_t AHT30_SetReg(uint8_t *buf, uint16_t len) {
if (!buf || len == 0) {
elog_e(AHT30_TAG, "无效参数");
return 0;
}
return AHT30_WriteCommand(buf, len);
}
/**
* @brief 读寄存器(扩展功能)
*/
uint8_t AHT30_GetReg(uint8_t *buf, uint16_t len) {
if (!buf || len == 0) {
elog_e(AHT30_TAG, "无效参数");
return 0;
}
return AHT30_ReadBytes(buf, len);
}
/**
* @brief 获取芯片信息
*/
uint8_t AHT30_GetInfo(AHT30_Info_t *info) {
if (!info) {
elog_e(AHT30_TAG, "信息指针为空");
return 0;
}
memset(info, 0, sizeof(AHT30_Info_t));
strncpy(info->chip_name, "ASAIR AHT30", 32);
strncpy(info->manufacturer_name, "ASAIR", 32);
strncpy(info->interface, "IIC", 8);
info->supply_voltage_min = 2.2f;
info->supply_voltage_max = 5.5f;
info->max_current = 0.60f;
info->temperature_min = -40.0f;
info->temperature_max = 85.0f;
return 1;
}

View File

@@ -0,0 +1,193 @@
/**
******************************************************************************
* @file bsp_aht30.h
* @brief AHT30温湿度传感器驱动头文件
******************************************************************************
* @attention
* AHT30是一种高精度、低功耗的温湿度传感器支持I2C通信协议
* I2C地址: 0x70 (7位地址8位地址为0xE0/0xE1)
******************************************************************************
*/
#ifndef __BSP_AHT30_H__
#define __BSP_AHT30_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f1xx_hal.h"
#include <stdint.h>
#include "main.h"
/* ================= 宏定义 ================= */
// AHT30 I2C地址
#define AHT30_I2C_ADDR 0x38 // 7位地址 (8位地址为0x70)
// AHT30命令定义
#define AHT30_CMD_CALIBRATE 0xE1 // 校准命令
#define AHT30_CMD_RESET 0xBA // 复位命令
#define AHT30_CMD_MEASURE 0xAC // 测量命令
#define AHT30_CMD_NORMAL_CMD1 0xA8 // 正常测量命令1
#define AHT30_CMD_NORMAL_CMD2 0x00 // 正常测量命令2
#define AHT30_CMD_NORMAL_CMD3 0x00 // 正常测量命令3
// AHT30测量参数
#define AHT30_MEASUREMENT_DELAY 85 // 测量等待时间(ms)
// AHT30状态位定义
#define AHT30_STATUS_BUSY (1 << 7) // 忙标志
#define AHT30_STATUS_NOR_MODE (0 << 5) // 正常模式
#define AHT30_STATUS_CYC_MODE (1 << 5) // 循环模式
#define AHT30_STATUS_CMD_MODE (2 << 5) // 命令模式
#define AHT30_STATUS_CRC_FLAG (1 << 4) // CRC标志
#define AHT30_STATUS_CAL_EN (1 << 3) // 校准使能
#define AHT30_STATUS_CMP_INT (1 << 2) // 比较中断
// 日志标签
#define AHT30_TAG "AHT30"
/* ================= 数据结构定义 ================= */
/**
* @brief AHT30温湿度数据结构体
*/
typedef struct {
float temperature; // 温度值(℃)
float humidity; // 湿度值(%RH)
uint8_t valid; // 数据有效标志: 1=有效, 0=无效
uint32_t timestamp; // 数据时间戳(ms)
} AHT30_Data_t;
/**
* @brief AHT30设备结构体
*/
typedef struct {
I2C_HandleTypeDef *hi2c; // I2C句柄
AHT30_Data_t data; // 传感器数据
uint8_t initialized; // 初始化标志
} AHT30_HandleTypeDef;
/**
* @brief AHT30芯片信息结构体
*/
typedef struct {
char chip_name[32]; // 芯片名称
char manufacturer_name[32]; // 制造商名称
char interface[8]; // 通信接口
float supply_voltage_min; // 最小供电电压
float supply_voltage_max; // 最大供电电压
float max_current; // 最大电流
float temperature_min; // 最小工作温度
float temperature_max; // 最大工作温度
} AHT30_Info_t;
/* ================= 函数声明 ================= */
/**
* @brief 初始化AHT30传感器
* @param hi2c I2C句柄指针
* @retval 1=成功, 0=失败
*/
uint8_t AHT30_Init(I2C_HandleTypeDef *hi2c);
/**
* @brief 软复位AHT30传感器
* @retval 1=成功, 0=失败
*/
uint8_t AHT30_Reset(void);
/**
* @brief 校准AHT30传感器
* @retval 1=成功, 0=失败
*/
uint8_t AHT30_Calibrate(void);
/**
* @brief 读取AHT30温湿度数据
* @param data 数据存储指针
* @retval 1=成功, 0=失败
*/
uint8_t AHT30_ReadData(AHT30_Data_t *data);
/**
* @brief 获取最新的温湿度数据
* @return AHT30数据结构体指针
*/
AHT30_Data_t* AHT30_GetData(void);
/**
* @brief 检查AHT30是否已初始化
* @retval 1=已初始化, 0=未初始化
*/
uint8_t AHT30_IsInitialized(void);
/**
* @brief 读取AHT30状态
* @param status 状态存储指针
* @retval 1=成功, 0=失败
*/
uint8_t AHT30_GetStatus(uint8_t *status);
/**
* @brief 仅读取温度数据
* @param temperature 温度存储指针
* @retval 1=成功, 0=失败
*/
uint8_t AHT30_ReadTemperature(float *temperature);
/**
* @brief 仅读取湿度数据
* @param humidity 湿度存储指针
* @retval 1=成功, 0=失败
*/
uint8_t AHT30_ReadHumidity(float *humidity);
/**
* @brief 写寄存器(扩展功能)
* @param buf 数据缓冲区
* @param len 数据长度
* @retval 1=成功, 0=失败
*/
uint8_t AHT30_SetReg(uint8_t *buf, uint16_t len);
/**
* @brief 读寄存器(扩展功能)
* @param buf 数据缓冲区
* @param len 数据长度
* @retval 1=成功, 0=失败
*/
uint8_t AHT30_GetReg(uint8_t *buf, uint16_t len);
/**
* @brief 获取芯片信息
* @param info 信息结构体指针
* @retval 1=成功, 0=失败
*/
uint8_t AHT30_GetInfo(AHT30_Info_t *info);
/**
* @brief 扫描I2C设备调试用
* @param hi2c I2C句柄指针
*/
void AHT30_ScanI2C(I2C_HandleTypeDef *hi2c);
/**
* @brief 软件I2C扫描硬件I2C失败时使用
*/
void AHT30_ScanI2C_Soft(void);
/**
* @brief AHT30 CRC8校验
* @param data 数据指针
* @param len 数据长度
* @return CRC校验值
*/
uint8_t AHT30_CRC8(uint8_t *data, uint8_t len);
#ifdef __cplusplus
}
#endif
#endif /* __BSP_AHT30_H__ */

View File

@@ -243,6 +243,7 @@ extern SPI_HandleTypeDef ST7735_SPI_PORT;
#define ST7735_CYAN 0x07FF // 青色
#define ST7735_MAGENTA 0xF81F // 洋红
#define ST7735_YELLOW 0xFFE0 // 黄色
#define ST7735_ORANGE 0xFD20 // 橙色
#define ST7735_WHITE 0xFFFF // 白色
#define ST7735_COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))

View File

@@ -33,6 +33,8 @@
#include "multi_button.h"
#include "spi_st7735s.h"
#include "stdio.h"
#include "bsp_aht30.h"
#include "i2c.h"
/* USER CODE END Includes */
@@ -110,6 +112,13 @@ const osThreadAttr_t button_attributes = {
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityRealtime2,
};
/* Definitions for sensor */
osThreadId_t sensorHandle;
const osThreadAttr_t sensor_attributes = {
.name = "sensor",
.stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
@@ -127,6 +136,7 @@ void StartDefaultTask(void *argument);
extern void wifi_task_mqtt(void *argument);
void LCD_Task(void *argument);
void button_task(void *argument);
void sensorTask(void *argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
@@ -169,6 +179,9 @@ void MX_FREERTOS_Init(void) {
/* creation of button */
buttonHandle = osThreadNew(button_task, NULL, &button_attributes);
/* creation of sensor */
sensorHandle = osThreadNew(sensorTask, NULL, &sensor_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
@@ -279,13 +292,13 @@ void LCD_Task(void *argument)
ST7735_FillScreen(bg_color);
ST7735_WriteString(2, 2, "Temp & Humi", &Font_7x10, text_color, bg_color);
// 显示温度
snprintf(display_str, sizeof(display_str), "T: %.1f C", sensor_data.temperature);
ST7735_WriteString(5, 20, display_str, &Font_11x18, text_color, bg_color);
// 显示温度(橙色 - 国际标准温度色)
snprintf(display_str, sizeof(display_str), "T: %.2f C", sensor_data.temperature);
ST7735_WriteString(5, 20, display_str, &Font_11x18, ST7735_ORANGE, bg_color);
// 显示湿度
snprintf(display_str, sizeof(display_str), "H: %.1f %%", sensor_data.humidity);
ST7735_WriteString(5, 45, display_str, &Font_11x18, text_color, bg_color);
// 显示湿度(青色 - 国际标准湿度色)
snprintf(display_str, sizeof(display_str), "H: %.2f %%", sensor_data.humidity);
ST7735_WriteString(5, 45, display_str, &Font_11x18, ST7735_CYAN, bg_color);
break;
case LCD_PAGE_FOOD_WEIGHT:
@@ -357,7 +370,7 @@ void LCD_Task(void *argument)
}
} else {
// 其他页面1秒刷新一次
osDelay(1000);
osDelay(2000);
}
}
/* USER CODE END LCD_Task */
@@ -384,6 +397,65 @@ void button_task(void *argument)
/* USER CODE END button_task */
}
/* USER CODE BEGIN Header_sensorTask */
/**
* @brief Function implementing the sensor thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_sensorTask */
void sensorTask(void *argument)
{
/* USER CODE BEGIN sensorTask */
elog_i(TAG, "启动传感器任务");
// 扫描I2C设备调试
AHT30_ScanI2C(&hi2c1);
// 如果硬件I2C扫描失败尝试软件I2C
uint8_t found = 0;
for (uint8_t addr = 1; addr < 128; addr++) {
if (HAL_I2C_IsDeviceReady(&hi2c1, addr << 1, 1, 50) == HAL_OK) {
found = 1;
break;
}
}
if (!found) {
elog_w(TAG, "硬件I2C未发现设备尝试软件I2C扫描...");
AHT30_ScanI2C_Soft();
}
// 初始化AHT30温湿度传感器
elog_i(TAG, "初始化AHT30温湿度传感器");
if (AHT30_Init(&hi2c1)) {
elog_i(TAG, "AHT30初始化成功");
} else {
elog_e(TAG, "AHT30初始化失败");
}
/* Infinite loop */
for(;;)
{
// 读取温湿度数据
AHT30_Data_t aht30_data;
if (AHT30_ReadData(&aht30_data)) {
// 数据读取成功更新sensor_data
sensor_data.temperature = aht30_data.temperature;
sensor_data.humidity = aht30_data.humidity;
elog_d(TAG, "温湿度数据 - 温度: %.2f℃, 湿度: %.2f%%",
aht30_data.temperature, aht30_data.humidity);
} else {
elog_w(TAG, "AHT30数据读取失败");
}
// 每2秒读取一次
osDelay(2000);
}
/* USER CODE END sensorTask */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

View File

@@ -74,6 +74,7 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* I2C1 clock enable */