STM32的can现场总线实验心得

最近在搞 stm32 实验板的 can 现场总线实验,之前只是搞过 STC51 的串口通信,相比之下,发觉 can 总线都挺复杂的。开始时,知道自己是新手,只知道 can 总线跟串行通信, 485 通信, I2C 通信一样都是用来传输数据通信的,对其工作原理一窍不通,还是从基础开始看书看资料,先了解它的基本原理吧。


原来 can 总线有以下特点:


主要特点
支持 CAN 协议 2.0A 2.0B 主动模式
波特率最高可达 1 兆位 /
支持时间触发通信功能


发送
3 个发送邮箱
发送报文的优先级特性可软件配置
记录发送 SOF 时刻的时间戳


接收
3 级深度的 2 个接收 FIFO
14 个位宽可变的过滤器组-由整个 CAN 共享
标识符列表
FIFO 溢出处理方式可配置
记录接收 SOF 时刻的时间戳


可支持时间触发通信模式
禁止自动重传模式
16 位自由运行定时器
定时器分辨率可配置
可在最后 2 个数据字节发送时间戳


管理
中断可屏蔽
邮箱占用单独 1 块地址空间,便于提高软件效率




看完这些特点后,疑问一个一个地出现,
1.         什么是时间触发功能?
2.         发送邮箱是什么来的?
3.         报文是什么来的?
4.         什么叫时间戳?
5.         什么叫接收 FIFO
6.         什么叫过滤器?


好了,带着疑问往下看,看完一遍后,


报文 :
报文包含了将要发送的完整的数据信息


发送邮箱 :
共有 3 个发送邮箱供软件来发送报文。发送调度器根据优先级决定哪个邮箱的报文先被发送。


接收过滤器 :
共有 14 个位宽可变 / 可配置的标识符过滤器组,软件通过对它们编程,从而在引脚收到的报文中选择它需要的报文,而把其它报文丢弃掉。


接收 FIFO
共有 2 个接收 FIFO ,每个 FIFO 都可以存放 3 个完整的报文。它们完全由硬件来管理


工作模式
bxCAN 3 个主要的工作模式:初始化、正常和睡眠模式。


初始化模式
* 软件通过对 CAN_MCR 寄存器的 INRQ 位置 1 ,来请求 bxCAN 进入初始化模式,然后等待硬件对 CAN_MSR 寄存器的 INAK 位置 1 来进行确认
* 软件通过对 CAN_MCR 寄存器的 INRQ 位清 0 ,来请求 bxCAN 退出初始化模式,当硬件对 CAN_MSR 寄存器的 INAK 位清 0 就确认了初始化模式的退出。
* bxCAN 处于初始化模式时,报文的接收和发送都被禁止,并且 CANTX 引脚输出隐性位(高电平)


正常模式
在初始化完成后,软件应该让硬件进入正常模式,以便正常接收和发送报文。软件可以通过对 CAN_MCR 寄存器的 INRQ 位清 0 ,来请求从初始化模式进入正常模式,然后要等待硬件对 CAN_MSR 寄存器的 INAK 位置 1 的确认。在跟 CAN 总线取得同步,即在 CANRX 引脚上监测到 11 个连续的隐性位(等效于总线空闲)后, bxCAN 才能正常接收和发送报文。


过滤器初值的设置不需要在初始化模式下进行,但必须在它处在非激活状态下完成(相应的 FACT 位为 0 )。而过滤器的位宽和模式的设置,则必须在初始化模式下,进入正常模式前完成。


睡眠模式(低功耗)
* 软件通过对 CAN_MCR 寄存器的 SLEEP 位置 1 ,来请求进入这一模式。在该模式下, bxCAN 的时钟停止了,但软件仍然可以访问邮箱寄存器。
* bxCAN 处于睡眠模式,软件想通过对 CAN_MCR 寄存器的 INRQ 位置 1 ,来进入初始化式,那么软件必须同时对 SLEEP 位清 0 才行

*2种方式可以唤醒(退出睡眠模式)bxCAN:通过软件对SLEEP位清0,或硬件检测CAN总线的活动。

工作流程

那么究竟can是怎样发送报文的呢?

