0

我正在使用 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);
}

然后我在主函数中运行以下命令来配置 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

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

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

4

1 回答 1

1

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

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

来自参考手册:收到消息后,FIFO 输出邮箱中的软件可以使用该消息。一旦软件处理了消息(例如读取消息),软件必须通过 CAN_RFR 寄存器中的 RFOM 位释放 FIFO 输出邮箱,以使下一个传入消息可用

HAL_CAN_Receive_IT 包含启用中断和释放 FIFO 的行...

/* Enable interrupts: */
    /*  - Enable Error warning Interrupt */
    /*  - Enable Error passive Interrupt */
    /*  - Enable Bus-off Interrupt */
    /*  - Enable Last error code Interrupt */
    /*  - Enable Error Interrupt */
    /*  - Enable Transmit mailbox empty Interrupt */
    __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG |
                              CAN_IT_EPV |
                              CAN_IT_BOF |
                              CAN_IT_LEC |
                              CAN_IT_ERR |
                              CAN_IT_TME  );   
    /* Process unlocked */
    __HAL_UNLOCK(hcan);

    if (FIFONumber == CAN_FIFO0)
    {
      /* Enable FIFO 0 message pending Interrupt */   
      __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP0);
    }
    else
    {
      /* Enable FIFO 1 message pending Interrupt */
      __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP1);
    }
于 2017-06-30T19:56:16.537 回答