STM32 CAN通信协议详解—小白入门(二)

文章目录

(一)CAN通信协议简介
(二)CAN物理层

      2.1、闭环总线网络2.2、开环总线网络2.3、通信节点2.4、差分信号2.5、CAN协议的差分信号

(三)协议层

      3.1、CAN的波特率及位同步 3.2、位时序分解        3.3、通讯的波特率3.4、同步过程分析3.5、CAN的报文种类及结构3.5.1、报文的种类3.6、数据帧的结构3.7、其他数据帧的结构

(四)STM32的CAN外设简介

      4.1、控制内核4.1.1、主控制寄存器 CAN_MCR4.1.2、位时序寄存器 (CAN_BTR) 及波特率4.2、CAN发送邮箱4.2.1、CAN接受FIFO4.3、验收筛选器4.4、整体逻辑控制

(五)CAN代码中的部分初始化代码

前言:因为CAN通信协议内容过多,我分为两节进行讲解,请结合STM32 CAN通信协议详解—小白入门(一)这一章阅读

(四)STM32的CAN外设简介
STM32 的芯片中具有 bxCAN 控制器 (Basic Extended CAN),它支持 CAN 协议 2.0A 和 2.0B 标准。该 CAN 控制器支持最高的通讯速率为 1Mb/s;可以自动地接收和发送 CAN 报文,支持使用标准ID 和扩展 ID 的报文;外设中具有 3 个发送邮箱,发送报文的优先级可以使用软件控制,还可以记录发送的时间;具有 2 个 3 级深度的接收 FIFO,可使用过滤功能只接收或不接收某些 ID 号的报文;可配置成自动重发;不支持使用 DMA 进行数据收发。
在这里插入图片描述图中是 STM32F105/107 系列互联型芯片的 CAN 外设架构图,图里具有 2 组 CAN 控制器,其中 CAN1 是主设备,框图中的“存储访问控制器”是由 CAN1 控制的,CAN2 无法直接访问存储区域,所以使用 CAN2 的时候必须使能 CAN1 外设的时钟。框图中主要包含 CAN 控制内核、发送邮箱、接收 FIFO 以及验收筛选器。我们实验板中使用的 STM32F103 系列芯片跟上述框图类似,但该系列只包含 1 组 CAN 控制器,即它们不包含图中标号的部分。
下面对框图中的各个部分进行介绍。

4.1、CAN的控制内核
框图中标号处的 CAN 控制内核包含了各种控制寄存器及状态寄存器,我们主要讲解其中的主控制寄存器 CAN_MCR 及位时序寄存器 CAN_BTR。

4.1.1、主控制寄存器 CAN_MCR
主控制寄存器 CAN_MCR 负责管理 CAN 的工作模式,它使用以下寄存器位实现控制。
(1) DBF 调试冻结功能
DBF(Debug freeze) 调试冻结,使用它可设置 CAN 处于工作状态或禁止收发的状态,禁止收发时仍可访问接收 FIFO 中的数据。这两种状态是当 STM32 芯片处于程序调试模式时才使用的,平时使用并不影响
(2) TTCM 时间触发模式
TTCM(Time triggered communication mode) 时间触发模式,它用于配置 CAN 的时间触发通信模式,在此模式下,CAN 使用它内部定时器产生时间戳,并把它保存在CAN_RDTxR、CAN_TDTxR 寄存器中。内部定时器在每个 CAN 位时间累加,在接收和发送的帧起始位被采样,并生成时间戳。利用它可以实现 ISO 11898-4 CAN 标准的分时同步通信功能。
(3) ABOM 自动离线管理
ABOM (Automatic bus-off management) 自动离线管理,它用于设置是否使用自动离线管理功能。当节点检测到它发送错误或接收错误超过一定值时,会自动进入离线状态,在离线状态中,CAN 不能接收或发送报文。处于离线状态的时候,可以软件控制恢复或者直接使用这个自动离线管理功能,它会在适当的时候自动恢复
(4) AWUM 自动唤醒
AWUM (Automatic bus-off management),自动唤醒功能,CAN 外设可以使用软件进入低功耗的睡眠模式,如果使能了这个自动唤醒功能,当 CAN 检测到总线活动的时候,会自动唤醒。
(5) NART 自动重传
NART(No automatic retransmission) 报文自动重传功能,设置这个功能后,当报文发送失败时会自动重传至成功为止。若不使用这个功能,无论发送结果如何,消息只发送一次
(6) RFLM 锁定模式
RFLM(Receive FIFO locked mode)FIFO 锁定模式,该功能用于锁定接收 FIFO 。锁定后,当接收 FIFO 溢出时,会丢弃下一个接收的报文。若不锁定,则下一个接收到的报文会覆盖原报文
(7) TXFP 报文发送优先级的判定方法
TXFP(Transmit FIFO priority) 报文发送优先级的判定方法,当 CAN 外设的发送邮箱中有多个待发送报文时,本功能可以控制它是根据报文的 ID 优先级还是报文存进邮箱的顺序来发送。

