diff --git a/CMakeLists.txt b/CMakeLists.txt index d340a72..4d2c3d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,7 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE User/device/supercap.c User/device/gimbal_imu.c User/device/referee.c + User/device/buzzer.c # User/module sources User/module/chassis.c diff --git a/Core/Src/tim.c b/Core/Src/tim.c index a586041..820883f 100644 --- a/Core/Src/tim.c +++ b/Core/Src/tim.c @@ -99,7 +99,7 @@ void MX_TIM12_Init(void) htim12.Instance = TIM12; htim12.Init.Prescaler = 24-1; htim12.Init.CounterMode = TIM_COUNTERMODE_UP; - htim12.Init.Period = 2500-1; + htim12.Init.Period = 2000-1; htim12.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim12.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim12) != HAL_OK) diff --git a/User/device/buzzer.c b/User/device/buzzer.c new file mode 100644 index 0000000..f5cc820 --- /dev/null +++ b/User/device/buzzer.c @@ -0,0 +1,171 @@ +#include "device/buzzer.h" +#include "bsp/time.h" +#include + +/* USER INCLUDE BEGIN */ + +/* USER INCLUDE END */ + +/* USER DEFINE BEGIN */ + +/* USER DEFINE END */ + +#define MUSIC_DEFAULT_VOLUME 0.5f +#define MUSIC_A4_FREQ 440.0f // A4音符频率 + +/* USER MUSIC MENU BEGIN */ +// RM音乐 +const Tone_t RM[] = { + {NOTE_B, 5, 200}, + {NOTE_G, 4, 200}, + {NOTE_B, 5, 400}, + {NOTE_G, 4, 200}, + {NOTE_B, 5, 400}, + {NOTE_G, 4, 200}, + {NOTE_D, 5, 400}, + {NOTE_G, 4, 200}, + {NOTE_C, 5, 200}, + {NOTE_C, 5, 200}, + {NOTE_G, 4, 200}, + {NOTE_B, 5, 200}, + {NOTE_C, 5, 200} +}; + +// Nokia 经典铃声音符 +const Tone_t NOKIA[] = { + {NOTE_E, 5, 125}, {NOTE_D, 5, 125}, {NOTE_FS, 4, 250}, {NOTE_GS, 4, 250}, + {NOTE_CS, 5, 125}, {NOTE_B, 4, 125}, {NOTE_D, 4, 250}, {NOTE_E, 4, 250}, + {NOTE_B, 4, 125}, {NOTE_A, 4, 125}, {NOTE_CS, 4, 250}, {NOTE_E, 4, 250}, + {NOTE_A, 4, 500} +}; +/* USER MUSIC MENU END */ + +static void BUZZER_Update(BUZZER_t *buzzer){ + buzzer->header.online = true; + buzzer->header.last_online_time = BSP_TIME_Get_ms(); +} + +// 根据音符和八度计算频率的辅助函数 +static float BUZZER_CalcFreq(NOTE_t note, uint8_t octave) { + if (note == NOTE_REST) { + return 0.0f; // 休止符返回0频率 + } + + // 将音符和八度转换为MIDI音符编号 + int midi_num = (int)note + (int)((octave + 1) * 12); + + // 使用A4 (440Hz) 作为参考,计算频率 + // 公式: freq = 440 * 2^((midi_num - 69)/12) + float freq = 440.0f * powf(2.0f, ((float)midi_num - 69.0f) / 12.0f); + + return freq; +} + +// 播放单个音符 +static int8_t BUZZER_PlayTone(BUZZER_t *buzzer, NOTE_t note, uint8_t octave, uint16_t duration_ms) { + if (buzzer == NULL || !buzzer->header.online) + return DEVICE_ERR; + + float freq = BUZZER_CalcFreq(note, octave); + + if (freq > 0.0f) { + // 播放音符 + if (BUZZER_Set(buzzer, freq, MUSIC_DEFAULT_VOLUME) != DEVICE_OK) + return DEVICE_ERR; + + if (BUZZER_Start(buzzer) != DEVICE_OK) + return DEVICE_ERR; + } else { + // 休止符,停止播放 + BUZZER_Stop(buzzer); + } + + // 等待指定时间 + BSP_TIME_Delay_ms(duration_ms); + + // 停止当前音符,为下一个音符做准备 + BUZZER_Stop(buzzer); + BSP_TIME_Delay_ms(20); // 短暂间隔 + + return DEVICE_OK; +} + +int8_t BUZZER_Init(BUZZER_t *buzzer, BSP_PWM_Channel_t channel) { + if (buzzer == NULL) return DEVICE_ERR; + + buzzer->channel = channel; + buzzer->header.online = true; + + BUZZER_Stop(buzzer); + + return DEVICE_OK ; +} + +int8_t BUZZER_Start(BUZZER_t *buzzer) { + if (buzzer == NULL || !buzzer->header.online) + return DEVICE_ERR; + BUZZER_Update(buzzer); + return (BSP_PWM_Start(buzzer->channel) == BSP_OK) ? + DEVICE_OK : DEVICE_ERR; +} + +int8_t BUZZER_Stop(BUZZER_t *buzzer) { + if (buzzer == NULL || !buzzer->header.online) + return DEVICE_ERR; + BUZZER_Update(buzzer); + return (BSP_PWM_Stop(buzzer->channel) == BSP_OK) ? + DEVICE_OK : DEVICE_ERR; +} + +int8_t BUZZER_Set(BUZZER_t *buzzer, float freq, float duty_cycle) { + if (buzzer == NULL || !buzzer->header.online) + return DEVICE_ERR; + + int result = DEVICE_OK ; + BUZZER_Update(buzzer); + if (BSP_PWM_SetFreq(buzzer->channel, freq) != BSP_OK) + result = DEVICE_ERR; + + if (BSP_PWM_SetComp(buzzer->channel, duty_cycle) != BSP_OK) + result = DEVICE_ERR; + + return result; +} + +int8_t BUZZER_PlayMusic(BUZZER_t *buzzer, MUSIC_t music) { + if (buzzer == NULL || !buzzer->header.online) + return DEVICE_ERR; + + const Tone_t *melody = NULL; + size_t melody_length = 0; + + // 根据音乐类型选择对应的音符数组 + switch (music) { + case MUSIC_RM: + melody = RM; + melody_length = sizeof(RM) / sizeof(Tone_t); + break; + case MUSIC_NOKIA: + melody = NOKIA; + melody_length = sizeof(NOKIA) / sizeof(Tone_t); + break; + default: + return DEVICE_ERR; + } + + // 播放整首音乐 + for (size_t i = 0; i < melody_length; i++) { + if (BUZZER_PlayTone(buzzer, melody[i].note, melody[i].octave, melody[i].duration_ms) != DEVICE_OK) { + BUZZER_Stop(buzzer); // 出错时停止播放 + return DEVICE_ERR; + } + } + + // 音乐播放完成后停止 + BUZZER_Stop(buzzer); + return DEVICE_OK; +} + +/* USER FUNCTION BEGIN */ + +/* USER FUNCTION END */ diff --git a/User/device/buzzer.h b/User/device/buzzer.h new file mode 100644 index 0000000..4ef7e43 --- /dev/null +++ b/User/device/buzzer.h @@ -0,0 +1,138 @@ +/** + * @file buzzer.h + * @brief 蜂鸣器设备驱动头文件 + * @details 提供蜂鸣器音频播放功能,支持单音符播放和预设音乐播放 + * @author Generated by STM32CubeMX + * @date 2025年10月23日 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ----------------------------------------------------------------- */ +#include "bsp/pwm.h" // PWM底层硬件抽象层 +#include "device.h" // 设备通用头文件 +#include // 标准定义 +#include // 标准整型定义 + +/* USER INCLUDE BEGIN */ + +/* USER INCLUDE END */ + +/* Exported constants ------------------------------------------------------- */ + +/* USER DEFINE BEGIN */ + +/* USER DEFINE END */ + +/* Exported types ----------------------------------------------------------- */ + +/** + * @brief 音符枚举类型 + * @details 定义标准十二平均律音符,用于音乐播放 + */ +typedef enum { + NOTE_C = 0, ///< Do音符 + NOTE_CS = 1, ///< Do#音符 (升Do) + NOTE_D = 2, ///< Re音符 + NOTE_DS = 3, ///< Re#音符 (升Re) + NOTE_E = 4, ///< Mi音符 + NOTE_F = 5, ///< Fa音符 + NOTE_FS = 6, ///< Fa#音符 (升Fa) + NOTE_G = 7, ///< Sol音符 + NOTE_GS = 8, ///< Sol#音符 (升Sol) + NOTE_A = 9, ///< La音符 + NOTE_AS = 10, ///< La#音符 (升La) + NOTE_B = 11, ///< Si音符 + NOTE_REST = 255 ///< 休止符 (无声音) +} NOTE_t; + +/** + * @brief 音调结构体 + * @details 定义一个完整的音调信息,包括音符、八度和持续时间 + */ +typedef struct { + NOTE_t note; ///< 音符名称 (使用NOTE_t枚举) + uint8_t octave; ///< 八度 (0-8,通常使用3-7) + uint16_t duration_ms; ///< 持续时间,单位毫秒 +} Tone_t; + +/** + * @brief 预设音乐枚举类型 + * @details 定义可播放的预设音乐类型 + */ +typedef enum { + /* USER MUSIC MENU BEGIN */ + MUSIC_RM, ///< RM战队音乐 + MUSIC_NOKIA, ///< 诺基亚经典铃声 + /* USER MUSIC MENU END */ +} MUSIC_t; + +/** + * @brief 蜂鸣器设备结构体 + * @details 蜂鸣器设备的完整描述,包含设备头信息和PWM通道 + */ +typedef struct { + DEVICE_Header_t header; ///< 设备通用头信息 (在线状态、时间戳等) + BSP_PWM_Channel_t channel; ///< PWM输出通道 +} BUZZER_t; + +/* USER STRUCT BEGIN */ + +/* USER STRUCT END */ + +/* Exported functions prototypes -------------------------------------------- */ + +/** + * @brief 初始化蜂鸣器设备 + * @param buzzer 蜂鸣器设备结构体指针 + * @param channel PWM输出通道 + * @return int8_t 返回值:DEVICE_OK(0) 成功,DEVICE_ERR(-1) 失败 + * @note 初始化后蜂鸣器处于停止状态 + */ +int8_t BUZZER_Init(BUZZER_t *buzzer, BSP_PWM_Channel_t channel); + +/** + * @brief 启动蜂鸣器播放 + * @param buzzer 蜂鸣器设备结构体指针 + * @return int8_t 返回值:DEVICE_OK(0) 成功,DEVICE_ERR(-1) 失败 + * @note 需要先调用BUZZER_Set设置频率和占空比 + */ +int8_t BUZZER_Start(BUZZER_t *buzzer); + +/** + * @brief 停止蜂鸣器播放 + * @param buzzer 蜂鸣器设备结构体指针 + * @return int8_t 返回值:DEVICE_OK(0) 成功,DEVICE_ERR(-1) 失败 + */ +int8_t BUZZER_Stop(BUZZER_t *buzzer); + +/** + * @brief 设置蜂鸣器频率和占空比 + * @param buzzer 蜂鸣器设备结构体指针 + * @param freq 频率 (Hz),通常范围20Hz-20kHz + * @param duty_cycle 占空比 (0.0-1.0),影响音量大小 + * @return int8_t 返回值:DEVICE_OK(0) 成功,DEVICE_ERR(-1) 失败 + * @note 设置后需要调用BUZZER_Start才能听到声音 + */ +int8_t BUZZER_Set(BUZZER_t *buzzer, float freq, float duty_cycle); + +/** + * @brief 播放预设音乐 + * @param buzzer 蜂鸣器设备结构体指针 + * @param music 音乐类型 (使用MUSIC_t枚举) + * @return int8_t 返回值:DEVICE_OK(0) 成功,DEVICE_ERR(-1) 失败 + * @note 这是一个阻塞函数,会播放完整首音乐后返回 + */ +int8_t BUZZER_PlayMusic(BUZZER_t *buzzer, MUSIC_t music); + +/* USER FUNCTION BEGIN */ + +/* USER FUNCTION END */ + +#ifdef __cplusplus +} +#endif diff --git a/User/device/dr16.c b/User/device/dr16.c index 85f2484..b13deb2 100644 --- a/User/device/dr16.c +++ b/User/device/dr16.c @@ -30,7 +30,6 @@ #define DR16_CH_VALUE_MIN (364u) #define DR16_CH_VALUE_MID (1024u) #define DR16_CH_VALUE_MAX (1684u) -//#define DR16_FRAME_SIZE (18u) // DR16数据帧固定18字节 /* USER DEFINE BEGIN */ @@ -42,29 +41,25 @@ static osThreadId_t thread_alert; static bool inited = false; +static DR16_t *dr16_instance = NULL; /* 用于空闲中断回调中访问实例 */ +static uint8_t sync_buf[32]; /* 帧同步时的丢弃缓冲区 */ /* Private function -------------------------------------------------------- */ static void DR16_RxCpltCallback(void) { osThreadFlagsSet(thread_alert, SIGNAL_DR16_RAW_REDY); } -//static void DR16_ErrorCallback(void) { -// UART_HandleTypeDef *huart = BSP_UART_GetHandle(BSP_UART_RC); -// -// // 清除所有错误标志(包括FIFO错误) -// __HAL_UART_CLEAR_OREFLAG(huart); -// __HAL_UART_CLEAR_NEFLAG(huart); -// __HAL_UART_CLEAR_FEFLAG(huart); -// __HAL_UART_CLEAR_PEFLAG(huart); -// -// // 清除FIFO超时标志(STM32H7特有) -// if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RTOF)) { -// __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_RTOF); -// } -// -// // 中止并清除当前DMA传输 -// HAL_UART_AbortReceive(huart); -//} +/** + * @brief 空闲中断回调 - 用于帧同步 + * 空闲中断表示一帧传输结束(总线空闲),此时停止当前DMA接收, + * 丢弃不完整的数据,这样下一次 StartDmaRecv 就能从帧头开始。 + */ +static void DR16_IdleCallback(void) { + /* 停止当前DMA接收(无论收了多少字节) */ + HAL_UART_AbortReceive(BSP_UART_GetHandle(BSP_UART_RC)); + /* 通知任务:可以启动下一次对齐的接收了 */ + osThreadFlagsSet(thread_alert, SIGNAL_DR16_RAW_REDY); +} static bool DR16_DataCorrupted(const DR16_t *dr16) { if (dr16 == NULL) return DEVICE_ERR_NULL; @@ -98,47 +93,57 @@ int8_t DR16_Init(DR16_t *dr16) { if (inited) return DEVICE_ERR_INITED; if ((thread_alert = osThreadGetId()) == NULL) return DEVICE_ERR_NULL; -// // 清零结构体 -// memset(dr16, 0, sizeof(DR16_t)); + dr16_instance = dr16; + /* 注册 DMA 接收完成回调 */ BSP_UART_RegisterCallback(BSP_UART_RC, BSP_UART_RX_CPLT_CB, DR16_RxCpltCallback); -// BSP_UART_RegisterCallback(BSP_UART_RC, BSP_UART_ERROR_CB, -// DR16_ErrorCallback); + + /* 注册空闲中断回调并使能空闲中断,用于帧同步 */ + BSP_UART_RegisterCallback(BSP_UART_RC, BSP_UART_IDLE_LINE_CB, + DR16_IdleCallback); + __HAL_UART_ENABLE_IT(BSP_UART_GetHandle(BSP_UART_RC), UART_IT_IDLE); + + /* + * 首次帧同步:启动一次丢弃式DMA接收。 + * 如果遥控器已经在发送,DMA会从帧中间开始收,空闲中断到来时 + * IdleCallback 会 Abort 这次接收并通知任务,下一次 StartDmaRecv + * 就能从完整帧头开始。 + */ + HAL_UART_Receive_DMA(BSP_UART_GetHandle(BSP_UART_RC), + sync_buf, sizeof(sync_buf)); + /* 等待空闲中断完成首次同步(最多50ms,足够等一帧) */ + osThreadFlagsWait(SIGNAL_DR16_RAW_REDY, osFlagsWaitAll, 50); inited = true; return DEVICE_OK; } int8_t DR16_Restart(void) { - __HAL_UART_DISABLE(BSP_UART_GetHandle(BSP_UART_RC)); - __HAL_UART_ENABLE(BSP_UART_GetHandle(BSP_UART_RC)); + UART_HandleTypeDef *huart = BSP_UART_GetHandle(BSP_UART_RC); + + /* 先终止当前DMA接收 */ + HAL_UART_AbortReceive(huart); + + /* 重置串口 */ + __HAL_UART_DISABLE(huart); + __HAL_UART_ENABLE(huart); + + /* 重新使能空闲中断 */ + __HAL_UART_ENABLE_IT(huart, UART_IT_IDLE); + + /* 重新做帧同步:丢弃式接收,等空闲中断对齐 */ + HAL_UART_Receive_DMA(huart, sync_buf, sizeof(sync_buf)); + osThreadFlagsWait(SIGNAL_DR16_RAW_REDY, osFlagsWaitAll, 50); + return DEVICE_OK; } int8_t DR16_StartDmaRecv(DR16_t *dr16) { - UART_HandleTypeDef *huart = BSP_UART_GetHandle(BSP_UART_RC); - -// // 确保之前的DMA接收已停止 -// if (huart->RxState != HAL_UART_STATE_READY) { -// HAL_UART_AbortReceive(huart); -// } -// -// // 清除所有可能的错误标志和IDLE标志 -// __HAL_UART_CLEAR_OREFLAG(huart); -// __HAL_UART_CLEAR_NEFLAG(huart); -// __HAL_UART_CLEAR_FEFLAG(huart); -// __HAL_UART_CLEAR_PEFLAG(huart); -// __HAL_UART_CLEAR_IDLEFLAG(huart); -// -// // 清除FIFO超时标志 -// if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RTOF)) { -// __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_RTOF); -// } - - if (HAL_UART_Receive_DMA(huart, (uint8_t *)&(dr16->raw_data), + if (HAL_UART_Receive_DMA(BSP_UART_GetHandle(BSP_UART_RC), + (uint8_t *)&(dr16->raw_data), sizeof(dr16->raw_data)) == HAL_OK) - return DEVICE_OK; + return DEVICE_OK; return DEVICE_ERR; } @@ -150,17 +155,9 @@ bool DR16_WaitDmaCplt(uint32_t timeout) { int8_t DR16_ParseData(DR16_t *dr16){ if (dr16 == NULL) return DEVICE_ERR_NULL; -// // STM32H7 D-Cache一致性处理:使DMA接收的数据对CPU可见 -// // D-Cache按32字节对齐,需要对齐处理 -// uint32_t addr = (uint32_t)&(dr16->raw_data); -// uint32_t size = sizeof(dr16->raw_data); -// // 向下对齐到32字节边界 -// uint32_t aligned_addr = addr & ~0x1FU; -// // 计算对齐后的大小 -// uint32_t aligned_size = ((size + (addr - aligned_addr) + 31) & ~0x1FU); -// SCB_InvalidateDCache_by_Addr((uint32_t *)aligned_addr, aligned_size); - if (DR16_DataCorrupted(dr16)) { + /* 数据损坏说明帧错位了,重启串口并重新同步 */ + DR16_Restart(); return DEVICE_ERR; } diff --git a/User/device/dr16.h b/User/device/dr16.h index 1b138e3..03fa526 100644 --- a/User/device/dr16.h +++ b/User/device/dr16.h @@ -36,9 +36,6 @@ typedef struct __packed { uint16_t key; uint16_t res; } DR16_RawData_t; -// typedef struct __packed { -// uint8_t buff[18]; // 原始接收缓冲区 -// } DR16_RawData_t; typedef enum { DR16_SW_ERR = 0, @@ -89,8 +86,9 @@ typedef struct { bool r_click; /* 右键 */ } mouse; /* 鼠标值 */ - struct { + union { bool key[DR16_KEY_NUM]; /* 键盘按键值 */ + uint16_t value; /* 键盘按键值的位映射 */ } keyboard; uint16_t res; /* 保留,未启用 */ diff --git a/User/module/cmd/cmd.c b/User/module/cmd/cmd.c index 32de059..a425aed 100644 --- a/User/module/cmd/cmd.c +++ b/User/module/cmd/cmd.c @@ -237,12 +237,13 @@ static void CMD_NUC_BuildShootCmd(CMD_t *ctx) { ctx->output.shoot.cmd.firecmd = false; break; case 2: - if (ctx->input.rc.sw[1]==CMD_SW_DOWN) { - ctx->output.shoot.cmd.ready = true; - ctx->output.shoot.cmd.firecmd = true; - }else { - ctx->output.shoot.cmd.ready = true; - ctx->output.shoot.cmd.firecmd = false; + if ((ctx->active_source == CMD_SRC_PC && ctx->input.pc.mouse.l_click) || + (ctx->active_source == CMD_SRC_RC && ctx->input.rc.sw[1] == CMD_SW_DOWN)) { + ctx->output.shoot.cmd.ready = true; + ctx->output.shoot.cmd.firecmd = true; + } else { + ctx->output.shoot.cmd.ready = true; + ctx->output.shoot.cmd.firecmd = false; } break; diff --git a/User/module/cmd/cmd_behavior.c b/User/module/cmd/cmd_behavior.c index 32e6d65..47855a9 100644 --- a/User/module/cmd/cmd_behavior.c +++ b/User/module/cmd/cmd_behavior.c @@ -49,14 +49,6 @@ int8_t CMD_Behavior_Handle_ACCELERATE(CMD_t *ctx) { return CMD_OK; } -int8_t CMD_Behavior_Handle_DECELERATE(CMD_t *ctx) { -#if CMD_ENABLE_MODULE_CHASSIS - ctx->output.chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_slow_mult; - ctx->output.chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_slow_mult; -#endif - return CMD_OK; -} - int8_t CMD_Behavior_Handle_FIRE(CMD_t *ctx) { #if CMD_ENABLE_MODULE_SHOOT ctx->output.shoot.cmd.firecmd = true; @@ -132,6 +124,12 @@ int8_t CMD_Behavior_Handle_CHECKSOURCERCPC(CMD_t *ctx) { return CMD_OK; } +extern bool reset; +int8_t CMD_Behavior_Handle_RESET(CMD_t *ctx) { + reset = !reset; + return CMD_OK; +} + /* 行为配置表 - 由宏生成 */ static const CMD_BehaviorConfig_t g_behavior_configs[] = { CMD_BEHAVIOR_TABLE(BUILD_BEHAVIOR_CONFIG) diff --git a/User/module/cmd/cmd_types.h b/User/module/cmd/cmd_types.h index 0e861e2..1b8fd22 100644 --- a/User/module/cmd/cmd_types.h +++ b/User/module/cmd/cmd_types.h @@ -253,13 +253,13 @@ typedef enum { X(LEFT, CMD_KEY_A, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ X(RIGHT, CMD_KEY_D, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ X(ACCELERATE, CMD_KEY_SHIFT, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ - X(DECELERATE, CMD_KEY_CTRL, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ X(FIRE, CMD_KEY_L_CLICK, CMD_ACTIVE_PRESSED, CMD_MODULE_SHOOT) \ X(FIRE_MODE, CMD_KEY_B, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_SHOOT) \ - X(ROTOR, CMD_KEY_E, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(ROTOR, CMD_KEY_CTRL, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ X(AUTOAIM, CMD_KEY_R_CLICK, CMD_ACTIVE_PRESSED, CMD_MODULE_NONE) \ - X(CHECKSOURCERCPC, CMD_KEY_CTRL|CMD_KEY_SHIFT|CMD_KEY_V, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_NONE) -/* 触发类型 */ + X(CHECKSOURCERCPC, CMD_KEY_CTRL|CMD_KEY_SHIFT|CMD_KEY_V, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_NONE)\ + X(RESET, CMD_KEY_CTRL|CMD_KEY_SHIFT|CMD_KEY_G, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_NONE) + /* 触发类型 */ typedef enum { CMD_ACTIVE_PRESSED, /* 按住时触发 */ CMD_ACTIVE_RISING_EDGE, /* 按下瞬间触发 */ diff --git a/User/module/shoot.c b/User/module/shoot.c index d4b9fbd..020f9c5 100644 --- a/User/module/shoot.c +++ b/User/module/shoot.c @@ -974,7 +974,7 @@ int8_t Shoot_Control(Shoot_t *s, Shoot_CMD_t *cmd) Shoot_CaluTargetRPM(s,233); /* 运行热量检测状态机 */ - // Shoot_HeatDetectionFSM(s); + Shoot_HeatDetectionFSM(s); /* 运行卡弹检测状态机 */ Shoot_JamDetectionFSM(s, cmd); diff --git a/User/task/blink.c b/User/task/blink.c index 93b3bf1..d971504 100644 --- a/User/task/blink.c +++ b/User/task/blink.c @@ -8,6 +8,7 @@ /* USER INCLUDE BEGIN */ #include "bsp/pwm.h" #include +#include "device/buzzer.h" /* USER INCLUDE END */ /* Private typedef ---------------------------------------------------------- */ @@ -15,7 +16,9 @@ /* Private macro ------------------------------------------------------------ */ /* Private variables -------------------------------------------------------- */ /* USER STRUCT BEGIN */ - +BUZZER_t buzzer; +static uint16_t count; +bool reset=0; /* USER STRUCT END */ /* Private function --------------------------------------------------------- */ @@ -31,14 +34,27 @@ void Task_blink(void *argument) { uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */ /* USER CODE INIT BEGIN */ - + BUZZER_Init(&buzzer, BSP_PWM_BUZZER); /* USER CODE INIT END */ while (1) { tick += delay_tick; /* 计算下一个唤醒时刻 */ /* USER CODE BEGIN */ - // 呼吸灯 - 基于tick的正弦波 - // float duty = (sinf(tick * 0.003f) + 1.0f) * 0.5f; // 0到1之间的正弦波,加快频率 + count++; + uint16_t phase = count % 1000; + if (count == 1001) count = 1; + if (phase == 0) { + /* 每秒开始播放C4音符 */ + BUZZER_Set(&buzzer, 261.63f, 0.5f); // C4音符频率约261.63Hz + BUZZER_Start(&buzzer); + } else if (phase == 50) { + /* 播放100ms后停止 (50/500Hz = 0.1s) */ + BUZZER_Stop(&buzzer); + } + if (reset) { + __set_FAULTMASK(1); /* 关闭所有中断 */ + NVIC_SystemReset(); /* 系统复位 */ + } /* USER CODE END */ osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */ } diff --git a/User/task/rc.c b/User/task/rc.c index e1a8c05..ced3704 100644 --- a/User/task/rc.c +++ b/User/task/rc.c @@ -31,7 +31,11 @@ // 将DR16变量放到RAM_D1 (0x24000000),用于DMA传输 // __attribute__((section(".ram_d1"))) __attribute__((aligned(32))) DR16_t dr16; +static DR16_SwitchPos_t last_sw_l = DR16_SW_ERR; /* 记录左拨杆上一次状态 */ #endif + +extern bool reset; +#include "stm32h7xx.h" /* USER STRUCT END */ /* Private function --------------------------------------------------------- */ @@ -78,6 +82,16 @@ void Task_rc(void *argument) { osMessageQueuePut(task_runtime.msgq.cmd.rc, &dr16, 0, 0); // 启动下一次DMA接收 DR16_StartDmaRecv(&dr16); + /* 检测左拨杆切换到UP位置时触发软件复位 */ + if (dr16.header.online) { + /* 拨杆从非UP状态切换到UP状态,且复位功能已使能,触发系统复位 */ + if ( + dr16.data.sw_l == DR16_SW_UP && + last_sw_l != DR16_SW_UP) { + reset=!reset; + } + last_sw_l = dr16.data.sw_l; /* 更新拨杆状态 */ + } #endif /* USER CODE END */ osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */