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

前言

S32K148自带3路CAN, 官方的SDK给了can_pal的例程, 本文更基础一点, 直接用flexcan组件相关的函数, CANFD需要相应的电平转换芯片速率上的支持, 我暂时用不到CANFD, 就只拿来做基础的CAN通信. 先测试CAN发送, 然后测试CAN的接收中断. 板子某宝淘的, 连接两路CAN到CAN分析仪:
在这里插入图片描述
左边是S32K148引出的两路CAN, 右边是CAN分析仪. 记得至少一边接120Ω终端电阻. CAN0和CAN1对应的引脚为:

CAN0_RXPTE4
CAN0_TXPTE5
CAN1_RXPTC6
CAN1_TXPTC7

本文中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配置:
在这里插入图片描述
Component Library中双击添加两组flexcan组件:
在这里插入图片描述
CAN0组件配置如下图, Device选CAN0, 设置250kbit/s, 不使能FD:
在这里插入图片描述
CAN1组件配置如下图, 设置500kbit/s:
在这里插入图片描述
点击生成代码:
在这里插入图片描述

发送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接收的扩展帧为例:
在这里插入图片描述
可以看到上图中增量时间里面是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返回的应该都是成功???:
在这里插入图片描述

具体是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中收到:
在这里插入图片描述
至于增量时间不是10ms, 待排查. 同样CAN1发送ID为0x1234568的报文也可以在CAN1中收到.

工程代码

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

微信公众号

欢迎扫描关注我的微信公众号, 及时获取最新文章:
在这里插入图片描述

  • 9
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
以下是S32K144-EVB开发板CAN的示例代码,包括初始化和发送数据的函数: ```c #include "S32K144.h" void CAN_Init(void) { // 开启CAN时钟 PCC->PCCn[PCC_FlexCAN0_INDEX] |= PCC_PCCn_CGC_MASK; // 复位CAN模块 FLEXCAN0->MCR |= FLEXCAN_MCR_SOFT_RST_MASK; while (FLEXCAN0->MCR & FLEXCAN_MCR_SOFT_RST_MASK); // 设置CAN为32位宽度 FLEXCAN0->MCR |= FLEXCAN_MCR_MAXMB(0x1F); // 最大邮箱号 FLEXCAN0->MCR |= FLEXCAN_MCR_FRZ_MASK; // 进入冻结模式 FLEXCAN0->MCR |= FLEXCAN_MCR_HALT_MASK; // 进入停止模式 FLEXCAN0->CTRL1 |= FLEXCAN_CTRL1_CLKSRC_MASK; // 选择系统时钟作为CAN时钟 FLEXCAN0->CTRL1 |= FLEXCAN_CTRL1_PRESDIV(0); // 分频系数为1 FLEXCAN0->MCR &= ~FLEXCAN_MCR_FRZ_MASK; // 退出冻结模式 FLEXCAN0->MCR &= ~FLEXCAN_MCR_HALT_MASK; // 退出停止模式 // 配置邮箱 FLEXCAN0->MB[0].CS |= FLEXCAN_MB_CS_IDE_MASK; // 使用扩展帧 FLEXCAN0->MB[0].CS |= FLEXCAN_MB_CS_SRR_MASK; // 启用自发自收 FLEXCAN0->MB[0].CS |= FLEXCAN_MB_CS_RTR_MASK; // 启用数据请求 FLEXCAN0->MB[0].ID |= FLEXCAN_MB_ID_EXT_MASK; // 使用扩展标识符 FLEXCAN0->MB[0].ID |= FLEXCAN_MB_ID_IDSTD(0x123); // 标准标识符 FLEXCAN0->MB[0].ID |= FLEXCAN_MB_ID_IDEXT(0x456); // 扩展标识符 FLEXCAN0->MB[0].WORD0 |= 0x11223344; // 数据字0 FLEXCAN0->MB[0].WORD1 |= 0x55667788; // 数据字1 // 开启邮箱接收中断 FLEXCAN0->IMASK |= (1 << 0); NVIC_EnableIRQ(CAN0_ORed_Message_buffer_IRQn); } void CAN_Send(uint8_t *data, uint8_t len) { uint32_t i; // 等待邮箱空闲 while (FLEXCAN0->IFLAG1 & (1 << 0)); // 发送数据 FLEXCAN0->MB[0].CS &= ~(FLEXCAN_MB_CS_DLC_MASK); FLEXCAN0->MB[0].CS |= FLEXCAN_MB_CS_DLC(len); for (i = 0; i < len; i++) { FLEXCAN0->MB[0].DATA_BYTE(i) = data[i]; } FLEXCAN0->MB[0].CS &= ~(FLEXCAN_MB_CS_CODE_MASK); FLEXCAN0->MB[0].CS |= FLEXCAN_MB_CS_CODE(0xC); // 发送数据帧 } ``` 在上述代码中,`CAN_Init`函数用于初始化CAN模块,包括开启时钟、复位、设置时钟、配置邮箱等操作。`CAN_Send`函数用于发送数据,首先等待邮箱空闲,然后设置数据、数据长度和发送帧类型,最后发送数据。需要注意的是,此处的邮箱号为0,如果需要使用其他邮箱,需要相应地修改代码。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值