2025-08-12 00:32:39 +08:00

204 lines
7.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "command.h"
#include "uart_ring_buffer.h"
#include "led.h"
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
/*
协议说明(依据用户提供的旧实现):
Host -> Device 帧格式:
[0] HEADER = 0xD5
[1] BOARD_TYPE = 0x03
[2] LEN = 数据区字节数
[3..(3+LEN-1)] 数据
[last] CRC = 从下标 1 到 (last-1) 的累加和低 8 位
数据示例(两字节命令):"M1" / "M2" / "M3"
Device -> Host 应答:复用 0xB5 开头:
[0] 0xB5, [1] TYPE(例如 0xF0=OK, 0xF1..=错误类), [2] LEN, [3..] payload, [last] CRC同上规则
*/
// 旧工程中的外部状态与复位函数(本工程暂不直接使用,按要求保留为注释):
// extern bool g_statusSwitch; // 来自其他业务模块
// void fwdgt_reset_mcu(void); // 看门狗复位
#define PROTOCOL_PACKAGE_HEADER 0xD5
#define PROTOCOL_BOARD_TYPE 0x03
#define PROTOCOL_PACKAGE_LENGTH 0x02
#define PACKAGE_MIN_LENGTH 6
/* 可选的应答类型定义(与示例保持一致,可按需扩展) */
#define RESP_HEADER 0xB5
#define RESP_TYPE_OK 0xF0
#define RESP_TYPE_CRC_ERR 0xF1
#define RESP_TYPE_HEADER_ERR 0xF2
#define RESP_TYPE_TYPE_ERR 0xF3
#define RESP_TYPE_LEN_ERR 0xF4
#define CMD_BUF_SIZE 64
/* 计算 CRC从索引 1 累加到 len-2不含 HEADER 与 CRC 字节) */
static uint8_t proto_sum_crc(const uint8_t *data, uint8_t len)
{
uint8_t crc = 0;
// 仅在满足协议最小帧长时计算header + type + len + payload + crc
if (len < PACKAGE_MIN_LENGTH) return 0;
// 累加从索引 1 到 len-2 的字节(不含 header 和 crc 字节)
for (uint8_t i = 1; i < (uint8_t)(len - 1); i++) {
crc += data[i];
}
return crc;
}
/* 发送应答header(0xB5), type, len, payload[len], crc */
static void send_response(uint8_t type, const uint8_t *payload, uint8_t len)
{
uint8_t buf_len = (uint8_t)(3 + len + 1);
uint8_t buf[16]; // 简单场景足够,必要时可增大
if (buf_len > sizeof(buf)) return; // 防御
buf[0] = RESP_HEADER;
buf[1] = type;
buf[2] = len;
for (uint8_t i = 0; i < len; i++) buf[3 + i] = payload ? payload[i] : 0;
buf[buf_len - 1] = proto_sum_crc(buf, buf_len);
for (uint8_t i = 0; i < buf_len; i++) {
printf("%c", buf[i]);
}
}
void handle_command(const uint8_t *cmd, uint8_t len) {
// 期望帧D5 03 02 'M' '1' CRC或 'M2'/'M3'
if (len < PACKAGE_MIN_LENGTH) return; // 最小长度 3+2+1
uint8_t payload_len = cmd[2];
if (payload_len < 2) return; // 我们期望 2 字节命令
char c0 = (char)cmd[3];
char c1 = (char)cmd[4];
if (c0 == 'M' && c1 == '1') {
led_on();
// g_statusSwitch = true; // 保留但注释:切换业务状态
// OK: 返回 "ok"
const uint8_t ok[] = { 'o', 'k' };
send_response(RESP_TYPE_OK, ok, sizeof(ok));
} else if (c0 == 'M' && c1 == '2') {
led_off();
// g_statusSwitch = false; // 保留但注释:切换业务状态
const uint8_t ok[] = { 'o', 'k' };
send_response(RESP_TYPE_OK, ok, sizeof(ok));
} else if (c0 == 'M' && c1 == '3') {
const uint8_t ok[] = { 'o', 'k' };
send_response(RESP_TYPE_OK, ok, sizeof(ok));
// fwdgt_reset_mcu(); // 保留但注释:触发 MCU 复位(依赖外部实现)
// 或NVIC_SystemReset();(需包含 CMSIS 头)
} else {
const uint8_t err[] = { 'e','r','r', 0x3C };
send_response(RESP_TYPE_HEADER_ERR, err, sizeof(err));
}
}
void command_process(void) {
static uint8_t cmd_buf[CMD_BUF_SIZE];
static uint8_t cmd_len = 0;
static uint8_t expected_total = 0; // 0 表示尚未确定总长度
while (uart_ring_buffer_available() > 0) {
int byte = uart_ring_buffer_get();
if (byte < 0) break;
if (cmd_len == 0) {
if ((uint8_t)byte == PROTOCOL_PACKAGE_HEADER) {
cmd_buf[cmd_len++] = (uint8_t)byte;
expected_total = 0; // 等待进一步字段以确定长度
} else {
// 丢弃非起始字节
}
continue;
}
// 累积后续字节
cmd_buf[cmd_len++] = (uint8_t)byte;
// 当到达长度字段(索引 2确定总长度3 + LEN + 1
if (cmd_len == 3) {
uint8_t payload_len = cmd_buf[2];
expected_total = (uint8_t)(3 + payload_len + 1);
if (expected_total > CMD_BUF_SIZE) {
// 异常:长度超界,复位状态机
cmd_len = 0;
expected_total = 0;
}
continue;
}
if (expected_total > 0 && cmd_len == expected_total) {
// 到帧尾,进行各项校验
bool ok = true;
if (cmd_buf[0] != PROTOCOL_PACKAGE_HEADER) {
const uint8_t err[] = { 'e','r','r', 0x3E }; // header 错
send_response(RESP_TYPE_HEADER_ERR, err, sizeof(err));
ok = false;
}
if (ok && cmd_buf[1] != PROTOCOL_BOARD_TYPE) {
const uint8_t err[] = { 'e','r','r', 0x3F }; // type 错
send_response(RESP_TYPE_TYPE_ERR, err, sizeof(err));
ok = false;
}
if (ok && cmd_buf[2] != PROTOCOL_PACKAGE_LENGTH) {
const uint8_t err[] = { 'e','r','r', 0x40 }; // length 错
send_response(RESP_TYPE_LEN_ERR, err, sizeof(err));
ok = false;
}
if (ok) {
uint8_t crc_calc = proto_sum_crc(cmd_buf, expected_total);
uint8_t crc_recv = cmd_buf[expected_total - 1];
if (crc_calc != crc_recv) {
const uint8_t err[] = { 'e','r','r', 0x3D }; // crc 错
send_response(RESP_TYPE_CRC_ERR, err, sizeof(err));
ok = false;
}
}
if (ok) {
handle_command(cmd_buf, expected_total);
}
// 复位,等待下一帧
cmd_len = 0;
expected_total = 0;
}
if (cmd_len >= CMD_BUF_SIZE) {
// 防御:缓冲溢出,复位状态机
cmd_len = 0;
expected_total = 0;
}
}
}
// -----------------------------------------------------------------------------
// 下列为与传感器相关的报告函数占位,按要求“保留但注释掉”。
// 原工程中依赖 ldc1612/tmp112a 读数并通过 0xB5 帧打印上报。
// 若后续集成这些传感器驱动,可解注释并补齐实现。
//
// static uint8_t package_header[3] = {0xB5, 0xF0, 0x04};
// static uint8_t package_data[4] = {0};
//
// void eddy_current_value_report(void) {
// uint32_t eddy_current_value_uint32 = ldc1612_get_raw_channel_result(CHANNEL_0);
// (void)eddy_current_value_uint32;
// // 按原协议组帧并 printf 发送B5 F0 04 [data3..data0] CRC
// }
//
// void tempture_value_report(void) {
// uint32_t temperature_uint32 = tmp112a_get_raw_channel_result();
// (void)temperature_uint32;
// // 按原协议组帧并 printf 发送B5 F0 04 [data3..data0] CRC
// }