上一篇文章是關于串口接收Overrun的問題,今天接著說串口,這次討論的是串口發(fā)送函數(shù)寫法的問題。串口發(fā)送可以通過輪詢、中斷或者DMA方式,這里我們討論輪詢發(fā)送方式。
串口發(fā)送有兩個關鍵的標志位:Transmit Data Register Empty Flag和Transmit Complete Flag,各家MCU寄存器名字可能略有不同,但是其實都是一個含義。比如ST MCU叫TXE和TC
復旦微MCU叫TXBE和TXSE
TXE/TDRE/TXBE為1表示發(fā)送數(shù)據(jù)寄存器為空,數(shù)據(jù)已經(jīng)發(fā)送到了移位寄存器里,這時就可以發(fā)送數(shù)據(jù)寄存器里寫數(shù)據(jù)了。
TC/TXSE為1表示發(fā)送數(shù)據(jù)寄存器為空,移位寄存器數(shù)據(jù)也為空,整個發(fā)送過程都完成了。
網(wǎng)絡上有很多關于這個話題的討論,其中有一篇文章還專門針對以下5種串口發(fā)送函數(shù)的寫法做了分析和好壞討論
寫法1:先判斷TXE,再寫數(shù)據(jù)
寫法2:先判斷TC,再寫數(shù)據(jù)
寫法3:先寫數(shù)據(jù),后判斷TXE
寫法4:先寫數(shù)據(jù),后判斷TC
寫法5:先判斷TXE,再寫數(shù)據(jù),最后判斷TC
文章最后結論是寫法5最好,真的是這樣嗎?
寫法5本身沒問題,但是如果按照下面這種寫法呢?
也就是每個字節(jié)之間只判斷TXE標志位,最后一個字節(jié)寫完之后判斷TC標志位。
這種寫法相比上述5寫法完成的功能一樣的,但是減少了字節(jié)之間的時間間隔,字節(jié)和字節(jié)之間不需要去判斷TC,只需要判斷TXE就可以做到字節(jié)間無間隔發(fā)送。
比如波特率為9600bps,發(fā)送時字節(jié)之間不加TC,可以看到兩個字節(jié)之間時間為1.041ms。1/9600101000=1.041。
當加上TC標志判斷之后,兩個字節(jié)數(shù)據(jù)之間時間為1.145ms
兩者相差的0.104ms(1.145ms-1.041ms=0.104ms)是因為加入了TC標志位判斷,導致最后高電平時間增加了104us。
至于所有字節(jié)都發(fā)送完之后,要不要去判斷一下TC,這個取決于實際應用。
不是任何情況都需要等待TC標志,比如循環(huán)往多個串口發(fā)送字符串,等待TC會拉長操作時間。第一個串口寫完字符串,可以馬上往第二個串口寫,如果等待第一個串口最后一個字符寫完,會拉長時間。
如果調(diào)用完串口發(fā)送函數(shù)后,緊接著就有關閉串口或進入低功耗的動作,那么就需要判斷TC標志位,否則就可能會導致最后一字節(jié)數(shù)據(jù)沒有正確發(fā)出去?;蛘咂渌恍靡蟊仨氁却跀?shù)據(jù)實際發(fā)送完成后才執(zhí)行其他動作,就得加上TC標志位的判斷。
所以這倆標志位到底怎么用,大家搞清楚了嗎?
關注我們:掃碼加入嵌入式交流群