shuichan_old/V1.1/STM32F103_App1/HardWare/UART/uart.c

210 lines
6.7 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 "uart.h"
#include <string.h>
#include <ctype.h>
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
UART_HandleTypeDef huart3;
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};
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();
}
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 波特率:只重写 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);
}
}
/* 在 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;
}