×
单片机 > 单片机程序设计 > 详情

STM32CubeMX开发stm32f103rbt6 CAN例程(二)

发布时间:2020-06-09 发布时间:
|

1、STM32CubeMX配置


 

 

 

 

2、生成代码查看


 

 

3、编写代码


程序下载:http://download.csdn.net/download/white_loong/10137468



4、使用CAN分析仪测试(波特率125K)


问题:


程序CAN收发同时打开例如:



1、main() {

     HAL_CAN_Receive_IT();

     HAL_CAN_Transmit_IT();

 }

 

 HAL_CAN_RxCpltCallback() {

  HAL_CAN_Receive_IT(); // Rearm receive

 }

 

 HAL_CAN_TxCpltCallback() {

  HAL_CAN_Transmit_IT(); // Rearm transmit

 }

 



例2:main() {


    HAL_CAN_Receive_IT();

    while(1){

         HAL_CAN_Transmit();

          }

 }

  HAL_CAN_RxCpltCallback() {

    HAL_CAN_Receive_IT(); // Rearm receive

 }

 

现象:调用

HAL_CAN_Receive_IT

/

HAL_CAN_Transmit_IT

函数失败,返回值为HAL_BUSY,之后无法再次接收/发送。

原因分析:


 


分析HAL库程序会发现:


HAL库在操作CAN总线时会进行上锁  __HAL_LOCK(hcan)/解锁 __HAL_LOCK(hcan)的操作,类似于进程线程操作中的互斥锁。


对例2进行分析:


主程序中HAL_CAN_Transmit()进行发送时CAN总线在上锁后解锁前,接收中断触发,进入中断回调函数。但是在再次开接收中断时CAN总线上锁导致,开中断失败。


具体程序如下:


 


HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout)

{

  uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX;

  uint32_t tickstart = 0;

 

  /* Check the parameters */

  assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));

  assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));

  assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));

 

  /* Process locked */

  __HAL_LOCK(hcan);

 

  if(hcan->State == HAL_CAN_STATE_BUSY_RX)

  {

    /* Change CAN state */

    hcan->State = HAL_CAN_STATE_BUSY_TX_RX;

  }

  else

  {

    /* Change CAN state */

    hcan->State = HAL_CAN_STATE_BUSY_TX;

  }

 

  /* Select one empty transmit mailbox */

  if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME0))

  {

    transmitmailbox = 0;

  }

        else if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME1))

                {

                    transmitmailbox = 1;

                    }

                else if (HAL_IS_BIT_SET(hcan->Instance->TSR, CAN_TSR_TME2))

                            {

                        transmitmailbox = 2;

                        }

                        else

                            {

                            transmitmailbox = CAN_TXSTATUS_NOMAILBOX;

                            }

 

  if (transmitmailbox != CAN_TXSTATUS_NOMAILBOX)

  {

    /* Set up the Id */

    hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;

    if (hcan->pTxMsg->IDE == CAN_ID_STD)

    {

      assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));  

      hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << CAN_TI0R_STID_BIT_POSITION) |

                                                           hcan->pTxMsg->RTR);

    }

    else

    {

      assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));

      hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << CAN_TI0R_EXID_BIT_POSITION) |

                                                           hcan->pTxMsg->IDE |

                                                           hcan->pTxMsg->RTR);

    }

    

    /* Set up the DLC */

    hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;

    hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0;

    hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;

 

    /* Set up the data field */

    WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDLR, ((uint32_t)hcan->pTxMsg->Data[3] << CAN_TDL0R_DATA3_BIT_POSITION) |

                                                                ((uint32_t)hcan->pTxMsg->Data[2] << CAN_TDL0R_DATA2_BIT_POSITION) |

                                                                ((uint32_t)hcan->pTxMsg->Data[1] << CAN_TDL0R_DATA1_BIT_POSITION) |

                                                                ((uint32_t)hcan->pTxMsg->Data[0] << CAN_TDL0R_DATA0_BIT_POSITION)  );

    WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDHR, ((uint32_t)hcan->pTxMsg->Data[7] << CAN_TDL0R_DATA3_BIT_POSITION) |

                                                                ((uint32_t)hcan->pTxMsg->Data[6] << CAN_TDL0R_DATA2_BIT_POSITION) |

                                                                ((uint32_t)hcan->pTxMsg->Data[5] << CAN_TDL0R_DATA1_BIT_POSITION) |

                                                                ((uint32_t)hcan->pTxMsg->Data[4] << CAN_TDL0R_DATA0_BIT_POSITION)  );

    /* Request transmission */

    SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TIR, CAN_TI0R_TXRQ);

 

    /* Get timeout */

    tickstart = HAL_GetTick();   

 

    /* Check End of transmission flag */

    while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))

    {

      /* Check for the Timeout */

      if(Timeout != HAL_MAX_DELAY)

      {

        if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))

        {

          hcan->State = HAL_CAN_STATE_TIMEOUT;

          

          /* Process unlocked */

          __HAL_UNLOCK(hcan);

          

          return HAL_TIMEOUT;

        }

      }

    }

    if(hcan->State == HAL_CAN_STATE_BUSY_TX_RX)

    {

      /* Change CAN state */

      hcan->State = HAL_CAN_STATE_BUSY_RX;

      

      /* Process unlocked */

      __HAL_UNLOCK(hcan);

    }

    else

    {

      /* Change CAN state */

      hcan->State = HAL_CAN_STATE_READY;

    }

    

    /* Process unlocked */

    __HAL_UNLOCK(hcan);

    

    /* Return function status */

    return HAL_OK;

  }

  else

  {

    /* Change CAN state */

    hcan->State = HAL_CAN_STATE_ERROR;

    

    /* Process unlocked */

    __HAL_UNLOCK(hcan);

 

    /* Return function status */

    return HAL_ERROR;

  }

}

 

 



 


 


HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)

{

  /* Check the parameters */

  assert_param(IS_CAN_FIFO(FIFONumber));

 

  if((hcan->State == HAL_CAN_STATE_READY) || (hcan->State == HAL_CAN_STATE_BUSY_TX))

  {

    /* Process locked */

    __HAL_LOCK(hcan);

 

    if(hcan->State == HAL_CAN_STATE_BUSY_TX)

    {

      /* Change CAN state */

      hcan->State = HAL_CAN_STATE_BUSY_TX_RX;

    }

    else

    {

      /* Change CAN state */

      hcan->State = HAL_CAN_STATE_BUSY_RX;


关键字:STM32CubeMX  stm32f103rbt6  CAN例程 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机CO2检测显示程序解析