基于S32K SDK FLEXCAN的通信
- 1 前言
- 2 基本流程
- 3 实例
-
- 3.1硬件资源
- 3.2 实现功能
- 3.3 实现
-
- 3.3.1 MCU配置
- 3.3.2 定义CAN通信配置及邮箱
- 3.3.3 初始化CAN实例及缓冲区
- 3.3.4 定义回调函数及处理内容
- 3.4 运行结果
- 后记
1 前言
在NXP S32K SDK中FLEXCAN提供了CAN和CAN FD的驱动。本文讲解基本CAN通信的程序方法。
2 基本流程
第一步:基本硬件配置
这一步主要配置S32Kxxx MCU的硬件资源。如时钟,引脚,CAN物理层。这一步利用Processor Expert完成。
第二步:定义CAN通信配置及邮箱。
第三步:初始化CAN实例及缓冲区。
第四部:定义回调函数及处理内容。
3 实例
3.1硬件资源
MCU: S32K118
使用引脚:
PTC1:按键
PTA10:LED输出
PTB1:CAN Tx
PTB0:CAN Rx
3.2 实现功能
a. 按下按键后以500Kbps波特率发送ID=1,长度为8,内容为0x01 02 03 04 05 06 07 08的数据。
b. 当接收到500Kbps波特率 ID=2的帧时,点亮LED灯。当接收到ID=4的帧时,关闭LED灯。
3.3 实现
3.3.1 MCU配置
在Processor Expert中:
a. GPIO配置
按使用引脚将PTA10, PTC1分别设置为输出和输入如下:
设置CAN通信所用引脚:
b. 设置CAN硬件参数
这部分设置在SDK生成代码后对应:canCom1.c的如下内容:
const flexcan_user_config_t canCom1_InitConfig0 = { /*CAN通信配置结构体名:canCom1_InitConfig0*/ .fd_enable = false, /*不使用CAN FD*/ .pe_clock = FLEXCAN_CLK_SOURCE_PERIPH, /*CAN通信使用外设时钟源*/ .max_num_mb = 10,/*邮箱数量为10*/ .num_id_filters = FLEXCAN_RX_FIFO_ID_FILTERS_8, /*CAN帧ID过滤器数量为8*/ .is_rx_fifo_needed = false, /*不使用FIFO*/ .flexcanMode = FLEXCAN_NORMAL_MODE, /*正常模式*/ .payload = FLEXCAN_PAYLOAD_SIZE_8, .bitrate = { /*仲裁场位时间设置*/ .propSeg = 7, .phaseSeg1 = 4, .phaseSeg2 = 1, .preDivider = 5, .rJumpwidth = 1 }, .bitrate_cbt = {/*数据场位时间设置*/ .propSeg = 7, .phaseSeg1 = 4, .phaseSeg2 = 1, .preDivider = 5, .rJumpwidth = 1 }, .transfer_type = FLEXCAN_RXFIFO_USING_INTERRUPTS,/*中断方式*/ .rxFifoDMAChannel = 0U };
3.3.2 定义CAN通信配置及邮箱
a ,配置CAN通信格式
在主程序设置配置结构体及接收数据缓冲区,例如接收部分如下:
flexcan_data_info_t Rx_dataInfo = { .data_length = 8U, .msg_id_type = FLEXCAN_MSG_ID_STD, /*使用11位标准ID格式*/ .enable_brs = false, /*因为不使用CAN FD所以关闭*/ .fd_enable = false, /*因为不使用CAN FD所以关闭*/ .fd_padding = 0U /*因为不使用CAN FD所以关闭*/ }; flexcan_msgbuff_t recvBuff; //接收数据缓冲区
在SDK中定义的数据缓冲区格式如下,后文将按这个结构体进行CAN报文的设置。
typedef struct { uint32_t cs; /*!< Code and Status*/ uint32_t msgId; /*!< Message Buffer ID*/ uint8_t data[64]; /*!< Data bytes of the FlexCAN message*/ uint8_t dataLen; /*!< Length of data in bytes */ } flexcan_msgbuff_t;
b. 定义通信邮箱
//定义发送邮箱,最后数字为CAN ID值 #define Tx_MB_01 (1UL) // 定义接收邮箱,最后的数字为CAN ID值 #define Rx_MB_02 (2UL) #define Rx_MB_04 (4UL)
3.3.3 初始化CAN实例及缓冲区
a. 配置CAN通信格式
在主程序中按前面Process Expert中指定的CAN实例及配置结构体名进行CAN口的初始化。
FLEXCAN_DRV_Init(INST_CANCOM1, &canCom1_State, &canCom1_InitConfig0);
b.初始化收发缓冲区
/*配置发送缓冲区*/ FLEXCAN_DRV_ConfigTxMb(INST_CANCOM1, Tx_MB_01, &sendBuff, 1);//ID=1 /*配置接收缓冲区*/ FLEXCAN_DRV_ConfigRxMb(INST_CANCOM1, Rx_MB_02, &recvBuff, 2); // ID=2 FLEXCAN_DRV_ConfigRxMb(INST_CANCOM1, Rx_MB_04, &recvBuff, 4); // ID=4
3.3.4 定义回调函数及处理内容
a. 定义回调函数
此处回调函数在SDK中的格式为:
typedef void(* flexcan_callback_t) (uint8_t instance, flexcan_event_type_t eventType, uint32_t buffIdx, flexcan_state_t *flexcanState)
本例中只用回调函数进行CAN的接收处理。
主程序中安装回调函数如下:
FLEXCAN_DRV_InstallEventCallback(INST_CANCOM1,CAN_CallBack,NULL); FLEXCAN_DRV_Receive(INST_CANCOM1, Rx_MB_02, &recvBuff); FLEXCAN_DRV_Receive(INST_CANCOM1, Rx_MB_04, &recvBuff);
程序中定义的回调函数为:CAN_CallBack()
由于基本的CAN收发函数除非使用阻塞型函数外,函数之后后直接退出。CAN的操作结束时会触发回调函数。因此在安装回调函数后,马上使用CAN的接收API函数FLEXCAN_DRV_Receive()进行读操作。若有数据被接收到了,则自动进入回调函数中。
b.回调函数
void CAN_CallBack(uint8_t instance, flexcan_event_type_t eventType, uint32_t buffIdx, flexcan_state_t *flexcanState) { (void) buffIdx; (void) flexcanState; if(eventType == FLEXCAN_EVENT_RX_COMPLETE) {/*CAN读完成事件触发时执行*/ if(recvBuff.msgId==2) { /*ID=2的帧点灯*/ PINS_DRV_SetPins(GPIO2_PORT, (1 << LED2)); FLEXCAN_DRV_Receive(INST_CANCOM1,Rx_MB_02, &recvBuff); } if(recvBuff.msgId==4) {/*ID=4的帧关灯*/ PINS_DRV_ClearPins(GPIO2_PORT, (1 << LED2)); FLEXCAN_DRV_Receive(INST_CANCOM1,Rx_MB_04, &recvBuff); } } }
其中“eventType”是事件类型,FLEXCAN_EVENT_RX_COMPLETE为读CAN完成事件。而后的程序按帧ID进行不同的开关灯操作。
c.CAN的发送处理
在按键处理程序中,当判断到有按键按下时,执行:
sendBuff.msgId=0x1; sendBuff.dataLen=8; for (int i=0;i<9;i++) { sendBuff.data[i]=i+1; } /* Send the information via CAN */ SendCANData(Tx_MB_01, sendBuff.msgId, sendBuff.data, 8UL);
SendCANData()
void SendCANData(uint32_t mailbox, uint32_t messageId, uint8_t * data, uint32_t len) { FLEXCAN_DRV_Send(INST_CANCOM1, mailbox, &Tx_dataInfo, messageId, data); }
3.4 运行结果
其中第一帧为硬件向上位机发送的CAN报文。第二,三帧为上位机发给硬件的开关灯报文。硬件开关灯正常,CAN通信收发成功。
后记
本文于2024.1.21日首发于“车灯电子扫地僧”。 如果你喜欢我的文章,也可以“车灯电子扫地僧”搜索微信订阅号。更多文章等待您的发掘。