stm32单片机学习(39)——STM32中的CAN外设
文章目录
bxCAN简介
bxCAN是基本扩展CAN(Basic Extended CAN)的缩写,它支持CAN协议2.0A和2.0B。它的设计目标是,以最小的CPU负荷来高效处理大量收到的报文。它也支持报文发送的优先级要求(优先级特性可软件配置)。对于安全紧要的应用,bxCAN提供所有支持时间触发通信模式所需的硬件功能。
bxCAN主要特点
- 支持CAN协议2.0A和2.0B主动模式
关于这一点我们在上一篇文章中已经接触了,只是没有展开,本质上也就还是标准帧和扩展帧。以下是控制器的三种兼容类型,这是理解"主动模式"的关键。CAN控制器按对2.0A/2.0B的支持程度分为三类
| 类型 | 发送标准帧(11位) | 发送扩展帧(29位) | 接收扩展帧(29位) | 说明 |
|---|---|---|---|---|
| A-only | ✅ | ❌ | ❌ | 最基础,只支持标准帧 |
| B-passive(被动模式) | ✅ | ❌ | ✅ | 能识别扩展帧,但不会主动发送 |
| B-active(主动模式) | ✅ | ✅ | ✅ | 完全支持,可收发两种帧 |
那么手册中的这一句的含义就是可以发送11位/29位的标准帧和扩展帧。
- 波特率最高可达1兆位/秒
这一部分就是我们自己设置的了 - 支持时间触发通信功能
CAN的数据帧可以附带时间戳,但是不能直接访问,可以通过寄存器或是提供的函数进行访问。
数据发送
-
3个发送邮箱
可以理解为一个缓冲区吧,之前提到过除了出现错误是不能打断正在传输的数据帧,所以这个时候,就会把待发送帧放入邮箱,待总线空闲再发送。你可能访问如果邮箱满了怎么办呢?那当然没有办法,要么覆盖数据,要么丢弃。 -
发送报文的优先级特性可软件配置
发送调度器根据优先级决定哪个邮箱的报文先被发送。如果总线一直繁忙,我们的发送邮箱堆积了数据帧,当总线释放的时候,这个时候可以根据优先级决定先发送哪一个邮箱的数据。但其实它的本质依旧是非破坏性仲裁也就是逻辑线与,所以就是ID号小的优先级会更大。 -
记录发送SOF时刻的时间戳
我个人理解也算是一种同步机制吧,可以让各个节点知道数据帧的先后顺序。
数据接收
-
3级深度的2个接收FIFO
共有2个接收FIFO,每个FIFO都可以存放3个完整的报文。它们完全由硬件来管理。FIFO应该都很清楚了,先进先出嘛,相当于一个数据接收队列,有可能接收数据之后我们来不及处理,但是有防止新数据过来覆盖。当然如果满了的话,和邮箱一样也是没有什么很好的办法。以下是其结构图,因为stm32f103c8t6只有一个CAN所以忽略下半部分就好
-
可变的过滤器组:
STM32F103xx系列产品中有14个过滤器组,过滤器的存在就极大的缓解了判断帧的压力。例如I2C,需要先传入一个地址再发送地址,要告诉总线上的其它设备是谁在说话。同样CAN是多主机的广播模式,没有统一的管理,如果有数据的传输的话,各个设备还要判断是给谁的。所以通过过滤器直接可以设置我需要接收哪些数据,不要接收哪些数据,而且这样也缓解了一个问题,就是我们上一篇文章中提到,多个设备监督一个设备发送可能插入超过六个相同位。过滤的器的出现就相当于班主任,每个班主任只看自己的数据帧就可以了,不必关系其它数据帧 -
标识符列表
因为逻辑线与的特性,我们可以据此像设置中断一样设置不同级别的ID,用来区分数据帧的紧急性 -
FIFO溢出处理方式可配置
-
记录接收SOF时刻的时间戳
时间触发通信模式
- 禁止自动重传模式
- 16位自由运行定时器
- 可在最后2个数据字节发送时间戳
管理
- 中断可屏蔽
- 邮箱占用单独1块地址空间,便于提高软件效率
双CAN(在stm32f103c8t6中只有一个CAN)
- CAN1:是主bxCAN,它负责管理在从bxCAN和512字节的SRAM存储器之间的通信
- CAN2:是从bxCAN,它不能直接访问SRAM存储器
- 这2个bxCAN模块共享512字节的SRAM存储器(
bxCAN总体描述
上面大致描述了CAN外设中都存在什么,下面我们简单概括总结一下。
在当今的CAN应用中,CAN网络的节点在不断增加,并且多个CAN常常通过网关连接起来,因此整个CAN网中的报文数量(每个节点都需要处理)急剧增加。除了应用层报文外,网络管理和诊断报文也被引入。
- 需要一个增强的过滤机制来处理各种类型的报文
此外,应用层任务需要更多CPU时间,因此报文接收所需的实时响应程度需要减轻。 - 接收FIFO的方案允许,CPU花很长时间处理应用层任务而不会丢失报文。
构筑在底层CAN驱动程序上的高层协议软件,要求跟CAN控制器之间有高效的接口。


bxCAN工作模式
bxCAN有3个主要的工作模式:初始化、正常和睡眠模式。在硬件复位后,bxCAN工作在睡眠模式以节省电能,同时CANTX引脚的内部上拉电阻被激活。软件通过对CAN_MCR寄存器的INRQ或SLEEP位置’1’,可以请求bxCAN进入初始化或睡眠模式。一旦进入了初始化或睡眠模式,bxCAN就对CAN_MSR寄存器的INAK或SLAK位置’1’来进行确认,同时内部上拉电阻被禁用。当INAK和SLAK位都为’0’时,bxCAN就处于正常模式。在进入正常模式前,bxCAN必须跟CAN总线取得同步;为取得同步,bxCAN要等待CAN总线达到空闲状态,即在CANRX引脚上监测到11个连续的隐性位。
初始化模式
软件初始化应该在硬件处于初始化模式时进行。设置CAN_MCR寄存器的INRQ位为’1’,请求bxCAN进入初始化模式,然后等待硬件对CAN_MSR寄存器的INAK位置’1’来进行确认。清除CAN_MCR寄存器的INRQ位为’0’,请求bxCAN退出初始化模式,当硬件对CAN_MSR寄存器的INAK位清’0’就确认了初始化模式的退出。当bxCAN处于初始化模式时,禁止报文的接收和发送,并且CANTX引脚输出隐性位(高电平)。初始化模式的进入,不会改变配置寄存器。软件对bxCAN的初始化,至少包括位时间特性(CAN_BTR)和控制(CAN_MCR)这2个寄存器。在对bxCAN的过滤器组(模式、位宽、FIFO关联、激活和过滤器值)进行初始化前,软件要对CAN_FMR寄存器的FINIT位设置’1’。对过滤器的初始化可以在非初始化模式下进行。
当FINIT=1时,报文的接收被禁止。
可以先对过滤器激活位清’0’(在CAN_FA1R中),然后修改相应过滤器的值。
如果过滤器组没有使用,那么就应该让它处于非激活状态(保持其FACT位为清’0’状态)。
正常模式
在初始化完成后,软件应该让硬件进入正常模式,以便正常接收和发送报文。软件可以通过对CAN_MCR寄存器的INRQ位清’0’,来请求从初始化模式进入正常模式,然后要等待硬件对CAN_MSR寄存器的INAK位置’1’的确认。在跟CAN总线取得同步,即在CANRX引脚上监测到11个连续的隐性位(等效于总线空闲)后,bxCAN才能正常接收和发送报文。
不需要在初始化模式下进行过滤器初值的设置,但必须在它处在非激活状态下完成(相应的FACT位为0)。而过滤器的位宽和模式的设置,则必须在初始化模式中进入正常模式前完成。
睡眠模式(低功耗)
bxCAN可工作在低功耗的睡眠模式。软件通过对CAN_MCR寄存器的SLEEP位置’1’,来请求进入这一模式。在该模式下,bxCAN的时钟停止了,但软件仍然可以访问邮箱寄存器。当bxCAN处于睡眠模式,软件必须对CAN_MCR寄存器的INRQ位置’1’并且同时对SLEEP位清’0’,才能进入初始化模式。
有2种方式可以唤醒(退出睡眠模式)bxCAN:通过软件对SLEEP位清’1’,或硬件检测到CAN总线的活动。如果CAN_MCR寄存器的AWUM位为’1’,一旦检测到CAN总线的活动,硬件就自动对SLEEP位清’0’来唤醒bxCAN。如果CAN_MCR寄存器的AWUM位为’0’,软件必须在唤醒中断里对SLEEP位清’0’才能退出睡眠状态。
如果唤醒中断被允许(CAN_IER寄存器的WKUIE位为’1’),那么一旦检测到CAN总线活动就会产生唤醒中断,而不管硬件是否会自动唤醒bxCAN。
在对SLEEP位清’0’后,睡眠模式的退出必须与CAN总线同步,请参考图196:bxCAN工作模式。
当硬件对SLAK位清’0’时,就确认了睡眠模式的退出。
测试模式
在使用CAN时,因为时多机通信,如果出现问题,就很难判断是哪里出的问题,所以提供了三种测试模式。我们可以在测试模式跑通的情况下,再改为正常模式就可以了。
通过对CAN_BTR寄存器的SILM和/或LBKM位置’1’,来选择一种测试模式。只能在初始化模式下,修改这2位。在选择了一种测试模式后,软件需要对CAN_MCR寄存器的INRQ位清’0’,来真正进入测试模式。
关于下面的介绍有关于寄存器的操作,其实我们制作了解即可,因为标准库已经都为我们封装好了函数,只需要知道这三种模式的区别就很好了。
静默模式
通过对CAN_BTR寄存器的SILM位置’1’,来选择静默模式。
在静默模式下,bxCAN可以正常地接收数据帧和远程帧,但只能发出隐性位,而不能真正发送报文。如果bxCAN需要发出显性位(确认位、过载标志、主动错误标志),那么这样的显性位在内部被接回来从而可以被CAN内核检测到,同时CAN总线不会受到影响而仍然维持在隐性位状态。因此,静默模式通常用于分析CAN总线的活动,而不会对总线造成影响-显性位(确认位、错误帧)不会真正发送到总线上。
环回模式
通过对CAN_BTR寄存器的LBKM位置’1’,来选择环回模式。在环回模式下,**bxCAN把发送的报文当作接收的报文并保存(如果可以通过接收过滤)在接收邮箱里。**环回模式可用于自测试。为了避免外部的影响,在环回模式下CAN内核忽略确认错误(在数据/远程帧的确认位时刻,不检测是否有显性位)。在环回模式下,bxCAN在内部把Tx输出回馈到Rx输入上,而完全忽略CANRX引脚的实际状态。发送的报文可以在CANTX引脚上检测到。
也就是说测试自己的初始化和过滤器的设置是否正确
环回静默模式
通过对CAN_BTR寄存器的LBKM和SILM位同时置’1’,可以选择环回静默模式。**该模式可用于“热自测试”,即可以像环回模式那样测试bxCAN,但却不会影响CANTX和CANRX所连接的整个CAN系统。**在环回静默模式下,CANRX引脚与CAN总线断开,同时CANTX引脚被驱动到隐性位状态。
bxCAN功能描述
标识符过滤
在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。因此,发送者乙广播的形式把报文发送给所有的接收者。节点在接收报文时-根据标识符的值-决定软件是否需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。
为满足这一需求,在互联型产品中,bxCAN控制器为应用程序提供了28个位宽可变的、可配置的过滤器组(270);在其它产品中,bxCAN控制器为应用程序提供了14个位宽可变的、可配置的过滤器组(130),以便只接收那些软件需要的报文。硬件过滤的做法节省了CPU开销,否则就必须由软件过滤从而占用一定的CPU开销。每个过滤器组x由2个32位寄存器,CAN_FxR0和CAN_FxR1组成。
可变的位宽
每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的不同,每个过滤器组可提供:
- 1个32位过滤器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位
- 2个16位过滤器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位
此外过滤器可配置为,屏蔽位模式和标识符列表模式。
- 屏蔽位模式
在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理。 - 标识符列表模式
在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一
个屏蔽位的方式,而是使用2个标识符寄存器。接收报文标识符的每一位都必须跟过滤器标识符相同。
过滤器组位宽和模式的设置
过滤器组可以通过相应的CAN_FMR寄存器配置。在配置一个过滤器组前,必须通过清除CAN_FAR寄存器的FACT位,把它设置为禁用状态。通过设置CAN_FS1R的相应FSCx位,可以配置一个过滤器组的位宽,请参见图202。通过CAN_FMR的FBMx位,可以配置对应的屏蔽/标识符寄存器的标识符列表模式或屏蔽位模式。
为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。
为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。
应用程序不用的过滤器组,应该保持在禁用状态。
过滤器组中的每个过滤器,都被编号为(叫做过滤器号)从0开始,到某个最大数值-取决于过滤
器组的模式和位宽的设置。
关于过滤器配置,参见下图。

过滤器匹配序号
一旦收到的报文被存入FIFO,就可被应用程序访问。通常情况下,报文中的数据被拷贝到SRAM中;为了把数据拷贝到合适的位置,应用程序需要根据报文的标识符来辨别不同的数据。bxCAN提供了过滤器匹配序号,以简化这一辨别过程。
根据过滤器优先级规则,过滤器匹配序号和报文一起,被存入邮箱中。因此每个收到的报文,都有与它相关联的过滤器匹配序号。过滤器匹配序号可以通过下面两种方式来使用:
- 把过滤器匹配序号跟一系列所期望的值进行比较
- 把过滤器匹配序号当作一个索引来访问目标地址
对于标识符列表模式下的过滤器(非屏蔽方式的过滤器),软件不需要直接跟标识符进行比较。
对于屏蔽位模式下的过滤器,软件只须对需要的那些屏蔽位(必须匹配的位)进行比较即可。
在给过滤器编号时,并不考虑过滤器组是否为激活状态。另外,每个FIFO各自对其关联的过滤器进行编号。请参考下图的例子。
过滤器优先级规则
根据过滤器的不同配置,有可能一个报文标识符能通过多个过滤器的过滤;在这种情况下,存放在接收邮箱中的过滤器匹配序号,根据下列优先级规则来确定:
- 位宽为32位的过滤器,优先级高于位宽为16位的过滤器
- 对于位宽相同的过滤器,标识符列表模式的优先级高于屏蔽位模式
- 位宽和模式都相同的过滤器,优先级由过滤器号决定,过滤器号小的优先级高

上面的例子说明了bxCAN的过滤器规则:在接收一个报文时,其标识符首先与配置在标识符列表模式下的过滤器相比较;如果匹配上,报文就被存放到相关联的FIFO中,并且所匹配的过滤器的序号被存入过滤器匹配序号中。如同例子中所显示,报文标识符跟#4标识符匹配,因此报文内容和FMI4被存入FIFO。
如果没有匹配,报文标识符接着与配置在屏蔽位模式下的过滤器进行比较。如果报文标识符没有跟过滤器中的任何标识符相匹配,那么硬件就丢弃该报文,且不会对软件有任何打扰。
发送处理
发送报文的流程为:应用程序选择1个空置的发送邮箱;设置标识符,数据长度和待发送数据;然后对CAN_TIxR寄存器的TXRQ位置’1’,来请求发送。TXRQ位置’1’后,邮箱就不再是空邮箱;而一旦邮箱不再为空置,软件对邮箱寄存器就不再有写的权限。TXRQ位置1后,邮箱马上进入挂号状态,并等待成为最高优先级的邮箱,参见发送优先级。一旦邮箱成为最高优先级的邮箱,其状态就变为预定发送状态。一旦CAN总线进入空闲状态,预定发送邮箱中的报文就马上被发送(进入发送状态)。一旦邮箱中的报文被成功发送后,它马上变为空置邮箱;硬件相应地对CAN_TSR寄存器的RQCP和TXOK位置1,来表明一次成功发送。如果发送失败,由于仲裁引起的就对CAN_TSR寄存器的ALST位置’1’,由于发送错误引起的就对TERR位置’1’。
发送中止
通过对CAN_TSR寄存器的ABRQ位置’1’,可以中止发送请求。邮箱如果处于挂号或预定状态,发送请求马上就被中止了。如果邮箱处于发送状态,那么中止请求可能导致2种结果。如果邮箱中的报文被成功发送,那么邮箱变为空置邮箱,并且CAN_TSR寄存器的TXOK位被硬件置’1’。如果邮箱中的报文发送失败了,那么邮箱变为预定状态,然后发送请求被中止,邮箱变为空置邮箱且TXOK位被硬件清’0’。因此如果邮箱处于发送状态,那么在发送操作结束后,邮箱都会变为空置邮箱。
禁止自动重传模式
该模式主要用于满足CAN标准中,时间触发通信选项的需求。通过对CAN_MCR寄存器的NART位置’1’,来让硬件工作在该模式。
在该模式下,发送操作只会执行一次。如果发送操作失败了,不管是由于仲裁丢失或出错,硬件都不会再自动发送该报文。
在一次发送操作结束后,硬件认为发送请求已经完成,从而对CAN_TSR寄存器的RQCP位置’1’,同时发送的结果反映在TXOK、ALST和TERR位上。
接收管理
接收到的报文,被存储在3级邮箱深度的FIFO中。FIFO完全由硬件来管理,从而节省了CPU的处理负荷,简化了软件并保证了数据的一致性。应用程序只能通过读取FIFO输出邮箱,来读取FIFO中最先收到的报文。
有效报文
根据CAN协议,当报文被正确接收(直到EOF域的最后一位都没有错误),且通过了标识符过滤,那么该报文被认为是有效报文。请参考22.7.4节:标识符过滤。
FIFO管理
FIFO从空状态开始,在接收到第一个有效的报文后,FIFO状态变为挂号_1(pending_1),硬件相应地把CAN_RFR寄存器的FMP[1:0]设置为’01’(二进制01b)。软件可以读取FIFO输出邮箱来读出邮箱中的报文,然后通过对CAN_RFR寄存器的RFOM位设置’1’来释放邮箱,这样FIFO又变为空状态了。如果在释放邮箱的同时,又收到了一个有效的报文,那么FIFO仍然保留在挂号_1状态,软件可以读取FIFO输出邮箱来读出新收到的报文。
如果应用程序不释放邮箱,在接收到下一个有效的报文后,FIFO状态变为挂号_2(pending_2),硬件相应地把FMP[1:0]设置为’10’(二进制10b)。重复上面的过程,第三个有效的报文把FIFO变为挂号_3状态(FMP[1:0]=11b)。此时,软件必须对RFOM位设置1来释放邮箱,以便FIFO可以有空间来存放下一个有效的报文;否则,下一个有效的报文到来时就会导致一个报文的丢失。
溢出
当FIFO处于挂号_3状态(即FIFO的3个邮箱都是满的),下一个有效的报文就会导致溢出,并且一个报文会丢失。此时,硬件对CAN_RFR寄存器的FOVR位进行置’1’来表明溢出情况。至于哪个报文会被丢弃,取决于对FIFO的设置:
- 如果禁用了FIFO锁定功能(CAN_MCR寄存器的RFLM位被清’0’),那么FIFO中最后收到的报文就被新报文所覆盖。这样,最新收到的报文不会被丢弃掉。
- 如果启用了FIFO锁定功能(CAN_MCR寄存器的RFLM位被置’1’),那么新收到的报文就被丢弃,软件可以读到FIFO中最早收到的3个报文。
接收相关的中断
一旦往FIFO存入一个报文,硬件就会更新FMP[1:0]位,并且如果CAN_IER寄存器的FMPIE位为’1’,那么就会产生一个中断请求。
当FIFO变满时(即第3个报文被存入),CAN_RFR寄存器的FULL位就被置’1’,并且如果CAN_IER寄存器的FFIE位为’1’,那么就会产生一个满中断请求。
在溢出的情况下,FOVR位被置’1’,并且如果CAN_IER寄存器的FOVIE位为’1’,那么就会产生一个溢出中断请求。
更多推荐

所有评论(0)