From 8712efa6f24973a7034b1ca5513773bd594420b2 Mon Sep 17 00:00:00 2001 From: Robofish <1683502971@qq.com> Date: Wed, 4 Feb 2026 12:43:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A5=BD=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- User/device/mrobot.c | 76 ++++++++++++++++++++++++++++++++++++++------ User/device/mrobot.h | 14 ++++++++ 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/User/device/mrobot.c b/User/device/mrobot.c index 2538807..35f3f1e 100644 --- a/User/device/mrobot.c +++ b/User/device/mrobot.c @@ -11,12 +11,28 @@ #include #include +/* Private constants -------------------------------------------------------- */ +static const char *const CLI_WELCOME_MESSAGE = + "\r\n" + " ______ __ _______ __ \r\n" + " | __ \\.-----.| |--.-----.| | |.---.-.-----.| |-.-----.-----.\r\n" + " | <| _ || _ | _ || || _ |__ --|| _| -__| _|\r\n" + " |___|__||_____||_____|_____||__|_|__||___._|_____||____|_____|__| \r\n" + " -------------------------------------------------------------------\r\n" + " FreeRTOS CLI. Type 'help' to view a list of registered commands. \r\n" + "\r\n"; + /* Private variables -------------------------------------------------------- */ static MRobot_Device_t devices[MROBOT_MAX_DEVICES]; static uint8_t device_count = 0; static char current_path[64] = "/"; static char output_buffer[MROBOT_MAX_OUTPUT_LEN]; +/* 自定义命令存储(最多16个) */ +#define MROBOT_MAX_CUSTOM_COMMANDS 16 +static CLI_Command_Definition_t *custom_commands[MROBOT_MAX_CUSTOM_COMMANDS]; +static uint8_t custom_command_count = 0; + /* UART 相关变量 */ static uint8_t uart_rx_char; static uint8_t cmd_buffer[128]; @@ -295,7 +311,7 @@ static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const ch /* 显示所有设备 */ if (print_count > 1) { offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, - "[第 %u/%u 次]\r\n", current_iteration + 1, print_count); + "[第 %lu/%lu 次]\r\n", (unsigned long)(current_iteration + 1), (unsigned long)print_count); } offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, "所有设备信息:\r\n"); for (uint8_t i = 0; i < device_count && offset < (int)xWriteBufferLen; i++) { @@ -317,8 +333,8 @@ static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const ch int offset = 0; if (print_count > 1) { offset = snprintf(pcWriteBuffer, xWriteBufferLen, - "[第 %u/%u 次] === %s ===\r\n", - current_iteration + 1, print_count, devices[i].name); + "[第 %lu/%lu 次] === %s ===\r\n", + (unsigned long)(current_iteration + 1), (unsigned long)print_count, devices[i].name); } else { offset = snprintf(pcWriteBuffer, xWriteBufferLen, "=== %s ===\r\n", devices[i].name); @@ -419,15 +435,24 @@ void MRobot_Init(void) { /* 启动 UART 接收 */ BSP_UART_Receive(BSP_UART_VOFA, &uart_rx_char, 1, false); + /* 等待用户按下回车键再显示欢迎消息 */ + volatile bool enter_pressed = false; + while (!enter_pressed) { + if (uart_rx_char == '\r' || uart_rx_char == '\n') { + enter_pressed = true; + } + osDelay(10); + } + /* 发送欢迎消息 */ - const char *welcome = "\r\n\r\n" - "================================\r\n" - " MRobot CLI v1.0\r\n" - " 输入 'help' 获取帮助\r\n" - "================================\r\n" - "root@mrobot:~$ "; tx_complete = false; - BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)welcome, strlen(welcome), true); + BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)CLI_WELCOME_MESSAGE, strlen(CLI_WELCOME_MESSAGE), true); + while (!tx_complete) { osDelay(1); } /* 等待发送完成 */ + + /* 发送提示符 */ + const char *prompt = "root@mrobot:~$ "; + tx_complete = false; + BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)prompt, strlen(prompt), true); while (!tx_complete) { osDelay(1); } /* 等待发送完成 */ } @@ -458,6 +483,37 @@ int8_t MRobot_RegisterMotor(const char *name, void *motor) { return MRobot_RegisterDevice(name, MROBOT_DEVICE_TYPE_MOTOR, motor, mrobot_print_motor); } +int8_t MRobot_RegisterCommand(const char *command, const char *help_text, + MRobot_CommandCallback_t callback, int8_t param_count) { + if (custom_command_count >= MROBOT_MAX_CUSTOM_COMMANDS) { + return -1; /* 命令数量已达上限 */ + } + + if (command == NULL || help_text == NULL || callback == NULL) { + return -1; /* 参数无效 */ + } + + /* 动态分配命令定义结构体 */ + CLI_Command_Definition_t *cmd_def = (CLI_Command_Definition_t *)pvPortMalloc(sizeof(CLI_Command_Definition_t)); + if (cmd_def == NULL) { + return -1; /* 内存分配失败 */ + } + + /* 强制转换以移除 const 限制(仅用于初始化) */ + *(const char **)&cmd_def->pcCommand = command; + *(const char **)&cmd_def->pcHelpString = help_text; + *(pdCOMMAND_LINE_CALLBACK *)&cmd_def->pxCommandInterpreter = (pdCOMMAND_LINE_CALLBACK)callback; + cmd_def->cExpectedNumberOfParameters = param_count; + + /* 注册到 FreeRTOS CLI */ + FreeRTOS_CLIRegisterCommand(cmd_def); + + /* 保存指针以便后续可能的清理(虽然一般不需要) */ + custom_commands[custom_command_count] = cmd_def; + custom_command_count++; + return 0; +} + void MRobot_Run(void) { /* 动态 htop 模式 */ if (htop_mode) { diff --git a/User/device/mrobot.h b/User/device/mrobot.h index f907037..f8c251e 100644 --- a/User/device/mrobot.h +++ b/User/device/mrobot.h @@ -51,6 +51,9 @@ typedef enum { /* 设备打印回调函数类型 */ typedef void (*MRobot_PrintCallback_t)(void *device_data, char *buffer, uint16_t buffer_size); +/* 命令处理回调函数类型(与 pdCOMMAND_LINE_CALLBACK 相同) */ +typedef long (*MRobot_CommandCallback_t)(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString); + /* 注册的设备结构 */ typedef struct { char name[32]; @@ -116,6 +119,17 @@ int8_t MRobot_RegisterIMU(const char *name, void *imu_device); */ int8_t MRobot_RegisterMotor(const char *name, void *motor); +/** + * @brief 注册自定义命令到 MRobot CLI + * @param command 命令名称(例如 "test") + * @param help_text 帮助文本(例如 "test: 测试命令\r\n") + * @param callback 命令处理回调函数 + * @param param_count 参数个数(0=无参数,-1=可变参数) + * @retval 0 成功, -1 失败 + */ +int8_t MRobot_RegisterCommand(const char *command, const char *help_text, + MRobot_CommandCallback_t callback, int8_t param_count); + /** * @brief MRobot 主循环,在 CLI 任务中调用 */