STM32F4 - CAN总线发送每次都成功,但CAN接收仅在第一次调用时成功

Posted

技术标签:

【中文标题】STM32F4 - CAN总线发送每次都成功,但CAN接收仅在第一次调用时成功【英文标题】:STM32F4 - CAN bus transmit succeeds every time, but CAN receive only succeeds on the first call 【发布时间】:2017-07-25 15:35:45 【问题描述】:

我正在使用 STM32F469 探索板,并且正在尝试使用 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 peripheral 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 peripheral 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);

然后我在我的 main 函数中运行以下命令来配置 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库文件后,我注意到有两种类型的接收/发送:

    HAL_CAN_Transmit_IT/HAL_CAN_Receive_IT HAL_CAN_Transmit/HAL_CAN_Receive

它说 1. 是非阻塞的 - 我认为这意味着可以在此发送/接收仍在运行时触发另一个中断?

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

【问题讨论】:

【参考方案1】:

每次收到响应时你都会调用 HAL_CAN_Receive_IT 吗?

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

【讨论】:

它应该做什么?为什么有必要?什么是操作理论?请通过editing (changing) your answer 回复,而不是在 cmets 中(without "Edit:"、"Update:" 或类似的 - 答案应该看起来像是今天写的)。

以上是关于STM32F4 - CAN总线发送每次都成功,但CAN接收仅在第一次调用时成功的主要内容,如果未能解决你的问题,请参考以下文章

STM32CubeMX stm32F4 CAN 使用步骤--全文复制粘贴

带有 STM32f103c8t6 Bluepill 和 CAN 总线的 HAL_CAN_ERROR_PARAM

STM32F4 在中断时从UART接收数据的问题

stm32f405和stm32f407的区别

STM32F429 没有收到 CAN 报文

没有来自 PC 的音频数据发送到 STM32F4 音频类 USB