简单理解:CAN 接线及其代码配置流程

这是一个典型的 CAN 总线通信电路,核心是 TJA1050 收发器芯片,它负责把 MCU(微控制器)的数字信号转换成 CAN 总线上的差分信号,也能把总线上的差分信号还原成 MCU 能识别的数字信号。
1. 核心芯片 TJA1050 各部分功能
-
左侧接口(和 MCU 连接)
CAN_TX(引脚 1):MCU 发送数据到 TJA1050 的输入引脚。CAN_RX(引脚 4):TJA1050 把总线上收到的数据输出给 MCU 的引脚。VCC(引脚 3):接 5V 电源(VCC5V),给芯片供电。GND(引脚 2):接地,提供参考电平。
-
右侧接口(和 CAN 总线连接)
CANH(引脚 7):CAN 总线的高电平线。CANL(引脚 6):CAN 总线的低电平线。RS(引脚 8):接地,将芯片设置为高速工作模式。Vref(引脚 5):悬空,在高速模式下无需连接。
2. 关键外围电路
-
终端电阻 R50(120Ω)接在
CANH和CANL之间,用于匹配 CAN 总线的特性阻抗,减少信号反射,保证通信稳定。这是 CAN 总线的标准配置,通常在总线的两端各接一个 120Ω 电阻。 -
电源滤波电容 C56(104,即 0.1μF)接在 VCC5V 和 GND 之间,用于滤除电源线上的高频干扰,给 TJA1050 提供更干净的电源。
3. 下方信号映射
这部分是 MCU 的引脚定义,说明:
CAN_RX连接到 MCU 的PD0/FSMC_D2/CAN1_RX引脚CAN_TX连接到 MCU 的PD1/FSMC_D3/CAN1_TX引脚这表明 MCU 是通过其内置的CAN1外设来和 TJA1050 通信的。
整体工作流程
- MCU 通过
CAN1_TX引脚发送数字信号 → TJA1050 的CAN_TX输入。 - TJA1050 将该信号转换为差分信号,通过
CANH和CANL发送到 CAN 总线。 - 总线上的差分信号被其他节点的 TJA1050 接收,转换为数字信号后,通过
CAN_RX输出给对应节点的 MCU。 - 整个过程通过差分传输和终端电阻,实现了高抗干扰性和长距离通信。

