PC通過串列埠助手如何給單片機發送小數,微控制器接收後如何處理?
兩種思路,供參考。
1. 原始位元組
按原始位元組資料傳送,這也是我個人比較傾向的方式。首先,位、位元組和位元組流本身沒有任何意義,如果按約定的方式去解析,才能有具體的含義。
用什麼約定方式呢?使用符合IEEE 754的浮點數標準,每個浮點數為4個位元組,按標準解析就可以了。
其實這個標準,包括STM32在內的很多微控制器,都是支援的,內部的表達方式都是一致的,而且效率很快。
技巧就是定義好一個聯合體,這一步很關鍵:
- union ByteDouble
- {
- float x;
- struct SB
- {
- uint8_t b3;
- uint8_t b2;
- uint8_t b1;
- uint8_t b0;
- }bb;
- }bd;
複製程式碼
然後在USART的串列埠中斷中,用4個uint8_t獲取這四個位元組,最後用float表示出來。
- //獲取資料中斷處理函式
- void USART1_IRQHandler(void)
- {
- if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)//Got Data
- {
- USART1_RX_BUFFER[USART1_RX_CNT++]=USART_ReceiveData(USART1);
- }
- else if(USART_GetITStatus(USART1,USART_IT_IDLE)!=RESET)
- {
- //Clear USART_IT_RXNE Flag
- USART1->DR;
- //Clear USART_IT_IDLE Flag
- USART1->SR;
- //Process Receive DATA Here
- ////////////////////////////////////////////////
- //Example:
- //printf("%s\r\n",USART1_RX_BUFFER);
- bd.bb.b0=USART1_RX_BUFFER[0];
- bd.bb.b1=USART1_RX_BUFFER[1];
- bd.bb.b2=USART1_RX_BUFFER[2];
- bd.bb.b3=USART1_RX_BUFFER[3];
- printf("%f\r\n",bd.x);
- ////////////////////////////////////////////////
- //Finally Clear Buffer
- memset(USART1_RX_BUFFER,0x00,USART1_RX_CNT);
- USART1_RX_CNT=0;
- }
- }
複製程式碼
測試如下:
這個是浮點數的表示形式,123.456按IEEE754的規範,表示成十六進位制就是42 F6 E9 79。
然後使用串列埠程式傳送給STM32:
兩個注意的地方:
a. 浮點數是近似表示,所以你看STM32解析的是123.456001,而不是精確的123.456,這並不違反IEEE 754標準,尤其是涉及到最後一個bit的四捨五入方法,在IEEE 754 中並沒有明確規定。
b. 位元組順序和對齊。你所有的工作只是定義好聯合體,然後填充好聯合體,STM32會自動替你完成轉換。不過需要注意的是,一些上位機採用的是大端對齊的方式, 傳送的位元組順序會相反。
2. 字串方式
如果是字串或者其他方式傳送,那就可以自定義一套轉換機制,甚至你的上位機在傳送2/5的分數,或者40%這樣的字串,都可以解析為0.4的浮點數,這種方式的靈活度非常高,但是對程式設計要求更復雜,而且相對而言,比較佔用MCU的CPU時間和Flash。
#include<stdlib.h> // 使用 atof()函式 需要包含此標頭檔案 |
轉自http://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=615818