feat: 添加小车控制指令解析和校验和计算工具
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
BIN
物流小车/app.exe
Normal file
BIN
物流小车/app.exe
Normal file
Binary file not shown.
72
物流小车/checksum.py
Normal file
72
物流小车/checksum.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
物流小车控制指令 - 校验和算法工具(交互式)
|
||||
|
||||
用法:
|
||||
python checksum.py # 启动交互模式,手动输入指令计算校验和
|
||||
"""
|
||||
|
||||
import sys
|
||||
import io
|
||||
|
||||
if sys.platform == 'win32':
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
|
||||
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
|
||||
|
||||
|
||||
def calc_checksum(data: str) -> str:
|
||||
"""计算校验和:ASCII码求和 % 256 → 2位十六进制"""
|
||||
total = sum(ord(c) for c in data)
|
||||
return format(total % 256, '02X')
|
||||
|
||||
|
||||
def print_ascii_detail(data: str):
|
||||
"""打印每个字符的 ASCII 码值"""
|
||||
print(f"\n 原始字符串: {data}")
|
||||
print(f" ASCII 码分解:")
|
||||
|
||||
total = 0
|
||||
parts = []
|
||||
for c in data:
|
||||
val = ord(c)
|
||||
total += val
|
||||
parts.append(f"'{c}'({val})")
|
||||
|
||||
print(" " + " + ".join(parts))
|
||||
print(f" 总和 = {total}")
|
||||
print(f" 取余 = {total} % 256 = {total % 256}")
|
||||
print(f" 十六进制 = {calc_checksum(data)}")
|
||||
|
||||
|
||||
def main():
|
||||
print("\n" + "=" * 55)
|
||||
print(" 物流小车指令校验和工具(交互式)")
|
||||
print(" 输入原始字符串,自动计算校验和并生成完整指令")
|
||||
print(" 输入 q 退出")
|
||||
print("=" * 55)
|
||||
|
||||
while True:
|
||||
print(f"\n{'─' * 55}")
|
||||
raw = input("\n 请输入指令内容(如 LOGI:GS:001): ").strip()
|
||||
|
||||
if raw.lower() in ('q', 'quit', 'exit'):
|
||||
print("\n 再见!\n")
|
||||
break
|
||||
|
||||
if not raw:
|
||||
continue
|
||||
|
||||
# 如果用户输入的不是以 LOGI: 开头,自动拼接
|
||||
if not raw.upper().startswith('LOGI:'):
|
||||
print(f"\n [提示] 检测到未包含帧头,已自动添加 LOGI:")
|
||||
raw = 'LOGI:' + raw
|
||||
|
||||
cs = calc_checksum(raw)
|
||||
full_cmd = f"{raw}:{cs}#"
|
||||
|
||||
# 显示计算过程
|
||||
print_ascii_detail(raw)
|
||||
print(f"\n >>> 完整指令: {full_cmd}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1 +0,0 @@
|
||||
0hhh
|
||||
Reference in New Issue
Block a user