STM8 CAN总线的IdMask模式的讲解 前言学习了STM8的CAN总线的IdMask模式。在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。因此,发送者以广播的形式把报文发送给所有的接收者。节点在接收报文时-根据标识符的值决定软件是否需要该报文;如果需要,就拷贝到RAM里;如果不需要,报文就被丢弃且无需软件的干预。为满足这一需求,beCAN为应用程序提供了个可配置的、位宽可变的6个(0-5)过滤器组,用于只接收那些软件需要的报文。硬件过滤的做法节省了CPU开销,否则就必须由软件进行过滤,从而占用一定的CPU资源。; {& J# d4 I' m$ A 一、IdMask模式 首先,需要明白IdMask的作用:. Q: t% ?8 z+ D* s4 ` 举个例子吧,过滤器长度为32位,模式为屏蔽模式,假如我要发送的标示符为0x1314;那过滤器设置如下 1、过滤器完全无效 接收到的标示符全部通过 0x1314 二进制码: 0000 0000 0000 0000 0001 0011 0001 0100 CAN_Filter xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx: K( ^- y- s0 ?0 R8 r CAN_FilterMask 0000 0000 0000 0000 0000 0000 0000 00000 {7 S6 k5 z( W, b8 T- x 因为 CAN_FilterMask屏蔽寄存器所有位都是0 ,对应标识符全为“不关心”,也就是接收到数据的ID(标识符)不用与 CAN_Filter寄存器的任何一位进行匹配。) _ v L' P8 @- J" V8 u 2、过滤器完全有效 接收到的标识符要跟据CAN_FilterMask寄存器指定需要匹配的位进行与CAN_Filter比较5 q! H5 j9 [5 x4 F 部分匹配 0x1314 二进制码: 0000 0000 0000 0000 0001 0011 0001 0100; `" a: z) o$ H# Q CAN_Filter xxxx xxxx xxxx xxxx xxxx xxx1 xxxx xxxx CAN_FilterMask 0000 0000 0000 0000 0000 0001 0000 00000 S8 N! y% P+ R( N6 a CAN_FilterMask 寄存器指定接收到的标示符要与第8位进行匹配,其他位不管。也就是说接收到的标示符第8位必须为1,否则报文就会被丢弃。 全部匹配 0x1314 二进制码: 0000 0000 0000 0000 0001 0011 0001 0100 CAN_Filter 0000 0000 0000 0000 0000 0011 0001 0100 CAN_FilterMask 1111 1111 1111 1111 1111 1111 1111 1111+ ?5 x- `* ]/ t( _' ~ 这种情况最为严格,接收到的标示符必须每一位都得与过滤器中的标示符的每一位进行匹配,有一位不对报文就会被丢弃。(这个标示符匹配的工作是CAN 模块内部硬件自动完成的)- U: h; z7 W" i1 Z 二、IdMask库代码 本程序中,使用的软件代码是: 软件:( t' w- H+ u( { \STM8S_StdPeriph_Lib\Project\STM8S_StdPeriph_Examples\CAN\CAN_Networking路径下面的代码, 硬件 STM8/128 EVAL板子,上面的MCU位STM8S208MBT6B ; 程序里面打开了接收的中断: 所以为了能够更有效的操作实践这一功能,我使用了: 如上图的,CAN总线的分析仪器USB-CAN200 ;以及它的上位机: 在这里需要说明一点,' K: \6 F; z4 O9 [+ K2 z0 X 将R0+与R0-相短接,则内部的120欧姆的电阻会被接入总线,不需要画蛇添足,在R0+与R0-之间自己再找一个120欧姆的电阻外部接上!!!!: e+ B/ ]* n' v6 S" o 在接收中断里面已经有现成的对标准桢结构;所以设置好,Idfliter或者Idmask就可以; 也就是上面的 这一段函数;' ^0 l7 f3 r7 z2 p3 S3 Z, M 按照刚才的理解,& X5 O4 W9 @- R' L7 [6 a- o2 Z3 J, | 如果我的扩展id是0x12345678 ;想只接收0x12xxxxxx的标识符号,那么是否填入+ l4 ~9 ^# q$ h% n% l* `5 q CAN_FilterID1 = 0x12 ; CAN_FilterIDMask = 0xFF& [6 m) ~, D" `/ M; z( H 就可以了呢? 本以为是这样,结果通过上位机发出去之后,led板上的符号并没有变化;说明并没有接收到;, S# j3 T- [- l z( E 这是为什么呢? o. |4 {/ A7 X+ R5 t 三、分析) ~6 O( q( z& `! W* [4 u$ d 所以对于扩展的ID号码它有29位,但是程序中设计的过滤器位32位,所以: 如果假设扩展id为0x12345678 (0001,0010,0011,0100,0101,0110,0111,1000) 所以扩展id的顺序填入如上图所示意,这儿假设的:2 X/ i5 h5 V* N' A6 ~ r: x5 q! C* m RTR位我们设置为0表示数据帧,IDE位设置为1表示扩展ID,因为我们的ID是29位的,所以RTR = 0; IDE = 1; 再来看我们参考手册中,定义的 : B% d% ]9 b9 ~ u5 @# I 将上面数据中的标示符号位再填入到figure的表过滤器中:) B# T" e2 {- E8 U, ~ 所以可以看到颜色的顺序已经被打乱了,4 |8 ]0 Y$ }; f" X5 m& R' E( ^" @ 如果要关心到具体的某一个比特位置;如果要过滤让它只接收0x12xxxxxx的表示符号;% U2 ` Y+ d/ W' [ 这时候要根据它实际在identify中的位置去修改idmask ; 前八个比特,对应的就是黄色和绿色的部分,/ A2 q" n) V1 o 所以其他的颜色,可以都填0表示不需要关心,则这里填入:1 1 1 1 ,1 x x x,我们这里 填入0xF8 ;- w) j1 R$ a0 Y) D+ F 即: 同理,对于下面的配置是只接收标准id= 0x321(0011,0010,0001)的ID(也是32位过滤器),) c1 Z. `- x# z 因为也是数据帧,所以RTR = 0,标准的id,所以IDE = 0 ;所以填入到: 如下图,测试通过; 四、附录 在CAN规范中并未定义代表逻辑电平的物理状态(例如电压),iCAN网络使用符合ISO11898-2标准的电平信号,典型地,CAN总线为“隐性”(逻辑1)时,CAN_H和CAN_L的电平为2.5V(电位差为0V);CAN总线为“显性”(逻辑0)时,CAN_H和CAN_L的电平分别是3.5V和1.5V(电位差为2.5V), % q* {. Z, k. {7 K 识别符& m# s8 f+ I) A7 p& N 识别符—标准格式 识别符的长度为11 位,相当于扩展格式的基本ID(Base ID)。这些位按ID-28 到ID-18 的顺序发送。最低位是ID-18。7 个最高位(ID-28 - ID-22)必须不能全是“隐性”。 识别符—扩展格式 和标准格式形成对比,扩展格式由29 位组成。其格式包含两个部分:11 位基本ID、18 位扩展ID。 基本ID:基本ID 包括11 位。它按ID-28 到ID-18 的顺序发送。它相当于标准识别符的格式。基本ID定义扩展帧的基本优先权。 扩展ID:扩展ID 包括18 位。它按ID-17 到ID-0 顺序发送。 标准帧里,识别符其后是RTR 位。 RTR 位(标准格式以及扩展格式) RTR 的全称为“远程发送请求位(Remote Transmission Request BIT)”。 RTR 位在数据帧里必须为“显性”,而在远程帧里必须为“隐性”9 Z" \! o) O. ~% [- \9 Y8 U 扩展格式里,基本ID 首先发送,其次是IDE 位和SRR 位。扩展ID 的发送位与SRR 位之后。 SRR 位(扩展格式) SRR 的全称是“替代远程请求位(Substitute Remote Request BIT)”。 SRR 是一隐性位。它在扩展格式的标准帧RTR 位位置,因此代替标准帧的RTR 位。因此,标准帧与扩展帧的冲突是通过标准帧优先于扩展帧这一途径得以解决的,扩展帧的基本ID(参见以下的“扩展识别符”)如同标准帧的识别符。 IDE 位(扩展格式) IDE 的全称是“识别符扩展位(Identifier Extension Bit)” IDE 位属于: - 扩展格式的仲裁场 - 标准格式的控制场 标准格式里的IDE 位为“显性(逻辑0)”,而扩展格式里的IDE 位为“隐性”。: y7 |$ p! q8 C / o0 a- U1 q' o; i7 @ 在标识符列表模式下,屏蔽寄存器当作标识符寄存器用。因此,使用2个标识符来代替上面的标识符加屏蔽位的方式。接收报文标识的每一位都必须跟过滤器标识符相同。. e' B- Z4 W8 Y: w k 设置过滤器0只接收ID为0x1828A0EF和0x1828A0EE的数据帧。(工作在标识符列表模式)& C6 p7 {* S1 N. P6 f 首先我们把这两个ID写成二进制: 0x1828A0EF: 0001 1000 0010 1000 1010 0000 1110 11113 ~" W9 u4 X' X q 0x1828A0EE: 0001 1000 0010 1000 1010 0000 1110 1110 然后我们将0x1828A0EF二进制的格数据组成如上图mapping所示的格式 Cna_fxr1:1100 0001 0xc1 Cna_fxr2:0100 1001 0x49 //这里有个RTR位我们设置为0表示数据帧,IDE位设置为1表示扩展ID, Cna_fxr3:0100 0001 0x41. a1 h$ v% |+ N% K, x' i& F6 Y Cna_fxr4:1101 1110 0xDE 这时我们工作在标识符列表模式,identifier/Mask的寄存器相当于identifier使用。 再将0x1828A0EE二进制的格数据组成如上图mapping所示的格式! u/ C, a1 F8 e6 A+ D: } Cna_fxr5:1100 0001 0xc1& {$ ^& Y9 j" v" N3 I3 X+ |4 T Cna_fxr6:0100 1001 0x49 //这里有个RTR位我们设置为零表示数据帧,IDE设置为1表示扩展ID Cna_fxr7:0100 0001 0x41 Cna_fxr8:1101 1100 0xDC* A: Q9 c- L( q1 ^+ E) j! F 以下是用库函数配置的程序小片段: CAN_FilterNumber =CAN_FilterNumber_0;, p1 I* l" z* ?3 a I6 p //注意这是的模式是跟IdMask例不一样的 * Y' m' y$ R1 g! o 相信看到这是你对这两种工作模式有一定的了解了吧!。 好了,例子就说完了,8位16位的位宽是相似的,和上面的分析是一样的。 ) `8 [( y" k, U* I5 g$ X$ e8 e6 [+ [' _ 文档下载地址: https://www.stmcu.org.cn/document/list/index/category-998 ( d! b$ |+ x0 ~ W J7 Y 实战经验汇总: https://www.stmcu.org.cn/module/forum/thread-576401-1-1.html |
学习学习 |
学习了!!! |
真是好贴啊 |
学习 |
学习学习 |