stm32串口中斷接收一幀數(shù)據(jù)
最近用到stm32的串口,中斷一個(gè)字符一個(gè)字符接收好心累,網(wǎng)上度了一下發(fā)現(xiàn)了一篇好的帖子,和大家分享一下,原貼地址:http://www.51hei.com/bbs/dpj-39885-1.html
再次感謝原貼樓主的分享,為了方便大家,我把原文復(fù)制過來》
今天說一下STM32單片機(jī)的接收不定長(zhǎng)度字節(jié)數(shù)據(jù)的方法。由于STM32單片機(jī)帶IDLE中斷,所以利用這個(gè)中斷,可以接收不定長(zhǎng)字節(jié)的數(shù)據(jù),由于STM32屬于ARM單片機(jī),所以這篇文章的方法也適合其他的ARM單片機(jī)。
IDLE中斷什么時(shí)候發(fā)生?
IDLE就是串口收到一幀數(shù)據(jù)后,發(fā)生的中斷。什么是一幀數(shù)據(jù)呢?比如說給單片機(jī)一次發(fā)來1個(gè)字節(jié),或者一次發(fā)來8個(gè)字節(jié),這些一次發(fā)來的數(shù)據(jù),就稱為一幀數(shù)據(jù),也可以叫做一包數(shù)據(jù)。
如何判斷一幀數(shù)據(jù)結(jié)束,就是我們今天討論的問題。因?yàn)楹芏囗?xiàng)目中都要用到這個(gè),因?yàn)橹挥薪邮盏揭粠瑪?shù)據(jù)以后,你才可以判斷這次收了幾個(gè)字節(jié)和每個(gè)字節(jié)的內(nèi)容是否符合協(xié)議要求。
看了前面IDLE中斷的定義,你就會(huì)明白了,一幀數(shù)據(jù)結(jié)束后,就會(huì)產(chǎn)生IDLE中斷。這個(gè)中斷真是太TMD有用了。省去了好多判斷的麻煩。
如何配置好IDLE中斷?
下面我們就配置好串口IDLE中斷吧。
這是串口CR1寄存器,其中,對(duì)bit4寫1開啟IDLE中斷,對(duì)bit5寫1開啟接收數(shù)據(jù)中斷。(注意:不同系列的STM32,對(duì)應(yīng)的寄存器位可能不同)
(RXNE中斷和IDLE中斷的區(qū)別?
當(dāng)接收到1個(gè)字節(jié),就會(huì)產(chǎn)生RXNE中斷,當(dāng)接收到一幀數(shù)據(jù),就會(huì)產(chǎn)生IDLE中斷。比如給單片機(jī)一次性發(fā)送了8個(gè)字節(jié),就會(huì)產(chǎn)生8次RXNE中斷,1次IDLE中斷。)
這是狀態(tài)寄存器,當(dāng)串口接收到數(shù)據(jù)時(shí),bit5就會(huì)自動(dòng)變成1,當(dāng)接收完一幀數(shù)據(jù)后,bit4就會(huì)變成1.
需要注意的是,在中斷函數(shù)里面,需要把對(duì)應(yīng)的位清0,否則會(huì)影響下一次數(shù)據(jù)的接收。比如RXNE接收數(shù)據(jù)中斷,只要把接收到的一個(gè)字節(jié)讀出來,就會(huì)清除這個(gè)中斷。IDLE中斷,如何是F0系列的單片機(jī),需要用ICR寄存器來清除,如果是F1系列的單片機(jī),清除方法是“先讀SR寄存器,再讀DR寄存器”。
/*使能接收中斷*/
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
/*使能空閑中斷*/
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
USART_Cmd(USART1,ENABLE);
重點(diǎn)是使能空閑中斷。
uint8_tch[20];
chari=0;
voidUSART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//接收到一個(gè)字節(jié)
{
//ch=USART1->DR;
ch[i++]=USART_ReceiveData(USART1);
}
elseif(USART_GetITStatus(USART1,USART_IT_IDLE)!=RESET)//接收到一幀數(shù)據(jù)
{
USART1->SR;//先讀SR
USART1->DR;//再讀DR
i=0;
printf("%s",ch);
}
}