4.1.2、位时序寄存器 (CAN_BTR) 及波特率
CAN 外设中的位时序寄存器 CAN_BTR 用于配置测试模式、波特率以及各种位内的段参数。
(1) 测试模式
为方便调试,STM32 的 CAN 提供了测试模式,配置位时序寄存器 CAN_BTR 的 SILM 及 LBKM寄存器位可以控制使用正常模式、静默模式、回环模式及静默回环模式,见下图。
在这里插入图片描述各个工作模式介绍如下:
• 正常模式
正常模式下就是一个正常的 CAN 节点,可以向总线发送数据和接收数据。
• 静默模式
静默模式下,它自己的输出端的逻辑 0 数据会直接传输到它自己的输入端,逻辑 1 可以被发送到总线,所以它不能向总线发送显性位 (逻辑 0),只能发送隐性位 (逻辑 1)。
输入端可以从总线接收内容。由于它只可发送的隐性位不会强制影响总线的状态,所以把它称为静默模式。这种模式一般用于监测,它可以用于分析总线上的流量,但又不会因为发送显性位而影响总线。
• 回环模式
回环模式下,它自己的输出端的所有内容都直接传输到自己的输入端,输出端的内容同时也会被传输到总线上,即也可使用总线监测它的发送内容。输入端只接收自己发送端的内容,不接收来自总线上的内容。使用回环模式可以进行自检。(这个模式我们自己使用一个开发板就可以实现了)
• 回环静默模式
回环静默模式是以上两种模式的结合,自己的输出端的所有内容都直接传输到自己的输入端,并且不会向总线发送显性位影响总线,不能通过总线监测它的发送内容。输入端只接收自己发送端的内容,不接收来自总线上的内容。这种方式可以在“热自检”时使用,即自我检查的时候,不会干扰总线。
以上说的各个模式,是不需要修改硬件接线的,例如,当输出直接连输入时,它是在 STM32 芯片内部连接的,传输路径不经过 STM32 的 CAN_Tx/Rx 引脚,更不经过外部连接的 CAN 收发器,只有输出数据到总线或从总线接收的情况下才会经过 CAN_Tx/Rx 引脚和收发器。

4.1.3、位时序及波特率
在这里插入图片描述STM32 的 CAN 外设位时序中只包含 3 段,分别是同步段 SYNC_SEG、位段 BS1 及位段 BS2,采样点位于 BS1 及 BS2 段的交界处。其中 SYNC_SEG 段固定长度为 1Tq,而 BS1 及 BS2 段可以在位时序寄存器 CAN_BTR 设置它们的时间长度,它们可以在重新同步期间增长或缩短,该长度SJW 也可在位时序寄存器中配置。

理解 STM32 的 CAN 外设的位时序时,可以把它的 BS1 段理解为是由前面介绍的 CAN 标准协议中 PTS 段与 PBS1 段合在一起的,而 BS2 段就相当于 PBS2 段。了解位时序后,我们就可以配置波特率了。通过配置位时序寄存器 CAN_BTR 的 TS1[3:0] 及TS2[2:0] 寄存器位设定 BS1 及 BS2 段的长度后,我们就可以确定每个 CAN 数据位的时间:
BS1 段时间:
TS1=Tq x (TS1[3:0] + 1),
BS2 段时间:
TS2= Tq x (TS2[2:0] + 1),
一个数据位的时间:
T1bit =1Tq+TS1+TS2 =1+ (TS1[3:0] + 1)+ (TS2[2:0] + 1)= N Tq
其中单个时间片的长度 Tq 与 CAN 外设的所挂载的时钟总线及分频器配置有关,CAN1 和 CAN2外设都是挂载在 APB1 总线上的,而位时序寄存器 CAN_BTR 中的 BRP[9:0] 寄存器位可以设置CAN 外设时钟的分频值,所以:
Tq = (BRP[9:0]+1) x TPCLK
其中的 PCLK 指 APB1 时钟,默认值为 42MHz。
最终可以计算出 CAN 通讯的波特率:
BaudRate = 1/N Tq
例如下表说明了一种把波特率配置为 1Mbps 的方式。

