S32K1XX_CAN收发的实现

本文章介绍一种基于S32K144芯片的CAN收发的实现,可以实现特定帧的接收与发送。
CAN驱动的代码相对比较复杂,为了大家方便理解,会讲解主要的电路,配置,以及如何实现。
本文章主要对驱动做介绍,如果是纯小白,建议先了解CAN的通信协议与应用。
同时,文章水平有限,如有遗漏或者错误的地方欢迎指出,我会及时更正,欢迎私信交流。

芯片手册

关于S32K144的CAN介绍在手册重描述的很详尽,简要的看一下关键信息,首先是关于S32K144有3路CAN通道可以使用,相对K3系列芯片的通道数要少一些,只有CAN0(芯片内部通道)支持CANFD,且可以容纳32个消息缓冲区。
此处的消息缓冲区,用于配置CAN ID的信息,比如0-10号邮箱可以负责发信号,11-20号邮箱负责收信号,最大可以容纳32个ID。当然,如果实际的应用超出了32个ID,就需要采用复用的方式,此处不做介绍。本篇文章尽量简约化的介绍如何搭建CAN驱动。
在这里插入图片描述

CAN外设芯片

如图所示为本人开发板上使用的CAN芯片和相关电路。
在这里插入图片描述
使用的是TJA1042的CAN芯片,
VCC和GND给芯片供电,
CAN_RX 和 CAN_TX连接到K144主控芯片,
VREF为CAN信号的参考电压,配合输出CAN高和CAN低信号,
S为芯片的STANDBY使能引脚,给高电平使能,为了让CAN芯片工作,此处下拉到地
两个62欧姆的电阻串联在其中,以增加阻抗,提升信号质量,电容用于滤波,均衡信号。
所以CAN信号的发送需要CAN芯片转化为差分信号,同时接收到信号也需要转化。

PIN配置

在这里插入图片描述

此处使用的为芯片内部CAN0通道,对应引脚为PTE5:CAN_TX , PTE4:CAN_RX

外设配置:

在这里插入图片描述

在外设配置中,注意右上角显示为CAN0的配置,使用哪一个内部通道,就选择对应通道。
Name里面flexcanInitConfig0包含了配置下面的配置信息,生成代码时,会有一个与这个名字一样的结构体
Read_Only可以不勾选,表示生成的一些结构体是否为const类型。
Operation Mode 表示通信模式:分别有NormalListen_OnlyLoopbackFreezedisable共5种模式,正常选择Normal,因为需要与外界通信。
Enable FD:是否使能CANFD,此处不使能
Payload Size表示报文最大的字节数,通常为8字节数据,实际收发也可以发送小于8字节的数据。
MBs Number表示消息缓冲区数,也表示邮箱数,CAN0最大支持32个,此处默认选择的16。
Use RX FIFO表示ID的掩码过滤功能,并没有使用,不勾选。
Bitrate to time segments要勾选,配合后面设置通信波特率
在最后Bitrate种填写波特率的大小,通常为500K,填写500

配置完成之后生成源代码即可。

软件流程:

1、先是常规的时钟,GPIO初始化

2、做CAN0的初始化,使用函数:

status_t FLEXCAN_DRV_Init(
uint8_t instance,
flexcan_state_t *state,
const flexcan_user_config_t *data)

instance 填入0.表示CAN0通道
stateflexcan_user_config_t 都会有系统生成的结构体,包含了CAN的配置信息,传入即可。

3、再做CAN接收的邮箱配置,使用函数:

status_t FLEXCAN_DRV_ConfigRxMb(
uint8_t instance,
uint8_t mb_idx,
const flexcan_data_info_t *rx_info,
uint32_t msg_id)

instance 填入0.表示CAN0通道
mb_idx 表示邮箱号0-31,配置哪些通道用于接收信号,
rx_info为一个结构体,表示接收的CAN信号的信息配置,详细见代码注释
msg_id 表示接收的ID

4、CAN接收的邮箱配置完成周,需要配置为保持接收,这样才能响应接收到的特定信号
使用函数:

status_t FLEXCAN_DRV_Receive(
uint8_t instance,
uint8_t mb_idx,
flexcan_msgbuff_t *data)

instance 填入0.表示CAN0通道
mb_idx 表示邮箱号0-31,
flexcan_msgbuff_t 需要传入一个结构体buffer,接收到的值自动幅值到buffer中

5、然后配置CAN回调函数:
使用函数:

void FLEXCAN_DRV_InstallEventCallback(uint8_t instance,
flexcan_callback_t callback,
void *callbackParam)

instance 填入0.表示CAN0通道
callback表示回调函数,需要自己定义一个函数,通过指针传递到自己定义的函数中
callbackParam填入空指针即可。
每次接收到对应ID信号之后,会进入到回调函数中,需要再次使用函数FLEXCAN_DRV_Receive,这样才能一直保持接收对应ID信号,否则接收一次之后不再接收

6、CAN信号发送函数:使用函数:
status_t FLEXCAN_DRV_Send(
uint8_t instance,
uint8_t mb_idx,
const flexcan_data_info_t *tx_info,
uint32_t msg_id,
const uint8_t *mb_data)
instance 填入0.表示CAN0通道
mb_idx表示邮箱号0-31
tx_info为结构体flexcan_data_info_t表示发送的数据参数信息
msg_id表示发送的ID
mb_data传入数组的指针,表示发送的数据

代码部分:


#include "sdk_project_config.h"
#include <interrupt_manager.h>
#include <stdint.h>
#include <stdbool.h>

#define CAN0_INS_0    0  //CAN0 内部通道


#define mail_box_0 0    //邮箱号0(缓冲区)
#define mail_box_1 1    //邮箱号1(缓冲区)

flexcan_msgbuff_t can_rxbuffer;   //声明CAN接收buffer
flexcan_msgbuff_t can_txbuffer=  //声明CAN发送buffer
{
		.data={8,7,6,5,4,3,2,1}  //发送的数据内容
};

void CAN0_RX_CALLBCK(uint8_t instance, flexcan_event_type_t eventType,
        uint32_t buffIdx, flexcan_state_t *flexcanState);  //CAN收发回调函数声明

int main(void)
{
    CLOCK_DRV_Init(&clockMan1_InitConfig0);   //时钟初始化
    PINS_DRV_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);  //GPIO初始化

    FLEXCAN_DRV_Init(CAN0_INS_0,&flexcanState0,&flexcanInitConfig0);  //CAN0初始化
    flexcan_data_info_t info;         //声明局部变量,函数中传入参数
    info.data_length = 8;             //数据字节长度
    info.enable_brs =  false;        //是否使能CANFD加速
    info.fd_enable   =  false;       //是否使能CANFD
    info.is_remote   = 0;              //0:数据帧 1:遥控帧
    info.msg_id_type = FLEXCAN_MSG_ID_STD;   //0:标准帧  1:拓展帧

    FLEXCAN_DRV_ConfigRxMb(CAN0_INS_0,mail_box_0,&info,0x111);    //配置接收信息
    FLEXCAN_DRV_Receive(CAN0_INS_0,mail_box_0,&can_rxbuffer);//做好准备接收
    FLEXCAN_DRV_InstallEventCallback(CAN0_INS_0,CAN0_RX_CALLBCK,NULL);  //配置中断回调函数

    while(1)
    {
		flexcan_data_info_t temp;  //配置发送信息
		temp.data_length = 8;
		temp.enable_brs =  false;
		temp.fd_enable   =  false;
		temp.is_remote   = 0;
		temp.msg_id_type = FLEXCAN_MSG_ID_STD;
    	FLEXCAN_DRV_Send(CAN0_INS_0,mail_box_1,&temp,0x7ff,can_txbuffer.data);  //发送信号
    }
}

void CAN0_RX_CALLBCK(uint8_t instance, flexcan_event_type_t eventType,
        uint32_t buffIdx, flexcan_state_t *flexcanState)
{
	//是否接收到信号  如果接收到信号,且该信号已配置在缓冲区中,会自动进入回调函数
	if(eventType == FLEXCAN_EVENT_RX_COMPLETE)
	{
		if(flexcanState->mbs[buffIdx].mb_message->msgId == 0x111)  //判断接收到得信号ID是否为0X111
		{
			FLEXCAN_DRV_Receive(CAN0_INS_0,mail_box_0,&can_rxbuffer);   //接收后清空缓冲区,继续准备接收数据
		}
		//如果有更多ID,就要加ID判断
	}
	//发送信号也会进入回调函数,这里不做处理
	if(eventType == FLEXCAN_EVENT_TX_COMPLETE)
	{

	}

}


效果展示

接上CAN卡,可以接收到发送的信号ID为7FF,数据为8,7,6,5,4,3,2,1

在这里插入图片描述

同样的,使用CAN卡工具 发送0X111信号
在这里插入图片描述
使用PE调试,可以观察到实时收到的信号,ID为273转换为十进制为0X111,数据为1,2,3,4,5,6,7,8,与预期符合
在这里插入图片描述

  • 41
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值