FlexCAN0通道引脚设置,PTC2是S32K344 CAN0的接收引脚,设置为输入RXD,PTC3是S32K344 CAN0的发送引脚,设置为输出TXD。
在 IntCtrl中断模块中使能CAN0中断。
这个部分对 S32K312来说,只有3个FlexCAN0_0, FlexCAN0_1, FlexCAN0_2三个选项。
这里如果选用S32K312的话,选择Payload size 64,则MailBox最多设置为14。Payload size选择8,16,32的话,MailBox最多可以设置为16。
FlexCAN0的时钟取自外部晶振的时钟FXOSC,16Mhz。
当然也可以选择 FlexCAN0的时钟为 AIPS_PLAT_CLK内部时钟,这样FlexCAN protocol Clock也要做相应的修改。
如果选择 16Mhz的外部时钟,采样点的比率也要和上位机 CAN OE或者CAN卡调试工具设置一致。
void flexcan0_Callback(uint8 instance, Flexcan_Ip_EventType eventType, uint32 buffIdx,
constFlexcan_Ip_StateType *flexcanState)
{
(void)flexcanState;
(void)instance;
switch(eventType)
{
caseFLEXCAN_EVENT_RX_COMPLETE:
dummyData[0]++;
if(buffIdx==1) // MB1 received, ext id
{
tx_info.msg_id_type = FLEXCAN_MSG_ID_EXT; // send ext ID message
FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &tx_info, MSG_ID, (uint8 *)&dummyData);
FlexCAN_Ip_Receive(INST_FLEXCAN_0, 1, &rxData, false);
}
elseif(buffIdx==2) // MB2 received, std id
{
tx_info.msg_id_type = FLEXCAN_MSG_ID_STD; // send std ID message
FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &tx_info, MSG_ID, (uint8 *)&dummyData);
FlexCAN_Ip_Receive(INST_FLEXCAN_0, 2, &rxData, false);
}
else {};
break;
caseFLEXCAN_EVENT_RXFIFO_COMPLETE:
break;
caseFLEXCAN_EVENT_TX_COMPLETE:
//FlexCAN_Ip_SendBlocking(INST_FLEXCAN_0, TX_MB_IDX, &tx_info, MSG_ID, (uint8 *)&dummyData,100);
break;
caseFLEXCAN_EVENT_ENHANCED_RXFIFO_COMPLETE:
// read rxFifoData[5]
FlexCAN_Ip_RxFifo(INST_FLEXCAN_0, &rxFifoData);
break;
caseFLEXCAN_EVENT_ENHANCED_RXFIFO_WATERMARK:
break;
default:
break;
}
}
int main(void)
{
uint8_t byte_0 = 0;
Flexcan_Ip_MsgBuffType rxData;
Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);
Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
IntCtrl_Ip_EnableIrq(FlexCAN0_1_IRQn);
IntCtrl_Ip_InstallHandler(FlexCAN0_1_IRQn, CAN0_ORED_0_31_MB_IRQHandler, NULL_PTR);
FlexCAN_Ip_Init(INST_FLEXCAN_0, &FlexCAN_State0, &FlexCAN_Config0);
FlexCAN_Ip_ConfigEnhancedRxFifo_Privileged(INST_FLEXCAN_0, &CAN0_EnhanceFIFO_IdFilterTable[0]);
FlexCAN_Ip_SetRxMaskType_Privileged(INST_FLEXCAN_0,FLEXCAN_RX_MASK_INDIVIDUAL);
FlexCAN_Ip_SetRxIndividualMask_Privileged(INST_FLEXCAN_0,1,0x1FFFFFFF);
FlexCAN_Ip_SetRxIndividualMask(INST_FLEXCAN_0,2,0x7FF<<18);
FlexCAN_Ip_SetStartMode(INST_FLEXCAN_0);
rx_info.is_polling = FALSE;
rx_info.msg_id_type = FLEXCAN_MSG_ID_EXT;
FlexCAN_Ip_ConfigRxMb(INST_FLEXCAN_0, RX_MB_IDX, &rx_info, 0xFACE);
rx_info.msg_id_type = FLEXCAN_MSG_ID_STD;
FlexCAN_Ip_ConfigRxMb(INST_FLEXCAN_0, 2, &rx_info, 0x1);
tx_info.is_polling = FALSE;
FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &tx_info, MSG_ID, (uint8*)&dummyData); //450us start bit
while(1)
{
if(FLEXCAN_STATUS_BUSY!=FlexCAN_Ip_GetTransferStatus(INST_FLEXCAN_0, TX_MB_IDX))
{
dummyData[0]=byte_0++;
FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &tx_info, MSG_ID, (uint8 *)&dummyData);
}
int ii;
for(ii=0;ii<50000;ii++);
//FlexCAN_Ip_Receive(INST_FLEXCAN_0, RX_MB_IDX, &rxData, TRUE);
}
//return 0;
}
S32K3xx 器件 | FlexCAN 通道个数 |
S32K312 | 6 |
S32K342 | 4 |
S32K314 | 6 |
S32K324 | 6 |
S32K344 | 6 |
如果在CAN总线上,调用FlexCAN_Ip_Send函数后,只出现发送一次的情况,此后CAN总线状态一直处于FLEXCAN_STATUS_BUSY,这种情况可能是由于ACK不能在can帧中激活, 检查接收数据时是否存在任何问题。
S32K344 FlexCAN: 如果配置 Rx MB mask接收不同ID的CAN FD消息呢?如下代码只能接收64字节,ID为 0x300的 CAN FD 消息,其他的ID不能触发回调,例如从ID 0x301 到0x37F。为什么呢?main.c 代码如下:
uint8 callbackRxCount;
uint8 callbackTxCount;
uint8 callbackOtherCount;
Flexcan_Ip_DataInfoType rx_info ={
.msg_id_type =FLEXCAN_MSG_ID_STD,
.data_length =64U,
.is_polling = FALSE,
.is_remote = FALSE
};
voidCANTxRxCallback(uint8 instance,
Flexcan_Ip_EventType eventType,
uint32 buffIdx,
conststruct FlexCANState *driverState){
switch(eventType){
caseFLEXCAN_EVENT_RX_COMPLETE:
callbackRxCount++;
memset(rxData.data,0,sizeof(rxData.data));
FlexCAN_Ip_Receive(INST_FLEXCAN_4, RX_MB_IDX,&rxData, TRUE);
break;
caseFLEXCAN_EVENT_TX_COMPLETE:
callbackTxCount++;
break;
default:
callbackOtherCount++;
}
}
intmain(void){
Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
IntCtrl_Ip_EnableIrq(FlexCAN4_1_IRQn);
IntCtrl_Ip_InstallHandler(FlexCAN4_1_IRQn,CAN4_ORED_0_31_MB_IRQHandler, NULL_PTR);
Siul2_Dio_Ip_WritePin(PTD15_EN_PORT , PTD15_EN_PIN,1U);
Siul2_Dio_Ip_WritePin(PTD13_STB_PORT , PTD13_STB_PIN,1U);
FlexCAN_Ip_Init(INST_FLEXCAN_4,&FlexCAN_State0,&FlexCAN_Config1);
FlexCAN_Ip_SetStartMode(INST_FLEXCAN_4);
//set global mask
FlexCAN_Ip_SetRxMaskType(INST_FLEXCAN_4,FLEXCAN_RX_MASK_GLOBAL);
FlexCAN_Ip_SetRxMbGlobalMask(INST_FLEXCAN_4,0xFFFFFF80);
FlexCAN_Ip_ConfigRxMb(INST_FLEXCAN_4, RX_MB_IDX,&rx_info,0x300);
FlexCAN_Ip_Receive(INST_FLEXCAN_4, RX_MB_IDX,&rxData, TRUE);
while(1){
if(FlexCAN_Ip_GetTransferStatus(INST_FLEXCAN_4, RX_MB_IDX)!=FLEXCAN_STATUS_SUCCESS){
FlexCAN_Ip_MainFunctionRead(INST_FLEXCAN_4, RX_MB_IDX);
}
}
}
FlexCAN_Ip_SetRxMaskType, FlexCAN_Ip_SetRxMbGlobalMask 函数必须从 StopMode 或者FreezeMode调用。因此要么将其放在FlexCAN_Ip_SetStartMode 函数前,或者在FlexCAN_Ip_EnterFreezeMode与FlexCAN_Ip_ExitFreezeMode之间调用。
CAN的滤波一般有多种形式:
1. 如果只使用MB的收发,是直接调用接口函数进行配置
A. 使用全局掩码,一个掩码为所有MB过滤报文。掩码的对应比特1表示比对,0表示不比对。比如0xFFFFFFFF,表示ID的每一个比特都会进行比对。
/* Set the global mask */
FlexCAN_Ip_SetRxMaskType(INST_FLEXCAN_0, FLEXCAN_RX_MASK_GLOBAL);
FlexCAN_Ip_SetRxMbGlobalMask(INST_FLEXCAN_0, 0xFFFFFFFF);
B. 使用独立掩码,为每个MB单独配置过滤。如下面的0x1FFFFFF0就是表示MB0的最后4个比特ID不会比对。假如配置了MB的ID是0x1001001F,那该MB会接收从0x10010010-0x1001001F之间的所有报文。
/* Set the individual mask type */
FlexCAN_Ip_SetRxMaskType(INST_FLEXCAN_1, FLEXCAN_RX_MASK_INDIVIDUAL);
FlexCAN_Ip_SetRxIndividualMask(INST_FLEXCAN_1, RX_MB0, 0x1FFFFFF0);
2. 如果使用CAN FD的FIFO,需要在CT中进行配置
如上面配置CAN FD 2个过滤表元素,FIFO水位线是1,1个扩展ID的过滤表元素。在主函数中调用以下接口来初始化FIFO的滤波。
FlexCAN_Ip_EnterFreezeMode(INST_FLEXCAN_0);
/* configure the FlexCAN enhanced FIFO filter table */
FlexCAN_Ip_ConfigEnhancedRxFifo_Privileged(INST_FLEXCAN_0, &CAN_EnhancedFIFO_FilterTable[0]);
FlexCAN_Ip_ExitFreezeMode(INST_FLEXCAN_0);
S32K344 CAN0 程序以及S32K312 CAN0程序欢迎用户来索取。