在这里插入图片描述
4.2、CAN 发送邮箱
回到图 24‑5 中的 CAN 外设框图,在标号处的是 CAN 外设的发送邮箱,它一共有 3 个发送邮箱,即最多可以缓存 3 个待发送的报文。
每个发送邮箱中包含有标识符寄存器 CAN_TIxR、数据长度控制寄存器 CAN_TDTxR 及 2 个数据寄存器 CAN_TDLxR、CAN_TDHxR,它们的功能见下表。
在这里插入图片描述当我们要使用 CAN 外设发送报文时,把报文的各个段分解,按位置写入到这些寄存器中,并对标识符寄存器 CAN_TIxR 中的发送请求寄存器位 TMIDxR_TXRQ 置 1,即可把数据发送出去。其中标识符寄存器 CAN_TIxR 中的 STDID 寄存器位比较特别。我们知道 CAN 的标准标识符的总位数为 11 位,而扩展标识符的总位数为 29 位的。当报文使用扩展标识符的时候,标识符寄存器 CAN_TIxR 中的 STDID[10:0] 等效于EXTID[18:28] 位,它与 EXTID[17:0] 共同组成完整的 29位扩展标识符。

4.2.1、CAN接受FIFO
图中的 CAN 外设框图,在标号处的是 CAN 外设的接收 FIFO,它一共有 2 个接收 FIFO,每个 FIFO 中有 3 个邮箱,即最多可以缓存 6 个接收到的报文。当接收到报文时,FIFO 的报文计数器会自增,而 STM32 内部读取 FIFO 数据之后,报文计数器会自减,我们通过状态寄存器可获知报文计数器的值,而通过前面主控制寄存器的 RFLM 位,可设置锁定模式,锁定模式下 FIFO溢出时会丢弃新报文,非锁定模式下 FIFO 溢出时新报文会覆盖旧报文。跟发送邮箱类似,每个接收 FIFO 中包含有标识符寄存器 CAN_RIxR、数据长度控制寄存器CAN_RDTxR 及 2 个数据寄存器 CAN_RDLxR、CAN_RDHxR,它们的功能见下表。
在这里插入图片描述通过中断或状态寄存器知道接收 FIFO 有数据后,我们再读取这些寄存器的值即可把接收到的报文加载到 STM32 的内存中。

4.3、验收筛选器
图中筛选器的 4 种工作状态:
每组筛选器包含 2 个 32 位的寄存器,分别为 CAN_FxR1 和 CAN_FxR2,它们用来存储要筛选的ID 或掩码,各个寄存器位代表的意义与图中两个寄存器下面“映射”的一栏一致,各个模式的说明见下表。
在这里插入图片描述例如下面的表格所示,在掩码模式时,第一个寄存器存储要筛选的 ID,第二个寄存器存储掩码,掩码为 1 的部分表示该位必须与 ID 中的内容一致,筛选的结果为表中第三行的 ID 值,它是一组包含多个的 ID 值,其中 x 表示该位可以为 1 可以为 0。

在这里插入图片描述
而工作在标识符模式时,2 个寄存器存储的都是要筛选的 ID,它只包含 2 个要筛选的 ID 值 (32位模式时)。如果使能了筛选器,且报文的 ID 与所有筛选器的配置都不匹配,CAN 外设会丢弃该报文,不存入接收 FIFO。

4.4、整体逻辑控制
回到结构框图,图中的标号处表示的是 CAN2 外设的结构,它与 CAN1 外设是一样的,他们共用筛选器且由于存储访问控制器由 CAN1 控制,所以要使用 CAN2 的时候必须要使能 CAN1的时钟。其中 STM32F103 系列芯片不具有 CAN2 控制器。

(五)CAN代码中的部分初始化代码
完整代码:(基于STM32F103ZET6)
(CAN回环模式实验)
链接: https://pan.baidu.com/s/1Im7SKKMvEBpEyqlkwFmWcg
提取码:errn
(CAN双机实验)
链接: https://pan.baidu.com/s/1gC63c1dgYfIj9isPE5oUFg
提取码:xd65

