STM32F 使用 HAL_CAN 库

Posted

技术标签:

【中文标题】STM32F 使用 HAL_CAN 库【英文标题】:STM32F using HAL_CAN Library 【发布时间】:2020-07-10 00:07:34 【问题描述】:

我正在尝试使用两个 STM32F 板之间的 HAL_CAN 库通过 CAN 进行通信。具体来说,问题似乎在于接收消息。按照文档:

 ==============================================================================
                    ##### How to use this driver #####
[..]
  (#) Initialize the CAN low level resources by implementing the
      HAL_CAN_MspInit():
     (++) Enable the CAN interface clock using __HAL_RCC_CANx_CLK_ENABLE()
     (++) Configure CAN pins
         (+++) Enable the clock for the CAN GPios
         (+++) Configure CAN pins as alternate function open-drain
     (++) In case of using interrupts (e.g. HAL_CAN_ActivateNotification())
         (+++) Configure the CAN interrupt priority using
               HAL_NVIC_SetPriority()
         (+++) Enable the CAN IRQ handler using HAL_NVIC_EnableIRQ()
         (+++) In CAN IRQ handler, call HAL_CAN_IRQHandler()

  (#) Initialize the CAN peripheral using HAL_CAN_Init() function. This
      function resorts to HAL_CAN_MspInit() for low-level initialization.

  (#) Configure the reception filters using the following configuration
      functions:
        (++) HAL_CAN_ConfigFilter()

  (#) Start the CAN module using HAL_CAN_Start() function. At this level
      the node is active on the bus: it receive messages, and can send
      messages.

  (#) To manage messages transmission, the following Tx control functions
      can be used:
        (++) HAL_CAN_AddTxMessage() to request transmission of a new
             message.
        (++) HAL_CAN_AbortTxRequest() to abort transmission of a pending
             message.
        (++) HAL_CAN_GetTxMailboxesFreeLevel() to get the number of free Tx
             mailboxes.
        (++) HAL_CAN_IsTxMessagePending() to check if a message is pending
             in a Tx mailbox.
        (++) HAL_CAN_GetTxTimestamp() to get the timestamp of Tx message
             sent, if time triggered communication mode is enabled.

  (#) When a message is received into the CAN Rx FIFOs, it can be retrieved
      using the HAL_CAN_GetRxMessage() function. The function
      HAL_CAN_GetRxFifoFillLevel() allows to know how many Rx message are
      stored in the Rx Fifo.

  (#) Calling the HAL_CAN_Stop() function stops the CAN module.

  (#) The deinitialization is achieved with HAL_CAN_DeInit() function.


  *** Polling mode operation ***
  ==============================
[..]
  (#) Reception:
        (++) Monitor reception of message using HAL_CAN_GetRxFifoFillLevel()
             until at least one message is received.
        (++) Then get the message using HAL_CAN_GetRxMessage().

  (#) Transmission:
        (++) Monitor the Tx mailboxes availability until at least one Tx
             mailbox is free, using HAL_CAN_GetTxMailboxesFreeLevel().
        (++) Then request transmission of a message using
             HAL_CAN_AddTxMessage().


  *** Interrupt mode operation ***
  ================================
[..]
  (#) Notifications are activated using HAL_CAN_ActivateNotification()
      function. Then, the process can be controlled through the
      available user callbacks: HAL_CAN_xxxCallback(), using same APIs
      HAL_CAN_GetRxMessage() and HAL_CAN_AddTxMessage().

  (#) Notifications can be deactivated using
      HAL_CAN_DeactivateNotification() function.

  (#) Special care should be taken for CAN_IT_RX_FIFO0_MSG_PENDING and
      CAN_IT_RX_FIFO1_MSG_PENDING notifications. These notifications trig
      the callbacks HAL_CAN_RxFIFO0MsgPendingCallback() and
      HAL_CAN_RxFIFO1MsgPendingCallback(). User has two possible options
      here.
        (++) Directly get the Rx message in the callback, using
             HAL_CAN_GetRxMessage().
        (++) Or deactivate the notification in the callback without
             getting the Rx message. The Rx message can then be got later
             using HAL_CAN_GetRxMessage(). Once the Rx message have been
             read, the notification can be activated again.
    我正在调用HAL_CAN_Init,它又调用HAL_CAN_MspInit 设置时钟、启用GPIO 并将CAN 引脚配置为备用功能开漏。当我使用中断时,它还将接收中断设置为:
    HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
    接收过滤器使用HAL_CAN_ConfigFilter()设置如下,没有返回错误:
  sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
  sFilterConfig.FilterIdHigh = 0;
  sFilterConfig.FilterIdLow = 0;
  sFilterConfig.FilterMaskIdHigh = 0;
  sFilterConfig.FilterMaskIdLow = 0;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.FilterBank = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.SlaveStartFilterBank = 14;
  HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig)
    HAL_CAN_Start 被调用,没有返回错误:
HAL_CAN_Start(&hcan1)
    使用按下蓝色按钮触发的中断发送消息:
void EXTI0_IRQHandler(void)

  /* USER CODE BEGIN EXTI0_IRQn 0 */
for(int n=0;n<1000000;n++);
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) 
    a++;
    if(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1))
        if(HAL_CAN_AddTxMessage(&hcan1, &pHeader, &a, &TxMailbox)==HAL_OK)
                if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_6) == GPIO_PIN_SET)
                    HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_RESET);
                 else
                    HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_SET);
                
        
    

    我已验证消息处于待处理状态,因为以下返回一个正值:
HAL_CAN_IsTxMessagePending(&hcan1, TxMailbox)
    但是,当消息可以接收时应该触发的以下中断永远不会触发:
void CAN1_RX0_IRQHandler(void)

  HAL_CAN_IRQHandler(&hcan1);
  /* USER CODE BEGIN CAN1_RX0_IRQn 1 */
  HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &pRxHeader, &r);
  HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);

  /* USER CODE END CAN1_RX0_IRQn 1 */

其他说明:

已验证正在使用的收发器均接收 3.3V

任何帮助将不胜感激, 罗斯

【问题讨论】:

刚刚偶然发现这个...问题同时解决了吗? 【参考方案1】:

我面临同样的问题..我启用了 CAN 中断传输和接收..但是,它不会随时进入 CAN1_RX0_IRQHandler().. 而 CAN1_TX_IRQHandler() 工作正常!而且,我可以看到总线上的数据(使用逻辑分析仪验证)

if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_TX_MAILBOX_EMPTY) != HAL_OK)

/* Notification Error */
Error_Handler();

【讨论】:

【参考方案2】:

您忘记启用“内部”CAN 中断:

    HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);

【讨论】:

以上是关于STM32F 使用 HAL_CAN 库的主要内容,如果未能解决你的问题,请参考以下文章

USB库STM32F0x2移植到STM32F070笔记

STM32F4 HAL库开发 -- 再识

STM32F103(二十)DAC(贼详细)

STM32F4 HAL库开发 -- STM32F407引脚图

STM32F4 HAL库开发 -- STM32F407引脚图

STM32F4 HAL库开发 -- STM32F407引脚图