STM32G431xxxx系列CAN通信(三)

本文详细介绍了TJA1042T/3-CAN通信硬件连接设置,包括电容选择、电阻作用以及STM32F407ZGT6的CAN发送与接收过程,涉及CAN通信原理、ID转换和中断管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、TJA1042T/3-CAN通信硬件连接

在这里插入图片描述

图1-1 CAN通信原理图

TJA1042T/3芯片有休眠模式,可以通过中断(低电平)唤醒,因此其STB和RXD引脚上通过上拉电阻接高电平,CAN_EN和CAN_RX引脚在MCU端是接在一起的,这样当CAN_RX引脚有显性电平时,会将STB引脚拉低,此芯片就从休眠模式进入正常模式。

C4的作用为降低差模干扰,稳定隐性电平,其值选择0.1uF最合适,可由下面几幅图片对比得到。
(本设计选用的CAN收发器需要5V供电,为了方便,也可以选择3.3V供电的SIT3051TK。)
在这里插入图片描述

图1-2 电容值对CAN波形的影响图

从上面四幅图可以看出,只有电容取为100nF时,CANH和CANL的波形是对称的,即两线电平变化幅度和速率相等。

R2、R6两个电阻起到限制瞬间电流的作用,可以提高防护能力。DT5起到抑制瞬间高电压的作用,与DT1组合起来实现差模、共模的防浪涌和静电。

最后的两个自恢复保险丝起到高压防护的作用,选择F1206的封装即可。

