feat: 添加小车控制指令解析和校验和计算工具

This commit is contained in:
2026-04-03 21:20:30 +08:00
parent 1cc8327f13
commit e382b06b03
4 changed files with 198 additions and 3 deletions

View File

@@ -8,6 +8,7 @@
*/
#include "protocol.h"
#include "bsp_motor.h"
#include "bsp_uart.h"
#include "checksum.h"
#include "cmsis_os.h"
@@ -19,6 +20,129 @@
/* 定义日志 TAG */
#define Protocol_TAG "Protocol"
/* 小车控制状态相关定义 */
#define CAR_PWM_MAX 3599U // PWM最大值对应100%
static uint8_t car_running = 0; // 小车运行状态1=运行0=停止)
static uint8_t car_speed_percent = 0; // 当前整体速度百分比0~100
static uint16_t car_target_station = 0; // 目标站点编号
/**
* @brief 百分比转PWM值
* @param percent 速度百分比0~100
* @return int16_t PWM占空比
*/
static int16_t CarCtrl_PercentToPwm(uint8_t percent)
{
if (percent > 100U) {
percent = 100U;
}
return (int16_t)((CAR_PWM_MAX * percent) / 100U);
}
/**
* @brief 停止所有电机
*/
static void CarCtrl_StopAll(void)
{
motor_stop(MOTOR_1);
motor_stop(MOTOR_2);
motor_stop(MOTOR_3);
motor_stop(MOTOR_4);
}
/**
* @brief 按当前 car_speed_percent 设置所有电机速度
*/
static void CarCtrl_ApplySpeed(void)
{
int16_t pwm = CarCtrl_PercentToPwm(car_speed_percent);
motor_set_speed(MOTOR_1, pwm);
motor_set_speed(MOTOR_2, pwm);
motor_set_speed(MOTOR_3, pwm);
motor_set_speed(MOTOR_4, pwm);
}
/**
* @brief 解析并执行协议命令
* @param cmd_payload 队列传入的命令字符串(如 "ST:RUN"、"SP:080"、"GS:005"
*/
static void CarCtrl_HandleCommand(const char *cmd_payload)
{
const char *arg = NULL;
if (cmd_payload == NULL || cmd_payload[0] == '\0') {
return;
}
// 查找冒号分隔符,分割命令类型和参数
arg = strchr(cmd_payload, ':');
if (arg == NULL) {
elog_w(Protocol_TAG, "未知控制指令: %s", cmd_payload);
return;
}
// 启动/停止命令(仅作为自动循迹任务的启动/暂停信号,不直接控制电机)
if (strncmp(cmd_payload, "ST", 2) == 0) {
if (strcmp(arg + 1, "RUN") == 0) {
car_running = 1;
elog_i(Protocol_TAG, "小车自动循迹启动, speed=%u%%, station=%u", car_speed_percent,
car_target_station);
} else if (strcmp(arg + 1, "STOP") == 0) {
car_running = 0;
elog_i(Protocol_TAG, "小车自动循迹暂停");
} else {
elog_w(Protocol_TAG, "未知启动/停止命令: %s", cmd_payload);
}
return;
}
// 设置整体速度命令
if (strncmp(cmd_payload, "SP", 2) == 0) {
unsigned int speed = 0;
// 解析速度参数百分比0~100
if (sscanf(arg + 1, "%u", &speed) == 1) {
if (speed > 100U) {
speed = 100U;
}
car_speed_percent = (uint8_t)speed;
elog_i(Protocol_TAG, "设置整体速度: %u%%", car_speed_percent);
// 如果当前处于运行状态,立即生效
if (car_running != 0U) {
CarCtrl_ApplySpeed();
}
} else {
elog_w(Protocol_TAG, "速度参数解析失败: %s", cmd_payload);
}
return;
}
// 设置目标站点命令
if (strncmp(cmd_payload, "GS", 2) == 0) {
unsigned int station = 0;
// 解析站点编号0~999
if (sscanf(arg + 1, "%u", &station) == 1) {
if (station > 999U) {
station = 999U;
}
car_target_station = (uint16_t)station;
elog_i(Protocol_TAG, "设置目标站点: %03u", car_target_station);
} else {
elog_w(Protocol_TAG, "站点参数解析失败: %s", cmd_payload);
}
return;
}
// 未知命令类型
elog_w(Protocol_TAG, "未支持的控制命令: %s", cmd_payload);
}
/* 引用在 freertos.c 中定义的消息队列句柄 */
extern osMessageQueueId_t CmdQueueHandle;
/**
@@ -110,7 +234,7 @@ void Protocol_HandleMessage(uint8_t *data, uint16_t len) {
void CarCtrl_Task(void *argument) {
/* USER CODE BEGIN CarCtrl_Task */
char cmd_payload[16];
char cmd_payload[16] = {0};
/* Infinite loop */
for (;;) {
/* 从消息队列中获取数据,阻塞等待 */
@@ -118,7 +242,7 @@ void CarCtrl_Task(void *argument) {
osOK) {
elog_i(CarCtrlTask_TAG, "CarCtrl: Received command (ASCII: %s) from queue",
cmd_payload);
/* 可以在这里添加根据 cmd_payload 控制小车的逻辑 */
CarCtrl_HandleCommand(cmd_payload);
}
// osDelay(1); // osMessageQueueGet 已经是阻塞的,不需要额外的 osDelay
}