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 使用步骤--全文复制粘贴