Files
SmartMassager_STM32/Core/Src/freertos.c

512 lines
15 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 "usart.h"
#include "adc.h"
#include "tim.h"
#include "motor_driver.h"
#include "elog.h"
#include <stdint.h>
#include <stdio.h>
#include "screen.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 Temp_Task */
osThreadId_t Temp_TaskHandle;
const osThreadAttr_t Temp_Task_attributes = {
.name = "Temp_Task",
.stack_size = 256 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* 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,
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void Key(void *argument);
void Sensor(void *argument);
void Temp(void *argument);
void Motor(void *argument);
void Screen(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 Temp_Task */
Temp_TaskHandle = osThreadNew(Temp, NULL, &Temp_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);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_EVENTS */
/* add 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 */
// 初始化命令
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 test_cmd[] = {0x7E, 0xFF, 0x06, 0x12, 0x00, 0x00, 0x01, 0xFE, 0xE8, 0xEF};
// 先让模块稳定
osDelay(2000);
// 初始化:先发送开启声音指令,再发送指定播放设备指令
HAL_UART_Transmit(&huart3, init_cmd1, sizeof(init_cmd1), 1000);
osDelay(1500); // 重要:等待模块响应
HAL_UART_Transmit(&huart3, init_cmd2, sizeof(init_cmd2), 1000);
osDelay(1500); // 重要:等待初始化完成
/* Infinite loop */
for(;;)
{
// 直接整包发送测试指令
HAL_UART_Transmit(&huart3, test_cmd, sizeof(test_cmd), 1000);
// 把发送的数据打印出来
//elog_d("mp3_cmd","发送测试指令: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", test_cmd[0], test_cmd[1], test_cmd[2], test_cmd[3], test_cmd[4], test_cmd[5], test_cmd[6], test_cmd[7], test_cmd[8], test_cmd[9]);
// 可选:等待发送完成
// while(__HAL_UART_GET_FLAG(&huart3, UART_FLAG_TC) == RESET);
HAL_GPIO_TogglePin(RUN_LED_GPIO_Port, RUN_LED_Pin);
osDelay(1000); // 延时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 */
/* 防抖轮询实现四个低电平有效按键检测 */
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 防抖 */
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 */
/* 按键处理任务 - 按键状态切换控制 */
/* 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;
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_Temp */
/**
* @brief Function implementing the Temp_Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Temp */
void Temp(void *argument)
{
/* USER CODE BEGIN Temp */
#ifdef ENABLE_TEMP_SENSOR
/* ADC采集参数 */
uint32_t adc_raw = 0; /* ADC原始值 */
uint32_t adc_sum = 0; /* 累加和(用于平均) */
uint16_t sample_count = 32; /* 采样次数 */
float voltage = 0.0f; /* 转换后的电压 */
float temperature = 0.0f; /* 转换后的温度 */
/* 电路参数 */
const float VREF = 3.3f; /* 参考电压 */
/* 一阶低通滤波器 */
float adc_filtered = 0.0f; /* 滤波后的ADC值 */
const float FILTER_ALPHA = 0.1f; /* 滤波系数 */
/* NTC 10K 3950参数 */
const float NTC_B_VALUE = 3950.0f; /* NTC B值 */
const float NTC_R0 = 10000.0f; /* 25°C时电阻10K */
const float NTC_T0 = 298.15f; /* 25°C对应的绝对温度(K) */
const float R_FIXED = 10000.0f; /* 分压电阻10K */
/* ADC校准 */
HAL_ADCEx_Calibration_Start(&hadc1);
/* 预热先采集几次丢弃稳定ADC */
for (uint16_t i = 0; i < 10; i++) {
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
osDelay(10);
}
/* Infinite loop */
for(;;)
{
/* 采集多次求平均,提高精度 */
adc_sum = 0;
for (uint16_t i = 0; i < sample_count; i++) {
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) {
adc_sum += HAL_ADC_GetValue(&hadc1);
}
HAL_ADC_Stop(&hadc1);
osDelay(20);
}
/* 计算平均值 */
adc_raw = adc_sum / sample_count;
/* 一阶低通滤波 */
if (adc_filtered == 0.0f) {
adc_filtered = (float)adc_raw;
} else {
adc_filtered = FILTER_ALPHA * (float)adc_raw + (1.0f - FILTER_ALPHA) * adc_filtered;
}
adc_raw = (uint32_t)(adc_filtered + 0.5f);
/* 转换为电压 */
voltage = ((float)adc_raw / 4095.0f) * VREF;
/* ==================== NTC 10K 3950 温度计算 ====================
* 电路3.3V ──[10K固定电阻]──┬── PA0 (ADC)
* │
* [NTC 10K]
* │
* GND
*
* Steinhart-Hart简化方程
* 1/T = 1/T0 + (1/B) * ln(R/R0)
*/
{
/* 计算NTC电阻值 */
float ntc_resistance = R_FIXED * voltage / (VREF - voltage);
/* Steinhart-Hart方程计算温度(K) */
float steinhart = logf(ntc_resistance / NTC_R0) / NTC_B_VALUE + 1.0f / NTC_T0;
temperature = 1.0f / steinhart - 273.15f; /* 转换为摄氏度 */
elog_i("Temp", "ADC:%lu 电压:%.3fV NTC:%.1fΩ 温度:%.1f°C",
adc_raw, voltage, ntc_resistance, temperature);
}
osDelay(1000);
}
#else
/* 温度传感器未启用,任务空转 */
elog_i("Temp", "温度传感器未启用等待NTC改装...");
for(;;)
{
osDelay(5000);
elog_i("Temp", "温度传感器未启用等待NTC改装...");
}
#endif /* ENABLE_TEMP_SENSOR */
/* USER CODE END Temp */
}
/* 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 */
/* 电机驱动初始化 */
Motor_Init();
/* Infinite loop */
for(;;)
{
/* 电机任务主要功能:
* - 监控电机状态(超温保护、过流保护等)
* - 定期打印状态信息
* - 响应紧急停止信号
*/
/* 每1秒打印一次电机状态 */
uint8_t current_gear = Motor_GetGear();
elog_i("Motor", "当前档位: %u (0=停止,1=低,2=中,3=高)", current_gear);
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 */
char buf[100];
sprintf(buf, "CLR(1);\r\n");
//HAL_UART_Transmit(&huart1, (uint8_t *)buf, strlen(buf), HAL_MAX_DELAY);
/* Infinite loop */
for(;;)
{
HAL_UART_Transmit(&huart1, (uint8_t *)buf, strlen(buf), HAL_MAX_DELAY);
osDelay(2000);
}
/* USER CODE END Screen */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/* USER CODE END Application */