/****************************************************************************** * @file jb_uart.c * @brief USART3 协议串口驱动实现 * @author cyWu <1917507415@qq.com> * @date 2026.08.10 * @version V1.0.0 * @history * - V1.0.0, 2026.08.10, cyWu, 首次发布 ******************************************************************************/ #include "jb_uart.h" #include "log.h" #include /*============================================================================*/ /* 私有宏 */ /*============================================================================*/ #define UART_DBG_BUF_SIZE (256U) #define UART_DBG_IDLE_MS (30U) /* 协议 MAX_PACKAGE_LEN(128) + 前置 0x00 */ #define JB_UART_TX_MAX_LEN (129U) /*============================================================================*/ /* 私有变量 */ /*============================================================================*/ UART_HandleTypeDef g_jb_uart_handle; static uint8_t s_initialized; static uint8_t s_uart_rx_byte; static JbUartRxCallback_t s_rx_cb; static uint8_t s_dbg_buf[UART_DBG_BUF_SIZE]; static volatile uint16_t s_dbg_head; static volatile uint16_t s_dbg_tail; static volatile uint32_t s_dbg_last_rx_ms; static volatile uint32_t s_rx_total; static volatile uint32_t s_err_code; static volatile uint8_t s_err_pending; /*============================================================================*/ /* 私有函数 */ /*============================================================================*/ /** * @brief ISR 安全:调试缓冲写入 1 字节 * @param byte 数据 */ static void uart_dbg_push(uint8_t byte) { uint16_t next = (uint16_t)((s_dbg_head + 1U) % UART_DBG_BUF_SIZE); if (next == s_dbg_tail) { s_dbg_tail = (uint16_t)((s_dbg_tail + 1U) % UART_DBG_BUF_SIZE); } s_dbg_buf[s_dbg_head] = byte; s_dbg_head = next; s_dbg_last_rx_ms = HAL_GetTick(); s_rx_total++; } /** * @brief 打印十六进制 * @param tag 标签 * @param buf 数据 * @param len 长度 */ static void uart_dbg_print_hex(const char *tag, const uint8_t *buf, uint32_t len) { uint32_t i; printf("UART %s %lu bytes:", tag, (unsigned long)len); for (i = 0; i < len; i++) { printf(" %02X", buf[i]); } printf("\r\n"); } /** * @brief 刷出 RX 调试与错误日志 */ static void uart_dbg_flush(void) { uint8_t dump[UART_DBG_BUF_SIZE]; uint16_t dump_len = 0; uint16_t tail; uint16_t head; if (s_err_pending) { s_err_pending = 0; printf("UART RX error: 0x%08lX, total_rx=%lu\r\n", (unsigned long)s_err_code, (unsigned long)s_rx_total); } head = s_dbg_head; tail = s_dbg_tail; if (head == tail) { return; } if ((HAL_GetTick() - s_dbg_last_rx_ms) < UART_DBG_IDLE_MS) { return; } while ((tail != head) && (dump_len < UART_DBG_BUF_SIZE)) { dump[dump_len++] = s_dbg_buf[tail]; tail = (uint16_t)((tail + 1U) % UART_DBG_BUF_SIZE); } s_dbg_tail = tail; uart_dbg_print_hex("RX", dump, dump_len); printf("UART RX total=%lu\r\n", (unsigned long)s_rx_total); } /*============================================================================*/ /* 公有接口 */ /*============================================================================*/ /** * @brief 注册 RX 回调 * @param cb 回调 */ void jb_uart_set_rx_callback(JbUartRxCallback_t cb) { s_rx_cb = cb; } /** * @brief 初始化 USART3 * @return JbUart_Ret_t */ JbUart_Ret_t jb_uart_init(void) { if (s_initialized) { return JB_UART_OK; } g_jb_uart_handle.Instance = JB_USART; g_jb_uart_handle.Init.BaudRate = JB_UART_BAUDRATE; g_jb_uart_handle.Init.WordLength = UART_WORDLENGTH_8B; g_jb_uart_handle.Init.StopBits = UART_STOPBITS_1; g_jb_uart_handle.Init.Parity = UART_PARITY_NONE; g_jb_uart_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; g_jb_uart_handle.Init.Mode = UART_MODE_TX_RX; g_jb_uart_handle.Init.OverSampling = UART_OVERSAMPLING_16; g_jb_uart_handle.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&g_jb_uart_handle) != HAL_OK) { return JB_UART_ERR_HAL; } if (HAL_UART_Receive_IT(&g_jb_uart_handle, &s_uart_rx_byte, 1U) != HAL_OK) { return JB_UART_ERR_HAL; } s_initialized = 1U; printf("USART3 ready: PB10=TX PB11=RX baud=%lu 8N1, waiting RX...\r\n", (unsigned long)JB_UART_BAUDRATE); return JB_UART_OK; } /** * @brief 主循环周期处理 */ void jb_uart_run(void) { if (!s_initialized) { return; } uart_dbg_flush(); } /** * @brief 阻塞发送 * @param buf 数据 * @param len 长度 * @return 成功返回 len,失败 -1 */ int32_t jb_uart_write(uint8_t *buf, uint32_t len) { static uint8_t s_tx_buf[JB_UART_TX_MAX_LEN]; uint32_t tx_len; if (!buf) { return -1; } if (len == 0U) { return 0; } if (!s_initialized) { return -1; } if ((len + 1U) > JB_UART_TX_MAX_LEN) { return -1; } /* 协议帧前加 0x00 后连续发送,避免越界读与帧间空隙 */ s_tx_buf[0] = 0x00U; s_tx_buf[1] = 0x00U; memcpy(&s_tx_buf[2], buf, len); tx_len = len + 2U; uart_dbg_print_hex("TX", s_tx_buf, tx_len); if (HAL_UART_Transmit(&g_jb_uart_handle, s_tx_buf, (uint16_t)tx_len, 1000U) != HAL_OK) { printf("UART TX failed, len=%lu\r\n", (unsigned long)tx_len); return -1; } return (int32_t)len; } /** * @brief 获取初始化状态 * @return JbUart_Ret_t */ JbUart_Ret_t jb_uart_get_status(void) { if (!s_initialized) { return JB_UART_ERR_NOT_INIT; } return JB_UART_OK; } /*============================================================================*/ /* HAL 回调 */ /*============================================================================*/ /** * @brief UART RX 完成回调 * @param huart 句柄 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == JB_USART) { uart_dbg_push(s_uart_rx_byte); if (s_rx_cb != NULL) { s_rx_cb(s_uart_rx_byte); } (void)HAL_UART_Receive_IT(&g_jb_uart_handle, &s_uart_rx_byte, 1U); } } /** * @brief UART 错误回调 * @param huart 句柄 */ void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { if (huart->Instance == JB_USART) { s_err_code = HAL_UART_GetError(huart); s_err_pending = 1U; __HAL_UART_CLEAR_PEFLAG(huart); __HAL_UART_CLEAR_FEFLAG(huart); __HAL_UART_CLEAR_NEFLAG(huart); __HAL_UART_CLEAR_OREFLAG(huart); (void)HAL_UART_Receive_IT(&g_jb_uart_handle, &s_uart_rx_byte, 1U); } }