你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

安臣学习stm32f072系列--------can通信事例  

[复制链接]
安臣 发布时间:2015-5-28 15:58
借鉴博客:http://blog.csdn.net/flydream0/article/details/8148791& a; h1 A9 C; D9 M! F! \
4 g% u3 Q: E9 Z1 \0 ?$ j8 ?
CAN ID值的结构分析
! N& \3 g3 l4 f, @

              在讲到代码实例之前,首先大家都弄懂一件事,当给定一个CAN ID,如0x1800f001,当然这个是扩展ID,这里要问的是,这个CAN ID的值本身包含两部分,即基本ID与扩展ID,即么你知道这个扩展ID0x1800f001的哪些位是基本ID,哪些位又是扩展ID?(在基本CANID格式下不存在这个问题)4 {( z0 x& _+ k! U

                在回答这个问题之前我们来看看ISO11898的定义,如下图:

3 e8 C5 a; d/ J4 N* H

                                                                                     图9

如上图,基本格式不存在扩展ID,而扩展格式中ID0~ID17为Extension ID,而ID18~ID28为Base ID.

因此CAN ID值0x1800f001用二进制表示为:0b 0001 1000 0000 0000 1111 0000 0000 0001,用括号分别区别为:0b 000[1 1000 0000 00][00 1111 0000 0000 0001],红色部分为扩展ID,蓝色部分为基本ID。那么知道这些有什么用呢?接下来的代码示例中你就会有什么用了。
% P3 r; F& T( l6 C& m

4.2 位宽为32位的屏蔽模式
; k+ ?2 N0 A% g1 \4 Q6 R

在此种模式下中过滤多个CAN ID,此时,过滤器包含两个寄存器,屏蔽码寄存器和标识符寄存器。此模式下最多只存在一个屏蔽过滤器。

如下图所示:

                                                                                 图10

如上图,上面的ID为标识符寄存器,中间部分的MASK为屏蔽码寄存器。每个寄存器都是32位的。最下边显示的是与CAN ID各位定位的映射关系。由4.1的知识很快可以发现,上图最下边的映射关系恰好等于扩展CAN值左移3位再补上IDE(扩展帧标识),RTR(远程帧标志)。

! y$ u& u9 N; W2 K

因此,我们初步得出这样的推论:对于一个扩展CAN ID,不能单纯地将它看到的一个数,而应该将它看成两部分,基本ID和扩展ID(当然标准CAN ID只包含基本ID部分),过滤器屏蔽码寄存器和标识符寄存器也应该看成多个部分,然后问题就变成了如何将CAN ID所表示的各部分如何针对过滤器寄存器各部分对号入座的问题了。

对号入座的方法多种多样,但万变不离其心,主要是掌握其核心思想即可:1:在各种过滤器模式下,CAN ID与寄存器相应位置一定要匹配;2:在屏蔽方式下,屏蔽码寄存器某位为1表示接收到的CAN ID对应的位必须对验证码寄存器对应的位相同。

& g7 x$ Q5 w2 r/ h+ o: b0 e4 z; Q

下面给出一个代码例子,假设我们要接收多个ID:0x7e9,0x1800f001,前面为标准ID,后面为扩展ID,要同时能接收这两个ID,那么该如何设置这个过滤器呢?

  1. CAN_FilterInitTypeDef  CAN_FilterInitStructure;4 `) j' u5 ?7 X% a% ^  A. f" W; ~3 N
  2. U16 std_id =0x7e9;
    2 _1 c% G( {/ Z8 _/ ~$ ^
  3. U32 ext_id =0x1800f001;/ ^4 ?9 r7 {. O" R
  4. U32 mask =0;
    6 D6 f$ ^7 I/ C2 g+ R7 v1 Q2 v( N: \
  5. 1 U$ |' S% n; m+ Y- I4 [: {6 i( M
  6. CAN_FilterInit(&CAN_FilterInitStructure);     //初始化CAN_FilterInitStructrue结构体变量
    . B3 U" U  q) h6 X/ x  }
  7. CAN_FilterInitStructure.CAN_FilterNumber=0;      //设置过滤器组0,范围为0~13, h" O) y/ Q# P3 k1 d& I% p  a
  8. CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;    //设置过滤器组0为屏蔽模式) u# h- Z6 Q. z, U: ]( T) {0 m
  9. CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;   //设置过滤器组0位宽为32位: w$ Q4 r( E! m4 G5 e7 I7 Z
  10. ( \4 l* u5 J( F& [* o0 r
  11. //标识位寄存器的设置0 f' k: J* {) o3 \! \2 V4 c0 ~
  12. //ext_id<<3对齐,见上图9,再>>16取高16位
    8 V5 B2 ]/ z* u: e! v9 m+ y" q
  13. CAN_FilterInitStructure.CAN_FilterIdHigh=((ext_id<<3) >>16) &0xffff;  //设置标识符寄存器高字节。( e( _- q: H( M! ]3 y
  14. CAN_FilterInitStructure.CAN_FilterIdLow=(U16)(ext_id<<3) | CAN_ID_EXT;   //设置标识符寄存器低字节
    5 v$ ]3 y1 K% l) s9 C/ s; I% i) ~
  15. //这里也可以这样设置6 f/ M# h$ X1 l+ N3 r6 x* @( C
  16. //CAN_FilterInitStructure.CAN_FilterIdHigh=std_id<<5;  //设置标识符寄存器高字节.这里为什么是左移5位呢?从上图可以看出,CAN_FilterIdHigh包含的是STD[0~10]和EXID[13~17],标准CAN ID本身是不包含扩展ID数据,因此为了要将标准CAN ID放入此寄存器,标准CAN ID首先应左移5位后才能对齐.5 ?" O" v3 [2 X
  17. //CAN_FilterInitStructure.CAN_FilterIdLow=0|CAN_ID_EXT;   //设置标识符寄存器低字节,这里也可以设置为CAN_ID_STD2 f/ x* `2 `0 t
  18. * L* w0 B* u) ]6 n9 c# w1 T$ D
  19. //屏蔽寄存器的设置
      A' V. _7 `+ W1 x3 J, ]- P
  20. //这里的思路是先将标准CAN ID和扩展CAN ID对应的ID值先异或后取反,为什么?异或是为了找出两个CAN ID有哪些位是相同的,是相同的位则说明需要关心,需要关心的位对应的屏蔽码位应该设置为1,因此需要取反一下。最后再整体左移3位。
    # Y3 q# L# E! |% P4 C
  21. mask =(std_id<<18);//这里为什么左移18位?因为从ISO11898中可以看出,标准CAN ID占ID18~ID28,为了与CAN_FilterIdHigh对齐,应左移2位,接着为了与扩展CAN对应,还应该再左移16位,因此,总共应左移2+16=18位。也可以用另一个方式来理解:直接看Mapping的内容,发现STDID相对EXID[0]偏移了18位,因此左移18位.
    + c* S; ^0 h8 A8 b% O
  22. mask ^=ext_id;//将对齐后的标准CAN与扩展CAN异或后取反! {+ c4 E8 @) i6 o+ {8 ]
  23. mask =~mask;" a0 x7 K$ q4 v: o, U
  24. mask <<=3;//再整体左移3位
    8 q' a' C2 H- r1 @1 z
  25. mask |=0x02; //只接收数据帧,不接收远程帧
    & u/ T3 g" Y7 s) V& v4 \
  26. CAN_FilterInitStructure.CAN_FilterMaskIdHigh=(mask>>16)&0xffff; //设置屏蔽寄存器高字节( {9 G' B( {; J4 b  @. Y, e5 J& [$ U/ H
  27. CAN_FilterInitStructure.CAN_FilterMaskIdLow=mask&0xffff;   //设置屏蔽寄存器低字节
    4 z1 ^% G$ o$ B8 C$ ~
  28. , L7 e3 P/ z, b  J
  29. CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;  //此过滤器组关联到接收FIFO05 r9 M' X$ p; W3 o
  30. CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活此过滤器组8 W5 q3 O+ g, V$ q. ?
  31. CAN_FilterInit(&CAN_FilterInitStructure); //设置过滤器
    . K" {" s! J1 U
复制代码

总结可知,当过滤器为屏蔽模式时,标识符寄存器对应的ID内容可为任意一需求接收的ID值,当同时要接收标准帧和扩展帧时,标识符寄存器对应IDE位也随意设置,屏蔽寄存器的IDE位设置为0,表示不关心标准帧还是扩展帧。而屏蔽寄存器对应的ID内容为各需求接收的ID值依次异或的结果再取反。

4.3 位宽为32位的标识符列表模式

在此种模式下,过滤器组包含的两个寄存器含义一样,此模式下只多存在两个标识符列表过滤器如下图:

                                                                                                   图11

  1. CAN_FilterInitTypeDef  CAN_FilterInitStructure;
    & V; h0 A. g( L) [3 x% q
  2. U16 std_id =0x7e9;! }* |( x# H) g6 a( R8 O
  3. U32 ext_id =0x1800f001;) ?* V  K8 k2 G8 f
  4. CAN_FilterInit(&CAN_FilterInitStructure); //初始化CAN_FilterInitStructrue结构体变量7 Z; e; k6 w" n) H6 Q& Q2 ~4 n2 K
  5. CAN_FilterInitStructure.CAN_FilterNumber=0;     //设置过滤器组0,范围为0~13& D; ?* i# s% r
  6. CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList;    //设置过滤器组0为标识符列表模式
    - m2 u' x: E% y8 c3 ~. S
  7. CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;   //设置过滤器组0位宽为32位1 ?3 y- ?1 p5 I6 @

  8. $ S6 `5 K2 C) I- W; o
  9. //设置屏蔽寄存器,这里当标识符寄存器用4 _3 ~$ ~6 _/ _. y
  10. CAN_FilterInitStructure.CAN_FilterIdHigh=std_id<<5) ;  //为什么左移5位?与上面相同道理,这里不再重复解释
    5 R& n# i/ A( D' B# l3 X
  11. CAN_FilterInitStructure.CAN_FilterIdLow=0|CAN_ID_STD; //设置标识符寄存器低字节,CAN_FilterIdLow的ID位可以随意设置,在此模式下不会有效。  @2 q2 P2 K( x; m. _
  12. 6 E" c; x( u2 ]( ], x2 t
  13. //设置标识符寄存器' P/ Q7 A. D' Z, ^. S4 d+ W4 D# |! ?
  14. CAN_FilterInitStructure.CAN_FilterMaskIdHigh=((ext_id<<3)>>16) & 0xffff; //设置屏蔽寄存器高字节7 B/ m/ ^6 W# G: r  \1 i+ e4 c
  15. CAN_FilterInitStructure.CAN_FilterMaskIdLow=((ext_id<<3)& 0xffff) | CAN_ID_EXT;   //设置屏蔽寄存器低字节' @* v. ~6 ~7 z* H

  16. , m8 S  q/ z/ y* s
  17. CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0;  //此过滤器组关联到接收FIFO0
    + I& P% r' A) a; J* x* z
  18. CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活此过滤器组$ |3 R0 @& L% u% H* e
  19. CAN_FilterInit(&CAN_FilterInitStructure); //设置过滤器3 `0 d- n* m5 A+ ]
复制代码
4.4 位宽为16位的屏蔽码模式

在此模式下,最多存在两个屏蔽码过滤器,如下图:

                                                                                                          图12

由上图映射可知,最下面的映射只包含STDID0~ID10,因此,此模式下的两个屏蔽过滤器只能实现对标准ID的过滤。具体代码就不介绍了,参见上图的映射即可。

. d6 p" J8 \7 m& R# {
4.5 位宽为16位的标识符列表模式

                                                                                              图13, w! E5 Q# m$ K5 H& c( Y

在此模式下,由于标识符寄存器的高16位和低16位,屏蔽寄存器的高16位和低16位都用来做标识符寄存器,因此,最多可存在4个标识符过滤器。同样,只能实现对标准帧的过滤。具体代码就不介绍了,参见上图的映射即可。

+ D$ f. M9 a6 h4 \$ s# f

以上是别人博客转载的


( a3 w% J% \/ V4 D: B8 s9 J  _

下面是i我自己的代码

  1. /**
    ! m; i: h9 U( r/ Q$ i; {
  2. * @brief This function config can's fiflter.7 R/ m& h9 o: [2 c! C
  3. */
    / v: |: |  O: B, W% _
  4. void Can_FilterConfig(void)
      P# q  X) C$ |1 I0 q, C
  5. {
    / X' g: v: o+ a
  6.         CAN_FilterConfTypeDef FilterConfig;+ ]9 s3 C: m4 G) L
  7.         ) G3 P7 h& N; ]5 _* x2 X
  8.         FilterConfig.FilterIdHigh         = ((ext_id<<3) >>16) &0xffff;5 B% Q$ s) i% `2 l) M) t
  9.         FilterConfig.FilterIdLow          = (uint16_t)(ext_id<<3) | CAN_ID_EXT | CAN_RTR_DATA;
    ; T# n7 W. ]' K1 d& O6 J
  10.         FilterConfig.FilterMaskIdHigh     = 0xfff8;8 i. _4 x- m0 K2 C/ V$ n, b0 r' h
  11.         FilterConfig.FilterMaskIdLow      = 0x07ff;
    - A/ x0 A+ s7 y# G0 t* v+ R
  12.         FilterConfig.FilterFIFOAssignment = 0x00;/ y' l5 \2 Y$ U% p- g: r0 |
  13.         FilterConfig.FilterNumber         = 0x00;# y/ m  G5 k7 W! T5 e9 i  g+ C5 |8 k
  14.         FilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;
    2 L/ V# I' j% y# _5 f( {
  15.         FilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;
    ; R3 K3 z  H! v* t
  16.         FilterConfig.FilterActivation     = ENABLE;
    ! Q. s) z/ Q3 \3 g1 ~
  17.         hcan.Instance = CAN;
    # I  c' a; F9 E. m( d& f
  18.         HAL_CAN_ConfigFilter(&hcan, &FilterConfig);
    4 c% q2 s- ]) H8 S
  19. }2 h$ x( Q) _% n' V8 W$ q
  20. /**' u" C+ T. i! f3 U+ U) X3 K% A
  21. * @brief This function is can send pross.
    * k4 B; c- x' ]" [$ N
  22. */; i1 ^# g1 X7 h/ o& E+ N9 M' G/ k1 V
  23. void Can_Assignin_Send_Pross(uint8_t *pbuf)8 P$ f" ]! _9 {
  24. {
    1 ]' ]+ ~( `# L1 e
  25.         hcan.Instance = CAN;
    ! p( P0 B) g! l' P
  26.         hcan.pTxMsg = &TxMsgStruct;
    / K6 b" ~" }8 ]! h
  27.         hcan.pRxMsg = &RxMsgStruct;
    6 ?" ^( ^: A* [7 H

  28. 7 W- `1 G" q, _6 N& Z) I1 h/ j
  29.         TxMsgStruct.ExtId = 0x18ff0004;+ n7 W8 o+ s. ^" C& O. D
  30.         TxMsgStruct.IDE   = CAN_ID_EXT  ;7 I! w! Z5 u' h/ m8 x5 d9 p; ^
  31.         TxMsgStruct.RTR   = CAN_RTR_DATA;
    ) i6 X. K$ h. D) a- b
  32.         TxMsgStruct.DLC   = 6;4 b/ P% ^9 W( e& @' O8 {
  33.         TxMsgStruct.Data[0] = pbuf[0];% R# D0 m# Q# k" E8 ^5 `" G7 B
  34.         TxMsgStruct.Data[1] = pbuf[1];" W. S0 V$ h( m6 C( B+ p% y
  35.         TxMsgStruct.Data[2] = pbuf[2];) C4 \9 e' T9 Y& l- P
  36.         TxMsgStruct.Data[3] = pbuf[3];
    0 F( J+ W  q1 N" o" ~8 {, T) E
  37.         TxMsgStruct.Data[4] = pbuf[4];2 Z7 x2 x4 \; `4 s& P
  38.         TxMsgStruct.Data[5] = pbuf[5];9 c4 d' B$ g' X. O7 V' m, ^
  39.         HAL_CAN_Transmit(&hcan,0);       
    * J7 k& |; I2 \5 t8 W' V

  40.   B, _6 E: ]2 m. l) k
  41.         HAL_CAN_Receive_IT(&hcan, 0x00);3 }! ^8 V7 ^* O6 {; m6 r1 s. V
  42. }  C4 S. f* e1 L
  43. /**
    & Q* k! I& a' \6 T/ f9 o" ^9 c# X
  44. * @brief This function handles CEC and CAN interrupts.  g; ~% e6 j4 H
  45. */
    + n0 M4 H; R& \. `
  46. void Can_Assignin_Rev_Pross(uint8_t *pbuf)
    4 k$ X9 x4 [! e) m
  47. {
    - D$ F# O/ ^" y* p% U, X- o! D/ }
  48.         hcan.Instance = CAN;1 o, n2 N" Z1 ^- V) ^
  49.         hcan.pRxMsg = &RxMsgStruct;- q2 C1 E2 _- F5 {. F
  50.   pbuf[0] = RxMsgStruct.Data[0];
    2 c; D7 |" w% R9 p
  51.         pbuf[1] = RxMsgStruct.Data[1];
    " b# Y# w5 z3 F: l7 v
  52.         pbuf[2] = RxMsgStruct.Data[2];
    7 k& Q, s: b" U3 C- B, F
  53.         pbuf[3] = RxMsgStruct.Data[3]; * n* J0 Q! T, O/ d8 h+ J
  54.         pbuf[4] = RxMsgStruct.Data[4]; & r  ^+ x( T; H% }
  55. }
复制代码
! w! i1 ?& B4 O. w! }7 G
: X3 ]2 h* v7 \. C& F2 H3 s

