STM32F4 - 每次TX都能成功,但CAN RX只能在第一次呼叫时成功

时间:2017-03-05 21:24:40

标签: interrupt stm32 can-bus stm32f4discovery stm32f4

我正在使用STM32F469 Discovery板,我正在尝试使用CAN功能。

据我所知,在此主板上CAN1不能与触摸屏同时使用。因此我需要使用CAN2,但为了启用CAN2,需要启用CAN1。

我的配置/回调代码如下:

/* CAN1 Values */
#define CAN1_CLK_ENABLE()               __HAL_RCC_CAN1_CLK_ENABLE()
#define CAN1_GPIO_CLK_ENABLE()          __HAL_RCC_GPIOB_CLK_ENABLE()
#define CAN1_FORCE_RESET()              __HAL_RCC_CAN1_FORCE_RESET()
#define CAN1_RELEASE_RESET()            __HAL_RCC_CAN1_RELEASE_RESET()
#define CAN1_TX_PIN                    GPIO_PIN_9
#define CAN1_TX_GPIO_PORT              GPIOB 
#define CAN1_TX_AF                     GPIO_AF9_CAN1
#define CAN1_RX_PIN                    GPIO_PIN_8
#define CAN1_RX_GPIO_PORT              GPIOB 
#define CAN1_RX_AF                     GPIO_AF9_CAN1
#define CAN1_RX_IRQn                   CAN1_RX0_IRQn
#define CAN1_RX_IRQHandler             CAN1_RX0_IRQHandler

/* CAN2 Values */
#define CAN2_CLK_ENABLE()               __HAL_RCC_CAN2_CLK_ENABLE()
#define CAN2_GPIO_CLK_ENABLE()          __HAL_RCC_GPIOB_CLK_ENABLE()
#define CAN2_FORCE_RESET()              __HAL_RCC_CAN2_FORCE_RESET()
#define CAN2_RELEASE_RESET()            __HAL_RCC_CAN2_RELEASE_RESET()
#define CAN2_TX_PIN                    GPIO_PIN_13
#define CAN2_TX_GPIO_PORT              GPIOB 
#define CAN2_TX_AF                     GPIO_AF9_CAN2
#define CAN2_RX_PIN                    GPIO_PIN_5
#define CAN2_RX_GPIO_PORT              GPIOB 
#define CAN2_RX_AF                     GPIO_AF9_CAN2
#define CAN2_RX_IRQn                   CAN2_RX0_IRQn
#define CAN2_RX_IRQHandler             CAN2_RX0_IRQHandler

CAN_HandleTypeDef    CanHandle1;
CAN_HandleTypeDef    CanHandle2;

static uint8_t Message_Data[8];

