![]() |
發布時間: 2022-8-1 20:34
正文摘要:由串口接收回的數據存儲在u8 USART2_RX_BUF[];下面是串口接收中斷函數 void USART2_IRQHandler(void) { u8 Res; & ... |
Y_G_G 發表于 2022-8-3 17:41 根本就不是什么MODBUS,要么用超時來做幀頭標記,中間可以是0x0~0xff任意數字,這是MODBUS/RTU的實現方法。要么用特殊字符比如:做幀頭,\r\n做幀尾標記,中間只能出現'0'~'9'、‘A’~‘Z’這類可打印的ASCII字符,絕對不可以在數據幀中間出現: \r \n這幾個幀標志,這是MODBUS/ASC的做法。 這個協議的制定者顯然是個不懂裝懂的半瓶醋,才會搞出這種有邏輯漏洞的東西。 |
coody_sz 發表于 2022-8-3 11:45 這個數據看著像modbus 兩個簡單的起始符和結束符意義并不大,接收到的數據中隨時有可能就出現了,搞不好數據還沒有接收完就結束了 |
這個像是Modbus通訊 1,當串口接收到第1個數據時,啟動定時器,并把數據保存到緩沖池中 2,接收到結束符,并且一定時間之后,如果再沒接收到新的數據,就認為這是一個完整的數據幀 3,把緩沖池的數據復制到另一個緩沖池中,在主程序對另一個緩沖池的數據進行處理,因為有可能你在處理的時候,來了新的數據,緩沖池的數據結構就不一樣了,讀取出來的就不一定是原始的數據了 我一般用的是結構struct //串口Buffer結構 { unsigned char buf_uart[32]; //留32個地址來存放串口的數據 unsigned char cnt_Byte; //接收到的字節數量 }Buffer0,Buffer1; //兩個結構變量,讓串口接收和保存不相互影響 接收到一個完整的數據幀之后,就直接 Buffer1=Buffer0;//把串口緩存的數據復制過來 memset(&Buffer0,0,sizeof(Buffer0));//清除串口接收緩沖 STM32有足夠的能力處理串口這點小數據的 讀取數據出來不就是很簡單的事情嗎?就是直接讀取數組的數據而已,9#已經給出方法了 |
首先你要確保USART2_RX_BUF[0]是':' 然后就簡單了 float *YaLi; float *LongDu; YaLi = (float*)&USART2_RX_BUF[4]); LongDu = (float*)&USART2_RX_BUF[10]); printf("YaLi = %0.2f, LongDu = %0.2f\r\n",*YaLi,*LongDu); |
coody_sz 發表于 2022-8-3 11:45 扯淡,這種協議從0x0~0xff任何字符都可能出現,如果設冒號回車換行這些轉義字符就亂套了。 很簡單,用超時,比如MODBUS/RTU規定超過3.5個字節的總線空閑就是幀頭標志。 |
協議不完善吧?沒有轉義字符?如果數據域中出現冒號或回車換行相同的數據,怎么辦? 這是字符同步通訊,我會設置3個特殊字符:命令開始字符、結束字符、轉義字符。數據域中出現等于這3個控制字符的數據時,使用轉義字符轉換一下。 |
這個不難,要自已把接收數據程序改一下,中斷接收采用超時方法進行,接收到有效數據后,置位一個標志位,在主程序中查詢,進行數據解析,不要所有工作都在串口中斷程序中進行。 |
yzwzfyz 發表于 2022-8-3 09:25 轉浮點是先將8位16進制轉成32位的二進制數,再對二進制進行計算,我現在完成了轉二進制,但是二進制數在單片機里也是十六進制表示的,又不會算了 |
1、研讀、了解通訊協議,按協議分解數據。 2、弄通浮點數的組數方式。 這樣你就會象板櫈一樣明白了。 |
數據內容里是3個數: 42 c8 5c 29 對應壓力值: 100.18 (浮點數); 00 10 對應模塊狀態:0x0010 (16進制數); 41 44 cc cd 對應濃度值: 12.3 (浮點數); |
頂一下 |