/** 函数名:CAN_GPIO_Config* 描述  :CAN的GPIO 配置* 输入  :无* 输出  : 无* 调用  :内部调用*/
static void CAN_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;   	/* Enable GPIO clock */RCC_APB2PeriphClockCmd(CAN_TX_GPIO_CLK|CAN_RX_GPIO_CLK, ENABLE);//重映射引脚GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);/* Configure CAN TX pins */GPIO_InitStructure.GPIO_Pin = CAN_TX_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		         // 复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(CAN_TX_GPIO_PORT, &GPIO_InitStructure);/* Configure CAN RX  pins */GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	             // 上拉输入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(CAN_RX_GPIO_PORT, &GPIO_InitStructure);}
/** 函数名:CAN_NVIC_Config* 描述  :CAN的NVIC 配置,第1优先级组,0,0优先级* 输入  :无* 输出  : 无* 调用  :内部调用*/
static void CAN_NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* Configure one bit for preemption priority */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);/*中断设置*/NVIC_InitStructure.NVIC_IRQChannel = CAN_RX_IRQ;	   //CAN1 RX0中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;		   //抢占优先级0NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;			   //子优先级为0NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}
/** 函数名:CAN_Mode_Config* 描述  :CAN的模式 配置* 输入  :无* 输出  : 无* 调用  :内部调用*/
static void CAN_Mode_Config(void)
{CAN_InitTypeDef        CAN_InitStructure;/************************CAN通信参数设置**********************************//* Enable CAN clock */RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);/*CAN寄存器初始化*/CAN_DeInit(CANx);CAN_StructInit(&CAN_InitStructure);/*CAN单元初始化*/CAN_InitStructure.CAN_TTCM=DISABLE;			   //MCR-TTCM  关闭时间触发通信模式使能CAN_InitStructure.CAN_ABOM=ENABLE;			   //MCR-ABOM  自动离线管理 CAN_InitStructure.CAN_AWUM=ENABLE;			   //MCR-AWUM  使用自动唤醒模式CAN_InitStructure.CAN_NART=DISABLE;			   //MCR-NART  禁止报文自动重传	  DISABLE-自动重传CAN_InitStructure.CAN_RFLM=DISABLE;			   //MCR-RFLM  接收FIFO 锁定模式  DISABLE-溢出时新报文会覆盖原有报文  CAN_InitStructure.CAN_TXFP=DISABLE;			   //MCR-TXFP  发送FIFO优先级 DISABLE-优先级取决于报文标示符 CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;  //正常工作模式CAN_InitStructure.CAN_SJW=CAN_SJW_2tq;		   //BTR-SJW 重新同步跳跃宽度 2个时间单元/* ss=1 bs1=5 bs2=3 位时间宽度为(1+5+3) 波特率即为时钟周期tq*(1+3+5)  */CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;		   //BTR-TS1 时间段1 占用了5个时间单元CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;		   //BTR-TS1 时间段2 占用了3个时间单元	/* CAN Baudrate = 1 MBps (1MBps已为stm32的CAN最高速率) (CAN 时钟频率为 APB1 = 36 MHz) */CAN_InitStructure.CAN_Prescaler =4;		   BTR-BRP 波特率分频器  定义了时间单元的时间长度 36/(1+5+3)/4=1 MbpsCAN_Init(CANx, &CAN_InitStructure);
}
/** 函数名:CAN_Filter_Config* 描述  :CAN的过滤器 配置* 输入  :无* 输出  : 无* 调用  :内部调用*/
static void CAN_Filter_Config(void)
{CAN_FilterInitTypeDef  CAN_FilterInitStructure;/*CAN筛选器初始化*/CAN_FilterInitStructure.CAN_FilterNumber=0;						//筛选器组0CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;	//工作在掩码模式CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;	//筛选器位宽为单个32位。/* 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */CAN_FilterInitStructure.CAN_FilterIdHigh= ((((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;		//要筛选的ID高位 CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要筛选的ID低位 CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0xFFFF;			//筛选器高16位每位必须匹配CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0xFFFF;			//筛选器低16位每位必须匹配CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ;				//筛选器被关联到FIFO0CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;			//使能筛选器CAN_FilterInit(&CAN_FilterInitStructure);/*CAN通信中断使能*/CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
}

Published by

风君子

独自遨游何稽首 揭天掀地慰生平