1.开启GPIO和CAN
GPIOD
CAN1
2.初始化GPIO
GPIO_Init(...);
GPIO_PinAFConfig(...);
3.初始化CAN
uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct);
参数:
CANx - 哪个CAN
CAN_InitStruct - 初始化结构
typedef struct
{
uint16_t CAN_Prescaler; /*!< 预分频系数 1 to 1024. */
uint8_t CAN_Mode; /*!< 工作模式 @ref CAN_operating_mode */
uint8_t CAN_SJW; /*!< 再同步补偿宽度 @ref CAN_synchronisation_jump_width */
uint8_t CAN_BS1; /*!< 位BS1时间 @ref CAN_time_quantum_in_bit_segment_1 */
uint8_t CAN_BS2; /*!< 位BS2时间 @ref CAN_time_quantum_in_bit_segment_2 */
FunctionalState CAN_TTCM; /*!< 时间触发使能 ENABLE or DISABLE. */
FunctionalState CAN_ABOM; /*!< 自动离线使能 ENABLE or DISABLE. */
FunctionalState CAN_AWUM; /*!< 自动唤醒使能 ENABLE or DISABLE. */
FunctionalState CAN_NART; /*!< 非自动重发使能 ENABLE or DISABLE. */
FunctionalState CAN_RFLM; /*!< 接收FIFO锁定模式使能 ENABLE or DISABLE. */
FunctionalState CAN_TXFP; /*!< 发送FIFO优先级使能 ENABLE or DISABLE. */
} CAN_InitTypeDef;
4.初始化CAN过滤器
void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct);
参数:
typedef struct
{
uint16_t CAN_FilterIdHigh; /*!< Specifies the filter identification number (MSBs for a 32-bit
configuration, first one for a 16-bit configuration).
This parameter can be a value between 0x0000 and 0xFFFF */
uint16_t CAN_FilterIdLow; /*!< Specifies the filter identification number (LSBs for a 32-bit
configuration, second one for a 16-bit configuration).
This parameter can be a value between 0x0000 and 0xFFFF */
uint16_t CAN_FilterMaskIdHigh; /*!< Specifies the filter mask number or identification number,
according to the mode (MSBs for a 32-bit configuration,
first one for a 16-bit configuration).
This parameter can be a value between 0x0000 and 0xFFFF */
uint16_t CAN_FilterMaskIdLow; /*!< Specifies the filter mask number or identification number,
according to the mode (LSBs for a 32-bit configuration,
second one for a 16-bit configuration).
This parameter can be a value between 0x0000 and 0xFFFF */
uint16_t CAN_FilterFIFOAssignment; /*!< Specifies the FIFO (0 or 1) which will be assigned to the filter.
This parameter can be a value of @ref CAN_filter_FIFO */
uint8_t CAN_FilterNumber; /*!< Specifies the filter which will be initialized. It ranges from 0 to 13. */
uint8_t CAN_FilterMode; /*!< Specifies the filter mode to be initialized.
This parameter can be a value of @ref CAN_filter_mode */
uint8_t CAN_FilterScale; /*!< Specifies the filter scale.
This parameter can be a value of @ref CAN_filter_scale */
FunctionalState CAN_FilterActivation; /*!< Enable or disable the filter.
This parameter can be set either to ENABLE or DISABLE. */
} CAN_FilterInitTypeDef;
5.配置发射和接收结构
typedef struct
{
uint32_t StdId; /*!< 标准帧ID between 0 to 0x7FF. */
uint32_t ExtId; /*!< 扩展帧ID between 0 to 0x1FFFFFFF. */
uint8_t IDE; /*!< IDE标志 标准帧/扩展帧 @ref CAN_identifier_type */
uint8_t RTR; /*!< RTR标志 数据帧/遥控帧 @ref CAN_remote_transmission_request */
uint8_t DLC; /*!< 数据段长度 0 to 8 */
uint8_t Data[8]; /*!< 数据 */
} CanTxMsg;
typedef struct
{
uint32_t StdId; /*!< 标准帧ID between 0 to 0x7FF. */
uint32_t ExtId; /*!< 扩展帧ID between 0 to 0x1FFFFFFF. */
uint8_t IDE; /*!< IDE标志 @ref CAN_identifier_type */
uint8_t RTR; /*!< RTR标志 @ref CAN_remote_transmission_request */
uint8_t DLC; /*!< 数据段长度 between 0 to 8 */
uint8_t Data[8]; /*!< 数据 */
uint8_t FMI; /*!< 存放过滤器编号 between 0 to 0xFF */
} CanRxMsg;
6.初始化NVIC和CAN中断
NVIC_Init(...);
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);
7.发送和接收数据
uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage);
uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox);
void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage);
案例
can.h
#ifndef _CAN_H_
#define _CAN_H_
#include
void can1_init(void);
u8 can1_send_message(u8 *data,u8 len,u32 message_id);
void parse_can_cmd(void);
#endif
can.c
#include
#include
#include
#include
void can1_init(void)
{
GPIO_InitTypeDef GPIO_InitStructer;
CAN_InitTypeDef CAN_InitStruct;
CAN_FilterInitTypeDef CAN_FilterInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
//1.开启时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
//2.初始化GPIO为CAN复用
GPIO_InitStructer.GPIO_Mode = GPIO_Mode_AF;//复用模式
GPIO_InitStructer.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructer.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;//PD0 PD1
GPIO_InitStructer.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上下拉
GPIO_InitStructer.GPIO_Speed = GPIO_Speed_50MHz;//快速
GPIO_Init(GPIOD,&GPIO_InitStructer);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1);
//3.初始化CAN 42M / 4 /(12+8+1) = 500Kbps
CAN_InitStruct.CAN_Prescaler = 4;//4分频
CAN_InitStruct.CAN_BS1 = CAN_BS1_12tq;//12Tq
CAN_InitStruct.CAN_BS2 = CAN_BS1_8tq;//8Tq
CAN_InitStruct.CAN_SJW = CAN_SJW_1tq;//1Tq
CAN_InitStruct.CAN_Mode = CAN_Mode_Normal;//CAN_Mode_LoopBack;//正常模式
CAN_InitStruct.CAN_ABOM = DISABLE;
CAN_InitStruct.CAN_AWUM = DISABLE;
CAN_InitStruct.CAN_NART = DISABLE;
CAN_InitStruct.CAN_RFLM = DISABLE;
CAN_InitStruct.CAN_SJW = DISABLE;
CAN_InitStruct.CAN_TTCM = DISABLE;
CAN_InitStruct.CAN_TXFP = DISABLE;
CAN_Init(CAN1,&CAN_InitStruct);
//4.过滤器的初始化
// CAN_FilterInitStruct.CAN_FilterActivation = ENABLE;//使能过滤器
// CAN_FilterInitStruct.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;//使用FIFO0
// CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdMask;//掩码模式
// CAN_FilterInitStruct.CAN_FilterNumber = 0;//过滤器编号
// CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_16bit;//过滤器长度
// CAN_FilterInitStruct.CAN_FilterIdHigh = 0x0000;
// CAN_FilterInitStruct.CAN_FilterIdLow = 0x0000;
// CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0x0000;
// CAN_FilterInitStruct.CAN_FilterMaskIdLow = 0x0000;
// CAN_FilterInit(&CAN_FilterInitStruct);
//16位列表模式
// CAN_FilterInitStruct.CAN_FilterActivation = ENABLE;//使能过滤器
// CAN_FilterInitStruct.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;//使用FIFO0
// CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdList;//列表模式
// CAN_FilterInitStruct.CAN_FilterNumber = 0;//过滤器编号
// CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_16bit;//过滤器长度
// //0x123 0x321 0x7ab 0x000这4个ID
// CAN_FilterInitStruct.CAN_FilterIdHigh = 0x123<<5;
// CAN_FilterInitStruct.CAN_FilterIdLow = 0x321<<5;
// CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0x7ab<<5;
// CAN_FilterInitStruct.CAN_FilterMaskIdLow = 0x0000;
// CAN_FilterInit(&CAN_FilterInitStruct);
// //32位列表模式
// CAN_FilterInitStruct.CAN_FilterActivation = ENABLE;//使能过滤器
// CAN_FilterInitStruct.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;//使用FIFO0
// CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdList;//列表模式
// CAN_FilterInitStruct.CAN_FilterNumber = 0;//过滤器编号
// CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_32bit;//过滤器长度
// //0x7890abc 0xcba9876 这2个ID
// CAN_FilterInitStruct.CAN_FilterIdHigh = 0x7890abc>>13;//ID高16位
// CAN_FilterInitStruct.CAN_FilterIdLow = ((0x7890abc<<3)&0xffff)|(0x1<<2);//(0x7890abc&0x1fff)<<3|(0x1<<2);//ID低13位放在高位,第2位置1(扩展帧)
// CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0xcba9876>>13;
// CAN_FilterInitStruct.CAN_FilterMaskIdLow = ((0xcba9876<<3)&0xffff)|(0x1<<2);
// CAN_FilterInit(&CAN_FilterInitStruct);
//16位掩码模式
// CAN_FilterInitStruct.CAN_FilterActivation = ENABLE;//使能过滤器
// CAN_FilterInitStruct.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;//使用FIFO0
// CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdMask;//掩码模式
// CAN_FilterInitStruct.CAN_FilterNumber = 0;//过滤器编号
// CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_16bit;//过滤器长度
// //0x1*3 0x*2*这2个ID
// CAN_FilterInitStruct.CAN_FilterIdHigh = 0x123<<5;
// CAN_FilterInitStruct.CAN_FilterIdLow = 0x321<<5;
// CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0x70f<<5;// 001 **** 0011
// CAN_FilterInitStruct.CAN_FilterMaskIdLow = 0xf0<<5; // *** 0010 ****
// CAN_FilterInit(&CAN_FilterInitStruct);
//32位掩码模式
CAN_FilterInitStruct.CAN_FilterActivation = ENABLE;//使能过滤器
CAN_FilterInitStruct.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;//使用FIFO0
CAN_FilterInitStruct.CAN_FilterMode = CAN_FilterMode_IdMask;//掩码模式
CAN_FilterInitStruct.CAN_FilterNumber = 0;//过滤器编号
CAN_FilterInitStruct.CAN_FilterScale = CAN_FilterScale_32bit;//过滤器长度
//0x*2*4**ff这个ID
CAN_FilterInitStruct.CAN_FilterIdHigh = 0x20400ff>>13;//ID高16位
CAN_FilterInitStruct.CAN_FilterIdLow = ((0x20400ff<<3)&0xffff)|(0x1<<2);
CAN_FilterInitStruct.CAN_FilterMaskIdHigh = 0xf0f00ff>>13;
CAN_FilterInitStruct.CAN_FilterMaskIdLow = ((0xf0f00ff<<3)&0xffff)|(0x1<<2);
CAN_FilterInit(&CAN_FilterInitStruct);
//5.初始化NVIC和CAN1接收中断
NVIC_InitStruct.NVIC_IRQChannel = CAN1_RX0_IRQn;//CAN1的FIFO0中断通道
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//中断通道使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x2;//抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x2;//响应优先级
NVIC_Init(&NVIC_InitStruct);
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);
}
CanTxMsg CAN1_TX_MSG;
CanRxMsg CAN1_RX_MSG;
//发送函数 0---成功 非0 ----- 失败
u8 can1_send_message(u8 *data,u8 len,u32 message_id)
{
u8 i,mailbox;
u32 cnt = 0;
if(len>8)
return 1;
//根据ID的值选择扩展帧/标准帧
if(message_id>0x7ff){//扩展帧
CAN1_TX_MSG.IDE = CAN_Id_Extended;
}
else{
CAN1_TX_MSG.IDE = CAN_Id_Standard;
}
CAN1_TX_MSG.RTR = CAN_RTR_Data;//数据帧
CAN1_TX_MSG.DLC = len;//数据长度
CAN1_TX_MSG.ExtId = message_id;//扩展帧ID
CAN1_TX_MSG.StdId = message_id;//标准帧ID
//传输数据
for(i=0;i=sizeof(can_buf)-8){
can_flag = 1;
}
//打印
//printf("%s
",CAN1_RX_MSG.Data);
//原路发回
// if(CAN1_RX_MSG.IDE==CAN_Id_Standard){
// can1_send_message(CAN1_RX_MSG.Data,CAN1_RX_MSG.DLC,CAN1_RX_MSG.StdId);
// }
// else if(CAN1_RX_MSG.IDE==CAN_Id_Extended){
// can1_send_message(CAN1_RX_MSG.Data,CAN1_RX_MSG.DLC,CAN1_RX_MSG.ExtId);
// }
//清除标志
CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
}
}
main.c
while(1){
if(can1_send_message("ledon*",6,0x20400ff)!=0){
printf("CAN发送失败!
");
}
parse_can_cmd();
// parse_cmd();
// delay_ms(100);
//喂狗
//IWDG_ReloadCounter();
delay_s(1);
if(can1_send_message("ledoff*",7,0x20400ff)!=0){
printf("CAN发送失败!
");
}
parse_can_cmd();
delay_s(1);
}