& @4 M9 z4 R$ R# O) ~

can.rar

下载

3.8 MB, 下载次数: 561

收藏 9 评论24 发布时间:2015-5-28 15:58

举报

24个回答
安臣 回答时间:2016-6-16 21:16:44
watershade 发表于 2016-5-10 21:04
) U* C/ ~* O8 M* E% T最近在玩CANopen,多交流呀。安臣移植canFestival吗

; X) |. p# l" L. E( H( H4 L, J4 Q没有啊  
DarkG 回答时间:2017-1-4 16:29:50
用最新的F1 V14.0 收到CAN的消息 能进中断 但是进了中断之后就马上死机了
watershade 回答时间:2016-5-10 21:04:01
最近在玩CANopen,多交流呀。安臣移植canFestival吗
netlhx 回答时间:2015-5-28 16:37:31
高大上的东西,不懂也顶
风子 回答时间:2015-5-28 18:00:56
啊,正好我这两天也在研究这个
wamcncn 回答时间:2015-5-28 19:41:39
CAN,看过一本书,北航的
wyxy163@126.com 回答时间:2015-5-29 08:29:36
提示: 作者被禁止或删除 内容自动屏蔽
为什么是EEFOCUS小白 回答时间:2015-5-29 08:55:45
谢谢分享   
安臣 回答时间:2015-11-20 20:51:37
这个好帖居然没人顶
lkl0305 回答时间:2015-11-20 21:06:25
多谢分享
abclsl 回答时间:2015-11-23 20:29:13
请问你,是没有试过接收没有数据的远程帧呢
abclsl 回答时间:2015-11-23 20:29:33
顶起
阿平 回答时间:2016-3-21 23:08:01
学习中正需要
斜阳 回答时间:2016-5-10 18:03:40
跟着臣哥学CAN通信
wuchao147 回答时间:2016-8-10 13:20:09
dsfdsafsaf
12下一页

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版