初级会员
- 积分
- 180
- 金钱
- 180
- 注册时间
- 2016-1-15
- 在线时间
- 49 小时
|
10金钱
本帖最后由 KCLin 于 2021-9-1 21:36 编辑
大家好
先說明,我是RTOS的新手,也不是資訊專業,如果用詞或是代碼錯得離譜,還請見諒
我以原子的列隊例程為基礎,以 HAL_UART_Receive_IT 做接收
寫一個在 usart6 接收 16進位 長度為 8 的 RTU 資料
例如 RTU_CMD[8]={01, 06, 10, 01, 00, 0C, 00, 00}
但是,每次中斷接收數個 byte 後就會將剩餘的BYTE拋棄
取決於波特率,波特率越小,能收到的byte就越多
例如 4800可以收到五個,
115200
115200可以收到兩個
波特率115200 連續發送4次,出現 0x1 0x6 出現四次,所以,可以推論,8 bytes 後面的 6 個bytes 都被捨棄了!
代碼的思路大略是使用 HAL_UART_Receive_IT 一次接收一個 BYTE,當接收完成 8 個 BYTE 後,就丟入列隊,並把 index 歸零
主要的代碼如下
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- if(huart->Instance==USART1)//如果是串口1
- {
- if((USART_RX_STA&0x8000)==0)//接收未完成
- {
- if(USART_RX_STA&0x4000)//接收到了0x0d
- {
- if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收错误,重新开始
- else USART_RX_STA|=0x8000; //接收完成了
- }
- else //还没收到0X0D
- {
- if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
- else
- {
- USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
- USART_RX_STA++;
- if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
- }
- }
- }
- }
-
- else if (huart->Instance==USART6){
- USART6_RX_BUF[index_USART6_RX]=aRxBuffer6[0] ;
- index_USART6_RX+=1;
- }
-
- }
- extern QueueHandle_t USART6_remote_comm_Queue;
- void USART6_IRQHandler(void)
- {
- u32 timeout=0;
- u32 maxDelay6=0x1FFFF;
- BaseType_t xHigherPriorityTaskWoken;
-
- HAL_UART_IRQHandler(&UART6_Handler); //調用HAL庫中斷處理公用函數
-
-
- timeout=0;
- while (HAL_UART_GetState(&UART6_Handler)!=HAL_UART_STATE_READY)//等待就緒
- {
- timeout++;////超時處理
- if(timeout>maxDelay6) break;
- }
-
- timeout=0;
- while(HAL_UART_Receive_IT(&UART6_Handler,(u8 *)aRxBuffer6, RXBUFFERSIZE)!=HAL_OK)//一次處理完成之後,重新開啟中斷並設置RxXferCount為1
- {
- timeout++; //超時處理
- if(timeout>maxDelay6) break;
- }
-
- printf("enter USART6_IRQHandler index_USART6_RX =%d \r\n",index_USART6_RX);
- // index_USART6_RX++;
- // delay_ms(1);
- if((((index_USART6_RX) == 8)&& USART6_remote_comm_Queue!=NULL)) //已經接收完畢,接下來向 queue 發送數據
- {
- printf("RX_data :");
- for(uint8_t i=0; i<8; i++){
- printf("0x%x", USART6_RX_BUF[i]);
- }
- printf("\r\n");
- index_USART6_RX =0;
- xQueueSendFromISR(USART6_remote_comm_Queue,USART6_RX_BUF,&xHigherPriorityTaskWoken);//向隊列中發 送數據
- memset(USART6_RX_BUF,0,USART2_REC_LEN);//清除數據接收緩衝區USART_RX_BUF,用於下一次數據接收
- portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的話進行一次任務切換
- //portYIELD_FROM_ISR 用於中段的任務切換函數, portYIELD() 會強行切換任務,放棄剩餘的時間片
- //xHigherPriorityTaskWoken 用來標記退出此函數是否進行任務切換,此變數由系統操作設定,用戶不必做任何設置,只須提供一個變量保存
- }
- }
- void REMOTE_COMM_task(void *pvParameters){
-
- uint8_t data[8];
- while(1){
- while(xQueueReceive(USART6_remote_comm_Queue,data,100)){
- printf("TASK_remote_comm : disp_data : ");
- printf("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\r\n",data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7] );
- if (data[0] == 0){
- mcu_comm_handle_func(data);
- }
- }
- vTaskDelay(100);
- }
- }
复制代码
在USART1 ,原子的例程接收是沒有問題的
理論上,我應該也可以逐一收到8個bytes的數據
一直無法解決問題,請大神協助一下,非常感謝
附帶一個問題,因為我要與PID控制器做通訊
如果收發分別寫在兩個 task, 也會發生接收不全的問題
如果收發寫在同一個Task, 也就是發送完畢後在同一個task裡面等待接收,接收完畢後,再發出第二個資料
這樣,就可以接收到完整的資料。
|
-
|