嵌入式系统与单片机|技术阅读
登录|注册

您现在的位置是:嵌入式系统与单片机 > 技术阅读 > S32K344/S32K312 CAN0通道 CAN FD配置步骤

S32K344/S32K312 CAN0通道 CAN FD配置步骤

    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不会比对。假如配置了MBID0x1001001F,那该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 FDFIFO,需要在CT中进行配置

    如上面配置CAN FD 2个过滤表元素,FIFO水位线是11个扩展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程序欢迎用户来索取。