正点原子STM32串口例程解析
???????學習32,串口的使用很重要,特別是現(xiàn)在學的越多就覺得在很多方面通信才是主角,原子歷程寫的挺好,但是我看論壇里好像沒怎么有這個的解析那就按自己的理解寫寫吧,希望能幫助到正在學習的同學。然后寫在前面,初學者或者想深入學習一定要多看看參考手冊。
???????在主函中使用以下語句實現(xiàn)將接收到的數(shù)據(jù)發(fā)送出去:
???????首先USART_RX_STA是什么呢?在"usart.c"里面有說明這是個接收狀態(tài)標記,它既指接收狀態(tài)又表明接收到數(shù)據(jù)的位數(shù),具體使用在下文的串口中斷部分中進行說明解釋。
u16 USART_RX_STA=0; //接收狀態(tài)標記???????USART_RX_STA的值在USART1_IRQHandler串口接收中斷函數(shù)中被改變,這里USART_RX_STA&0x8000就是判斷是否已經(jīng)接收到了0x0a,0x0a是LF(line feed)換行的意思,光標到達下一行,也是判斷數(shù)據(jù)接收結(jié)束的標志。
???????提一下,中斷中是以是否接收到0x0d 0x0a這兩個數(shù)據(jù),判斷數(shù)據(jù)是否發(fā)送結(jié)束的。假如你發(fā)的數(shù)據(jù)沒有回車(0x0d )、換行(0x0a)那么單片機是不會停止接收的(在PC中回車、換行使用回車按鍵就都包含了,感興趣可以具體查查)。
???????程序使用數(shù)組進行數(shù)據(jù)的存儲,于是這段代碼也就引出一個BUG,具體描述不會描述就簡單說下,嘴笨是硬傷。
???????比如我給單片機發(fā)送 0x01 0x02 0x03 0x04 0x05 0x06 0x0d,這時候程序還在運行繼續(xù)等待接收,
?????????????????????????????再發(fā)送 0x07 0x08 0x0d 0x0a這時候接收結(jié)束,看看最后輸出什么?
???????導致這個BUG的原因就是數(shù)組存儲了信息,知道出錯但沒有清除,只是提一下,注意一點就行,一般使用還是可以的。
這句話呢就是判斷是否接收到回車(0x0d ),接收到了回車,那么讓USART_RX_STA標志位第二位為1。
if(USART_RX_STA&0x4000) { if(Res!=0x0a)USART_RX_STA=0; else USART_RX_STA|=0x8000; }這句話呢就是判斷是否接收到換行(0x0a),如果收到換行并進行判斷確認收到換行符那么讓USART_RX_STA標志位最高位為1。不是很懂的話,那就看看后面的那個圖。至此中斷就差不多說明白了,要是還有其他問題,看看下面的注釋,這里我是想說怎么進行的數(shù)據(jù)處理,畢竟我覺得這一塊是個難點。
void USART1_IRQHandler(void) //串口1中斷服務程序{u8 Res;//中間變量,讀取的數(shù)據(jù)進行保存if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //查看RXNE寄存器是否為空,以此判斷是否有數(shù)據(jù)發(fā)送過來//接收中斷(接收到的數(shù)據(jù)必須是0x0d 0x0a結(jié)尾)//這里判斷發(fā)送接收完成的依據(jù)就是串口數(shù)據(jù)0x0d 0x0a,//0x0d是CR(carriage return)回車的意思,光標回到最左邊,//0x0a是LF(line feed)換行的意思,光標到達下一行,//但是在PC上回車和換行是在一起的就是按下回車按鍵//當然可以更改程序使用其他進行判斷例如使用0x2a也就是*進行結(jié)束判斷{Res =USART_ReceiveData(USART1);//(USART1->DR); //讀取接收到的數(shù)據(jù),存放到變量Res中if((USART_RX_STA&0x8000)==0)//判斷接收是否未完成//接收完成未清除標志位,還是會不斷進入到接收中斷,所以使用標志進行判斷,//當接收完成便不會跳入到判斷,從而不執(zhí)行任何指令,空等待//使用條件判斷是否已經(jīng)接收完數(shù)據(jù),這里判斷接收完的依據(jù)就是收到了0x0a;//具體判斷在后面{if(USART_RX_STA&0x4000)//如果接收到了0x0d,那么再進一步執(zhí)行是否接收到0x0a的判斷{if(Res!=0x0a)USART_RX_STA=0;//沒有接收到0x0a那么說明,數(shù)據(jù)未正確傳輸或者接收錯誤,重新開始判斷,//但是這里沒有將接收到的數(shù)據(jù)進行清空,也沒有退出接收中斷,此程序只是從頭開始執(zhí)行接收判斷else USART_RX_STA|=0x8000; //接收完成了,收到了0x0a那么標志位USART_RX_STA將會變成0x8000(使用或指令,只改變最高位),將不再進行數(shù)據(jù)檢測與存儲}else //還沒收到0X0D,說明數(shù)據(jù)還未發(fā)送結(jié)束繼續(xù)進行數(shù)據(jù)的檢測與存儲{ if(Res==0x0d)USART_RX_STA|=0x4000;//收到了數(shù)據(jù)0x0d,標志位USART_RX_STA變成0x4000(使用或指令,只改變次高位)else{//如果沒有接收到數(shù)據(jù)0x0d,執(zhí)行判斷是否存儲數(shù)組已滿,已滿則重新開始接收USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;//將接收到的數(shù)據(jù)寫進數(shù)組,標志位USART_RX_STA與上0X3FFF清除前兩位以防止標志位與8000和4000沖突USART_RX_STA++;//數(shù)組地址加一,向后排if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數(shù)據(jù)錯誤,超出數(shù)組大小,又開始接收向數(shù)組重新寫 } }} } }???????判斷接收結(jié)束再判斷此次接收數(shù)據(jù)的長度,USART_RX_STA也表明接收數(shù)據(jù)的位數(shù),要想將接收到的數(shù)據(jù)全部發(fā)送出去就需要知道,一共接收到了幾位然后一位一位的傳出去,所以len=USART_RX_STA&0x3fff;就實現(xiàn)了將數(shù)據(jù)長度賦值給變量len,然后使用for循環(huán)依次將接收到的數(shù)據(jù)發(fā)送出去。這里也許會糊涂為什么是0x3fff呢?看下圖能理解么?
???????接收到0x0d ,USART_RX_STA的值變成0x4000,又接收到0x0a,USART_RX_STA的值變成0xC000那么很容易發(fā)現(xiàn)數(shù)據(jù)的的前兩位是作為標志位了,所以用來記錄其他數(shù)據(jù)位數(shù)就只有0x3fff。
???????差不多就是這樣,不懂的可以評論,有錯誤也請指正。一般使用串口不是這么判斷使用的,具體看有沒有時間,有時間整理一份。過些時候?qū)⒆⑨尩奈募蟼饕员阆螺d閱讀。
總結(jié)
以上是生活随笔為你收集整理的正点原子STM32串口例程解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [原创]mybatis中整合ehcach
- 下一篇: 解决鼠标滚动的时候多次执行函数