<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 關(guān)于STM32串口的理解

關(guān)于STM32串口的理解

作者: 時(shí)間:2016-11-18 來(lái)源:網(wǎng)絡(luò ) 收藏

總的來(lái)說(shuō),STM32單片機串口還是很好理解的,編程也不算復雜。當然我更愿意希望其中斷系統51單片機一樣的簡(jiǎn)單。

本文引用地址:http://dyxdggzs.com/article/201611/315877.htm

對于接收終端,就是RXNE了,這只在接收完成后才產(chǎn)生,在執行USART_ITConfig(USART1, USART_IT_RXNE, ENABLE)代碼時(shí)不會(huì )進(jìn)入ISR。但麻煩的就是發(fā)送有關(guān)的中斷了:TXE或者TC,根據資料和測試的結果,TXE在復位后就是置1的,即在執行USART_ITConfig(USART1, USART_IT_TXE, ENABLE)后會(huì )立即產(chǎn)生中斷請求。因此這造成一個(gè)麻煩的問(wèn)題:如果沒(méi)有真正的發(fā)送數據,TXE中斷都會(huì )發(fā)生,而且沒(méi)有休止,這將占用很大部分的CPU時(shí)間,甚至影響其他程序的運行!

因此建議的是在初始化時(shí)不好啟用TXE中斷,只在要發(fā)送數據(尤其是字符串、數組這樣的系列數據)時(shí)才啟用TXE。在發(fā)送完成后立即將其關(guān)閉,以免引起不必要的麻煩。

對于發(fā)送,需要注意TXE和TC的差別——這里簡(jiǎn)單描述一下,假設串口數據寄存器是DR、串口移位寄存器是SR以及TXD引腳TXDpin,其關(guān)系是DR->SR->TXDpin。當DR中的數據轉移到SR中時(shí)TXE置1,如果有數據寫(xiě)入DR時(shí)就能將TXE置0;如果SR中的數據全部通過(guò)TXDpin移出并且沒(méi)有數據進(jìn)入DR,則TC置1。并且需要注意TXE只能通過(guò)寫(xiě)DR來(lái)置0,不能直接將其清零,而TC可以直接將其寫(xiě)1清零。

對于發(fā)送單個(gè)字符可以考慮不用中斷,直接以查詢(xún)方式完成。

對于發(fā)送字符串/數組類(lèi)的數據,唯一要考慮的是只在最后一個(gè)字符發(fā)送后關(guān)閉發(fā)送中斷,這里可以分為兩種情況:對于發(fā)送可顯示的字符串,其用0x00作為結尾的,因此在ISR中就用0x00作為關(guān)閉發(fā)送中斷(TXE或者TC)的條件;第二種情況就是發(fā)送二進(jìn)制數據,那就是0x00~0xFF中間的任意數據,就不能用0x00來(lái)判斷結束了,這時(shí)必須知道數據的具體長(cháng)度。

這里簡(jiǎn)單分析上面代碼的執行過(guò)程:TXE中斷產(chǎn)生于前一個(gè)字符從DR送入SR,執行效果是后一個(gè)字符送入DR。對于第一種情況,如果是可顯示字符,就執行USART_SendData來(lái)寫(xiě)DR(也就清零了TXE),當最后一個(gè)可顯示的字符從DR送入SR之后,產(chǎn)生的TXE中斷發(fā)現要送入DR的是字符是0x00——這當然不行——此時(shí)就關(guān)閉TXE中斷,字符串發(fā)送過(guò)程就算結束了。當然這時(shí)不能忽略一個(gè)隱含的結果:那就是最后一個(gè)可顯示字符從DR轉入SR后TXE是置1的,但關(guān)閉了TXE中斷,因此只要下次再開(kāi)啟TXE中斷就會(huì )立即進(jìn)入ISR。對于第二種情況,其結果和第一種的相同。

對于第一種情況,其程序可以這么寫(xiě):其中TXS是保存了要發(fā)送數據的字符串,TxCounter1是索引值:

extern __IO uint8_t TxCounter1;
extern uint8_t *TXS;
extern __IO uint8_t TxLen;

void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
{
if(TXS[TxCounter1]) //如果是可顯示字符
{ USART_SendData(USART1,TXS[TxCounter1++]);}
else //發(fā)送完成后關(guān)閉TXE中斷,
{ USART_ITConfig(USART1,USART_IT_TXE,DISABLE);}
}
}

對于第二種情況,和上面的大同小異,其中TXLen表示要發(fā)送的二進(jìn)制數據長(cháng)度:

void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET) //對USART_DR的寫(xiě)操作,將該位清零。
{
if(TxCounter1{ USART_SendData(USART1,TXS[TxCounter1++]);}
else //發(fā)送完成后關(guān)閉TXE中斷
{ USART_ITConfig(USART1,USART_IT_TXE,DISABLE);}
}
}

事實(shí)上第一種情況是第二種的特殊形式,就是說(shuō)可以用第二種情況去發(fā)送可顯示的字符——當然沒(méi)人有閑心去數一句話(huà)里有多少個(gè)字母空格和標點(diǎn)符號!

在使用時(shí),只要將TXS指向要發(fā)送的字符串或者數組,設置TxLen為要發(fā)送的數據長(cháng)度,然后執行USART_ITConfig(USART1,USART_IT_TXE,ENABLE)就立即開(kāi)始發(fā)送過(guò)程。用戶(hù)可以檢查T(mén)xCounter1來(lái)確定發(fā)送了多少字節。比如以第二種情況為例:

uint32_t *TXS;
uint8_t TxBuffer1[]="0123456789ABCDEF";
uint8_t DST2[]="ASDFGHJKL";
__IO uint8_t TxLen = 0x00;

TxLen=8; //發(fā)送8個(gè)字符,最終發(fā)送的是01234567
TXS=(uint32_t *)TxBuffer1; //將TXS指向字符串TxBuffer1
TxCounter1=0; //復位索引值
USART_ITConfig(USART1, USART_IT_TXE,ENABLE); //啟用TXE中斷,即開(kāi)始發(fā)送過(guò)程
while(TxCounter1!=TxLen); //等待發(fā)送完成

TXS=(uint32_t *)TxBuffer2; //同上,最終發(fā)送的是ASDFGHJK
TxCounter1=0;
USART_ITConfig(USART1, USART_IT_TXE,ENABLE);
while(TxCounter1!=TxLen);

以上就是我認為的最佳方案,但串口中斷方式數據有多長(cháng)就中斷多少次,我認為還是占用不少CPU時(shí)間,相比之下DMA方式就好多了,因為DMA發(fā)送字符串時(shí)最多中斷兩次(半傳輸完成,全傳輸完成),并且將串口變成類(lèi)似16C550的器件。關(guān)于DMA方式的這里就不介紹了,有空再說(shuō)。




關(guān)鍵詞: STM32串

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>