发送报文的流程为:
应用程序选择1个空发送邮箱;设置标识符,数据长度和待发送数据;
然后对CAN_TIxR寄存器的TXRQ位置1,来请求发送。TXRQ位置1后,邮箱就不再是空邮箱;而一旦邮箱不再为空,软件对邮箱寄存器就不再有写的权限。TXRQ位置1后,邮箱马上进入挂号状态,并等待成为最高优先级的邮箱,参见发送优先级。一旦邮箱成为最高优先级的邮箱,其状态就变为预定发送状态。一旦CAN总线进入空闲状态,预定发送邮箱中的报文就马上被发送(进入发送状态)。一旦邮箱中的报文被成功发送后,它马上变为空邮箱;硬件相应地对CAN_TSR寄存器的RQCP和TXOK位置1,来表明一次成功发送。

如果发送失败,由于仲裁引起的就对CAN_TSR寄存器的ALST位置1,由于发送错误引起的
就对TERR位置1。

原来发送的优先级可以由标识符和发送请求次序决定:
由标识符决定
当有超过1个发送邮箱在挂号时,发送顺序由邮箱中报文的标识符决定。根据CAN协议,标识符数值最低的报文具有最高的优先级。如果标识符的值相等,那么邮箱号小的报文先被发送。

由发送请求次序决定
通过对CAN_MCR寄存器的TXFP位置1,可以把发送邮箱配置为发送FIFO。在该模式下,发送的优先级由发送请求次序决定。
该模式对分段发送很有用。

时间触发通信模式
在该模式下,CAN硬件的内部定时器被激活,并且被用于产生时间戳,分别存储在
CAN_RDTxR/CAN_TDTxR寄存器中。内部定时器在接收和发送的帧起始位的采样点位置被采样,并生成时间戳(标有时间的数据)。

接着又是怎样接收报文的呢?

接收管理
接收到的报文,被存储在3级邮箱深度的FIFO中。FIFO完全由硬件来管理,从而节省了CPU
的处理负荷,简化了软件并保证了数据的一致性。应用程序只能通过读取FIFO输出邮箱,来读取FIFO中最先收到的报文。

有效报文
根据CAN协议,当报文被正确接收(直到EOF域的最后1位都没有错误),且通过了标识符
过滤,那么该报文被认为是有效报文。

接收相关的中断条件
* 一旦往FIFO存入1个报文,硬件就会更新FMP[1:0]位,并且如果CAN_IER寄存器的FMPIE位为1,那么就会产生一个中断请求。

* 当FIFO变满时(即第3个报文被存入),CAN_RFxR寄存器的FULL位就被置1,并且如果CAN_IER寄存器的FFIE位为1,那么就会产生一个满中断请求。

* 在溢出的情况下,FOVR位被置1,并且如果CAN_IER寄存器的FOVIE位为1,那么就会产生一个溢出中断请求

标识符过滤
在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。因此,发送者以广播的形式把报文发送给所有的接收者。(注:不是一对一通信,而是多机通信)节点在接收报文时-根据标识符的值-决定软件是否需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。
为满足这一需求,bxCAN为应用程序提供了14个位宽可变的、可配置的过滤器组(13~0),以便只接收那些软件需要的报文。硬件过滤的做法节省了CPU开销,否则就必须由软件过滤从而占用一定的CPU开销。每个过滤器组x由2个32位寄存器,CAN_FxR0和CAN_FxR1组成。


过滤器的模式的设置
通过设置CAN_FM0R的FBMx位,可以配置过滤器组为标识符列表模式或屏蔽位模式。
为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。
为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。
应用程序不用的过滤器组,应该保持在禁用状态。

过滤器优先级规则
􀁺 1位宽为32位的过滤器,优先级高于位宽为16位的过滤器

􀁺 2对于位宽相同的过滤器,标识符列表模式的优先级高于屏蔽位模式

􀁺 3位宽和模式都相同的过滤器,优先级由过滤器号决定,过滤器号小的优先级高


图128 过滤器机制的例子

(原文件名:无标题.jpg) 

上面的例子说明了bxCAN的过滤器规则:在接收一个报文时,其标识符首先与配置在标识符列表模式下的过滤器相比较;如果匹配上,报文就被存放到相关联的FIFO中,并且所匹配的过滤器的序号被存入过滤器匹配序号中。如同例子中所显示,报文标识符跟#4标识符匹配,
因此报文内容和FMI4被存入FIFO。
如果没有匹配,报文标识符接着与配置在屏蔽位模式下的过滤器进行比较。
如果报文标识符没有跟过滤器中的任何标识符相匹配,那么硬件就丢弃该报文,且不会对软件有任何打扰。


中断
bxCAN占用4个专用的中断向量。通过设置CAN中断允许寄存器(CAN_IER),每个中断源都可以单独允许和禁用。


