久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1509|回復: 6
打印 上一主題 下一主題
收起左側

關于MCU USART-DMA數據傳輸的一個bug請教

[復制鏈接]
跳轉到指定樓層
樓主
ID:644357 發表于 2023-4-28 15:59 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
問題描述:奇怪的MCU bug
16進制給板子發送數據
比如:
串口助手:發-04 03 01 02 03 0A C5 98
板子          收-04 03 01 02 03 0A C5 98
就能完成的完成數據傳輸
但是發
發-04 03 00 00 00 0A C5 98時


收到的就是
收-04 03 00 00 00 00 00 00

數據流收發沒問題,但是只要是00,就會把后面的數據給抹掉
串口中斷:
  1. void USART1_IRQHandler(void)
  2. {
  3.     OSIntEnter();

  4.     HAL_UART_IRQHandler(&huart1);

  5.         user_uart1IT_ReceiveCallback();
  6.    
  7.     OSIntExit();
  8. }

  9. void user_uart1IT_ReceiveCallback(void)
  10. {
  11.         uint8_t temp;
  12.         if((__HAL_UART_GET_FLAG(UART_DEBUG, UART_FLAG_IDLE) != RESET))  //獲取IDLE標志位,idle標志被置位
  13.         {
  14.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);                                                                                                                //清除空閑中斷標志位
  15.                 HAL_UART_DMAStop(UART_DEBUG);                                                                                                                                        //停止串口DMA功能
  16.                
  17.                 temp = huart1.hdmarx->Instance->CNDTR;                                                                                                //得到當前還剩余多少個數據
  18.                 uartDMA_data.bits.recive_count = BUFFER_SIZE - temp;                                        //接收數據計數
  19.                
  20.                 uartDMA_data.bits.interrupt_idle = ON;                                                                                                // 接受完成標志位置1        
  21.                
  22.         }
  23. }
復制代碼
數據接收服務,放在一個5ms定時一次的定時器中斷里
  1. void USART1DMA_rx_service(void)
  2. {
  3.    
  4.     /*在72MHZ系統時鐘工況下,此函數運行時間為無空閑中斷0.78ms-0.81ms;
  5.                                              有空閑中斷,需要處理 運行時間為72.114ms*/

  6.     /*將此接收服務判定函數置于中斷中,有較小概率產生數據丟包BUG*/
  7.     /*此任務函數置于定時中斷中,進行循環檢測*/
  8.     if(uartDMA_data.bits.interrupt_idle == ON)                //有空閑中斷
  9.     {
  10.         uartDMA_data.bits.interrupt_idle = OFF;

  11.         /*加入臨界段保護-----------------------------------------------------------------------------------------------------------------*/
  12.         CPU_SR_ALLOC();
  13.         CPU_CRITICAL_ENTER();  
  14.         
  15.         memset(uartDMA_data.bits.uart_buffer, 0, sizeof(uartDMA_data.bits.uart_buffer));                                    //清除緩存數據數組
  16.         memcpy(uartDMA_data.bits.uart_buffer, uartDMA_data.bits.rx_buffer, strlen((char *)uartDMA_data.bits.rx_buffer));    //取出數據
  17.         memset(uartDMA_data.bits.rx_buffer, 0, sizeof(uartDMA_data.bits.rx_buffer));                                        //清空數組
  18.         HAL_UART_Receive_DMA(UART_DEBUG, uartDMA_data.bits.rx_buffer, sizeof(uartDMA_data.bits.rx_buffer));                 //重新啟動串口DMA功能
  19.         
  20.         CPU_CRITICAL_EXIT();
  21.          /*加入臨界段保護-----------------------------------------------------------------------------------------------------------------*/
  22.         
  23.         if((DEBUG_USART_ENABLE==1)&&(Modbus_ENABLE==0)){
  24.             /*測試模式,向PC發送接收到的數據*/
  25.             
  26.         }
  27.         if((Modbus_ENABLE==1)&&(DEBUG_USART_ENABLE==0)){     /*進入MODBUS通訊模式*/
  28.             
  29.             uint8_t icnt;
  30.             /*空閑中斷發生,將DMA接收緩存數據轉存至MODBUS數據緩存中*/
  31.             Modbus_data_len =  uartDMA_data.bits.recive_count;
  32.             //HAL_UART_Transmit_DMA(UART_DEBUG, (uint8_t *)uartDMA_data.bits.uart_buffer, strlen((char *)uartDMA_data.bits.uart_buffer));        //打印接收到的數據
  33.             ModbusbuffAllow = 0;    //modbus緩存寫保護
  34.             for(icnt=0;icnt<Modbus_data_len;icnt++)
  35.             {
  36.                 modbus_Rx_buff[icnt] = uartDMA_data.bits.uart_buffer[icnt];
  37.             }
  38.             
  39.             ModbusbuffAllow = 1;    //modbus緩存解除寫保護
  40.             /*數據已經寫入modbus緩存*/
  41.             //HAL_UART_Transmit_DMA(UART_DEBUG,modbus_Rx_buff,Modbus_data_len);
  42.         }
  43.         
  44.         
  45. //                Debug_Printf(UART_DEBUG, "\r\n*******************************串口 DMA方式接收打印如下 *****************************\r\n ");         HAL_Delay(100);
  46. //                        
  47. //                        Debug_Printf(UART_DEBUG, "\r\n HAL_UART_Transmit_DMA 庫函數打印\t:");         HAL_Delay(100);
  48. //                        HAL_UART_Transmit_DMA(UART_DEBUG, (uint8_t *)uartDMA_data.bits.uart_buffer, strlen((char *)uartDMA_data.bits.uart_buffer));        //打印接收到的數據
  49. //                        HAL_Delay(100);
  50. //                        Debug_Printf(UART_DEBUG, "\r\nDebug_Printf函數打印數組\t\t:");                                         HAL_Delay(100);
  51. //                        Debug_Printf(UART_DEBUG, (char *)uartDMA_data.bits.uart_buffer);        
  52. //                        HAL_Delay(100);
  53. //                        Debug_Printf(UART_DEBUG, "\r\nDebug_Printf函數打印字符\t\t:");                                         HAL_Delay(100);
  54. //                        Debug_Printf(UART_DEBUG, "uart MDA Debug printf function");
  55. //                        HAL_Delay(100);
  56. //                        Debug_Printf(UART_DEBUG, "\r\nDebug_Printf函數打印串口接收計數值\t:");                                         HAL_Delay(100);
  57. //                        Debug_Printf(UART_DEBUG, "recive_count: %d\r\n", uartDMA_data.bits.recive_count);
  58.     }
  59. }
