上一篇文章是关于串口接收Overrun的问题,今天接着说串口,这次讨论的是串口发送函数写法的问题。串口发送可以通过轮询、中断或者DMA方式,这里我们讨论轮询发送方式。
串口发送有两个关键的标志位:Transmit Data Register Empty Flag和Transmit Complete Flag,各家MCU寄存器名字可能略有不同,但是其实都是一个含义。比如ST MCU叫TXE和TC
复旦微MCU叫TXBE和TXSE
TXE/TDRE/TXBE为1表示发送数据寄存器为空,数据已经发送到了移位寄存器里,这时就可以发送数据寄存器里写数据了。
TC/TXSE为1表示发送数据寄存器为空,移位寄存器数据也为空,整个发送过程都完成了。
网络上有很多关于这个话题的讨论,其中有一篇文章还专门针对以下5种串口发送函数的写法做了分析和好坏讨论
写法1:先判断TXE,再写数据
写法2:先判断TC,再写数据
写法3:先写数据,后判断TXE
写法4:先写数据,后判断TC
写法5:先判断TXE,再写数据,最后判断TC
文章最后结论是写法5最好,真的是这样吗?
写法5本身没问题,但是如果按照下面这种写法呢?
也就是每个字节之间只判断TXE标志位,最后一个字节写完之后判断TC标志位。
这种写法相比上述5写法完成的功能一样的,但是减少了字节之间的时间间隔,字节和字节之间不需要去判断TC,只需要判断TXE就可以做到字节间无间隔发送。
比如波特率为9600bps,发送时字节之间不加TC,可以看到两个字节之间时间为1.041ms。1/9600101000=1.041。
当加上TC标志判断之后,两个字节数据之间时间为1.145ms
两者相差的0.104ms(1.145ms-1.041ms=0.104ms)是因为加入了TC标志位判断,导致最后高电平时间增加了104us。
至于所有字节都发送完之后,要不要去判断一下TC,这个取决于实际应用。
不是任何情况都需要等待TC标志,比如循环往多个串口发送字符串,等待TC会拉长操作时间。第一个串口写完字符串,可以马上往第二个串口写,如果等待第一个串口最后一个字符写完,会拉长时间。
如果调用完串口发送函数后,紧接着就有关闭串口或进入低功耗的动作,那么就需要判断TC标志位,否则就可能会导致最后一字节数据没有正确发出去。或者其它一些应用要求必须要等串口数据实际发送完成后才执行其他动作,就得加上TC标志位的判断。
所以这俩标志位到底怎么用,大家搞清楚了吗?
关注我们:扫码加入嵌入式交流群