􀁺 发送中断可由下列事件产生:

─ 发送邮箱0变为空,CAN_TSR寄存器的RQCP0位被置1。
─ 发送邮箱1变为空,CAN_TSR寄存器的RQCP1位被置1。
─ 发送邮箱2变为空,CAN_TSR寄存器的RQCP2位被置1。

􀁺 FIFO0中断可由下列事件产生:

─ FIFO0接收到一个新报文,CAN_RF0R寄存器的FMP0位不再是‘00’。
─ FIFO0变为满的情况,CAN_RF0R寄存器的FULL0位被置1。
─ FIFO0发生溢出的情况,CAN_RF0R寄存器的FOVR0位被置1。

􀁺 FIFO1中断可由下列事件产生:

─ FIFO1接收到一个新报文,CAN_RF1R寄存器的FMP1位不再是‘00’。
─ FIFO1变为满的情况,CAN_RF1R寄存器的FULL1位被置1。
─ FIFO1发生溢出的情况,CAN_RF1R寄存器的FOVR1位被置1。

􀁺 错误和状态变化中断可由下列事件产生:

─ 出错情况,关于出错情况的详细信息请参考CAN错误状态寄存器(CAN_ESR)。
─ 唤醒情况,在CAN接收引脚上监视到帧起始位(SOF)。
─ CAN进入睡眠模式。

工作流程大概就是这个样子,接着就是一大堆烦人的can寄存器,看了一遍总算有了大概的了解,况且这么多的寄存器要一下子把他们都记住是不可能的。根据以往的经验,只要用多几次,对寄存器的功能就能记住。

好了,到读具体实验程序的时候了,这时候就要打开“STM32库函数”的资料因为它里面有STM32打包好的库函数的解释,对读程序很有帮助。


好吧,首先我不得不承认这是一篇有关失败实验经历的帖子,但我还是想写出来,因为在此期间还是有一些收获的。先来说说关于CAN总线的实验想法:学习了STM32 的can总线模块后,总想着实现多机通讯,实验室有人用c8051f040芯片搭了一个can总线的双机通讯电路,所以想将STM32的板子加进去,实现三机通讯。有了这个想法后着手去做了,但没有实现。
先来说说我在学习STM32 can总线模块时的一些心得吧:
这部分主要是位时序和过滤器的理解心得:

位时序,就是发送一位所用的时间,在这样一段短暂时间里,又分了四段:同步段、传播段、相位缓冲段1、相位缓冲段2.这些都是在其他总线通信中不曾遇到的,有些初学者看到手册上后面的介绍基本就晕菜了,很难接受和理解,不知道为什么要这么做,其实把这样一小段时间又分成4段就是为了进行同步。

CAN总线的通讯时采用NRZ(Non-Return to Zero,非归零)码,数据本身并不携带时钟信息,也就是说在每一位的开始或结束没有同步信号,发送单元以位时序同步的方式开始发送帧数据,接收单元根据总线电平的变化进行同步并进行接收。可以这样理解,总线上的发送端和接收端以相同的频率振荡,这个振荡就是时钟信息,很同步,很和谐,这样发送端发个数据,它就这样以同样的频率振啊振的振到接收端,接收端察觉并接收,很完美哈?可这只是理想情况,在实际情况中,发送端和接收端会存在时间误差,传输路径也会有相位误差,这些都可能使二者在收发操作中失去同步关系,这个时候要想再实现通讯,接收端就必须调用同步机制,调整它的操作时序。

CAN bus 有两个同步机制:硬同步和重同步

硬同步:在总线空闲状态时,接收单元检测到SOF就会执行这个同步调整过程,“隐式”电平跳变到“显式”电平的边缘的时间点被认为是接收端位时序的同步段,不用管SJW的值。这种同步在一个帧中只出现一次,就是在开头。

重同步:接收节点在一帧中间如果检测到信号从1到0 的变换边沿是在传播段或者相位缓冲段1中,则认为自己的位时序提前了,这是因为采样时间点会出现在相位缓冲段1与2 之间,过早采样会造成采样不准,所以接收端就将这个位时序周期的相位缓冲段1延长;反之,如果检测到边沿在相位缓冲段2中,则将相位缓冲段2缩短,最终让信号变化的边沿变回到同步段,这样,是不是觉得一个位时间分成四段很合理了呢。

对于这个同步机制,我也没有特别深入的研究,如果有谁在这方面有更好的心得,欢迎分享。








  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值