日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

正点原子STM32串口例程解析

發布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 正点原子STM32串口例程解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

???????學習32,串口的使用很重要,特別是現在學的越多就覺得在很多方面通信才是主角,原子歷程寫的挺好,但是我看論壇里好像沒怎么有這個的解析那就按自己的理解寫寫吧,希望能幫助到正在學習的同學。然后寫在前面,初學者或者想深入學習一定要多看看參考手冊。
???????在主函中使用以下語句實現將接收到的數據發送出去:

if(USART_RX_STA&0x8000){ len=USART_RX_STA&0x3fff;printf("\r\n您發送的消息為:\r\n\r\n");for(t=0;t<len;t++){USART_SendData(USART1, USART_RX_BUF[t]);while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);}

???????首先USART_RX_STA是什么呢?在"usart.c"里面有說明這是個接收狀態標記,它既指接收狀態又表明接收到數據的位數,具體使用在下文的串口中斷部分中進行說明解釋。

u16 USART_RX_STA=0; //接收狀態標記

???????USART_RX_STA的值在USART1_IRQHandler串口接收中斷函數中被改變,這里USART_RX_STA&0x8000就是判斷是否已經接收到了0x0a,0x0a是LF(line feed)換行的意思,光標到達下一行,也是判斷數據接收結束的標志。
???????提一下,中斷中是以是否接收到0x0d 0x0a這兩個數據,判斷數據是否發送結束的。假如你發的數據沒有回車(0x0d )、換行(0x0a)那么單片機是不會停止接收的(在PC中回車、換行使用回車按鍵就都包含了,感興趣可以具體查查)。
???????程序使用數組進行數據的存儲,于是這段代碼也就引出一個BUG,具體描述不會描述就簡單說下,嘴笨是硬傷。
???????比如我給單片機發送 0x01 0x02 0x03 0x04 0x05 0x06 0x0d,這時候程序還在運行繼續等待接收,
?????????????????????????????再發送 0x07 0x08 0x0d 0x0a這時候接收結束,看看最后輸出什么?
???????導致這個BUG的原因就是數組存儲了信息,知道出錯但沒有清除,只是提一下,注意一點就行,一般使用還是可以的。

if(Res==0x0d)USART_RX_STA|=0x4000;

這句話呢就是判斷是否接收到回車(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。不是很懂的話,那就看看后面的那個圖。至此中斷就差不多說明白了,要是還有其他問題,看看下面的注釋,這里我是想說怎么進行的數據處理,畢竟我覺得這一塊是個難點。

void USART1_IRQHandler(void) //串口1中斷服務程序{u8 Res;//中間變量,讀取的數據進行保存if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //查看RXNE寄存器是否為空,以此判斷是否有數據發送過來//接收中斷(接收到的數據必須是0x0d 0x0a結尾)//這里判斷發送接收完成的依據就是串口數據0x0d 0x0a,//0x0d是CR(carriage return)回車的意思,光標回到最左邊,//0x0a是LF(line feed)換行的意思,光標到達下一行,//但是在PC上回車和換行是在一起的就是按下回車按鍵//當然可以更改程序使用其他進行判斷例如使用0x2a也就是*進行結束判斷{Res =USART_ReceiveData(USART1);//(USART1->DR); //讀取接收到的數據,存放到變量Res中if((USART_RX_STA&0x8000)==0)//判斷接收是否未完成//接收完成未清除標志位,還是會不斷進入到接收中斷,所以使用標志進行判斷,//當接收完成便不會跳入到判斷,從而不執行任何指令,空等待//使用條件判斷是否已經接收完數據,這里判斷接收完的依據就是收到了0x0a;//具體判斷在后面{if(USART_RX_STA&0x4000)//如果接收到了0x0d,那么再進一步執行是否接收到0x0a的判斷{if(Res!=0x0a)USART_RX_STA=0;//沒有接收到0x0a那么說明,數據未正確傳輸或者接收錯誤,重新開始判斷,//但是這里沒有將接收到的數據進行清空,也沒有退出接收中斷,此程序只是從頭開始執行接收判斷else USART_RX_STA|=0x8000; //接收完成了,收到了0x0a那么標志位USART_RX_STA將會變成0x8000(使用或指令,只改變最高位),將不再進行數據檢測與存儲}else //還沒收到0X0D,說明數據還未發送結束繼續進行數據的檢測與存儲{ if(Res==0x0d)USART_RX_STA|=0x4000;//收到了數據0x0d,標志位USART_RX_STA變成0x4000(使用或指令,只改變次高位)else{//如果沒有接收到數據0x0d,執行判斷是否存儲數組已滿,已滿則重新開始接收USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;//將接收到的數據寫進數組,標志位USART_RX_STA與上0X3FFF清除前兩位以防止標志位與8000和4000沖突USART_RX_STA++;//數組地址加一,向后排if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數據錯誤,超出數組大小,又開始接收向數組重新寫 } }} } }

???????判斷接收結束再判斷此次接收數據的長度,USART_RX_STA也表明接收數據的位數,要想將接收到的數據全部發送出去就需要知道,一共接收到了幾位然后一位一位的傳出去,所以len=USART_RX_STA&0x3fff;就實現了將數據長度賦值給變量len,然后使用for循環依次將接收到的數據發送出去。這里也許會糊涂為什么是0x3fff呢?看下圖能理解么?
???????接收到0x0d ,USART_RX_STA的值變成0x4000,又接收到0x0a,USART_RX_STA的值變成0xC000那么很容易發現數據的的前兩位是作為標志位了,所以用來記錄其他數據位數就只有0x3fff。

if(USART_RX_STA&0x8000)//如果在串口接收中斷中接收到0x0a,數據已接收完畢{ len=USART_RX_STA&0x3fff;//得到此次接收到的數據長度,傳給for循環,循環依次發出接收到的數據printf("\r\n您發送的消息為:\r\n\r\n");for(t=0;t<len;t++)//通過for循環依次將接收到的數據發送出去{USART_SendData(USART1, USART_RX_BUF[t]);//向串口1發送數據,USART_SendData是庫函數控制DR寄存器while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待發送結束,看TC寄存器的狀態 TC:發送完成 (Transmission complete) }

???????差不多就是這樣,不懂的可以評論,有錯誤也請指正。一般使用串口不是這么判斷使用的,具體看有沒有時間,有時間整理一份。過些時候將注釋的文件上傳以便下載閱讀。

總結

以上是生活随笔為你收集整理的正点原子STM32串口例程解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。