static void CAN1_Config( void )
{
    GPIO_InitTypeDef   GPIO_InitStruct;
    CAN_FilterConfTypeDef CAN_FilterInitStructure;

    static CanTxMsgTypeDef        TxMessage;
    static CanRxMsgTypeDef        RxMessage;

    /* CAN1 Periph clock enable */
    CAN1_CLK_ENABLE();
    CAN1_GPIO_CLK_ENABLE();

    /* CAN1 TX GPIO pin configuration */
    GPIO_InitStruct.Pin = CAN1_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Alternate =  CAN1_TX_AF;

    HAL_GPIO_Init(CAN1_TX_GPIO_PORT, &GPIO_InitStruct);

    /* CAN1 RX GPIO pin configuration */
    GPIO_InitStruct.Pin = CAN1_RX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Alternate =  CAN1_RX_AF;

    HAL_GPIO_Init(CAN1_RX_GPIO_PORT, &GPIO_InitStruct);

    /* NVIC configuration for CAN1 Reception complete interrupt */
    HAL_NVIC_SetPriority(CAN1_RX_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(CAN1_RX_IRQn);

    CanHandle1.Instance = CAN1;
    CanHandle1.pTxMsg = &TxMessage;
    CanHandle1.pRxMsg = &RxMessage;

    /* CAN peripheral init */
    CanHandle1.Init.TTCM = DISABLE;
    CanHandle1.Init.ABOM = DISABLE;
    CanHandle1.Init.AWUM = DISABLE;
    CanHandle1.Init.NART = DISABLE;
    CanHandle1.Init.RFLM = DISABLE;
    CanHandle1.Init.TXFP = DISABLE;
    CanHandle1.Init.Mode = CAN_MODE_LOOPBACK;
    CanHandle1.Init.SJW = CAN_SJW_1TQ;
    CanHandle1.Init.BS1 = CAN_BS1_6TQ;
    CanHandle1.Init.BS2 = CAN_BS2_8TQ;
    CanHandle1.Init.Prescaler = 2;

    HAL_CAN_Init( &CanHandle1 );

    /* CAN filter init */
    CAN_FilterInitStructure.FilterNumber = 0;
    CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
    CAN_FilterInitStructure.FilterScale=CAN_FILTERSCALE_32BIT;
    CAN_FilterInitStructure.FilterIdHigh = 0x0000;
    CAN_FilterInitStructure.FilterIdLow = 0x0000;
    CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000;
    CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
    CAN_FilterInitStructure.FilterFIFOAssignment = 0;
    CAN_FilterInitStructure.FilterActivation = ENABLE;
    CAN_FilterInitStructure.BankNumber = 0;

    HAL_CAN_ConfigFilter( &CanHandle1, &CAN_FilterInitStructure );

    /* Configure transmission */
    CanHandle1.pTxMsg->StdId = 0x7DF; 
    CanHandle1.pTxMsg->ExtId = 0x7DF; 
    CanHandle1.pTxMsg->RTR = CAN_RTR_DATA;
    CanHandle1.pTxMsg->IDE = CAN_ID_STD;
    CanHandle1.pTxMsg->DLC = 8;
}    

static void CAN2_Config( void )
{
    GPIO_InitTypeDef   GPIO_InitStruct;
    CAN_FilterConfTypeDef CAN_FilterInitStructure;

    static CanTxMsgTypeDef        TxMessage;
    static CanRxMsgTypeDef        RxMessage;

    /* CAN2 Periph clock enable */
    CAN2_CLK_ENABLE();
    CAN2_GPIO_CLK_ENABLE();

    /* CAN2 TX GPIO pin configuration */
    GPIO_InitStruct.Pin = CAN2_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Alternate =  CAN2_TX_AF;

    HAL_GPIO_Init(CAN2_TX_GPIO_PORT, &GPIO_InitStruct);

    /* CAN2 RX GPIO pin configuration */
    GPIO_InitStruct.Pin = CAN2_RX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Alternate =  CAN2_RX_AF;

    HAL_GPIO_Init(CAN2_RX_GPIO_PORT, &GPIO_InitStruct);

    /* NVIC configuration for CAN2 Reception complete interrupt */
    HAL_NVIC_SetPriority(CAN2_RX_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(CAN2_RX_IRQn);

    CanHandle2.Instance = CAN2;
    CanHandle2.pTxMsg = &TxMessage;
    CanHandle2.pRxMsg = &RxMessage;

    /* CAN peripheral init */
    CanHandle2.Init.TTCM = DISABLE;
    CanHandle2.Init.ABOM = DISABLE;
    CanHandle2.Init.AWUM = DISABLE;
    CanHandle2.Init.NART = DISABLE;
    CanHandle2.Init.RFLM = DISABLE;
    CanHandle2.Init.TXFP = DISABLE;
    CanHandle2.Init.Mode = CAN_MODE_LOOPBACK;
    CanHandle2.Init.SJW = CAN_SJW_1TQ;
    CanHandle2.Init.BS1 = CAN_BS1_6TQ;
    CanHandle2.Init.BS2 = CAN_BS2_8TQ;
    CanHandle2.Init.Prescaler = 2;

    HAL_CAN_Init( &CanHandle2 );

    /* CAN filter init */
    CAN_FilterInitStructure.FilterNumber = 0; //14 enables CAN1;
    CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
    CAN_FilterInitStructure.FilterScale=CAN_FILTERSCALE_32BIT;
    CAN_FilterInitStructure.FilterIdHigh = 0x0000;
    CAN_FilterInitStructure.FilterIdLow = 0x0000;
    CAN_FilterInitStructure.FilterMaskIdHigh = 0x0000;
    CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
    CAN_FilterInitStructure.FilterFIFOAssignment = 0;
    CAN_FilterInitStructure.FilterActivation = ENABLE;
    CAN_FilterInitStructure.BankNumber = 0; //14 enables CAN1

    HAL_CAN_ConfigFilter( &CanHandle2, &CAN_FilterInitStructure );

    /* Configure transmission */
    CanHandle2.pTxMsg->StdId = 0x7DF; 
    CanHandle2.pTxMsg->ExtId = 0x7DF; 
    CanHandle2.pTxMsg->RTR = CAN_RTR_DATA;
    CanHandle2.pTxMsg->IDE = CAN_ID_STD;
    CanHandle2.pTxMsg->DLC = 8;
}

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
  EwBspYellowLedOn();

  Message_Data[0] = CanHandle->pRxMsg->Data[0];
  Message_Data[1] = CanHandle->pRxMsg->Data[1];
  Message_Data[2] = CanHandle->pRxMsg->Data[2];
  Message_Data[3] = CanHandle->pRxMsg->Data[3];
  Message_Data[4] = CanHandle->pRxMsg->Data[4];
  Message_Data[5] = CanHandle->pRxMsg->Data[5];
  Message_Data[6] = CanHandle->pRxMsg->Data[6];
  Message_Data[7] = CanHandle->pRxMsg->Data[7];

  if ( HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0) != HAL_OK)
  {
    EwBspRedLedOn();
  }
}

