云计算百科
云计算领域专业知识百科平台

《嵌入式通讯协议栈实战》2 UART

第 2 篇:UART——串口的坑比你想象的多


1. 物理层:TTL、RS232、RS485 的区别

标准电平距离节点数
TTL 0=0V, 1=3.3V <1m 1对1
RS232 -12V/+12V <15m 1对1
RS485 差分 ±2V <1200m 最多 256 个

2. GD32 UART + DMA + 空闲中断

void uart_dma_init(void) {
rcu_periph_clock_enable(RCU_USART0);
rcu_periph_clock_enable(RCU_DMA0);

// UART 配置 115200-8-N-1
usart_deinit(USART0);
usart_baudrate_set(USART0, 115200);
usart_word_length_set(USART0, USART_WL_8BIT);
usart_stop_bit_set(USART0, USART_STB_1BIT);
usart_parity_config(USART0, USART_PM_NONE);

// DMA 接收(循环模式)
dma_parameter_struct dma_init_struct;
dma_deinit(DMA0, DMA_CH4);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.periph_addr = (uint32_t)&USART_RDATA(USART0);
dma_init_struct.memory_addr = (uint32_t)rx_dma_buf;
dma_init_struct.number = RX_BUF_SIZE;
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init(DMA0, DMA_CH4, &dma_init_struct);
dma_circulation_enable(DMA0, DMA_CH4); // 循环接收

usart_dma_receive_config(USART0, USART_RECEIVE_DMA_ENABLE);
usart_interrupt_enable(USART0, USART_INT_IDLE); // 空闲中断
usart_enable(USART0);
}


3. 环形缓冲区 + 空闲中断断帧

void USART0_IRQHandler(void) {
if (usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)) {
usart_data_receive(USART0); // 清除 IDLE 标志
uint16_t len = RX_BUF_SIZE dma_transfer_number_get(DMA0, DMA_CH4);
ringbuf_write(&rx_ring, rx_dma_buf, len);

// 通知解析任务
xSemaphoreGiveFromISR(xRXSemaphore, &woken);
}
}

空闲中断是 UART 断帧的最优雅方案——不需要帧头帧尾,不需要固定长度,一帧结束后自动触发。


下一篇:UART 协议设计——定义你自己的通讯协议

赞(0)
未经允许不得转载:网硕互联帮助中心 » 《嵌入式通讯协议栈实战》2 UART
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!