/* 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 "cmsis_os.h" #include "main.h" #include "task.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 #include #include #include #include "mp3_driver.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 timer_minutes = 0; // 当前设定的分钟数 (0/10/20/30) static uint32_t remaining_seconds = 0; // 剩余秒数 static uint8_t is_running = 0; // 运行状态标志 (0=停止, 1=运行) static uint8_t last_display_minutes = 0xFF; // 上一次显示的分钟数 static uint8_t run_led_state = 0; // RUN_LED闪烁状态 (0=灭, 1=亮) /* 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 */ /** * @brief 检查是否可以进行操作(电机/加热) * @return 1=允许操作, 0=禁止操作 */ uint8_t Timer_CanOperate(void) { return (timer_minutes > 0) ? 1 : 0; } /** * @brief 获取剩余秒数(供外部调用显示倒计时) * @return 剩余秒数 */ uint32_t Timer_GetRemainingSeconds(void) { return remaining_seconds; } /** * @brief 获取设定的分钟数 * @return 设定的分钟数 */ uint8_t Timer_GetMinutes(void) { return timer_minutes; } /** * @brief 获取运行状态 * @return 1=运行中, 0=停止 */ uint8_t Timer_IsRunning(void) { return is_running; } /** * @brief 动态生成剩余时间 GBK 字符串 * @param minutes 剩余分钟数 (0-99) * @param buf 输出缓冲区(至少需要 14 字节) * @return 生成的字符串长度 */ static uint8_t FormatRemainingTime(uint8_t minutes, uint8_t *buf) { uint8_t len = 0; // 固定前缀 "时间:剩余" (GBK: 0xCA,0xB1,0xBC,0xE4,0x3A,0xCA,0xA3,0xD3,0xE0) const uint8_t prefix[] = {0xCA, 0xB1, 0xBC, 0xE4, 0x3A, 0xCA, 0xA3, 0xD3, 0xE0}; for (uint8_t i = 0; i < sizeof(prefix); i++) { buf[len++] = prefix[i]; } // 动态数字部分:将分钟数转换为 ASCII if (minutes >= 10) { buf[len++] = '0' + (minutes / 10); // 十位 } buf[len++] = '0' + (minutes % 10); // 个位 // 固定后缀 "分" (GBK: 0xB7, 0xD6) buf[len++] = 0xB7; buf[len++] = 0xD6; return len; } // 全局缓冲区 static uint8_t gbk_remaining_buf[16]; /** * @brief 更新 Zone 1 的时间显示 */ static void Display_UpdateTime(void) { if (is_running) { // 运行中:显示剩余时间(动态计算) uint8_t remaining_minutes = remaining_seconds / 60; uint8_t len = FormatRemainingTime(remaining_minutes, gbk_remaining_buf); Screen_ShowInZone(1, gbk_remaining_buf, len); } else if (timer_minutes > 0) { // 已设定时间但未运行:显示设定时间 switch (timer_minutes) { case 10: Screen_ShowInZone(1, text_time_1, text_time_1_LEN); break; case 20: Screen_ShowInZone(1, text_time_2, text_time_2_LEN); break; case 30: Screen_ShowInZone(1, text_time_3, text_time_3_LEN); break; default: break; } } else { // 无定时:显示停止状态 Screen_ShowInZone(1, text_stop, text_stop_LEN); } } /** * @brief 定时器倒计时处理(每秒调用一次) */ void Timer_Tick(void) { if (is_running && remaining_seconds > 0) { remaining_seconds--; // 时间到,停止所有设备 if (remaining_seconds == 0) { is_running = 0; timer_minutes = 0; // 停止电机 Motor_SetGear(0); // 停止加热 hot_state = 0; __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0); elog_i("Timer", "定时结束,设备已停止"); // 播放语音: 定时结束,按摩结束 MP3_Play(18); // 更新 Zone 1 显示为停止状态 Screen_ShowInZone(1, text_stop, text_stop_LEN); // 更新 Zone 2 显示为停止状态(按摩已停止) Screen_ShowInZone(2, text_massage_off, text_massage_off_LEN); // 重置显示记录,避免下次启动时的显示问题 last_display_minutes = 0xFF; } } } /* 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 */ // 启动TIM1的PWM输出 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // 启动PWM输出(加热) Screen_Init(); // Screen_DrawText16_GBK(1, 30, text_device_loading, text_device_loading_LEN, // TEXT_COLOR); Screen_ShowInZone(1, text_loading, text_loading_LEN); // 等待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_DrawText16V_GBK(1, 30, text_stop_massage, text_stop_massage_LEN, // 15); Screen_ShowInZone(1, text_stop, text_stop_LEN); Screen_ShowInZone(2, text_massage_off, text_massage_off_LEN); Screen_ShowInZone(3, text_heat_off, text_heat_off_LEN); } 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)) { if (Timer_CanOperate()) { // 添加判断 /* M__KEY 按下:加档(提高转速) */ elog_i("Key", "M__KEY按下 - 加档"); if (Motor_GetGear() == 0) { Motor_StartupBoost(); is_running = 1; // 开始运行 remaining_seconds = timer_minutes * 60; // 播放语音: 按摩开始 MP3_Play(7); } else { // 检查当前档位,如果已经是3档则提示已到最大 uint8_t old_gear = Motor_GetGear(); if (old_gear == 3) { MP3_Play(11); // 已到最大档位 } else { Motor_GearUp(); uint8_t new_gear = Motor_GetGear(); // 档位变化时播放语音 if (new_gear == 1) { MP3_Play(8); // 一档 } else if (new_gear == 2) { MP3_Play(9); // 二档 } else if (new_gear == 3) { MP3_Play(10); // 三档 } } } } else { elog_w("Key", "M__KEY无效 - 请先设定时间"); // 播放语音: 请先设定时间 MP3_Play(17); elog_d("LED", "Sensor任务: ERR_LED亮"); HAL_GPIO_WritePin(ERR_LED_GPIO_Port, ERR_LED_Pin, GPIO_PIN_RESET); // ERR亮 osDelay(1000); // LED亮1秒 elog_d("LED", "Sensor任务: ERR_LED灭"); HAL_GPIO_WritePin(ERR_LED_GPIO_Port, ERR_LED_Pin, GPIO_PIN_SET); // ERR灭 } } /* ===== M__KEYC7 (bit1) 控制 ===== */ if (key_pressed & (1 << 1)) { if (Timer_CanOperate()) { // 添加判断 /* M__KEYC7 按下:降档(降低转速) */ elog_i("Key", "M__KEYC7按下 - 降档"); Motor_GearDown(); uint8_t new_gear = Motor_GetGear(); // 降档时播放语音 if (new_gear == 0) { MP3_Play(14); // 按摩停止 is_running = 0; } else if (new_gear == 1) { MP3_Play(12); // 一档 } else if (new_gear == 2) { MP3_Play(13); // 二档 } } else { elog_w("Key", "M__KEYC7无效 - 请先设定时间"); // 播放语音: 请先设定时间 MP3_Play(17); elog_d("LED", "Sensor任务: ERR_LED亮"); HAL_GPIO_WritePin(ERR_LED_GPIO_Port, ERR_LED_Pin, GPIO_PIN_RESET); // ERR亮 osDelay(1000); // LED亮1秒 elog_d("LED", "Sensor任务: ERR_LED灭"); HAL_GPIO_WritePin(ERR_LED_GPIO_Port, ERR_LED_Pin, GPIO_PIN_SET); // ERR灭 } } /* ===== HOT_KEY (bit2) 控制 ===== */ if (key_pressed & (1 << 2)) { if (Timer_CanOperate()) { // 添加判断 /* HOT_KEY 按下:切换热功能 */ hot_state = !hot_state; if (hot_state) { __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 300); elog_d("Hot", "设置PWM为300"); // 播放语音: 加热已开启 MP3_Play(15); } else { __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0); elog_d("Hot", "设置PWM为0"); // 播放语音: 加热已关闭 MP3_Play(16); } } else { elog_w("Key", "HOT_KEY无效 - 请先设定时间"); // 播放语音: 请先设定时间 MP3_Play(17); elog_d("LED", "Sensor任务: ERR_LED亮"); HAL_GPIO_WritePin(ERR_LED_GPIO_Port, ERR_LED_Pin, GPIO_PIN_RESET); // ERR亮 osDelay(1000); // LED亮1秒 elog_d("LED", "Sensor任务: ERR_LED灭"); HAL_GPIO_WritePin(ERR_LED_GPIO_Port, ERR_LED_Pin, GPIO_PIN_SET); // ERR灭 } } /* ===== TIME_KEY (bit3) 控制 ===== */ if (key_pressed & (1 << 3)) { /* TIME_KEY 按下:循环设定时间 0→10→20→30→0 */ if (!is_running) { if (timer_minutes >= 30) { timer_minutes = 0; } else { timer_minutes += 10; } elog_i("Timer", "设定时间: %d 分钟", timer_minutes); // 播放语音提示 if (timer_minutes == 10) { MP3_Play(2); // 定时10分钟 } else if (timer_minutes == 20) { MP3_Play(3); // 定时20分钟 } else if (timer_minutes == 30) { MP3_Play(4); // 定时30分钟 } else if (timer_minutes == 0) { MP3_Play(5); // 定时已取消 } // 如果设定了时间,显示在屏幕上(调用你的倒计时接口) if (timer_minutes > 0) { remaining_seconds = timer_minutes * 60; Display_UpdateTime(); } else { Screen_ShowInZone(1, text_stop, text_stop_LEN); } } else { // 运行中按下TIME_KEY,取消定时并停止 is_running = 0; timer_minutes = 0; remaining_seconds = 0; // 停止电机和加热 Motor_SetGear(0); hot_state = 0; __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0); elog_i("Timer", "定时取消,设备已停止"); // 播放语音: 按摩已停止 MP3_Play(6); // 更新 Zone 1 显示为停止状态 Screen_ShowInZone(1, text_stop, text_stop_LEN); // 延时一下,确保屏幕更新完成 osDelay(50); // 更新 Zone 2 显示为停止状态(按摩已停止) Screen_ShowInZone(2, text_massage_off, text_massage_off_LEN); // 重置显示记录 last_display_minutes = 0xFF; } } 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(); /* 初始化LED状态 (LED是低电平点亮,GPIO_PIN_SET灭,GPIO_PIN_RESET亮) */ HAL_GPIO_WritePin(RUN_LED_GPIO_Port, RUN_LED_Pin, GPIO_PIN_SET); // RUN灭 HAL_GPIO_WritePin(ERR_LED_GPIO_Port, ERR_LED_Pin, GPIO_PIN_SET); // ERR灭 run_led_state = 0; elog_d("LED", "Motor任务初始化: RUN_LED灭, ERR_LED灭"); osEventFlagsSet(init_okHandle, 1 << 2); /* Infinite loop */ static uint32_t tick_counter = 0; for (;;) { tick_counter++; // 每1000ms调用一次Timer_Tick(每2个循环周期) if (tick_counter % 2 == 0) { Timer_Tick(); // 倒计时处理 } // RUN_LED闪烁控制:运行时500ms翻转一次 (LED低电平点亮) if (is_running) { run_led_state = !run_led_state; HAL_GPIO_WritePin(RUN_LED_GPIO_Port, RUN_LED_Pin, run_led_state ? GPIO_PIN_RESET : GPIO_PIN_SET); } else { // 停止时保持灭 if (run_led_state != 0) { run_led_state = 0; HAL_GPIO_WritePin(RUN_LED_GPIO_Port, RUN_LED_Pin, GPIO_PIN_SET); } } // ERR_LED确保熄灭(LED低电平点亮,所以灭用GPIO_PIN_SET) static uint8_t last_err_led_state = 0; HAL_GPIO_WritePin(ERR_LED_GPIO_Port, ERR_LED_Pin, GPIO_PIN_SET); if (last_err_led_state != 0) { elog_d("LED", "Motor任务: ERR_LED灭"); last_err_led_state = 0; } // 每1000ms更新显示(每2个循环周期检查一次) if (tick_counter % 2 == 0) { if (is_running) { uint8_t current_minutes = remaining_seconds / 60; // 只有当分钟数变化时才刷新屏幕 if (current_minutes != last_display_minutes) { last_display_minutes = current_minutes; Display_UpdateTime(); elog_d("Screen", "更新倒计时显示: %d分", current_minutes); } } } osDelay(500); // 500ms循环周期 } /* 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 */ static uint8_t last_hot_state = 0; // 记录上一次的热状态 static uint8_t last_gear = 0xFF; // 记录上一次的挡位(初始为无效值) 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 (;;) { uint8_t current_gear = Motor_GetGear(); // 挡位变化时更新屏幕(第2区域显示挡位) if (current_gear != last_gear) { last_gear = current_gear; // 0 档位显示停止 if (current_gear == 0) { Screen_ShowInZone(2, text_massage_off, text_massage_off_LEN); } // 1级 if (current_gear == 1) { Screen_ShowInZone(2, text_gear_1, text_gear_1_LEN); } // 2级 else if (current_gear == 2) { Screen_ShowInZone(2, text_gear_2, text_gear_2_LEN); } // 3级 else if (current_gear == 3) { Screen_ShowInZone(2, text_gear_3, text_gear_3_LEN); } } // 只在状态变化时更新屏幕 if (hot_state != last_hot_state) { last_hot_state = hot_state; if (hot_state) { // 第3区域显示热功能开启 Screen_ShowInZone(3, text_heat_on, text_heat_on_LEN); } else { // 第3区域显示热功能关闭 Screen_ShowInZone(3, text_heat_off, text_heat_off_LEN); } } osDelay(10); // 添加延时,避免CPU空转 } /* 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"); elog_d("MP3", "USART3波特率: 9600"); // 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 // // 等待模块上电稳定 // elog_d("MP3", "等待模块上电稳定..."); // osDelay(2000); // // 发送初始化命令1,等待模块 ACK // elog_d("MP3", "发送初始化命令1: 开启声音"); // HAL_StatusTypeDef ret1 = HAL_UART_Transmit(&huart3, init_cmd1, sizeof(init_cmd1), 100); // elog_d("MP3", "命令1返回值: %d", ret1); // osDelay(100); // // 发送初始化命令2 // elog_d("MP3", "发送初始化命令2: 选择TF卡"); // HAL_StatusTypeDef ret2 = HAL_UART_Transmit(&huart3, init_cmd2, sizeof(init_cmd2), 100); // elog_d("MP3", "命令2返回值: %d", ret2); // osDelay(500); // 等待模块上电稳定 osDelay(2000); // 初始化MP3模块 HAL_StatusTypeDef ret = MP3_Init(); if (ret != HAL_OK) { elog_e("MP3", "MP3模块初始化失败"); return; } elog_i("MP3", "模块初始化完成"); MP3_Play(1); osEventFlagsSet(init_okHandle, 1 << 4); /* Infinite loop */ for (;;) { osDelay(10000); } /* USER CODE END MP3 */ } /* Private application code --------------------------------------------------*/ /* USER CODE BEGIN Application */ /* USER CODE END Application */