STM32 hal庫Can發送數據時第一包會發送兩次

該問題在發送can數據時,採用查詢方式
那麼就會進行一個等待超時:
    while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))
    {
      /* Check for the Timeout */
      if(Timeout != HAL_MAX_DELAY)
      {
       if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
       {
         hcan->State = HAL_CAN_STATE_TIMEOUT;

         __HAL_CAN_CANCEL_TRANSMIT(hcan, transmitmailbox);

         /* Process unlocked */
         __HAL_UNLOCK(hcan);
         return HAL_TIMEOUT;
        }
      }
    }
產生等待超時,返回hal_timeout;但是此時卻發送成功了;
此時那麼應該考慮是不是該標誌在檢測之間已經被清除了,那麼還會有什麼東西可能這檢查之前就去清標誌呢?
 答案中有一個:進入中斷了。

那又是什麼中斷呢? can發送中斷

好那我們看一下發送中斷裏邊會清除這些標誌嗎?
void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan)
.........
if(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME))
.........
 /* Clear transmission status flags (RQCPx and TXOKx) */
      SET_BIT(hcan->Instance->TSR, CAN_TSR_RQCP0  | CAN_TSR_RQCP1  | CAN_TSR_RQCP2 | \
                                   CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2);
......
我們可以看到,在郵箱都爲空時會清除,我們由於採用查詢方式自然只會佔一個郵箱,那麼它發送ok了自然會產生郵箱爲空的中斷請求。
此時can發送中斷函數如果沒有編寫中斷函數或者中斷函數沒有相應的HAL_CAN_Transmit_IT()來開啓相應中斷,,那麼can發送中斷相關中斷的標誌位不會再打開了,也就相當於關閉了can發送中斷

好,到這兒應該也明白了爲什麼會出現標題所說的現象:
在調用HAL_CAN_Transmit()後,can將該消息發送出去了,產生中斷清除了標誌,然後我們還在那兒傻等標誌變化爲發送成功,等不到自然就會增生timeout,然後我們判斷髮送沒成功,進行下一次發送,can發送中斷此時相當於關閉狀態,本次發送數據時不會再有人來清除發送標誌了,所以can發送成功,不會再有timeout了。

解決方案:要用中斷髮送就用中斷髮送就好,不用中斷髮送的話關閉/不開啓can發送中斷就好。

另外多說一嘴:採用查詢發送時,發送成功後應清除相應標誌,否則那兒永遠都是發送成功。
    		while( HAL_CAN_Transmit(&hcan1, 0x1) != HAL_OK) {
			if(retry++ > 5) {
				iSysDebug(0, "send can data failed\r\n");
				SET_BIT(hcan1.Instance->TSR, CAN_TSR_RQCP0  | CAN_TSR_RQCP1  | CAN_TSR_RQCP2 | \
				        CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2);
				return HAL_ERROR;
			}
		}
		/* Clear transmission status flags (RQCPx and TXOKx) */
		SET_BIT(hcan1.Instance->TSR, CAN_TSR_RQCP0  | CAN_TSR_RQCP1  | CAN_TSR_RQCP2 | \
		        CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章