CAN (CAN1+CAN2)
CAN配置(MX)
-
打开CAN1选项卡 - 选择Activatde
-
Parameter Settings -
-
Prescaler - 分频系数
Tbs1 - 时间系数1
Tbs2 - 时间系数2
ReSynchronization J W - 重新同步跳跃宽度(一般1Time)
CAN波特率计算方式
波特率=时钟频率 / ((Tbs1 + Tbs2 + 1) * 分频系数)
采样点设置 :采样点=(1 + Tbs1) / (1 + Tbs1 + Tbs2)
建议尽可能的把采样点设置为 CiA 推荐的值:
当波特率 > 800Kpbs时,采样点建议采用75%;
当波特率 > 500Kbps时,采样点建议采用80%;
当波特率 <= 500Kbps时,采样点建议采用87.5% 。
TTCM - 时间触发通信模式
ABOM - 软件自动离线管理
AWUM - 睡眠模式通过软件唤醒
AURE - 自动重传
RFLM - 报文不锁定,新的覆盖旧的
TFP - 传输先进先出优先级
O Mode - 传输模式
-
NVIC Settings - 打开CAN接收中断,根据工程需求选择
-
RX0中断-表示滤波器邮箱关联到FIFO0
RX1中断-表示滤波器邮箱关联到FIFO1
TX中断 - 此处没有打开
注:
此处个人理解是:
打开RX0表示打开关联到FIFO0的接收回调函数接口打开RX1表示打开关联到FIFO1的接收回调函数接口
打开TX - 类比理解为打开发送回调函数接口
我没有使用到发送回调函数,所以没有打开TX中断
实际上我认为真正使能中断的是 HAL_CAN_ActivateNotification()
这个函数,@brief Enable interrupts.
-
GPIO Settings - 修改对应的IO引脚
MX-CAN1配置完成
CAN2的配置于CAN1的相同
配置CAN滤波器
void bsp_CAN_Filt_init(void)
{
CAN_FilterTypeDef hcan_Filt;
hcan_Filt.FilterIdHigh=0x0000;
hcan_Filt.FilterIdLow=0x0000;
hcan_Filt.FilterMaskIdHigh=0x0000;
hcan_Filt.FilterMaskIdLow=0x0000;
hcan_Filt.FilterFIFOAssignment=CAN_FILTER_FIFO0;//FIFO0
hcan_Filt.FilterBank=0;
hcan_Filt.FilterMode=CAN_FILTERMODE_IDMASK;
hcan_Filt.FilterScale=CAN_FILTERSCALE_32BIT;
hcan_Filt.FilterActivation=CAN_FILTER_ENABLE;
HAL_CAN_ConfigFilter(&hcan1,&hcan_Filt);
HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);//FIFO0
HAL_CAN_Start(&hcan1);
hcan_Filt.FilterBank=14;
hcan_Filt.SlaveStartFilterBank=14;
hcan_Filt.FilterFIFOAssignment=CAN_FILTER_FIFO1;//FIFO1
HAL_CAN_ConfigFilter(&hcan2,&hcan_Filt);
HAL_CAN_ActivateNotification(&hcan2,CAN_IT_RX_FIFO1_MSG_PENDING);//FIFO1
HAL_CAN_Start(&hcan2);
}
注:要注意FIFO0和FIFO1对应的中断回调以及初始化配置都不一样,是相互对应的。
如果配置的滤波器都关联到了FIFO0,那么只需要一个接收回调函数
如果分别关联到FIFO0和FIFO1,那么需要两个接收回调函数
并且在MX里,对应的RX0中断或者RX1中断也要打开
否则可能不进入接收中断回调函数
参考:https://blog.csdn.net/xiaoyaofriend/article/details/104138618
此文章中写了几个问题,需要注意一下,对于不同芯片,不同库函数,配置方式也是有区别的。
CAN发送
void bsp_CAN_wire_CAN1()
{
CAN_TxHeaderTypeDef hcan_tx1;
uint32_t CAN_TX_BOX;//这是一个返回值,不用赋值
uint8_t bsp_CAN_wire_data_buf[8]={0};
hcan_tx1.StdId=ID;
//hcan_tx1.ExtId=XXX;
hcan_tx1.IDE=CAN_ID_STD;
hcan_tx1.RTR=CAN_RTR_DATA;
hcan_tx1.DLC=0X08;
bsp_CAN_wire_data_buf[0]=data0;
bsp_CAN_wire_data_buf[1]=data1;
bsp_CAN_wire_data_buf[2]=data2;
bsp_CAN_wire_data_buf[3]=data3;
bsp_CAN_wire_data_buf[4]=data4;
bsp_CAN_wire_data_buf[5]=data5;
bsp_CAN_wire_data_buf[6]=data6;
bsp_CAN_wire_data_buf[7]=data7;
HAL_CAN_AddTxMessage(&hcan1,&hcan_tx1,bsp_CAN_wire_data_buf,&CAN_TX_BOX);
}
HAL_CAN_AddTxMessage()-调用此函数
会自动将数据挂号到邮箱,并且激活一次数据传输,进行发送。
CAN接收
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
uint8_t bsp_u8_CAN_read_data_buf[8]={0};
if(hcan == &hcan1)
{
HAL_CAN_GetRxMessage(&hcan1,CAN_RX_FIFO0,&hcan_rx1,bsp_u8_CAN_read_data_buf);
switch(hcan_rx1.StdId)
{
case 0x01 ://
break;
default : break;
}
}
}
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
uint8_t bsp_u8_CAN_read_data_buf[8]={0};
if(hcan == &hcan2)
{
HAL_CAN_GetRxMessage(&hcan2,CAN_RX_FIFO1,&hcan_rx2,bsp_u8_CAN_read_data_buf);
switch(hcan_rx2.StdId)
{
case 0x02 ://
break;
default : break;
}
}
}
-
HAL_CAN_RxFifo0MsgPendingCallback() - 对应FIFO0的接收缓存邮箱
HAL_CAN_RxFifo1MsgPendingCallback() - 对应FIFO1的接收缓存邮箱
调用这个函数时不区分CAN1和CAN2
-
在这个接收回调函数内部进行判断
以便于区分CAN1和CAN2
if(hcan == &hcan1) - CAN1
if(hcan == &hcan2) - CAN2
CAN采样点
-
采样点设置 :采样点=(1 + Tbs1) / (1 + Tbs1 + Tbs2)
建议尽可能的把采样点设置为 CiA 推荐的值:
当波特率 > 800Kpbs时,采样点建议采用75%;
当波特率 > 500Kbps时,采样点建议采用80%;
当波特率 <= 500Kbps时,采样点建议采用87.5% 。
-
参考
-
https://bbs.robomaster.com/forum.php?mod=viewthread&tid=12348
https://www.chuandong.com/tech/tech41712.html