#include "uart.h" #include "network.h" #include #include UART_HandleTypeDef huart1; UART_HandleTypeDef huart2; UART_HandleTypeDef huart3; UART_HandleTypeDef huart4; uint16_t Rx_Len = 0; uint8_t Rx_Buf[Rx_Max] = {0}; volatile uint8_t uart1_rx_ready = 0; uint8_t uart1_rx_buf[UART1_RX_BUF_SIZE] = {0}; /* 诊断计数:UART4 高吞吐接收健康状况(OTA 排障用) */ volatile uint32_t g_uart4_rxcplt_cnt = 0; /* DMA 填满重启次数 */ volatile uint32_t g_uart4_ore_cnt = 0; /* 溢出错误次数 */ volatile uint8_t uart2_rx_ready = 0; uint8_t uart2_rx_buf[UART2_RX_BUF_SIZE] = {0}; static uint8_t uart1_rx_byte = 0; static uint8_t uart1_cmd_buf[UART1_RX_BUF_SIZE] = {0}; static uint8_t uart1_cmd_index = 0; static uint32_t uart1_last_rx_tick = 0; static uint8_t uart2_rx_byte = 0; static uint8_t uart2_cmd_buf[UART2_RX_BUF_SIZE] = {0}; static uint8_t uart2_cmd_index = 0; static uint32_t uart2_last_rx_tick = 0; #define UART1_CMD_TIMEOUT_MS 100u /* 无换行时,字符间隔超过该时间视为命令结束 */ #define UART2_CMD_TIMEOUT_MS 20u /* 485 返回帧较短,20ms 视为帧结束 */ void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) Error_Handler(); } void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 9600; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) Error_Handler(); } void MX_USART3_UART_Init(void) { huart3.Instance = USART3; huart3.Init.BaudRate = 115200; /* 上电默认 115200(安全档),cat_connect_network 里再自适应切 921600 */ huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart3.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart3) != HAL_OK) Error_Handler(); } /* UART4: WiFi ESP-01S 模块 (PC10=TX -> ESP_RXD, PC11=RX <- ESP_TXD) * 上电初始 115200(ESP-01S AT 固件出厂默认), * esp_reset 里探测成功后会用 AT+UART_DEF 固定为 WIFI_BAUD_TARGET */ void MX_UART4_UART_Init(void) { huart4.Instance = UART4; huart4.Init.BaudRate = 115200; huart4.Init.WordLength = UART_WORDLENGTH_8B; huart4.Init.StopBits = UART_STOPBITS_1; huart4.Init.Parity = UART_PARITY_NONE; huart4.Init.Mode = UART_MODE_TX_RX; huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart4.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart4) != HAL_OK) Error_Handler(); } void USART3_StartRx(void) { /* 避免重复启动 DMA: 若已在接收则先停止再启动 */ if (huart3.RxState != HAL_UART_STATE_READY) { HAL_UART_DMAStop(&huart3); } HAL_UART_Receive_DMA(&huart3, Rx_Buf, Rx_Max); __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); } /* 停止 USART3 DMA 接收:WiFi/4G 互斥复用 Rx_Buf,切 WiFi 通道时必须先停 4G 接收 */ void USART3_StopRx(void) { __HAL_UART_DISABLE_IT(&huart3, UART_IT_IDLE); HAL_UART_DMAStop(&huart3); } /* 启动 UART4 DMA+IDLE 接收:与 USART3 复用同一块 Rx_Buf(两通道互斥,靠 StartRx/StopRx 保证) */ void UART4_StartRx(void) { if (huart4.RxState != HAL_UART_STATE_READY) { HAL_UART_DMAStop(&huart4); } HAL_UART_Receive_DMA(&huart4, Rx_Buf, Rx_Max); __HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE); } void UART4_StopRx(void) { __HAL_UART_DISABLE_IT(&huart4, UART_IT_IDLE); HAL_UART_DMAStop(&huart4); } /* 运行中切换 UART4 波特率:只重写 BRR 寄存器,不动 GPIO/NVIC/DMA 配置。 * UART4 挂在 APB1(36MHz) 上 */ void UART4_SetBaudRate(uint32_t baud) { if (huart4.RxState != HAL_UART_STATE_READY) { HAL_UART_DMAStop(&huart4); } huart4.Init.BaudRate = baud; UART4->BRR = UART_BRR_SAMPLING16(36000000u, baud); __HAL_UART_CLEAR_PEFLAG(&huart4); __HAL_UART_CLEAR_FEFLAG(&huart4); __HAL_UART_CLEAR_NEFLAG(&huart4); __HAL_UART_CLEAR_OREFLAG(&huart4); __HAL_UART_CLEAR_IDLEFLAG(&huart4); HAL_UART_Receive_DMA(&huart4, Rx_Buf, Rx_Max); __HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE); } /* UART 错误回调:ORE(溢出) 等错误会让 HAL 中止整个 DMA 接收 * (stm32f1xx_hal_uart.c: UART_EndRxTransfer + HAL_DMA_Abort_IT), * 此后模块应答全丢,必须立即重新武装接收。 * 921600 高波特率下,模块连续突发数据撞上 IDLE 处理的 DMA 重启窗口 * 时容易触发 ORE,这里按当前激活的网络通道自愈。 */ void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { if (huart->Instance == UART4) { g_uart4_ore_cnt++; __HAL_UART_CLEAR_OREFLAG(huart); __HAL_UART_CLEAR_PEFLAG(huart); __HAL_UART_CLEAR_FEFLAG(huart); __HAL_UART_CLEAR_NEFLAG(huart); __HAL_UART_CLEAR_IDLEFLAG(huart); huart->ErrorCode = HAL_UART_ERROR_NONE; if (NET_GetActiveBackend() == NET_BACKEND_WIFI) { HAL_UART_Receive_DMA(&huart4, Rx_Buf, Rx_Max); __HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE); } } else if (huart->Instance == USART1) { __HAL_UART_CLEAR_OREFLAG(huart); __HAL_UART_CLEAR_PEFLAG(huart); __HAL_UART_CLEAR_FEFLAG(huart); __HAL_UART_CLEAR_NEFLAG(huart); __HAL_UART_CLEAR_IDLEFLAG(huart); huart->ErrorCode = HAL_UART_ERROR_NONE; HAL_UART_Receive_IT(&huart1, &uart1_rx_byte, 1); /* 蓝牙/调试口被 ORE 弄挂后立即恢复接收 */ } else if (huart->Instance == USART2) { __HAL_UART_CLEAR_OREFLAG(huart); __HAL_UART_CLEAR_PEFLAG(huart); __HAL_UART_CLEAR_FEFLAG(huart); __HAL_UART_CLEAR_NEFLAG(huart); __HAL_UART_CLEAR_IDLEFLAG(huart); huart->ErrorCode = HAL_UART_ERROR_NONE; HAL_UART_Receive_IT(&huart2, &uart2_rx_byte, 1); /* RS485 秤口同样自愈 */ } else if (huart->Instance == USART3) { __HAL_UART_CLEAR_OREFLAG(huart); __HAL_UART_CLEAR_PEFLAG(huart); __HAL_UART_CLEAR_FEFLAG(huart); __HAL_UART_CLEAR_NEFLAG(huart); __HAL_UART_CLEAR_IDLEFLAG(huart); huart->ErrorCode = HAL_UART_ERROR_NONE; if (NET_GetActiveBackend() == NET_BACKEND_4G) { HAL_UART_Receive_DMA(&huart3, Rx_Buf, Rx_Max); __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); } } } /* 运行中切换 USART3 波特率:只重写 BRR 寄存器,不动 GPIO/NVIC/DMA 配置。 * USART3 挂在 APB1(36MHz) 上 */ void USART3_SetBaudRate(uint32_t baud) { if (huart3.RxState != HAL_UART_STATE_READY) { HAL_UART_DMAStop(&huart3); } huart3.Init.BaudRate = baud; USART3->BRR = UART_BRR_SAMPLING16(36000000u, baud); __HAL_UART_CLEAR_PEFLAG(&huart3); __HAL_UART_CLEAR_FEFLAG(&huart3); __HAL_UART_CLEAR_NEFLAG(&huart3); __HAL_UART_CLEAR_OREFLAG(&huart3); __HAL_UART_CLEAR_IDLEFLAG(&huart3); HAL_UART_Receive_DMA(&huart3, Rx_Buf, Rx_Max); __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); } void USART1_StartRx(void) { uart1_rx_ready = 0; uart1_cmd_index = 0; uart1_last_rx_tick = 0; memset(uart1_cmd_buf, 0, sizeof(uart1_cmd_buf)); memset(uart1_rx_buf, 0, sizeof(uart1_rx_buf)); HAL_UART_Receive_IT(&huart1, &uart1_rx_byte, 1); } void USART2_StartRx(void) { uart2_rx_ready = 0; uart2_cmd_index = 0; uart2_last_rx_tick = 0; memset(uart2_cmd_buf, 0, sizeof(uart2_cmd_buf)); memset(uart2_rx_buf, 0, sizeof(uart2_rx_buf)); HAL_UART_Receive_IT(&huart2, &uart2_rx_byte, 1); } /* 从 USART2 接收缓冲区取出一帧(20ms 无新字节结束),返回帧长度,0 表示暂无完整帧 */ uint16_t USART2_GetFrame(uint8_t *out, uint16_t out_size) { if (uart2_rx_ready) { uart2_rx_ready = 0; uint16_t len = uart2_cmd_index < out_size ? uart2_cmd_index : out_size - 1; memcpy(out, uart2_cmd_buf, len); out[len] = '\0'; uart2_cmd_index = 0; return len; } return 0; } /* 中断接收回调:把单个字符追加到命令缓冲区,回车换行结束; * 无换行时,字符间隔超过 UART1_CMD_TIMEOUT_MS 自动提交 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART1) { uint8_t ch = uart1_rx_byte; if (ch == '\r' || ch == '\n') { if (uart1_cmd_index > 0) { uart1_cmd_buf[uart1_cmd_index] = '\0'; memcpy(uart1_rx_buf, uart1_cmd_buf, uart1_cmd_index + 1); uart1_rx_ready = 1; uart1_cmd_index = 0; } } else if (uart1_cmd_index < UART1_RX_BUF_SIZE - 1) { uart1_cmd_buf[uart1_cmd_index++] = ch; uart1_last_rx_tick = HAL_GetTick(); } HAL_UART_Receive_IT(&huart1, &uart1_rx_byte, 1); } else if (huart->Instance == USART2) { uint8_t ch = uart2_rx_byte; if (uart2_cmd_index < UART2_RX_BUF_SIZE - 1) { uart2_cmd_buf[uart2_cmd_index++] = ch; uart2_last_rx_tick = HAL_GetTick(); } HAL_UART_Receive_IT(&huart2, &uart2_rx_byte, 1); } else if (huart->Instance == UART4) { /* DMA(NORMAL) 填满 Rx_Buf:连续数据流没有空闲间隙、IDLE 不触发, * 若不在这里搬运并重启,接收将永久停摆(WiFi OTA 大流量下载必现) */ g_uart4_rxcplt_cnt++; if (NET_GetActiveBackend() == NET_BACKEND_WIFI && (U2_CopyIndex + Rx_Max) < (U2_COPY_SIZE - 1)) { memcpy(U2_CopyBuff + U2_CopyIndex, Rx_Buf, Rx_Max); U2_CopyIndex += Rx_Max; U2_CopyBuff[U2_CopyIndex] = '\0'; U2_CopyFlag = 1; } __HAL_UART_CLEAR_IDLEFLAG(&huart4); HAL_UART_Receive_DMA(&huart4, Rx_Buf, Rx_Max); __HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE); } else if (huart->Instance == USART3) { /* 同理:4G 侧理论上也可能遇到连续无间隙数据流 */ if (NET_GetActiveBackend() == NET_BACKEND_4G && (U2_CopyIndex + Rx_Max) < (U2_COPY_SIZE - 1)) { memcpy(U2_CopyBuff + U2_CopyIndex, Rx_Buf, Rx_Max); U2_CopyIndex += Rx_Max; U2_CopyBuff[U2_CopyIndex] = '\0'; U2_CopyFlag = 1; } __HAL_UART_CLEAR_IDLEFLAG(&huart3); HAL_UART_Receive_DMA(&huart3, Rx_Buf, Rx_Max); __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); } } /* 在 USART2_GetFrame 被轮询前,20ms 无新字节自动提交帧 */ void USART2_Tick(void) { if (uart2_cmd_index > 0 && (HAL_GetTick() - uart2_last_rx_tick) > UART2_CMD_TIMEOUT_MS) { uart2_rx_ready = 1; } } /* 不区分大小写的字符串比较 */ static int uart_strcasecmp(const char *a, const char *b) { while (*a && *b) { char ca = (char)toupper((unsigned char)*a); char cb = (char)toupper((unsigned char)*b); if (ca != cb) return ca - cb; a++; b++; } return (char)toupper((unsigned char)*a) - (char)toupper((unsigned char)*b); } /* 检查 USART1 是否收到指定命令(不区分大小写),检查后清除 ready */ int USART1_CheckCommand(const char *cmd) { const char *got = USART1_GetCommand(); if (!got) return 0; return (uart_strcasecmp(got, cmd) == 0); } /* 获取当前接收到的命令字符串(用于自定义解析)。 * 支持两种结束方式:收到 \r/\n 立即结束;无换行时字符间隔超过 100ms 自动结束。 */ const char *USART1_GetCommand(void) { if (uart1_rx_ready) { uart1_rx_ready = 0; return (const char *)uart1_rx_buf; } if (uart1_cmd_index > 0 && (HAL_GetTick() - uart1_last_rx_tick) > UART1_CMD_TIMEOUT_MS) { uart1_cmd_buf[uart1_cmd_index] = '\0'; memcpy(uart1_rx_buf, uart1_cmd_buf, uart1_cmd_index + 1); uart1_cmd_index = 0; return (const char *)uart1_rx_buf; } return NULL; }