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