CAN_Transmit_Message( void )
{
  CanHandle2.pTxMsg->StdId = 0x7DF;
  CanHandle2.pTxMsg->ExtId = 0x7DF;
  CanHandle2.pTxMsg->Data[0] = 0x02;
  CanHandle2.pTxMsg->Data[1] = 0x01;
  CanHandle2.pTxMsg->Data[2] = 0x0D;
  CanHandle2.pTxMsg->Data[3] = 0x55;
  CanHandle2.pTxMsg->Data[4] = 0x55;
  CanHandle2.pTxMsg->Data[5] = 0x55;
  CanHandle2.pTxMsg->Data[6] = 0x55;
  CanHandle2.pTxMsg->Data[7] = 0x55;

  if ( HAL_CAN_Transmit(&CanHandle, 10) != HAL_OK )
  {
    EwBspOrangeLedOn();
  }

  HAL_Delay(10);
}

然后我在主函数中运行以下命令来配置CAN1,CAN2和中断:

/* Configure interrupt for CAN transmission */
CAN1_Config();
CAN2_Config();
HAL_CAN_Receive_IT(&CanHandle2, CAN_FIFO0);

然后我运行CAN_Transmit_Message()

执行此操作时,我已验证消息已成功发送(橙色LED未亮起),然后执行接收中断处理程序(黄色LED亮起)并成功接收消息(红色LED不亮)

然而,在第二次传输消息(另一次呼叫CAN_Transmit_Message())时,传输再次成功,但接收失败(红色LED亮起)。

我按照CAN_Networking示例代码中的结构创建了此代码,但我无法弄清楚为什么它在第二条消息的HAL_CAN_Receive_IT函数失败(在成功收到第一条消息之后)。

注意:在读取stm32f4xx_HAL_CAN库文件后,我注意到有两种类型的接收/发送:

  1. HAL_CAN_Transmit_IT / HAL_CAN_Receive_IT
  2. HAL_CAN_Transmit / HAL_CAN_Receive
  3. 它表示1.非阻塞 - 我认为这意味着在发送/接收仍在运行时可以触发另一个中断?

    在我的情况下,我想确保在发送传输请求后收到响应数据,所以我应该使用功能2吗?即我会用合适的超时调用HAL_CAN_Transmit,然后在完成调用HAL_CAN_Receive后再次使用合适的超时。

1 个答案:

答案 0 :(得分:1)

每次收到回复都会调用HAL_CAN_Receive_IT吗?

这是一次性的。要继续接收,请在中断处理程序中再次调用它。