S32K148----SDK笔记----CAN收发

文章目录

    • 前言
    • 建立工程
    • ProcessorExpert配置
    • 发送CAN报文
    • CAN接收中断
    • 工程代码
    • 微信公众号

前言

S32K148自带3路CAN, 官方的SDK给了can_pal的例程, 本文更基础一点, 直接用flexcan组件相关的函数, CANFD需要相应的电平转换芯片速率上的支持, 我暂时用不到CANFD, 就只拿来做基础的CAN通信. 先测试CAN发送, 然后测试CAN的接收中断. 板子某宝淘的, 连接两路CAN到CAN分析仪:

左边是S32K148引出的两路CAN, 右边是CAN分析仪. 记得至少一边接120Ω终端电阻. CAN0和CAN1对应的引脚为:

CAN0_RX PTE4
CAN0_TX PTE5
CAN1_RX PTC6
CAN1_TX PTC7

本文中CAN0设置为250K, CAN1设置为500K.

建立工程

步骤:

  • File -> New -> S32DS Application Project
  • Processors 选择 S32K148, Project Name 填你自己的工程名
  • Select SDK: SDKs 选择 S32K148_SDK 3.0.0, Debugger选择J-Link, Finish.

ProcessorExpert配置

双击工程名, 点击Components窗口Components目录下的 pin_mux:PinSetting, CAN配置:
S32K148----SDK笔记----CAN收发_第1张图片
Component Library中双击添加两组flexcan组件:
S32K148----SDK笔记----CAN收发_第2张图片
CAN0组件配置如下图, Device选CAN0, 设置250kbit/s, 不使能FD:
S32K148----SDK笔记----CAN收发_第3张图片
CAN1组件配置如下图, 设置500kbit/s:
S32K148----SDK笔记----CAN收发_第4张图片
点击生成代码:
S32K148----SDK笔记----CAN收发_第5张图片

发送CAN报文

先是日常一贴的时钟和引脚配置:

  /* For example: for(;;) { } */
    CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,
                        g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
    CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_FORCIBLE);
    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);

然后是CAN组件的初始化:

    FLEXCAN_DRV_Init(INST_CANCOM0, &canCom0_State, &canCom0_InitConfig0);
    FLEXCAN_DRV_Init(INST_CANCOM1, &canCom1_State, &canCom1_InitConfig0);

然后就可以发CAN报文了:

#define TX_MAILBOX_0 10
#define TX_MAILBOX_1 11
#define TIMEOUT 10U
flexcan_data_info_t data_std_info = {
	.msg_id_type = FLEXCAN_MSG_ID_STD,
	.data_length = 8U,
	.is_remote = false
};
flexcan_data_info_t data_ext_info = {
	.msg_id_type = FLEXCAN_MSG_ID_EXT,
	.data_length = 8U,
	.is_remote = false
};

uint32_t msg_id0 = 0x123;
uint8_t data0[8] = {1, 2, 3, 4, 5, 6, 7, 0xFF};
uint32_t msg_id1 = 0x1234567;
uint8_t data1[8] = {7, 6, 5, 4, 3, 2, 1, 0xFE};

//==============================================

    while(1) {

    	++data0[7];
    	++data1[7];

    	FLEXCAN_DRV_SendBlocking(INST_CANCOM0, TX_MAILBOX_0 , &data_std_info , msg_id0, data0, TIMEOUT);
    	FLEXCAN_DRV_SendBlocking(INST_CANCOM1, TX_MAILBOX_1 , &data_ext_info , msg_id1, data1, TIMEOUT);

    	OSIF_TimeDelay(1);
    }

调试运行, 可以看到CAN分析仪的上位机里面接收到了数据, 这里以500K CAN1接收的扩展帧为例:
S32K148----SDK笔记----CAN收发_第6张图片
可以看到上图中增量时间里面是1.8ms, 而我们程序里只有1ms的延时 OSIF_TimeDelay(1);, 是因为Blocking占用了时间, 我们不用Block的方式, 直接Send:

    while(1) {

    	++data0[7];
    	++data1[7];

    	FLEXCAN_DRV_Send(INST_CANCOM0, TX_MAILBOX_0 , &data_std_info , msg_id0, data0);
    	FLEXCAN_DRV_Send(INST_CANCOM1, TX_MAILBOX_1 , &data_ext_info , msg_id1, data1);

    	OSIF_TimeDelay(1);
    }

