Files
vd_960/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/usart_biz.c
wangfq 4fbda96078 feat(vd960DBN): 实现 DLD960Loop 串口通信协议 (0x7F)
新增:
- docs/DLD960Loop_串口通信协议.md — 协议文档 V1.02
- loop_uart_proto.h/c — 协议实现: checksum/组包/解析/帧状态机/命令状态机

修改:
- usart_biz.c: 使用 lup_feed_byte() 帧解析器替代 timeout heuristic; 波特率修正为 115200
- tcp_json_srv.c/h: loop_param_set/query 真实实现(0x63/0x64), 0xC0 传感器推流, 延迟响应机制
- peripheral_main.c: 添加 tcp_json_push_sensor() 调用, 帧解析器超时保护

校验验证: 5个协议例程 XOR+SUM 全部通过
2026-07-02 09:26:34 +08:00

215 lines
6.8 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.
/*
* usart_biz.c
*
* Created on: 2026-02-26
* Author: wangfq
* Updated: 2026-07-02 — 使用 loop_uart_proto 帧解析器替代 timeout heuristic
*/
#include "config.h"
#include "cmcng.h"
#include "loop_uart_proto.h"
#include <string.h>
#include "dbn_ble_srv.h"
void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void uart_init(void){
GPIO_InitTypeDef GPIO_InitStructure = {0};
USART_InitTypeDef USART_InitStructure = {0};
NVIC_InitTypeDef NVIC_InitStructure = {0};
// usart1 : peripheral / DEBUG
//usart2 :loop mcu
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // Tx
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // Rx
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200; // 115200 (协议规定)
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART2, &USART_InitStructure);
// USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_Cmd(USART2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 初始化帧解析器
lup_frame_reset();
}
/*********************************************************************
* @fn USART1_IRQHandler
*
* @brief This function handles USART1 global interrupt request.
*
* @return none
*/
void USART1_IRQHandler(void)
{
}
/*********************************************************************
* @fn USART2_IRQHandler
*
* @brief USART2 RX — 使用 lup_feed_byte() 帧解析器
* 当解析出完整帧时,复制到 g_pkg_uart_2.pkg 并设置 flag
*
* @return none
*/
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
uint8_t _dat = USART_ReceiveData(USART2);
// 喂给帧解析器
if (lup_feed_byte(_dat)) {
// 帧接收完成,复制到 g_pkg_uart_2
const uint8_t *frame = lup_frame_data();
uint16_t frame_len = lup_frame_len();
if (frame_len <= BUFF_STACK_SIZE) {
memcpy(g_pkg_uart_2.pkg, frame, frame_len);
g_pkg_uart_2.offset = frame_len;
g_pkg_uart_2.flag = 1;
g_pkg_uart_2.tick = 0;
}
lup_frame_reset();
} else if (g_lup_parser.state != LUP_FRAME_STATE_IDLE) {
// 正在接收帧中tick 归零
g_pkg_uart_2.tick = 0;
}
}
}
void UART2_SendString(uint8_t *buf, uint16_t len)
{
uint16_t _len = len;
while(_len){
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
USART_SendData(USART2, *buf++);
_len--;
}
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
}
void UART1_SendString(uint8_t *buf, uint16_t len)
{
uint16_t _len = len;
while(_len){
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
USART_SendData(USART1, *buf++);
_len--;
}
}
/*
* uart_srv — 主循环中调用,处理已接收完整的 UART2 帧
*
* 处理流程:
* 1. 0x7F + 0xC0/0x0C → 传感器数据上报
* - 若无 BLE 连接 → 标记 `_report_flag`,在 TCP JSON 中处理
* - 若有 BLE 连接且 acs_enable → 转 0x8F 前缀发给 BLE
* 2. 0x7F + 其他 CMD → 响应帧,交给 lup_process_frame() 匹配挂起命令
* 3. 非 0x7F → 调试打印(可能是字符串等)
*/
void uart_srv(void)
{
uint8_t i;
uint8_t _report_flag = 0;
// 检查命令超时
lup_cmd_check_timeout();
if(g_pkg_uart_2.flag){
if(g_flag_counter_ota.flag == 0){
if(g_pkg_uart_2.pkg[0] == 0x7F){
uint8_t cmd = g_pkg_uart_2.pkg[3];
// --- 传感器上报 (0xC0) ---
if(cmd == 0xC0 && g_pkg_uart_2.pkg[4] == 0x0C)
{
if(g_dbn_ble_state_acs_enable.flag == 0){
// 无 BLE ACS 连接 → 标记为 TCP JSON 上报
_report_flag = 1;
}
else{
// BLE ACS 已连接 → 改 Magic 为 0x8F 发给 BLE
g_pkg_uart_2.pkg[0] = 0x8F;
}
}
else {
// --- 命令响应 → 交给协议处理器 ---
lup_process_frame(g_pkg_uart_2.pkg, g_pkg_uart_2.offset);
}
// 调试打印
for(i = 0; i < g_pkg_uart_2.offset; i++){
PRINT(" %02X", g_pkg_uart_2.pkg[i]);
}
PRINT("\n");
if(_report_flag){
// 传感器帧保留在 pkg 中供上层 (tcp_json_srv) 处理
// 不 InitPkgUart — 由上层消费后再 InitPkgUart
}
}
else {
// 非 0x7F 魔法字节
PRINT("Rcv_len:%d,dat: %s\n", g_pkg_uart_2.offset, g_pkg_uart_2.pkg);
}
}
else{
// OTA 模式 — 忽略 Loop MCU 数据
}
if(g_flag_bt_state){
g_flag_notify_temp = set_response_tran_to_notify(g_pkg_uart_2.pkg, g_pkg_uart_2.offset, &g_notify_buftemp);
}
else{
g_dbn_ble_state_acs_enable.flag = 0;
}
// 只有非 _report_flag 时才立即清空
// _report_flag 的帧由 tcp_json 消费后清理
if (!_report_flag) {
InitPkgUart(&g_pkg_uart_2);
}
}
}