这里使用了CAN1的接口,具体使用MX创建项目就不放了
需要注意的是,由于是最小核心没有CAN的收发模块需要外接一个
STM32核心板接CAN收发模块不需要交叉
/**CAN GPIO Configuration
PA11 ------> CAN_RX
PA12 ------> CAN_TX
*/
CAN收发模块的H、L接线不需要交叉
接口的关键代码配置如下:
void MX_CAN_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 6;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_3TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;
hcan1.Init.TimeTriggeredMode = ENABLE;
hcan1.Init.AutoBusOff = DISABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = ENABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
}
HAL_StatusTypeDef CAN_SetFilters(void){
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 0; //chenal 0
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0020;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0020;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;
sFilterConfig.SlaveStartFilterBank = 0;
return HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);
}
void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(canHandle->Instance==CAN1)
{
/* CAN1 clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**CAN GPIO Configuration
PA11 ------> CAN_RX
PA12 ------> CAN_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
}
}
最后给出Main主线程里的测试代码
//初始化
MX_CAN_Init();
//设置过滤
if (CAN_SetFilters() == HAL_OK){
//开启CAN口
HAL_CAN_Start(&hcan1);
}
//测试计数
int Count = 0 ;
//发包缓存
uint8_t TxData[8] = {0};
//发送邮箱
uint32_t tx_mailbox;
//数据帧头部结构填充
CAN_TxHeaderTypeDef CAN_tx;
CAN_tx.StdId = 0x01; //使用频道 1 - 0x7FF
CAN_tx.RTR = CAN_RTR_DATA;
CAN_tx.IDE = CAN_ID_STD;
CAN_tx.DLC = 8; //最大8个字节
CAN_tx.TransmitGlobalTime = DISABLE;
//接收数据帧
CAN_RxHeaderTypeDef CAN_rx;
while (1) {
//计数重置
if (Count > 255){
Count = 0;
}
//判断空闲
while (HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) <1){}
TxData[7] = Count & 0xFF;
//发送数据
if (HAL_CAN_AddTxMessage(&hcan1,&CAN_tx,TxData,&tx_mailbox) == HAL_OK){
//发送成功
}
//等待空闲,如果没取走会卡在这里
while (HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)!= 3){}
HAL_Delay(10);
//判断是否有数据
while (HAL_CAN_GetRxFifoFillLevel(&hcan1,CAN_RX_FIFO0) != 0){
//收数据
if (HAL_CAN_GetRxMessage(&hcan1,CAN_RX_FIFO0,&CAN_rx,szCache) == HAL_OK){
//接收成功
}
}
HAL_Delay(100);
}
需要注意,这里演示的是数据帧的收发,每帧携带数据最大8个字节,超过会被截断