这个是没有TIMEOUT参数的, 调试运行, 可以看到增量时间是正常的1ms, 大概是甩给DMA了吧, 要注意Blocking方式可以返回成功失败, 非Blocking返回的应该都是成功???:
S32K148----SDK笔记----CAN收发_第7张图片

具体是Blocking还是非阻塞, 看对结果看重还是对时间要求严格, 前者失败了可以设定重传以及最大重传次数, 在有一定CAN负载率时有一定的必要, 后者自信当甩手掌柜单发单收时用起来很爽.

CAN接收中断

步骤:

  • FLEXCAN_DRV_ConfigRxMb 配置接收缓存(message buffer)
  • FLEXCAN_DRV_InstallEventCallback 添加中断
  • FLEXCAN_DRV_Receive 开始接收(有一种FIFO的接收方式, 这里暂时未用)
  • 然后我们补全接收中断函数 typedef void (*flexcan_callback_t)(uint8_t instance, flexcan_event_type_t eventType, uint32_t buffIdx, flexcan_state_t *flexcanState); 在接收中断里, 判断完成和端口, 然后把CAN0接收到ID为0x87的标准帧报文转发给CAN1; 把CAN1接收到ID为0x1234568的扩展帧报文转发给CAN0.
#define RX_MAILBOX_0 0U
#define RX_MAILBOX_1 1U

flexcan_msgbuff_t recvMsg0;
flexcan_msgbuff_t recvMsg1;

void canRxCallback(uint8_t instance, flexcan_event_type_t eventType,
		uint32_t buffIdx, flexcan_state_t *flexcanState) {
	if(eventType == FLEXCAN_EVENT_RX_COMPLETE) {
		if(instance == INST_CANCOM0) {
			FLEXCAN_DRV_Receive(INST_CANCOM0, RX_MAILBOX_0, &recvMsg0);
			FLEXCAN_DRV_Send(INST_CANCOM1, TX_MAILBOX_1, &data_std_info, recvMsg0.msgId, recvMsg0.data);
		} else if(instance == INST_CANCOM1) {
			FLEXCAN_DRV_Receive(INST_CANCOM1, RX_MAILBOX_1, &recvMsg1);
			FLEXCAN_DRV_Send(INST_CANCOM0, TX_MAILBOX_0, &data_ext_info, recvMsg1.msgId, recvMsg1.data);
		}
	}
}

	//main
	FLEXCAN_DRV_ConfigRxMb(INST_CANCOM0, RX_MAILBOX_0, &data_std_info, 0x87);
    FLEXCAN_DRV_InstallEventCallback(INST_CANCOM0, canRxCallback, NULL);

    FLEXCAN_DRV_ConfigRxMb(INST_CANCOM1, RX_MAILBOX_1, &data_ext_info, 0x1234568);
    FLEXCAN_DRV_InstallEventCallback(INST_CANCOM1, canRxCallback, NULL);

    FLEXCAN_DRV_Receive(INST_CANCOM0, RX_MAILBOX_0, &recvMsg0);
    FLEXCAN_DRV_Receive(INST_CANCOM1, RX_MAILBOX_1, &recvMsg1);

    while(1) {

    }

调试运行, 在CAN分析仪上位机里面可以看到CAN0发送的ID为0x87的报文可以在CAN1中收到:
S32K148----SDK笔记----CAN收发_第8张图片
至于增量时间不是10ms, 待排查. 同样CAN1发送ID为0x1234568的报文也可以在CAN1中收到.

工程代码

https://download.csdn.net/download/weifengdq/11916783

微信公众号

欢迎扫描关注我的微信公众号, 及时获取最新文章:
S32K148----SDK笔记----CAN收发_第9张图片

你可能感兴趣的:(S32K148,S32K,S32K148,CAN,FLEXCAN)