Files
SmartMassager_STM32/Core/Src/freertos.c

466 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "elog.h"
#include "gbk_text.h"
#include "motor_driver.h"
#include "screen.h"
#include "tim.h"
#include "usart.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/_intsup.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE {
HAL_UART_Transmit(&huart5, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* 按键状态位: bit0..bit3 分别对应 M__KEY, M__KEYC7, HOT_KEY, TIME_KEY,
* 为1表示按下 */
volatile uint8_t key_state = 0;
volatile uint8_t key_state_prev = 0; /* 上一次的按键状态,用于检测按键变化 */
/* 设备状态标志0表示关闭1表示打开 */
static uint8_t hot_state = 0; /* HOT 设备状态 */
static uint8_t time_state = 0; /* TIME_KEY 时间状态 */
/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for KeyTask */
osThreadId_t KeyTaskHandle;
const osThreadAttr_t KeyTask_attributes = {
.name = "KeyTask",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityRealtime,
};
/* Definitions for Sensor_Task */
osThreadId_t Sensor_TaskHandle;
const osThreadAttr_t Sensor_Task_attributes = {
.name = "Sensor_Task",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityHigh7,
};
/* Definitions for Motor_Task */
osThreadId_t Motor_TaskHandle;
const osThreadAttr_t Motor_Task_attributes = {
.name = "Motor_Task",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityNormal1,
};
/* Definitions for Screen_Tsak */
osThreadId_t Screen_TsakHandle;
const osThreadAttr_t Screen_Tsak_attributes = {
.name = "Screen_Tsak",
.stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for MP3_Play_Task */
osThreadId_t MP3_Play_TaskHandle;
const osThreadAttr_t MP3_Play_Task_attributes = {
.name = "MP3_Play_Task",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for init_ok */
osEventFlagsId_t init_okHandle;
const osEventFlagsAttr_t init_ok_attributes = {
.name = "init_ok"
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void Key(void *argument);
void Sensor(void *argument);
void Motor(void *argument);
void Screen(void *argument);
void MP3(void *argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
easylogger_init(); /* 初始化 EasyLogger */
__enable_irq(); // 开启全局中断
elog_i("task_init", "任务初始!");
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* creation of KeyTask */
KeyTaskHandle = osThreadNew(Key, NULL, &KeyTask_attributes);
/* creation of Sensor_Task */
Sensor_TaskHandle = osThreadNew(Sensor, NULL, &Sensor_Task_attributes);
/* creation of Motor_Task */
Motor_TaskHandle = osThreadNew(Motor, NULL, &Motor_Task_attributes);
/* creation of Screen_Tsak */
Screen_TsakHandle = osThreadNew(Screen, NULL, &Screen_Tsak_attributes);
/* creation of MP3_Play_Task */
MP3_Play_TaskHandle = osThreadNew(MP3, NULL, &MP3_Play_Task_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* Create the event(s) */
/* creation of init_ok */
init_okHandle = osEventFlagsNew(&init_ok_attributes);
/* USER CODE BEGIN RTOS_EVENTS */
/* USER CODE END RTOS_EVENTS */
}
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
Screen_Init();
Screen_DrawText16_GBK(1, 30, text_device_loading, text_device_loading_LEN,
TEXT_COLOR);
// 等待bit0+bit1+bit2都被设置所有模块初始化完成
uint32_t flags = osEventFlagsWait(
init_okHandle, // 目标事件标志组
(1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4), // 要等待的bit位多个用|拼接)
osFlagsWaitAll, // 等待所有bit都被设置
osWaitForever // 永久等待(直到满足条件)
);
if(flags == ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4))) {
Screen_ClearContent();
// 所有初始化完成,开始执行按摩逻辑
Screen_DrawText16V_GBK(1, 30, text_stop_massage, text_stop_massage_LEN, 15);
}
elog_d("Init","完成所有的初始化");
/* Infinite loop */
for (;;) {
// 可选:等待发送完成
// while(__HAL_UART_GET_FLAG(&huart3, UART_FLAG_TC) == RESET);
osDelay(10000); // 延时1秒
}
/* USER CODE END StartDefaultTask */
}
/* USER CODE BEGIN Header_Key */
/**
* @brief Function implementing the KeyTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Key */
void Key(void *argument)
{
/* USER CODE BEGIN Key */
elog_d("Init", "Key task started");
/* 防抖轮询实现四个低电平有效按键检测 */
GPIO_TypeDef *key_ports[4] = {M__KEY_GPIO_Port, M__KEYC7_GPIO_Port,
HOT_KEY_GPIO_Port, TIME_KEY_GPIO_Port};
const uint16_t key_pins[4] = {M__KEY_Pin, M__KEYC7_Pin, HOT_KEY_Pin,
TIME_KEY_Pin};
uint8_t press_count[4] = {0};
uint8_t release_count[4] = {0};
uint8_t pressed[4] = {0};
const uint8_t THRESH = 3; /* 3 * 10ms = 30ms 防抖 */
osEventFlagsSet(init_okHandle, 1<<0); // 设置初始化完成标志
for (;;) {
for (int i = 0; i < 4; i++) {
GPIO_PinState level = HAL_GPIO_ReadPin(key_ports[i], key_pins[i]);
if (level == GPIO_PIN_RESET) { /* 低电平有效 */
press_count[i]++;
release_count[i] = 0;
if (!pressed[i] && press_count[i] >= THRESH) {
pressed[i] = 1;
key_state |= (1 << i); /* bit0..3 分别对应四个按键按下状态 */
}
} else {
release_count[i]++;
press_count[i] = 0;
if (pressed[i] && release_count[i] >= THRESH) {
pressed[i] = 0;
key_state &= ~(1 << i);
}
}
}
osDelay(10); /* 10ms 轮询间隔 */
}
/* USER CODE END Key */
}
/* USER CODE BEGIN Header_Sensor */
/**
* @brief Function implementing the Sensor_Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Sensor */
void Sensor(void *argument)
{
/* USER CODE BEGIN Sensor */
elog_d("Init", "Sensor task started");
/* 按键处理任务 - 按键状态切换控制 */
osEventFlagsSet(init_okHandle, 1<<1);
/* Infinite loop */
for (;;) {
/* 检测新按下的按键 */
uint8_t key_pressed = key_state & ~key_state_prev;
key_state_prev = key_state;
/* ===== M__KEY (bit0) 控制 ===== */
if (key_pressed & (1 << 0)) {
/* M__KEY 按下:加档(提高转速) */
elog_i("Key", "M__KEY按下 - 加档");
if (Motor_GetGear() == 0) {
Motor_StartupBoost();
} else {
Motor_GearUp();
}
}
/* ===== M__KEYC7 (bit1) 控制 ===== */
if (key_pressed & (1 << 1)) {
/* M__KEYC7 按下:降档(降低转速) */
elog_i("Key", "M__KEYC7按下 - 降档");
Motor_GearDown();
}
/* ===== HOT_KEY (bit2) 控制 ===== */
if (key_pressed & (1 << 2)) {
/* HOT_KEY 按下:切换热功能 */
hot_state = !hot_state;
elog_d("HOT", "加热的状态: %d", hot_state);
HAL_GPIO_WritePin(HOT_GPIO_Port, HOT_Pin,
hot_state ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
/* ===== TIME_KEY (bit3) 控制 ===== */
if (key_pressed & (1 << 3)) {
/* TIME_KEY 按下:切换定时 */
time_state = !time_state;
if (time_state) {
// TODO: 添加定时启动逻辑
} else {
// TODO: 添加定时关闭逻辑
}
}
osDelay(20); /* 20ms 检查一次按键状态 */
}
/* USER CODE END Sensor */
}
/* USER CODE BEGIN Header_Motor */
/**
* @brief Function implementing the Motor_Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Motor */
void Motor(void *argument)
{
/* USER CODE BEGIN Motor */
elog_d("Init", "Motor task started");
/* 电机驱动初始化 */
Motor_Init();
osEventFlagsSet(init_okHandle, 1<<2);
/* Infinite loop */
for (;;) {
/* 电机任务主要功能:
* - 监控电机状态(超温保护、过流保护等)
* - 定期打印状态信息
* - 响应紧急停止信号
*/
/* 每1秒打印一次电机状态 */
uint8_t current_gear = Motor_GetGear();
elog_i("Motor", "当前档位: %u (0=停止,1=低,2=中,3=高)", current_gear);
HAL_GPIO_TogglePin(RUN_LED_GPIO_Port, RUN_LED_Pin);
osDelay(1000);
}
/* USER CODE END Motor */
}
/* USER CODE BEGIN Header_Screen */
/**
* @brief Function implementing the Screen_Tsak thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Screen */
void Screen(void *argument)
{
/* USER CODE BEGIN Screen */
elog_d("Init", "Screen task started");
osEventFlagsSet(init_okHandle, 1<<3);
// HAL_UART_Transmit(&huart1, (uint8_t *)buf, strlen(buf), HAL_MAX_DELAY);
/* Infinite loop */
for (;;) {
}
/* USER CODE END Screen */
}
/* USER CODE BEGIN Header_MP3 */
/**
* @brief Function implementing the MP3_Play_Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_MP3 */
void MP3(void *argument)
{
/* USER CODE BEGIN MP3 */
elog_d("Init", "MP3 task started");
uint8_t init_cmd1[] = {0x7E, 0xFF, 0x06, 0x06, 0x00, 0x00, 0x1E, 0xFE, 0xD7, 0xEF}; // 开启声音
uint8_t init_cmd2[] = {0x7E, 0xFF, 0x06, 0x09, 0x00, 0x00, 0x02, 0xFE, 0xF0, 0xEF}; // TF卡
uint8_t play_cmd[] = {0x7E, 0xFF, 0x06, 0x12, 0x00, 0x00, 0x01, 0xFE, 0xE8, 0xEF}; // 播放文件1
// 等待模块上电稳定
osDelay(2000);
// 发送初始化命令1等待模块 ACK
HAL_UART_Transmit(&huart3, init_cmd1, sizeof(init_cmd1), 100);
// 发送初始化命令2
HAL_UART_Transmit(&huart3, init_cmd2, sizeof(init_cmd2), 100);
elog_i("MP3", "模块初始化完成");
osEventFlagsSet(init_okHandle, 1<<4);
/* Infinite loop */
for(;;)
{
// 发送播放命令
HAL_UART_Transmit(&huart3, play_cmd, sizeof(play_cmd), 100);
osDelay(10000);
}
/* USER CODE END MP3 */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/* USER CODE END Application */