STM32 CAN通讯配置

原文地址::STM32 CAN通讯配置

相关文章

1、STM32F103C8T6 CAN通信详解----STM32F103C8T6 CAN通信详解 

2、STM32 CAN配置----https://www.cnblogs.com/tec2019/p/16148183.html

3、STM32 CAN配置----STM32 CAN配置_stm32can配置_天问XUiRH的博客-CSDN博客 

4、stm32之CAN配置流程----stm32之CAN配置流程_Good boy-dai的博客-CSDN博客 

5、STM32 CAN 参数设置----STM32 CAN 参数设置_can参数配置_新时代弄潮儿的博客-CSDN博客 

6、can部分 6 stm32的can波特率配置----can部分 6 stm32的can波特率配置 - 哔哩哔哩 

简介

CAN通信帧共分为数据帧、远程帧、错误帧、过载帧和帧间隔,本文这里以数据帧为例。

注:显性电平对应逻辑0,CAN_H和CAN_L之差为2.5V左右。而隐性电平对应逻辑1,CAN_H和CAN_L之差为0V, 数据帧有标准帧和扩张帧两种格式,一个11位,一个29位

标准帧和扩张帧两种格式区别:

  • 扩展帧的仲裁域有29位,可以出现2^29中报文,且在数据链路上是有间隙的(对操作者透明),帧ID的范围是0000 0000-1FFF FFFF。(PS:目的就是构造29位的CAN ID,可以实现更加庞大的ID群)
  • 标准帧的仲裁域是连续的11位,可以出现2^11种报文,也就是帧ID的范围是000-7FF;
  • 标准帧和扩张帧的控制帧中的DLC(数据长度)完全相同,但保留位不同,标准帧为IDE、R0,扩展帧为R1、R0,必须以显性电平发送(由数据链路层操作)

注意:这里的帧ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级(帧ID值越小,优先级越高,最小是0x00000000)

CAN协议特点:

1、多主控制。
2、系统柔软性。
3、通讯速度快,通讯距离远。
4、具有错误检测、错误通知、错误恢复功能。
5、故障封闭功能。
6、连接节点多。

CAN总线具有自动仲裁功能,这样就提高了总线的利用率。

CAN总线没有被发送出去的隐性信号,会由CAN控制器后续发送出去。这里牵涉到CAN总线优先级的问题,后续进一步讲述。
当然,CAN相比485具有明显优势,主要原因还是在于CAN控制器。

CAN直接通过TX连接对方的RX引脚,单向传输可以,双向传输就不行,因为CAN控制器会实时监测发送出去的信号是否正确。也就是说TX要与RX信号一致才行,否则CAN控制器认为你发送失败。

CAN总线收发,中断方式接收配置

平台:STM32F103RB
STM32CUBEMX V5.3


配置CAN

CAN的波特率最大为1Mbps。

波特率计算方法:时钟主频 / 分频 / (tq1 + tq2 + swj)

以500K的波特率配置为例
stm32f103的CAN的时钟主频是36M,分9频就是4M,在除以(5 + 2 + 1)得到500K的波特率。
注意:stm32cubemx生成的CAN代码是不带过滤器的,需要自己手动添加。

在这里插入图片描述
在这里插入图片描述

CAN之数据帧格式

在这里插入图片描述

代码部分

CAN初始化

CAN_HandleTypeDef hcan1;
CAN_FilterTypeDef sFilterConfig;//CAN初始化:/* CAN init function */
void MX_CAN_Init(void)
{hcan1.Instance = CAN1;hcan1.Init.Prescaler = 9;hcan1.Init.Mode = CAN_MODE_LOOPBACK;					// 回环模式,测试用。hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;hcan1.Init.TimeSeg1 = CAN_BS1_5TQ;hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;hcan1.Init.TimeTriggeredMode = DISABLE;					// 时间触发通信模式禁能hcan1.Init.AutoBusOff = DISABLE;						// 软件自动离线管理禁能hcan1.Init.AutoWakeUp = DISABLE;						// 睡眠模式自动唤醒禁能hcan1.Init.AutoRetransmission = DISABLE;				// 报文自动重传禁能hcan1.Init.ReceiveFifoLocked = DISABLE;					// 报文锁定禁能,新报文覆盖旧报文hcan1.Init.TransmitFifoPriority = ENABLE;				// 使能优先级由报文标识符决定if (HAL_CAN_Init(&hcan1) != HAL_OK){Error_Handler();}sFilterConfig.FilterBank = 0;									// 使用过滤器0sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;				// 屏蔽位模式sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;				// 32位宽sFilterConfig.FilterIdHigh = 0x0000;							// ID高十六位sFilterConfig.FilterIdLow = 0x0000;								// ID低十六位sFilterConfig.FilterMaskIdHigh = 0x0000;						// ID掩码高十六位sFilterConfig.FilterMaskIdLow = 0x0000;							// ID掩码低十六位sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;				// 过滤器0关联到FIFO0sFilterConfig.FilterActivation = ENABLE;						// 激活过滤器0sFilterConfig.SlaveStartFilterBank = 14;if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK){Error_Handler();}if (HAL_CAN_Start(&hcan1) != HAL_OK){Error_Handler();}if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)		// 使能FIFO0数据中断接收{Error_Handler();}
}

