
做STM32开发,串口可以说真的是无处不在,芯片与芯片之间的通信可以用TTL电平,多机通信可以用RS485工控总线,对外上位机需要RS232串口通信,那么作为一款经典的单片机系列STM32,应该怎么处理串口报文最有效快捷呢,无数的实践证明,大量的项目经验告诉我们答案永远是串口空闲中断。" R5 R8 [4 C& s+ d 那么什么是串口空闲中断呢,大家都知道串口在空闲的时候默认是高电平,在发数据的时候有起始位,数据位,结束位等等,传统的串口处理数据的方式是一个个字节接收,这样做猛地一看好像没有啥问题,但却留下很多隐患,比如:1.固定的报头,一个个字节接收少接收一字节,导致报文接收异常;2.同时开两个115200波特率的串口,因为两个串口本身是独立的,一个个字节接收数据导致频繁进入中断,存在中断嵌套的风险;3.驱动底层代码会非常繁琐,把一个STM32硬生生玩成一个FPGA,判断报头报尾,CRC校验还需要C语言做成类似Verilog状态机的逻辑等等,笔者在这里不在赘述了,因为不是这篇博客的重点。+ j( H& L' V- h# b, M. }" I8 B% G+ ` , A% t2 T+ _. f 串口空闲中断可以简单地理解成,当串口不发数据的时候产生中断,然后我们可以巧妙地把这些数据通过DMA搬运到指定变量地址上,这样当主机不发数据的时候,即可以得到整条报文的数据,和报文的长度,之后再对整条报文进行处理,包括CRC校验,逻辑层赋值,应用层控制等其他相关操作,这样就极大地减少了频繁进入中断的次数,也优化了底层逻辑,因为收到是一整条报文而不是一个个字节,如图1所示,笔者这里用到的STM32F103RCT6芯片,PCB上把STM32的PB6和PB7作为UART1,查阅芯片手册可以看到如图2所示,DMA1的通道4和通道5是UART1的对应的DMA通道,所以我们在编写完初始化USART1_Init后,还需要如图3所示打开两个通道的中断。 3 M/ {/ t) x: \$ [ ![]() 6 D; l4 w6 a$ j# s! a" G5 Y ![]() ![]() ![]() ![]() ![]() 3 A7 O' W' y, I; S) {+ V+ N1 w 2 f7 t5 I* E" ` 图1 USART1的初始化函数" Z5 K0 x& Q A/ ` / i5 N, R* K; A0 _4 [# D) _ ![]() 2 W. `6 V: ?& O% I6 Q9 ] 图2 STM32F103系列的DMA通道示意图 # \5 S) B' \* [1 L, x* Z, c, c- C; Z( T ![]() 图3 DMA通道4和通道5中断开启 如图4所示,定义了串口收发的数据报文,这里面flag在串口空闲中断里置位,表示接收到一包数据,在主函数里再进行数据解包处理操作,切记在STM32中断里不要做过多的判断和等待或者其他复杂操作,假设来了一个中断,CPU处理了10秒钟,那么大家都知道STM32也好,ARM LIUNX也好运行的原理,中断来了要压栈保护现场,屏蔽IRQ等其他中断,如果一个中断处理太长时间,那么对于用户来说体验会非常差,其他操作都不被CPU响应,仿佛是死机了一样,毫无实时性可言,如图5所示是串口空闲中断处理函数,这里需要说明几个地方:1.因为开始DMA接收的数据长度设定的是2048个字节,所以USART1_Type.RX_Count = 2048-Uart1Handle.hdmarx->Instance->CNDTR这句话,代表把整包报文的数据字节长度赋值给USART1_Type.RX_Count;2.需要在空闲中断里先关DMA,再使能DMA才能在下一次串口空闲中断产生的时候触发;3.可以在串口空闲中断处简单地判断报头,简化了逻辑层的设计。 " [/ \3 ~0 W1 J% d6 C$ m2 i ![]() 图4 串口收发数据报文定义 r) ~) Y( {' _/ ` ![]() 图5 串口空闲中断处理函数- N2 w9 i9 z( J ————————————————/ u9 T H" }$ j6 ~5 ]1 F9 N 版权声明:青青豌豆+ k, h8 W) f. ~4 G* `' ?1 s 如有侵权请联系删除+ \6 t+ b- U1 _3 V, J: ~' b+ ?! J |
实战经验 | TrustZone应用中串口通信的DMA传输失败问题
狂欢三】STM32C031使用TIM定时器DMA方式实现WS2812彩灯输出(三)
stm32使用定时器触发dma传输,启动dma没反应的几种情况的解决方法
STM32的DMA双缓冲模式详解
基于STM32的心率计以DMA方式获取传感器数据经验分享
基于STM32利用ADC+DMA采样显示经验分享
【经验分享】STM32使用DMA接收串口数据
基于STM32的DMA经验分享
基于STM32的ADC+DMA采样与板载运放跟随经验分享
基于STM32F407和Cubemx的ADC采集+DMA传输实现简易示波器经验分享