GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_CAN1_CLK_ENABLE(); //即使是仅使用CAN2,也需要使能CAN1的时钟,因为CAN2不能直接防止512字节的SRAM
__HAL_RCC_CAN2_CLK_ENABLE(); //使能时钟
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_13 | GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; //这个好像只要是复用功能就可以
GPIO_InitStruct.Pull = GPIO_PULLUP; //两个管脚,都必须要加上拉,要不然初始化的时候,退不出SLEEP
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; //好像都可以
GPIO_InitStruct.Alternate = GPIO_AF9_CAN2; //功能复用
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
hcan1.Instance = CAN2;
hcan1.Init.AutoBusOff = ENABLE; //
hcan1.Init.AutoRetransmission = ENABLE; //使能自动重发
hcan1.Init.TransmitFifoPriority = ENABLE; //发送按照请求的时间顺序
hcan1.Init.Mode = CAN_MODE_LOOPBACK;
hcan1.Init.Prescaler = 2; //APB1时钟是42M
hcan1.Init.SyncJumpWidth = CAN_SJW_2TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_7TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_6TQ;
status = HAL_CAN_Init(&hcan1);
//筛选器是必须要的,要不然数据没有办法过到接收FIFO里面去
CAN2_Filter.FilterBank = 15;
CAN2_Filter.FilterMode = CAN_FILTERMODE_IDMASK; //不知道为什么列表模式没有过,初步调试时,建议使用掩码模式,相当于不使用筛选器
CAN2_Filter.FilterScale = CAN_FILTERSCALE_32BIT;
CAN2_Filter.FilterIdHigh = 0;
CAN2_Filter.FilterIdLow = 0;
CAN2_Filter.FilterMaskIdHigh = 0; //通过这两个设置,取消掉筛选器的功能,不是禁止使能
CAN2_Filter.FilterMaskIdLow = 0;
CAN2_Filter.FilterFIFOAssignment = CAN_RX_FIFO0; //数据通过筛选器后,更新到SRAM中
CAN2_Filter.FilterActivation = CAN_FILTER_ENABLE;
//hcan1.Instance = CAN1;
if(HAL_CAN_ConfigFilter(&hcan1,&CAN2_Filter)) //筛选器必须在非正常模式下初始化
{
return;
}
//hcan1.Instance = CAN2;
HAL_CAN_Start(&hcan1); //最后才进入正常模式
1.调试能完成环回的代码见上面;
2.还有一个疑问。手册上,当FMR中的FINIT置位时,CAN接收停用。但是仿真调试时,发现还是能正常接收。
FINIT=1 时,CAN 接收停用。
3.增加列表模式下,设置筛选器值的封装函数
/*
*std_id :标准ID,低11位有效
*ext_id :扩展ID,低18位有效
*l_IDE : IDE位
*l_RTR :RTE位
*/
static uint32_t set_CAN_filter_val(uint32_t std_id,uint32_t ext_id,uint8_t l_IDE, uint8_t l_RTR)
{
uint32_t temp = 0;
/*写入STID*/
temp = std_id;
/*写入ext_ID*/
temp <<= 18;
temp |= (ext_id & 0x3ffff);
/*写入IDE*/
temp <<= 1;
temp |= l_IDE;
/*写入l_RTR*/
temp <<= 1;
temp |= l_RTR;
/*写入0*/
temp <<= 1;
return temp;
}
4.增加发送函数时,填写ID的封装函数
static uint32_t set_TX_ExdID(uint32_t std_id,uint32_t ext_id)
{
uint32_t temp = 0;
/*写入STID*/
temp = std_id;
/*写入ext_ID*/
temp <<= 18;
temp |= (ext_id & 0x3ffff);
return temp;
}
5.由数据手册可知,CAN2和CAN1共用筛选器,所以在调试时,无法通过CAN2查看筛选器的设置值,只能通过CAN1查看。
6.在DEBUG模式下,需要手动取消CAN_MCR寄存器中的DBF位