覆写接收中断回调函数

(注意:上面的配置我们使用的式FIFO0,所以要覆写FIFO0的中断回调函数):

void can_msg_info(CAN_RxHeaderTypeDef* hdr, const void* data)
{printf("IDE     : %s\r\n",hdr->IDE == CAN_ID_STD ? "CAN_ID_STD" : "CAN_ID_EXT");printf("RTR     : %s\r\n",hdr->RTR == CAN_RTR_DATA ? "CAN_RTR_DATA" : "CAN_RTR_REMOTE");printf("DLC     : %ld\r\n", hdr->DLC);printf("StdId   : 0x%X\r\n", hdr->StdId);printf("ExtId   : 0x%X\r\n", hdr->ExtId);printf("Data    : %s\r\n", (char *) data);
}void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{if (hcan->Instance == hcan1.Instance){uint8_t buf[8];CAN_RxHeaderTypeDef CAN_RX_HDR;if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &CAN_RX_HDR, buf)			// 获得接收到的数据头和数据== HAL_OK){can_msg_info(&CAN_RX_HDR, buf);HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);	// 再次使能FIFO0接收中断}}
}

CA发送函数:

uint8_t CAN_Transmit(const void* buf, uint32_t len)
{uint32_t txmailbox = 0;uint32_t offset = 0;CAN_TxHeaderTypeDef hdr;hdr.IDE = CAN_ID_STD;				// 帧ID:标准帧hdr.RTR = CAN_RTR_DATA;				// 帧类型:数据帧hdr.StdId = 0x12;					// 标准帧ID,最大11位,也就是0x7FFhdr.ExtId = 0x12;					// 扩展帧ID,最大29位,也就是0x1FFFhdr.TransmitGlobalTime = DISABLE;while(len != 0){hdr.DLC = len > 8 ? 8 : len;		// 数据长度if(HAL_CAN_AddTxMessage(&hcan1, &hdr, ((uint8_t *)buf) + offset, &txmailbox) != HAL_OK)return 1;offset += hdr.DLC;len -= hdr.DLC;}return 0;
}

附注:stm32cubemx can配置参数详解:

配置参数

参数意思
Prescaler预分频,即位时序提到的APB1 peripheral clocks继续分一次频
Time Quantum最小时间单位Tq,自动计算出来的,不需要填写
Time Quanta in Bit Segment 1PBS1段长度
Time Quanta in Bit Segment 2PBS2段长度
ReSynchronization Jump Width重同步跳跃宽度,即位时序提到的SJW
Time Triggered Communication Mode是否使能时间触发
Automatic Bus-Off Management是否使能自动离线管理
Automatic Wake-Up Modet是否使能自动唤醒
Qutomatic Retransmission是否使能自动重传
Receive Fifo Locked Mode是否使能锁定FIFO
Transmit Fifo Priority配置报文优先级的判断方法
Oprating Mode操作模式
  1. 这些参数也可以在can.c中自行修改
  2. 中断(NVIC)设置,根据需要设置,一般勾上CAN1 RX0 Interrupt

8.1.2 协议层

位时序

意义:为了实现正确的总线电平采样,确保通讯正常。最小单位是Tq(Time Quantum),一个完整位由8~25个Tq组成
组成:SS段、PTS 段、PBS1段、PBS2段

段名意义作用
SS(1Tq)同步段补偿物理延时,是传播时间、收发器延时之和的两倍
PTS(1~8Tq)传播时间段补偿变压阶段误差
PBS1(1~8Tq)相位缓冲段1使总线各节点同步
PBS2(2~8Tq)相位缓冲段2补偿边沿阶段误差
SJW(1~4Tq)再同步补偿宽度补偿时钟频率偏差、传输延迟等

例如
在这里插入图片描述

通讯波特率的计算:CAN使用的时钟线是APB1 peripheral clocks(假设是APC),即一般是SYSCLK的四分频。而CAN通讯还要对此进行预分频(假设是Prescaler),则一个Tq为 Prescaler / APC(单位s)。而一个数据位占(SS+PTS+PBS1+PBS2+SJW)个Tq。则一秒可以传输的位数就是1 T q ∗ 一 个 位 得 T q 数 \frac{1}{Tq一个位得Tq数}Tq∗一个位得Tq数1
例如:在时钟树查得APB1 peripheral clocks是45MHz,预分频为5,则一个Tq为 4 45 M H z = 111.1111 … ( n s ) \frac{4}{45MHz}=111.1111\dots(ns)45MHz4=111.1111…(ns) ,上图中有19个Tq,则此时波特率为1 19 ∗ 111.11 ∗ 1 0 − 9 ≈ 473689 ( b p s ) \frac{1}{19
111.11*10^{-9}}\approx473689(bps)19∗111.11∗10−91≈473689(bps)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值