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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1532|回復: 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 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品久久久久久久久久免费看 | 在线观看免费福利 | 国产a区| 粉嫩国产精品一区二区在线观看 | 一区二区三区四区在线 | 黄网站免费观看 | 亚洲精品99久久久久久 | 精品国产一区二区三区性色 | 亚洲免费一区二区 | 国产一区二区精华 | 天天拍天天插 | 亚洲xx在线 | 毛片日韩| 欧美日韩在线一区二区三区 | 久久久精品亚洲 | 久久久黑人 | 精品国产乱码久久久久久影片 | 国产91av视频在线观看 | 日本三级电影免费观看 | 成人精品系列 | 国产一级视频在线播放 | 国产精品一区二区无线 | 亚洲国产成人精品一区二区 | 美日韩免费 | 亚洲女人天堂成人av在线 | 中文字幕av网站 | 久久人人国产 | 成人免费看片又大又黄 | 色妹子综合网 | 日韩精品在线网站 | 毛片网络 | 91毛片网| 国产成人免费网站 | 久久国产日本 | 成人免费在线视频 | 激情亚洲| 久久久.com | 精品久久久久久中文字幕 | 毛片网站在线观看 | 精品视频一区二区三区在线观看 | 国产一区二区三区在线看 |