復制代碼

源碼奉上: test.7z (818.38 KB, 下載次數: 4)

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

來自 6#
ID:77589 發表于 2023-5-4 11:38 | 只看該作者
估計問題出在這里了:
memcpy(uartDMA_data.bits.uart_buffer, uartDMA_data.bits.rx_buffer, strlen((char *)uartDMA_data.bits.rx_buffer));    //取出數據
你是不熟悉strlen這個函數的用法,它是用于獲取字符串長度的,再想想,字符串是以什么結尾的?是不是'\0',這個東西轉成熟悉的十六進制是為是0x00?,所以遇到0x00就已經表示字符串結束了,后面的字節理所當然的就被拋棄了啊!
你不是在總線空閑中斷處獲取了接收數據長度么,直接用那個長度就好了。
回復

使用道具 舉報

沙發
ID:644357 發表于 2023-4-28 17:30 | 只看該作者
初步查到問題是在HAL_UART_IRQHandler里,0x00會導致數據停止接收。
回復

使用道具 舉報

板凳
ID:94031 發表于 2023-4-28 19:27 | 只看該作者
看來你是MODBUS協議沒搞明白。
回復

使用道具 舉報

地板
ID:644357 發表于 2023-5-4 09:23 | 只看該作者
xuyaqi 發表于 2023-4-28 19:27
看來你是MODBUS協議沒搞明白。

并不是,里面雖然有MODBUS的前置處理函數,問題并不在modbus里面,協議硬件部分是純手擼的,HAL庫的回調函數會把0x00判定為命令。停止接收。
回復

使用道具 舉報

5#
ID:644357 發表于 2023-5-4 11:27 | 只看該作者
  1.         memset(uartDMA_data.bits.uart_buffer, 0, sizeof(uartDMA_data.bits.uart_buffer));                                    //清除緩存數據數組
  2.         memcpy(uartDMA_data.bits.uart_buffer, uartDMA_data.bits.rx_buffer, strlen((char *)uartDMA_data.bits.rx_buffer));    //取出數據
  3.         memset(uartDMA_data.bits.rx_buffer, 0, sizeof(uartDMA_data.bits.rx_buffer));                                        //清空數組
  4.         HAL_UART_Receive_DMA(UART_DEBUG, uartDMA_data.bits.rx_buffer, sizeof(uartDMA_data.bits.rx_buffer));                 //重新啟動串口DMA功能
  5.         
復制代碼


問題已找到,strlen會把0x00識別為\0結束符,導致提前結束取出數據
回復

使用道具 舉報

7#
ID:644357 發表于 2023-5-5 09:15 | 只看該作者
Longan.Wang 發表于 2023-5-4 11:38
估計問題出在這里了:
memcpy(uartDMA_data.bits.uart_buffer, uartDMA_data.bits.rx_buffer, strlen((cha ...

大哥正解,通過這個BUG,感覺自己的C基礎還有待提高
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 最新午夜综合福利视频 | 欧美一区免费 | 免费视频99 | 国产伦一区二区三区 | 国产精品999| 免费小视频在线观看 | 亚洲一区二区三区乱码aⅴ 四虎在线视频 | 国产成人在线视频 | 日日夜夜天天 | 欧美一级二级三级视频 | 久久精品毛片 | 99pao成人国产永久免费视频 | 久久天天综合 | 91在线色视频 | 欧美精品一区二区免费视频 | 国产美女免费视频 | a精品视频| 精品国产第一区二区三区 | 国产亚洲一区二区精品 | 亚洲电影第三页 | 韩国av电影网 | 毛片久久久 | 亚洲品质自拍视频 | 粉嫩高清一区二区三区 | 欧美日韩久久久久 | 久久av一区二区三区 | 免费观看视频www | 成人h视频在线观看 | 欧美午夜精品 | 亚洲精品一区二区三区中文字幕 | 成人在线小视频 | 亚洲综合久久网 | 免费一级片 | 久久久久久久久久久久久久av | 久久久久国产一区二区三区 | 啪啪综合网 | 欧美日韩综合 | 青青草免费在线视频 | 欧美久久一级特黄毛片 | 日韩成人免费视频 | 在线欧美a|