FlexCAN是一种高性能的CAN总线控制器,可以在汽车电子、工业控制等领域中被广泛使用。下面是基于S32K342芯片与TJA1145T/FD收发器实现FlexCAN通信的代码和详细解释。 首先,需要在S32K342芯片中配置CAN总线控制器。以下是CAN控制器的初始化代码: ```c void CAN_Init(void) { PCC->PCCn[PCC_FlexCAN0_INDEX] |= PCC_PCCn_PCS(0b001) | PCC_PCCn_CGC_MASK; // 设置时钟源,启用时钟 FLEXCAN0->MCR |= FLEXCAN_MCR_MDIS_MASK; // 进入配置模式 FLEXCAN0->CTRL1 |= FLEXCAN_CTRL1_CLKSRC_MASK; // 时钟源选择为外部时钟 FLEXCAN0->MCR &= ~FLEXCAN_MCR_MDIS_MASK; // 退出配置模式 FLEXCAN0->CTRL1 &= ~FLEXCAN_CTRL1_PRESDIV_MASK; // 清除预分频器 FLEXCAN0->CTRL1 |= FLEXCAN_CTRL1_PRESDIV(5); // 设置预分频器值为5,CAN总线时钟为40MHz/(5+1)=6.67MHz FLEXCAN0->CTRL1 |= FLEXCAN_CTRL1_BOFFREC_MASK; // 失能总线关闭恢复模式 FLEXCAN0->CTRL1 &= ~FLEXCAN_CTRL1_ERRMSK_MASK; // 使能错误中断 FLEXCAN0->CTRL1 |= FLEXCAN_CTRL1_TWRNMSK_MASK | FLEXCAN_CTRL1_RWRNMSK_MASK; // 失能警告中断 FLEXCAN0->MCR &= ~FLEXCAN_MCR_AEN_MASK; // 禁用自动离线管理模式 FLEXCAN0->MCR |= FLEXCAN_MCR_IRMQ_MASK; // 使能个别接收模式 FLEXCAN0->MCR |= FLEXCAN_MCR_FRZ_MASK; // 进入冻结模式 FLEXCAN0->MCR |= FLEXCAN_MCR_HALT_MASK; // 进入等待模式 FLEXCAN0->CTRL1 |= FLEXCAN_CTRL1_LBUF_MASK; // 启用本地缓冲区 FLEXCAN0->MCR &= ~FLEXCAN_MCR_HALT_MASK; // 退出等待模式 FLEXCAN0->MCR &= ~FLEXCAN_MCR_FRZ_MASK; // 退出冻结模式 } ``` 接下来,需要配置TJA1145T/FD收发器。以下是收发器的初始化代码: ```c void CAN_Transceiver_Init(void) { PCC->PCCn[PCC_PORTB_INDEX] |= PCC_PCCn_CGC_MASK; // 启用 PORTB 时钟 PORTB->PCR[2] |= PORT_PCR_MUX(5); // 配置 PTB2 引脚为 FLEXCAN0_TX PORTB->PCR[3] |= PORT_PCR_MUX(5); // 配置 PTB3 引脚为 FLEXCAN0_RX PCC->PCCn[PCC_PORTD_INDEX] |= PCC_PCCn_CGC_MASK; // 启用 PORTD 时钟 PORTD->PCR[5] |= PORT_PCR_MUX(1); // 配置 PTD5 引脚为 TJA1145T/FD 的 STB 引脚 PORTD->PCR[6] |= PORT_PCR_MUX(1); // 配置 PTD6 引脚为 TJA1145T/FD 的 EN 引脚 PTD5_OUT; // 配置 PTD5 引脚为输出模式 PTD6_OUT; // 配置 PTD6 引脚为输出模式 PTD5_H; // 设置 PTD5 引脚为高电平 PTD6_H; // 设置 PTD6 引脚为高电平 } ``` 接下来,需要定义CAN消息结构体。以下是CAN消息结构体的定义: ```c typedef struct { uint32_t id; // 消息ID uint8_t data[8]; // 数据 uint8_t len; // 数据长度 } CAN_MessageTypeDef; ``` 然后,需要实现CAN消息的发送和接收功能。以下是CAN消息发送函数的代码: ```c void CAN_SendMessage(uint32_t id, uint8_t *data, uint8_t len) { CAN_MessageTypeDef msg; // 定义CAN消息结构体 msg.id = id; // 设置消息ID msg.len = len > 8 ? 8 : len; // 设置数据长度 for (uint8_t i = 0; i < msg.len; i++) { msg.data[i] = data[i]; // 设置数据内容 } while (!(FLEXCAN0->IFLAG1 & FLEXCAN_IFLAG1_BUF0I_MASK)); // 等待发送缓冲区0可用 FLEXCAN0->IFLAG1 |= FLEXCAN_IFLAG1_BUF0I_MASK; // 清除发送缓冲区0中断标志位 FLEXCAN0->MB[0].CS |= FLEXCAN_MB_CS_CODE(0x08); // 将发送缓冲区0设置为发送数据帧 FLEXCAN0->MB[0].ID = FLEXCAN_MB_ID_IDSTD(id); // 设置消息ID FLEXCAN0->MB[0].WORD0 = ((uint32_t)msg.data[3] << 24) | ((uint32_t)msg.data[2] << 16) | ((uint32_t)msg.data[1] << 8) | ((uint32_t)msg.data[0]); // 设置数据内容 FLEXCAN0->MB[0].WORD1 = ((uint32_t)msg.data[7] << 24) | ((uint32_t)msg.data[6] << 16) | ((uint32_t)msg.data[5] << 8) | ((uint32_t)msg.data[4]); // 设置数据内容 FLEXCAN0->MB[0].CS |= FLEXCAN_MB_CS_SRR_MASK; // 设置自请求复位 FLEXCAN0->MB[0].CS |= FLEXCAN_MB_CS_TX_MASK; // 启动发送 } ``` 以下是CAN消息接收函数的代码: ```c void CAN_ReceiveMessage(CAN_MessageTypeDef *msg) { while (!(FLEXCAN0->IFLAG1 & FLEXCAN_IFLAG1_BUF4I_MASK)); // 等待接收缓冲区4有新消息 FLEXCAN0->IFLAG1 |= FLEXCAN_IFLAG1_BUF4I_MASK; // 清除接收缓冲区4中断标志位 msg->id = (FLEXCAN0->MB[4].ID & FLEXCAN_MB_ID_IDSTD_MASK) >> FLEXCAN_MB_ID_IDSTD_SHIFT; // 获取消息ID msg->len = FLEXCAN0->MB[4].CS & FLEXCAN_MB_CS_DLC_MASK; // 获取数据长度 msg->data[0] = (uint8_t)(FLEXCAN0->MB[4].WORD0 >> 0); // 获取数据内容 msg->data[1] = (uint8_t)(FLEXCAN0->MB[4].WORD0 >> 8); // 获取数据内容 msg->data[2] = (uint8_t)(FLEXCAN0->MB[4].WORD0 >> 16); // 获取数据内容 msg->data[3] = (uint8_t)(FLEXCAN0->MB[4].WORD0 >> 24); // 获取数据内容 msg->data[4] = (uint8_t)(FLEXCAN0->MB[4].WORD1 >> 0); // 获取数据内容 msg->data[5] = (uint8_t)(FLEXCAN0->MB[4].WORD1 >> 8); // 获取数据内容 msg->data[6] = (uint8_t)(FLEXCAN0->MB[4].WORD1 >> 16); // 获取数据内容 msg->data[7] = (uint8_t)(FLEXCAN0->MB[4].WORD1 >> 24); // 获取数据内容 } ``` 最后,在主程序中调用CAN初始化函数、CAN收发器初始化函数、CAN消息发送函数和CAN消息接收函数即可完成FlexCAN通信。 ```c int main(void) { CAN_Init(); // 初始化CAN控制器 CAN_Transceiver_Init(); // 初始化CAN收发器 CAN_MessageTypeDef tx_msg, rx_msg; // 定义发送消息和接收消息结构体 uint8_t tx_data[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; // 设置发送数据内容 tx_msg.len = 8; // 设置发送数据长度 while (1) { CAN_SendMessage(0x123, tx_data, tx_msg.len); // 发送CAN消息 CAN_ReceiveMessage(&rx_msg); // 接收CAN消息 } return 0; } ``` 以上就是基于S32K342芯片与TJA1145T/FD收发器实现FlexCAN通信的详细代码和解释。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值