feat: 添加HX711称重传感器支持并清理旧文档
- 新增HX711称重传感器驱动(bsp_hx711.c/h) - 添加HX711相关文档和README - 更新MP3驱动和FreeRTOS配置 - 修改CMakeLists.txt构建配置 - 删除旧的DX-WF24 WiFi模块开发文档和示例代码 - 整理Development_Docs目录结构
This commit is contained in:
46
Core/Bsp/BSP_Device/bsp_hx711/README.md
Normal file
46
Core/Bsp/BSP_Device/bsp_hx711/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# HX711 称重传感器驱动
|
||||
|
||||
## 目录结构
|
||||
- `bsp_hx711.h` - 驱动头文件
|
||||
- `bsp_hx711.c` - 驱动源文件
|
||||
- `README.md` - 说明文档
|
||||
|
||||
## 功能特性
|
||||
- 支持HX711称重传感器的基本操作
|
||||
- 提供单次读取和多次平均读取功能
|
||||
- 支持校准功能
|
||||
- 支持重量计算
|
||||
|
||||
## 硬件连接
|
||||
- HX711_SCK -> PA3
|
||||
- HX711_DOUT -> PA2
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 1. 初始化
|
||||
```c
|
||||
HX711_Init();
|
||||
```
|
||||
|
||||
### 2. 校准
|
||||
```c
|
||||
float calibration_factor = 0.0f;
|
||||
HX711_Calibration(&calibration_factor);
|
||||
```
|
||||
|
||||
### 3. 读取重量
|
||||
```c
|
||||
float weight = HX711_GetWeight(calibration_factor, 10);
|
||||
elog_info("HX711","重量: %.2fg\r\n", weight);
|
||||
```
|
||||
|
||||
### 4. 直接读取原始数据
|
||||
```c
|
||||
uint32_t raw_data = HX711_ReadData(HX711_GAIN_128);
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
- GPIO初始化已在gpio.c中完成,无需重复初始化
|
||||
- 校准过程需要放置已知重量的物体
|
||||
- 建议使用多次采样平均以提高精度
|
||||
- 增益设置建议使用HX711_GAIN_128以获得最高精度
|
||||
96
Core/Bsp/BSP_Device/bsp_hx711/bsp_hx711.c
Normal file
96
Core/Bsp/BSP_Device/bsp_hx711/bsp_hx711.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "bsp_hx711.h"
|
||||
|
||||
// 全局变量(零点偏移值、标定系数)
|
||||
int32_t hx711_zero_offset = 0; // 零点偏移(空载时的AD值)
|
||||
float hx711_scale = 0.002762; // 标定系数(重量/AD差值)
|
||||
// #################### 基础函数 ####################
|
||||
|
||||
void delay_us(uint32_t us) {
|
||||
uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
|
||||
while (delay--) {
|
||||
;
|
||||
}
|
||||
}
|
||||
// 初始化HX711引脚(SCK输出,DOUT输入)
|
||||
void HX711_Init(void) {
|
||||
|
||||
}
|
||||
// 读取单次AD原始数据(gain:增益选择)
|
||||
int32_t HX711_ReadData(uint8_t gain) {
|
||||
int32_t data = 0;
|
||||
uint8_t i = 0;
|
||||
// 等待数据就绪(DOUT变低)
|
||||
while (HAL_GPIO_ReadPin(HX711_DOUT_GPIO_Port, HX711_DOUT_Pin) == GPIO_PIN_SET);
|
||||
// 读取24位数据(先MSB后LSB)
|
||||
for (i = 0; i < 24; i++) {
|
||||
// 发送时钟脉冲(SCK高电平)
|
||||
HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_SET);
|
||||
delay_us(1); // 延时1us,保证时序稳定(关键!)
|
||||
// 移位读取数据(DOUT为当前位)
|
||||
data |= (HAL_GPIO_ReadPin(HX711_DOUT_GPIO_Port, HX711_DOUT_Pin) << (23 - i));
|
||||
// 时钟脉冲拉低
|
||||
HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_RESET);
|
||||
delay_us(1);
|
||||
}
|
||||
// 发送增益选择脉冲(1~3个)
|
||||
for (i = 0; i < gain; i++) {
|
||||
HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_SET);
|
||||
delay_us(1);
|
||||
HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_RESET);
|
||||
delay_us(1);
|
||||
}
|
||||
// 处理24位有符号数据(HX711输出为二进制补码)
|
||||
if (data & 0x800000) { // 最高位为1表示负数,转换为十进制
|
||||
data |= ~0xFFFFFF; // 扩展符号位到32位(int32_t)
|
||||
}
|
||||
return data;
|
||||
}
|
||||
// #################### 校准与重量计算 ####################
|
||||
// 校准零点(空载时调用,消除传感器自重误差)
|
||||
void HX711_CalibrateZero(void) {
|
||||
uint8_t i = 0;
|
||||
int32_t temp = 0;
|
||||
hx711_zero_offset = 0;
|
||||
// 采样10次取平均值(提高零点精度)
|
||||
for (i = 0; i < 10; i++) {
|
||||
temp += HX711_ReadData(HX711_GAIN_128);
|
||||
HAL_Delay(10); // 采样间隔
|
||||
}
|
||||
hx711_zero_offset = temp / 10; // 零点偏移值 = 空载平均AD值
|
||||
}
|
||||
// 标定量程(放已知重量的物体后调用,计算AD值与重量的比例)
|
||||
void HX711_CalibrateScale(float weight) {
|
||||
uint8_t i = 0;
|
||||
int32_t temp = 0;
|
||||
int32_t ad_diff = 0;
|
||||
// 采样10次取平均AD值
|
||||
for (i = 0; i < 10; i++) {
|
||||
temp += HX711_ReadData(HX711_GAIN_128);
|
||||
HAL_Delay(10);
|
||||
}
|
||||
temp = temp / 10;
|
||||
// 计算AD差值(加载后AD值 - 零点AD值)
|
||||
ad_diff = temp - hx711_zero_offset;
|
||||
if (ad_diff <= 0) {
|
||||
hx711_scale = 1.0f; // 异常情况,避免除零
|
||||
return;
|
||||
}
|
||||
// 标定系数 = 已知重量 / AD差值(后续通过AD差值计算重量)
|
||||
hx711_scale = weight / (float)ad_diff;
|
||||
}
|
||||
// 获取重量(sample_num:采样次数,次数越多精度越高,推荐10~20次)
|
||||
float HX711_GetWeight(uint8_t sample_num) {
|
||||
uint8_t i = 0;
|
||||
int32_t temp = 0;
|
||||
float weight = 0.0f;
|
||||
if (sample_num == 0) sample_num = 1; // 避免采样次数为0
|
||||
// 多次采样取平均
|
||||
for (i = 0; i < sample_num; i++) {
|
||||
temp += HX711_ReadData(HX711_GAIN_128);
|
||||
HAL_Delay(5);
|
||||
}
|
||||
temp = temp / sample_num; // 平均AD值
|
||||
// 计算重量 = (当前AD值 - 零点偏移) * 标定系数
|
||||
weight = (temp - hx711_zero_offset) * hx711_scale;
|
||||
return weight;
|
||||
}
|
||||
26
Core/Bsp/BSP_Device/bsp_hx711/bsp_hx711.h
Normal file
26
Core/Bsp/BSP_Device/bsp_hx711/bsp_hx711.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef __HX711_H
|
||||
#define __HX711_H
|
||||
#include "stm32f1xx_hal.h"
|
||||
#include "stdio.h"
|
||||
// #################### 引脚定义(根据你的硬件修改!)####################
|
||||
#define HX711_SCK_GPIO_Port GPIOA
|
||||
#define HX711_SCK_Pin GPIO_PIN_3
|
||||
#define HX711_DOUT_GPIO_Port GPIOA
|
||||
#define HX711_DOUT_Pin GPIO_PIN_2
|
||||
|
||||
// 全局变量(零点偏移值、标定系数)
|
||||
extern int32_t hx711_zero_offset; // 零点偏移(空载时的AD值)
|
||||
extern float hx711_scale; // 标定系数(重量/AD差值)
|
||||
|
||||
|
||||
// 增益选择(默认用通道A+128倍增益)
|
||||
#define HX711_GAIN_128 1 // 通道A,128倍增益(推荐)
|
||||
#define HX711_GAIN_64 2 // 通道A,64倍增益
|
||||
#define HX711_GAIN_32 3 // 通道B,32倍增益
|
||||
// 函数声明
|
||||
void HX711_Init(void); // 初始化(引脚配置)
|
||||
int32_t HX711_ReadData(uint8_t gain); // 读取原始AD数据
|
||||
void HX711_CalibrateZero(void); // 校准零点(空载时调用)
|
||||
void HX711_CalibrateScale(float weight); // 标定量程(放已知重量时调用)
|
||||
float HX711_GetWeight(uint8_t sample_num); // 获取平均重量(sample_num:采样次数)
|
||||
#endif
|
||||
@@ -59,8 +59,7 @@ HAL_StatusTypeDef MP3_Init(void)
|
||||
HAL_StatusTypeDef ret1 = MP3_SendCommand(init_cmd1, sizeof(init_cmd1));
|
||||
elog_d("MP3", "开启声音命令返回值: %d", ret1);
|
||||
|
||||
// 设置为低音量-测试用
|
||||
MP3_SetVolume(2);
|
||||
|
||||
|
||||
// 延时等待模块响应
|
||||
HAL_Delay(100);
|
||||
|
||||
@@ -19,24 +19,26 @@
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "main.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "cmsis_os2.h"
|
||||
#include "main.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "bsp_aht30.h"
|
||||
#include "bsp_hx711.h"
|
||||
#include "bsp_rtc.h"
|
||||
#include "device_ctrl.h"
|
||||
#include "dx_wf_24.h"
|
||||
#include "elog.h"
|
||||
#include "i2c.h"
|
||||
#include "mp3_driver.h"
|
||||
#include "mp3_play_index.h"
|
||||
#include "multi_button.h"
|
||||
#include "spi_st7735s.h"
|
||||
#include "stdio.h"
|
||||
#include "bsp_aht30.h"
|
||||
#include "bsp_rtc.h"
|
||||
#include "i2c.h"
|
||||
#include "stepper_motor.h" // 添加步进电机驱动头文件
|
||||
#include "stepper_motor.h" // 添加步进电机驱动头文件
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
@@ -53,9 +55,10 @@
|
||||
#define KEY2_MANUAL_FEED // 按键2:手动喂食(仅手动模式有效)
|
||||
#define KEY3_DISPLAY_NEXT // 按键3:切换显示界面
|
||||
#define KEY4_TIME_SET // 按键4:长按设置时间
|
||||
/***********************人体存在和水位检测作为两个单独的按键(GPIO输入)******************* */
|
||||
#define KEY_WATER_LEVEL // 水位检测
|
||||
#define KEY_BODY_EXIST // 人体存在
|
||||
/***********************人体存在和水位检测作为两个单独的按键(GPIO输入)*******************
|
||||
*/
|
||||
#define KEY_WATER_LEVEL // 水位检测
|
||||
#define KEY_BODY_EXIST // 人体存在
|
||||
|
||||
/* USER CODE END PD */
|
||||
|
||||
@@ -87,67 +90,68 @@ typedef struct {
|
||||
|
||||
// 喂食控制命令枚举
|
||||
typedef enum {
|
||||
FEED_CMD_NONE = 0, // 无命令
|
||||
FEED_CMD_MANUAL, // 手动喂食
|
||||
FEED_CMD_AUTO, // 自动喂食
|
||||
FEED_CMD_REMOTE, // 远程喂食
|
||||
FEED_CMD_TEST // 测试喂食
|
||||
FEED_CMD_NONE = 0, // 无命令
|
||||
FEED_CMD_MANUAL, // 手动喂食
|
||||
FEED_CMD_AUTO, // 自动喂食
|
||||
FEED_CMD_REMOTE, // 远程喂食
|
||||
FEED_CMD_TEST // 测试喂食
|
||||
} Feed_Cmd_t;
|
||||
|
||||
// 全局变量
|
||||
static LCD_Page_t current_page = LCD_PAGE_TIME; // 当前显示页面
|
||||
static Sensor_Data_t sensor_data = {0}; // 传感器数据
|
||||
static volatile uint8_t lcd_force_refresh = 0; // 强制刷新标志(RTC更新时设置)
|
||||
static volatile uint8_t system_mode = 1; // 系统模式:1=自动模式,0=手动模式(全局变量)
|
||||
static volatile uint8_t lcd_force_refresh = 0; // 强制刷新标志(RTC更新时设置)
|
||||
static volatile uint8_t system_mode =
|
||||
1; // 系统模式:1=自动模式,0=手动模式(全局变量)
|
||||
static volatile uint8_t feeding_in_progress = 0; // 喂食进行中标志
|
||||
|
||||
// 喂食控制相关全局变量
|
||||
static volatile Feed_Cmd_t feed_command = FEED_CMD_NONE; // 喂食命令标志
|
||||
static volatile uint16_t feed_angle = 90; // 喂食角度(默认90度)
|
||||
static volatile uint8_t feed_amount = 1; // 喂食份数
|
||||
static volatile Feed_Cmd_t feed_command = FEED_CMD_NONE; // 喂食命令标志
|
||||
static volatile uint16_t feed_angle = 90; // 喂食角度(默认90度)
|
||||
static volatile uint8_t feed_amount = 1; // 喂食份数
|
||||
|
||||
/* USER CODE END Variables */
|
||||
/* Definitions for defaultTask */
|
||||
osThreadId_t defaultTaskHandle;
|
||||
const osThreadAttr_t defaultTask_attributes = {
|
||||
.name = "defaultTask",
|
||||
.stack_size = 256 * 4,
|
||||
.priority = (osPriority_t) osPriorityHigh1,
|
||||
.name = "defaultTask",
|
||||
.stack_size = 256 * 4,
|
||||
.priority = (osPriority_t)osPriorityHigh1,
|
||||
};
|
||||
/* Definitions for wifi_mqtt */
|
||||
osThreadId_t wifi_mqttHandle;
|
||||
const osThreadAttr_t wifi_mqtt_attributes = {
|
||||
.name = "wifi_mqtt",
|
||||
.stack_size = 3000 * 4,
|
||||
.priority = (osPriority_t) osPriorityHigh,
|
||||
.name = "wifi_mqtt",
|
||||
.stack_size = 3000 * 4,
|
||||
.priority = (osPriority_t)osPriorityHigh,
|
||||
};
|
||||
/* Definitions for LCD_SHOW_Task */
|
||||
osThreadId_t LCD_SHOW_TaskHandle;
|
||||
const osThreadAttr_t LCD_SHOW_Task_attributes = {
|
||||
.name = "LCD_SHOW_Task",
|
||||
.stack_size = 1024 * 4,
|
||||
.priority = (osPriority_t) osPriorityHigh,
|
||||
.name = "LCD_SHOW_Task",
|
||||
.stack_size = 1024 * 4,
|
||||
.priority = (osPriority_t)osPriorityHigh,
|
||||
};
|
||||
/* Definitions for button */
|
||||
osThreadId_t buttonHandle;
|
||||
const osThreadAttr_t button_attributes = {
|
||||
.name = "button",
|
||||
.stack_size = 512 * 4,
|
||||
.priority = (osPriority_t) osPriorityRealtime2,
|
||||
.name = "button",
|
||||
.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,
|
||||
.name = "sensor",
|
||||
.stack_size = 1024 * 4,
|
||||
.priority = (osPriority_t)osPriorityNormal,
|
||||
};
|
||||
/* Definitions for step_motor */
|
||||
osThreadId_t step_motorHandle;
|
||||
const osThreadAttr_t step_motor_attributes = {
|
||||
.name = "step_motor",
|
||||
.stack_size = 512 * 4,
|
||||
.priority = (osPriority_t) osPriorityNormal,
|
||||
.name = "step_motor",
|
||||
.stack_size = 512 * 4,
|
||||
.priority = (osPriority_t)osPriorityNormal,
|
||||
};
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
@@ -160,7 +164,7 @@ void LCD_UpdateSensorData(float temp, float humi, float weight, uint8_t water,
|
||||
uint8_t mode);
|
||||
Sensor_Data_t *LCD_GetSensorData(void);
|
||||
void user_button_init(void);
|
||||
void RTC_TimeUpdateCallback(void); // RTC时间更新回调函数
|
||||
void RTC_TimeUpdateCallback(void); // RTC时间更新回调函数
|
||||
/* USER CODE END FunctionPrototypes */
|
||||
|
||||
void StartDefaultTask(void *argument);
|
||||
@@ -173,16 +177,14 @@ void step_motor_task(void *argument);
|
||||
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
|
||||
|
||||
/**
|
||||
* @brief FreeRTOS initialization
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
* @brief FreeRTOS initialization
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void MX_FREERTOS_Init(void) {
|
||||
/* USER CODE BEGIN Init */
|
||||
ST7735_Init(); // 初始化ST7735显示屏
|
||||
|
||||
|
||||
|
||||
/* USER CODE END Init */
|
||||
|
||||
/* USER CODE BEGIN RTOS_MUTEX */
|
||||
@@ -203,7 +205,8 @@ void MX_FREERTOS_Init(void) {
|
||||
|
||||
/* Create the thread(s) */
|
||||
/* creation of defaultTask */
|
||||
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
|
||||
defaultTaskHandle =
|
||||
osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
|
||||
|
||||
/* creation of wifi_mqtt */
|
||||
wifi_mqttHandle = osThreadNew(wifi_task_mqtt, NULL, &wifi_mqtt_attributes);
|
||||
@@ -227,7 +230,6 @@ void MX_FREERTOS_Init(void) {
|
||||
/* USER CODE BEGIN RTOS_EVENTS */
|
||||
/* add events, ... */
|
||||
/* USER CODE END RTOS_EVENTS */
|
||||
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_StartDefaultTask */
|
||||
@@ -237,8 +239,7 @@ void MX_FREERTOS_Init(void) {
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_StartDefaultTask */
|
||||
void StartDefaultTask(void *argument)
|
||||
{
|
||||
void StartDefaultTask(void *argument) {
|
||||
/* USER CODE BEGIN StartDefaultTask */
|
||||
// 1. 打开运行灯
|
||||
Device_Control(DEVICE_LED_RUN, 1);
|
||||
@@ -256,6 +257,9 @@ void StartDefaultTask(void *argument)
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置为低音量-测试用
|
||||
MP3_SetVolume(20);
|
||||
|
||||
elog_i("MP3", "模块初始化完成");
|
||||
MP3_Play(SYS_POWER_ON); // 播放系统启动音
|
||||
|
||||
@@ -277,8 +281,7 @@ void StartDefaultTask(void *argument)
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_LCD_Task */
|
||||
void LCD_Task(void *argument)
|
||||
{
|
||||
void LCD_Task(void *argument) {
|
||||
/* USER CODE BEGIN LCD_Task */
|
||||
|
||||
char display_str[32];
|
||||
@@ -306,71 +309,87 @@ void LCD_Task(void *argument)
|
||||
case LCD_PAGE_TIME:
|
||||
// 时间显示页面
|
||||
ST7735_FillScreen(bg_color);
|
||||
|
||||
|
||||
// 绘制标题栏
|
||||
ST7735_FillRectangle(0, 0, ST7735_WIDTH, 15, ST7735_BLUE);
|
||||
ST7735_WriteString(5, 2, "Time", &Font_7x10, ST7735_WHITE, ST7735_BLUE);
|
||||
|
||||
|
||||
// 使用RTC时间(独立于SNTP,即使网络断开也能显示)
|
||||
if (BSP_RTC_GetTime(&rtc_time) == 0) {
|
||||
// 显示时间(大字体,只显示时:分,不显示秒)
|
||||
snprintf(display_str, sizeof(display_str), "%02d:%02d", rtc_time.hour, rtc_time.minute);
|
||||
ST7735_WriteString(40, 30, display_str, &Font_16x26, ST7735_WHITE, bg_color);
|
||||
snprintf(display_str, sizeof(display_str), "%02d:%02d", rtc_time.hour,
|
||||
rtc_time.minute);
|
||||
ST7735_WriteString(40, 30, display_str, &Font_16x26, ST7735_WHITE,
|
||||
bg_color);
|
||||
|
||||
// 显示年月日(小字体,向下移动并居中)
|
||||
snprintf(display_str, sizeof(display_str), "%04d-%02d-%02d",
|
||||
rtc_time.year, rtc_time.month, rtc_time.day);
|
||||
ST7735_WriteString(30, 65, display_str, &Font_7x10, ST7735_CYAN, bg_color);
|
||||
ST7735_WriteString(30, 65, display_str, &Font_7x10, ST7735_CYAN,
|
||||
bg_color);
|
||||
} else {
|
||||
ST7735_WriteString(40, 30, "--:--", &Font_16x26, ST7735_WHITE, bg_color);
|
||||
ST7735_WriteString(30, 65, "----/--/--", &Font_7x10, ST7735_CYAN, bg_color);
|
||||
ST7735_WriteString(40, 30, "--:--", &Font_16x26, ST7735_WHITE,
|
||||
bg_color);
|
||||
ST7735_WriteString(30, 65, "----/--/--", &Font_7x10, ST7735_CYAN,
|
||||
bg_color);
|
||||
}
|
||||
break;
|
||||
|
||||
case LCD_PAGE_TEMP_HUMI:
|
||||
// 温湿度页面
|
||||
ST7735_FillScreen(bg_color);
|
||||
|
||||
|
||||
// 绘制标题栏
|
||||
ST7735_FillRectangle(0, 0, ST7735_WIDTH, 15, ST7735_GREEN);
|
||||
ST7735_WriteString(5, 2, "Temp & Humi", &Font_7x10, ST7735_WHITE, ST7735_GREEN);
|
||||
|
||||
ST7735_WriteString(5, 2, "Temp & Humi", &Font_7x10, ST7735_WHITE,
|
||||
ST7735_GREEN);
|
||||
|
||||
// 绘制分隔线
|
||||
ST7735_DrawLine(0, 15, ST7735_WIDTH, 15, ST7735_WHITE);
|
||||
|
||||
// 显示温度(橙色 - 国际标准温度色)
|
||||
snprintf(display_str, sizeof(display_str), "Temp:");
|
||||
ST7735_WriteString(5, 25, display_str, &Font_7x10, ST7735_WHITE, bg_color);
|
||||
snprintf(display_str, sizeof(display_str), "%.3fC", sensor_data.temperature);
|
||||
ST7735_WriteString(40, 25, display_str, &Font_16x26, ST7735_ORANGE, bg_color);
|
||||
ST7735_WriteString(5, 25, display_str, &Font_7x10, ST7735_WHITE,
|
||||
bg_color);
|
||||
snprintf(display_str, sizeof(display_str), "%.3fC",
|
||||
sensor_data.temperature);
|
||||
ST7735_WriteString(40, 25, display_str, &Font_16x26, ST7735_ORANGE,
|
||||
bg_color);
|
||||
|
||||
// 显示湿度(青色 - 国际标准湿度色)
|
||||
snprintf(display_str, sizeof(display_str), "Humi:");
|
||||
ST7735_WriteString(5, 55, display_str, &Font_7x10, ST7735_WHITE, bg_color);
|
||||
snprintf(display_str, sizeof(display_str), "%.3f%%", sensor_data.humidity);
|
||||
ST7735_WriteString(40, 55, display_str, &Font_16x26, ST7735_CYAN, bg_color);
|
||||
ST7735_WriteString(5, 55, display_str, &Font_7x10, ST7735_WHITE,
|
||||
bg_color);
|
||||
snprintf(display_str, sizeof(display_str), "%.3f%%",
|
||||
sensor_data.humidity);
|
||||
ST7735_WriteString(40, 55, display_str, &Font_16x26, ST7735_CYAN,
|
||||
bg_color);
|
||||
break;
|
||||
|
||||
case LCD_PAGE_FOOD_WEIGHT:
|
||||
// 食物重量页面
|
||||
ST7735_FillScreen(bg_color);
|
||||
|
||||
|
||||
// 绘制标题栏
|
||||
ST7735_FillRectangle(0, 0, ST7735_WIDTH, 15, ST7735_YELLOW);
|
||||
ST7735_WriteString(5, 2, "Food Weight", &Font_7x10, ST7735_BLACK, ST7735_YELLOW);
|
||||
|
||||
ST7735_WriteString(5, 2, "Food Weight", &Font_7x10, ST7735_BLACK,
|
||||
ST7735_YELLOW);
|
||||
|
||||
// 绘制分隔线
|
||||
ST7735_DrawLine(0, 15, ST7735_WIDTH, 15, ST7735_WHITE);
|
||||
|
||||
// 显示食物重量
|
||||
snprintf(display_str, sizeof(display_str), "%.2f g", sensor_data.food_weight);
|
||||
ST7735_WriteString(15, 25, display_str, &Font_16x26, ST7735_WHITE, bg_color);
|
||||
snprintf(display_str, sizeof(display_str), "%.2f g",
|
||||
sensor_data.food_weight);
|
||||
ST7735_WriteString(15, 25, display_str, &Font_16x26, ST7735_WHITE,
|
||||
bg_color);
|
||||
|
||||
// 显示状态
|
||||
if (sensor_data.food_weight < 50.0f) {
|
||||
ST7735_WriteString(20, 65, "LOW", &Font_11x18, ST7735_RED, bg_color);
|
||||
} else if (sensor_data.food_weight < 100.0f) {
|
||||
ST7735_WriteString(15, 65, "MEDIUM", &Font_11x18, ST7735_YELLOW, bg_color);
|
||||
ST7735_WriteString(15, 65, "MEDIUM", &Font_11x18, ST7735_YELLOW,
|
||||
bg_color);
|
||||
} else {
|
||||
ST7735_WriteString(20, 65, "GOOD", &Font_11x18, ST7735_GREEN, bg_color);
|
||||
}
|
||||
@@ -379,11 +398,12 @@ void LCD_Task(void *argument)
|
||||
case LCD_PAGE_WATER_LEVEL:
|
||||
// 水位页面
|
||||
ST7735_FillScreen(bg_color);
|
||||
|
||||
|
||||
// 绘制标题栏
|
||||
ST7735_FillRectangle(0, 0, ST7735_WIDTH, 15, ST7735_CYAN);
|
||||
ST7735_WriteString(5, 2, "Water Level", &Font_7x10, ST7735_BLACK, ST7735_CYAN);
|
||||
|
||||
ST7735_WriteString(5, 2, "Water Level", &Font_7x10, ST7735_BLACK,
|
||||
ST7735_CYAN);
|
||||
|
||||
// 绘制分隔线
|
||||
ST7735_DrawLine(0, 15, ST7735_WIDTH, 15, ST7735_WHITE);
|
||||
|
||||
@@ -391,30 +411,36 @@ void LCD_Task(void *argument)
|
||||
if (sensor_data.water_level == 0) {
|
||||
// 绘制警告背景
|
||||
ST7735_FillRectangle(0, 20, ST7735_WIDTH, 30, ST7735_RED);
|
||||
ST7735_WriteString(20, 20, "NO WATER", &Font_16x26, ST7735_WHITE, ST7735_RED);
|
||||
ST7735_WriteString(10, 60, "Add water", &Font_16x26, ST7735_YELLOW, bg_color);
|
||||
ST7735_WriteString(20, 20, "NO WATER", &Font_16x26, ST7735_WHITE,
|
||||
ST7735_RED);
|
||||
ST7735_WriteString(10, 60, "Add water", &Font_16x26, ST7735_YELLOW,
|
||||
bg_color);
|
||||
} else {
|
||||
// 绘制正常背景
|
||||
ST7735_FillRectangle(0, 20, ST7735_WIDTH, 30, ST7735_GREEN);
|
||||
ST7735_WriteString(5, 20, "WATER OK", &Font_16x26, ST7735_WHITE, ST7735_GREEN);
|
||||
ST7735_WriteString(10, 60, "Not add", &Font_16x26, ST7735_WHITE, bg_color);
|
||||
ST7735_WriteString(5, 20, "WATER OK", &Font_16x26, ST7735_WHITE,
|
||||
ST7735_GREEN);
|
||||
ST7735_WriteString(10, 60, "Not add", &Font_16x26, ST7735_WHITE,
|
||||
bg_color);
|
||||
}
|
||||
break;
|
||||
|
||||
case LCD_PAGE_SYSTEM_STATUS:
|
||||
// 系统状态页面
|
||||
ST7735_FillScreen(bg_color);
|
||||
|
||||
|
||||
// 绘制标题栏
|
||||
ST7735_FillRectangle(0, 0, ST7735_WIDTH, 15, ST7735_MAGENTA);
|
||||
ST7735_WriteString(5, 2, "System", &Font_7x10, ST7735_WHITE, ST7735_MAGENTA);
|
||||
|
||||
ST7735_WriteString(5, 2, "System", &Font_7x10, ST7735_WHITE,
|
||||
ST7735_MAGENTA);
|
||||
|
||||
// 绘制分隔线
|
||||
ST7735_DrawLine(0, 15, ST7735_WIDTH, 15, ST7735_WHITE);
|
||||
|
||||
// 显示MQTT连接状态
|
||||
snprintf(display_str, sizeof(display_str), "MQTT:");
|
||||
ST7735_WriteString(5, 25, display_str, &Font_7x10, ST7735_WHITE, bg_color);
|
||||
ST7735_WriteString(5, 25, display_str, &Font_7x10, ST7735_WHITE,
|
||||
bg_color);
|
||||
if (WIFI_Is_MQTT_Connected()) {
|
||||
ST7735_WriteString(40, 25, "OK", &Font_7x10, ST7735_GREEN, bg_color);
|
||||
} else {
|
||||
@@ -423,16 +449,19 @@ void LCD_Task(void *argument)
|
||||
|
||||
// 显示系统模式
|
||||
snprintf(display_str, sizeof(display_str), "Mode:");
|
||||
ST7735_WriteString(5, 45, display_str, &Font_7x10, ST7735_WHITE, bg_color);
|
||||
ST7735_WriteString(5, 45, display_str, &Font_7x10, ST7735_WHITE,
|
||||
bg_color);
|
||||
if (sensor_data.system_mode) {
|
||||
ST7735_WriteString(40, 45, "AUTO", &Font_7x10, ST7735_GREEN, bg_color);
|
||||
} else {
|
||||
ST7735_WriteString(40, 45, "MANUAL", &Font_7x10, ST7735_YELLOW, bg_color);
|
||||
ST7735_WriteString(40, 45, "MANUAL", &Font_7x10, ST7735_YELLOW,
|
||||
bg_color);
|
||||
}
|
||||
|
||||
|
||||
// 显示喂食状态
|
||||
snprintf(display_str, sizeof(display_str), "Feed:");
|
||||
ST7735_WriteString(5, 65, display_str, &Font_7x10, ST7735_WHITE, bg_color);
|
||||
ST7735_WriteString(5, 65, display_str, &Font_7x10, ST7735_WHITE,
|
||||
bg_color);
|
||||
if (feeding_in_progress) {
|
||||
ST7735_WriteString(40, 65, "Busy", &Font_7x10, ST7735_ORANGE, bg_color);
|
||||
} else {
|
||||
@@ -445,18 +474,19 @@ void LCD_Task(void *argument)
|
||||
LCD_Page_t displayed_page = current_page;
|
||||
|
||||
// 根据当前页面设置不同的刷新间隔
|
||||
if (current_page == LCD_PAGE_TIME || current_page == LCD_PAGE_SYSTEM_STATUS) {
|
||||
if (current_page == LCD_PAGE_TIME ||
|
||||
current_page == LCD_PAGE_SYSTEM_STATUS) {
|
||||
// 时间页面和系统状态页面:30秒刷新一次,但每100ms检查一次是否需要切换页面
|
||||
for (int i = 0; i < 300; i++) {
|
||||
if (current_page != displayed_page) {
|
||||
break; // 检测到页面切换,立即跳出
|
||||
break; // 检测到页面切换,立即跳出
|
||||
}
|
||||
if (lcd_force_refresh) {
|
||||
// RTC时间更新,立即刷新LCD
|
||||
lcd_force_refresh = 0;
|
||||
break;
|
||||
}
|
||||
osDelay(100); // 每100ms检查一次,总共30秒
|
||||
osDelay(100); // 每100ms检查一次,总共30秒
|
||||
}
|
||||
} else {
|
||||
// 其他页面:1秒刷新一次
|
||||
@@ -468,19 +498,17 @@ void LCD_Task(void *argument)
|
||||
|
||||
/* USER CODE BEGIN Header_button_task */
|
||||
/**
|
||||
* @brief Function implementing the button thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
* @brief Function implementing the button thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_button_task */
|
||||
void button_task(void *argument)
|
||||
{
|
||||
void button_task(void *argument) {
|
||||
/* USER CODE BEGIN button_task */
|
||||
user_button_init();
|
||||
|
||||
/* Infinite loop */
|
||||
for(;;)
|
||||
{
|
||||
for (;;) {
|
||||
button_ticks();
|
||||
osDelay(5);
|
||||
}
|
||||
@@ -489,17 +517,29 @@ void button_task(void *argument)
|
||||
|
||||
/* USER CODE BEGIN Header_sensorTask */
|
||||
/**
|
||||
* @brief Function implementing the sensor thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
* @brief Function implementing the sensor thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_sensorTask */
|
||||
void sensorTask(void *argument)
|
||||
{
|
||||
void sensorTask(void *argument) {
|
||||
/* USER CODE BEGIN sensorTask */
|
||||
elog_i(TAG, "启动传感器任务");
|
||||
|
||||
// #################### 校准流程(首次使用必须执行!)####################
|
||||
HAL_Delay(1000); // 上电稳定
|
||||
elog_i(TAG, "开始校准零点...");
|
||||
HX711_CalibrateZero(); // 空载时调用(传感器上不放任何东西)
|
||||
elog_i(TAG, "零点校准完成!零点AD值:%d", hx711_zero_offset);
|
||||
HAL_Delay(1000);
|
||||
// elog_i(TAG, "请在传感器上放置已知重量的物体,3秒后开始标定...");
|
||||
// HAL_Delay(3000);
|
||||
// HX711_CalibrateScale(350.0f); // 放置100g的物体(根据实际重量修改)
|
||||
elog_i(TAG, "量程标定完成!标定系数:%.6f", hx711_scale);
|
||||
// #################### 循环读取重量 ####################
|
||||
|
||||
// 扫描I2C设备(调试)
|
||||
elog_i(TAG, "扫描I2C设备");
|
||||
AHT30_ScanI2C(&hi2c1);
|
||||
|
||||
// 如果硬件I2C扫描失败,尝试软件I2C
|
||||
@@ -525,8 +565,7 @@ void sensorTask(void *argument)
|
||||
}
|
||||
|
||||
/* Infinite loop */
|
||||
for(;;)
|
||||
{
|
||||
for (;;) {
|
||||
// 读取温湿度数据
|
||||
AHT30_Data_t aht30_data;
|
||||
if (AHT30_ReadData(&aht30_data)) {
|
||||
@@ -540,6 +579,9 @@ void sensorTask(void *argument)
|
||||
elog_w(TAG, "AHT30数据读取失败");
|
||||
}
|
||||
|
||||
sensor_data.food_weight= HX711_GetWeight(10); // 采样10次取平均
|
||||
elog_d(TAG, "当前重量:%.2f g", sensor_data.food_weight);
|
||||
|
||||
// 每2秒读取一次
|
||||
osDelay(2000);
|
||||
}
|
||||
@@ -558,12 +600,13 @@ uint8_t Request_Feed(Feed_Cmd_t cmd, uint16_t angle, uint8_t amount) {
|
||||
elog_w("FEED", "喂食进行中,无法接受新命令");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
feed_command = cmd;
|
||||
feed_angle = angle;
|
||||
feed_amount = amount;
|
||||
|
||||
elog_i("FEED", "喂食请求已提交: cmd=%d, angle=%d, amount=%d", cmd, angle, amount);
|
||||
|
||||
elog_i("FEED", "喂食请求已提交: cmd=%d, angle=%d, amount=%d", cmd, angle,
|
||||
amount);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -571,16 +614,12 @@ uint8_t Request_Feed(Feed_Cmd_t cmd, uint16_t angle, uint8_t amount) {
|
||||
* @brief 获取当前喂食命令
|
||||
* @retval 当前喂食命令
|
||||
*/
|
||||
Feed_Cmd_t Get_Feed_Command(void) {
|
||||
return feed_command;
|
||||
}
|
||||
Feed_Cmd_t Get_Feed_Command(void) { return feed_command; }
|
||||
|
||||
/**
|
||||
* @brief 清除喂食命令
|
||||
*/
|
||||
void Clear_Feed_Command(void) {
|
||||
feed_command = FEED_CMD_NONE;
|
||||
}
|
||||
void Clear_Feed_Command(void) { feed_command = FEED_CMD_NONE; }
|
||||
|
||||
/**
|
||||
* @brief 执行喂食操作
|
||||
@@ -592,30 +631,30 @@ static void Execute_Feed(Feed_Cmd_t cmd, uint16_t angle, uint8_t amount) {
|
||||
if (feeding_in_progress) {
|
||||
return; // 防止重复执行
|
||||
}
|
||||
|
||||
|
||||
feeding_in_progress = 1;
|
||||
|
||||
|
||||
// 根据命令类型播放不同音频
|
||||
switch (cmd) {
|
||||
case FEED_CMD_MANUAL:
|
||||
MP3_Play(FEED_MANUAL_TRIGGER);
|
||||
elog_i("FEED", "执行手动喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_AUTO:
|
||||
MP3_Play(FEED_AUTO_START);
|
||||
elog_i("FEED", "执行自动喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_REMOTE:
|
||||
MP3_Play(REMOTE_CMD_RECEIVED);
|
||||
elog_i("FEED", "执行远程喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_TEST:
|
||||
elog_i("FEED", "执行测试喂食: 角度%d度", angle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case FEED_CMD_MANUAL:
|
||||
MP3_Play(FEED_MANUAL_TRIGGER);
|
||||
elog_i("FEED", "执行手动喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_AUTO:
|
||||
MP3_Play(FEED_AUTO_START);
|
||||
elog_i("FEED", "执行自动喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_REMOTE:
|
||||
MP3_Play(REMOTE_CMD_RECEIVED);
|
||||
elog_i("FEED", "执行远程喂食: 角度%d度, %d份", angle, amount);
|
||||
break;
|
||||
case FEED_CMD_TEST:
|
||||
elog_i("FEED", "执行测试喂食: 角度%d度", angle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// 执行实际的喂食动作
|
||||
for (uint8_t i = 0; i < amount; i++) {
|
||||
Stepper_Motor_RotateAngle(angle, STEPPER_DIR_CW, 2, STEPPER_MODE_FULL_STEP);
|
||||
@@ -623,49 +662,47 @@ static void Execute_Feed(Feed_Cmd_t cmd, uint16_t angle, uint8_t amount) {
|
||||
osDelay(1000); // 多份之间间隔1秒
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 等待食物落下
|
||||
osDelay(3000);
|
||||
|
||||
|
||||
// 停止电机
|
||||
Stepper_Motor_Stop();
|
||||
|
||||
|
||||
// 播放完成音效
|
||||
MP3_Play(FEED_COMPLETE);
|
||||
elog_i("FEED", "喂食完成");
|
||||
|
||||
|
||||
feeding_in_progress = 0;
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Header_step_motor_task */
|
||||
/**
|
||||
* @brief Function implementing the step_motor thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
* @brief Function implementing the step_motor thread.
|
||||
* @param argument: Not used
|
||||
* @retval None
|
||||
*/
|
||||
/* USER CODE END Header_step_motor_task */
|
||||
void step_motor_task(void *argument)
|
||||
{
|
||||
void step_motor_task(void *argument) {
|
||||
/* USER CODE BEGIN step_motor_task */
|
||||
// 初始化步进电机
|
||||
Stepper_Motor_Init();
|
||||
|
||||
|
||||
/* Infinite loop */
|
||||
for(;;)
|
||||
{
|
||||
for (;;) {
|
||||
// 检查是否有喂食命令需要执行
|
||||
if (feed_command != FEED_CMD_NONE && !feeding_in_progress) {
|
||||
Feed_Cmd_t current_cmd = feed_command;
|
||||
uint16_t current_angle = feed_angle;
|
||||
uint8_t current_amount = feed_amount;
|
||||
|
||||
|
||||
// 清除命令标志
|
||||
Clear_Feed_Command();
|
||||
|
||||
|
||||
// 执行喂食
|
||||
Execute_Feed(current_cmd, current_angle, current_amount);
|
||||
}
|
||||
|
||||
|
||||
osDelay(100); // 短暂延时,保持任务响应性
|
||||
}
|
||||
/* USER CODE END step_motor_task */
|
||||
@@ -678,12 +715,12 @@ void step_motor_task(void *argument)
|
||||
|
||||
/* USER CODE BEGIN KEY Prototypes */
|
||||
|
||||
static Button KEY1; // 按键1
|
||||
static Button KEY2; // 按键2
|
||||
static Button KEY3; // 按键3
|
||||
static Button KEY4; // 按键4
|
||||
static Button M3_IO; // M3 IO
|
||||
static Button HC_SR505; //HC-SR505
|
||||
static Button KEY1; // 按键1
|
||||
static Button KEY2; // 按键2
|
||||
static Button KEY3; // 按键3
|
||||
static Button KEY4; // 按键4
|
||||
static Button M3_IO; // M3 IO
|
||||
static Button HC_SR505; // HC-SR505
|
||||
|
||||
uint8_t read_button_gpio(uint8_t button_id) {
|
||||
switch (button_id) {
|
||||
@@ -717,16 +754,17 @@ uint8_t read_button_gpio(uint8_t button_id) {
|
||||
void key1_single_click_handler(Button *btn) {
|
||||
// 切换系统模式
|
||||
system_mode = !system_mode; // 0和1之间切换
|
||||
|
||||
|
||||
// 更新传感器数据中的模式状态
|
||||
sensor_data.system_mode = system_mode;
|
||||
|
||||
|
||||
// 记录日志
|
||||
elog_i("KEY", "按键1单击 - 模式切换: %s", system_mode ? "自动模式" : "手动模式");
|
||||
|
||||
elog_i("KEY", "按键1单击 - 模式切换: %s",
|
||||
system_mode ? "自动模式" : "手动模式");
|
||||
|
||||
// 播放模式切换音效
|
||||
MP3_Play(system_mode ? MODE_AUTO : MODE_MANUAL);
|
||||
|
||||
|
||||
// 强制刷新LCD显示以更新模式状态
|
||||
lcd_force_refresh = 1;
|
||||
}
|
||||
@@ -752,27 +790,24 @@ void key2_single_click_handler(Button *btn) {
|
||||
}
|
||||
}
|
||||
|
||||
void key3_single_click_handler(Button *btn) {
|
||||
elog_i("KEY", "按键3单击");
|
||||
void key3_single_click_handler(Button *btn) {
|
||||
elog_i("KEY", "按键3单击");
|
||||
LCD_NextPage();
|
||||
}
|
||||
|
||||
void key4_single_click_handler(Button *btn) { elog_i("KEY", "按键4单击"); }
|
||||
|
||||
void M3_long_press_start_handler(Button *btn) {
|
||||
elog_i("KEY", "M3水位传感器检测到有水(低电平)");
|
||||
void M3_long_press_start_handler(Button *btn) {
|
||||
elog_i("KEY", "M3水位传感器检测到有水(低电平)");
|
||||
sensor_data.water_level = 1;
|
||||
}
|
||||
|
||||
void M3_press_up_handler(Button *btn) {
|
||||
elog_i("KEY", "M3水位传感器检测到无水(高电平)");
|
||||
void M3_press_up_handler(Button *btn) {
|
||||
elog_i("KEY", "M3水位传感器检测到无水(高电平)");
|
||||
sensor_data.water_level = 0;
|
||||
}
|
||||
void HC_SR055_long_click_handler(Button *btn) { elog_i("KEY", "HC-SR505触发"); }
|
||||
|
||||
|
||||
|
||||
|
||||
void user_button_init(void) {
|
||||
// 初始化按键 (active_level: 0=低电平有效, 1=高电平有效)
|
||||
button_init(&KEY1, read_button_gpio, 0, 1);
|
||||
@@ -790,7 +825,8 @@ void user_button_init(void) {
|
||||
button_attach(&KEY4, BTN_SINGLE_CLICK, key4_single_click_handler);
|
||||
button_attach(&M3_IO, BTN_LONG_PRESS_START, M3_long_press_start_handler);
|
||||
button_attach(&M3_IO, BTN_PRESS_UP, M3_press_up_handler);
|
||||
button_attach(&HC_SR505, BTN_LONG_PRESS_START, HC_SR055_long_click_handler); // 长按触发
|
||||
button_attach(&HC_SR505, BTN_LONG_PRESS_START,
|
||||
HC_SR055_long_click_handler); // 长按触发
|
||||
|
||||
elog_i("BUTTON", "按键回调函数设置完成");
|
||||
|
||||
@@ -801,7 +837,7 @@ void user_button_init(void) {
|
||||
button_start(&KEY4);
|
||||
button_start(&M3_IO);
|
||||
button_start(&HC_SR505);
|
||||
|
||||
|
||||
elog_i("BUTTON", "按键任务已启动");
|
||||
}
|
||||
|
||||
@@ -809,9 +845,7 @@ void user_button_init(void) {
|
||||
* @brief 获取当前系统模式
|
||||
* @retval 系统模式 (0=手动, 1=自动)
|
||||
*/
|
||||
uint8_t Get_System_Mode(void) {
|
||||
return system_mode;
|
||||
}
|
||||
uint8_t Get_System_Mode(void) { return system_mode; }
|
||||
|
||||
/**
|
||||
* @brief 设置系统模式
|
||||
@@ -830,9 +864,7 @@ void Set_System_Mode(uint8_t mode) {
|
||||
* @brief 检查是否正在喂食
|
||||
* @retval 1=正在喂食, 0=空闲
|
||||
*/
|
||||
uint8_t Is_Feeding_In_Progress(void) {
|
||||
return feeding_in_progress;
|
||||
}
|
||||
uint8_t Is_Feeding_In_Progress(void) { return feeding_in_progress; }
|
||||
|
||||
/* USER CODE END KEY Prototypes */
|
||||
|
||||
@@ -916,9 +948,7 @@ Sensor_Data_t *LCD_GetSensorData(void) { return &sensor_data; }
|
||||
* @brief RTC时间更新回调函数
|
||||
* @note 当RTC通过SNTP更新时间时调用,立即刷新LCD显示
|
||||
*/
|
||||
void RTC_TimeUpdateCallback(void) {
|
||||
lcd_force_refresh = 1;
|
||||
}
|
||||
void RTC_TimeUpdateCallback(void) { lcd_force_refresh = 1; }
|
||||
|
||||
/* USER CODE END LCD_Page_Functions */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user