S32K146 FLEXCAN SDK解读:
FlexCAN 模块是一个通信控制器,该模块实现了 CAN 协议即CAN2.0B 协议规范。 FlexCAN 模块的字模块,包括了用来存储消息缓冲的相关联的内存区域,Rx 全局掩码寄存器、Rx 私有掩码寄存器、Rx 先进先出队列以及 Rx 队列标识过滤器。消息缓冲区存储在一个专用于 FlexCAN 模块的 RAM 区,请求存取 RAM 接收和传输消息帧,验证接收到的消息以及进行错误处理。控制器主机接口子模块用来选择接收和传输的消息缓冲区,使用仲裁与 ID 匹配算法,以建立同 CPU 或者其他模块的连接。
私有掩码则有64个,RXIMR0 - RXIMR63,对应MB0 – MB63,是一一对应的关系,所以私有掩码和对应的MB可以放到一起配置。
掩码不影响筛选表,而是与对应的ID位是否需要去和MB里面设定的预期ID对比。eg:flexcan_msgbuff_t recmsg;
当设置私有掩码时
#define CAN_ID_STD_MASK 0x1FFC0000u
0xC0000000|0x7FF ID为标准帧
(stdMask << CAN_ID_STD_SHIFT) & CAN_ID_STD_MASK;
0xC0000000|0x7FF左移18与上0x1FFC0000还是为 0x1FFC0000
即(base->RXIMR[msgBuffIdx])为0x1FFC0000 二进制00011111111111000000000000000000
标准帧看29-19位 11111111111 也就是全关心
所以筛选id设置啥只接收啥
中断
uint8_t canrxdata[8];
flexcan_msgbuff_t recmsg;
flexcan_id_table_t canidtable[8];
void canrxcallback(uint8_t instance, flexcan_event_type_t eventType,
uint32_t buffIdx, flexcan_state_t *flexcanState)
{
// RxFIFO接收完成
if(eventType == FLEXCAN_EVENT_RXFIFO_COMPLETE) {
// CAN0接收
if(instance == INST_CANCOM1)
{
memcpy(&canrxdata, &recmsg.data, 8);
//此函数使用 Rx FIFO 接收 CAN 帧。该函数立即返回。如果安装了回调,则在接收到帧并读入指定的缓冲区后,将调用该回调。
FLEXCAN_DRV_RxFifo(INST_CANCOM1, &recmsg);
}
}
}
void can_fifo_init(void){
FLEXCAN_DRV_Init(INST_CANCOM1, &canCom1_State, &canCom1_InitConfig0);
//过滤器表元素设置
flexcan_id_table_t canidtable[8];
for(uint8_t i=0;i<8;i++)
{
canidtable[i].isExtendedFrame = 0;
canidtable[i].isRemoteFrame = 0;
canidtable[i].id = 0x11;
}
//配置RX FIFO ID过滤器表元素,并启用RX中断
FLEXCAN_DRV_ConfigRxFifo(INST_CANCOM1,FLEXCAN_RX_FIFO_ID_FORMAT_A,canidtable);
/*私有掩码设置*/
/* FLEXCAN_DRV_SetRxMaskType(INST_CANCOM1,FLEXCAN_RX_MASK_INDIVIDUAL);
for(uint8_t id_index=0;id_index<8;id_index++)
{
FLEXCAN_DRV_SetRxIndividualMask(INST_CANCOM1,FLEXCAN_MSG_ID_STD,id_index,0xc0000000|0x7ff);
}*/
/*自定义
flexcan_id_table_t canidtable[8];
for(uint8_t i=0;i<8;i++)
{
canidtable[i].isExtendedFrame = true;
canidtable[i].isRemoteFrame = false;
canidtable[i].id = 0x12345678;
}
FLEXCAN_DRV_ConfigRxFifo(INST_CANCOM1,FLEXCAN_RX_FIFO_ID_FORMAT_A,canidtable);
*/
//将RX掩码类型设置为RX全局掩码或RX单个掩码
FLEXCAN_DRV_SetRxMaskType(INST_CANCOM1,FLEXCAN_RX_MASK_GLOBAL);
//将Rx FIFO全局掩码设置为11位标准掩码或29位扩展掩码
FLEXCAN_DRV_SetRxFifoGlobalMask(INST_CANCOM1,FLEXCAN_MSG_ID_STD,0);
FLEXCAN_DRV_InstallEventCallback(INST_CANCOM1,canrxcallback,NULL);
//此函数使用 Rx FIFO 接收 CAN 帧。该函数立即返回。如果安装了回调,则在接收到帧并读入指定的缓冲区后,将调用该回调。
FLEXCAN_DRV_RxFifo(INST_CANCOM1,&recmsg);
}
void can_fifosend(void){
flexcan_data_info_t can_tx_data_config;
can_tx_data_config.msg_id_type = FLEXCAN_MSG_ID_STD;
//8字节数据帧
can_tx_data_config.data_length = 8;
can_tx_data_config.is_remote = 0;
//不使能自动波特率
can_tx_data_config.enable_brs = 0;
// CAN 邮箱 配置 发送ID 数据
FLEXCAN_DRV_Send(INST_CANCOM1,2,&can_tx_data_config,0x1,canrxdata);
}
DMA的代码和中断一样
只要配置DMA通道和初始化
代码中会自动调用