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

【经验分享】STM32中CAN总线接口发送和接收数据

[复制链接]
STMCU小助手 发布时间:2022-3-16 21:00
CAN协议基础知识6 F) X2 O$ ?/ Q) K# I( L- O  _
I2C.SPI总线多用于短距离传输,协议简单,数据量少,主要用于IC之间的通讯,而 CAN 总线则不同,CAN(Controller Area Network) 总线定义了更为优秀的物理层、数据链路层,并且拥有种类丰富、简繁不一的上层协议。与I2C、SPI有时钟信号的同步通讯方式不同,CAN通讯并不是以时钟信号来进行同步的,它是一种异步通讯,只具有CAN_High和CAN_Low两条信号线,共同构成一组差分信号线,以差分信号的形式进行通讯。+ y# P5 ~: e9 o8 Y2 `6 D& \

" ^9 ~$ G& W5 g( Y9 D. o4 LCAN物理层的形式主要分为闭环总线及开环总线网络两种,一个适合于高速通讯,一个适合于远距离通讯。CAN闭环通讯网络是一种遵循ISO11898标准的高速、短距离网络,它的总线最大长度为40m,通信速度最高为1Mbps,总线的两端各要求有一个
( I, O  o6 C- I: M) c6 j
) u2 k  G% W* ^2 y+ A" I# e“120欧”的电阻来做阻抗匹配,以减少回波反射。" I% L6 e. O; B+ ], Z) l4 b: S

0 |4 ^7 ?1 X4 ~- U( O. w6 o: ?0 f
$ ~3 G% z! k- n" ]- ^% ~& B闭环总线网络
9 a! n4 E! @5 i. @7 Y, j6 M8 C5 W

8 y0 o0 f  Q' {( q0 v C6B_FO]A5AU2E3_C3N6QEUL.png
, T8 y& p9 D$ m- K: R+ C8 \6 w" m! J) }8 z: b: }
CAN开环总线网络是遵循ISO11519-2标准的低速、远距离网络,它的最大传输距离为1km,最高通讯速率为125kbps,两根总线是独立的、不形成闭环,要求每根总线上各串联有一个“2.2千欧”的电阻。
/ h2 K/ l  J( Q0 z; |; l
; P# y, b% F* q; r7 r5 O/ Q* O) l4 n0 N; T
开环总线网络

/ f4 C0 z4 Y/ I$ I8 i6 k7 J# ]
, s, Y2 z+ h% V  t YY_5%7%S81V8L~8XYRASX.png 9 X4 c! Q! J. S, h8 m2 X

6 ~) q% o1 S  HCAN总线上可以挂载多个通讯节点,节点之间的信号经过总线传输,实现节点间通讯。由于CAN通讯协议不对节点进行地址编码,而是对数据内容进行编码,所以网络中的节点个数理论上不受限制,只要总线的负载足够即可,可以通过中继器增强负载。
* Y* D* z* i4 H2 R; x$ z: ^# s, v! m2 V
CAN通讯节点由一个CAN控制器及CAN收发器组成,控制器与收发器之间通过CAN_Tx及CAN_Rx信号线相连,收发器与CAN总线之间使用CAN_High及CAN_Low信号线相连。其中CAN_Tx及CAN_Rx使用普通的类似TTL逻辑信号,而CAN_High及CAN_Low是一对差分信号线,使用比较特别的差分信号。当CAN节点需要发送数据时,控制器把要发送的二进制编码通过CAN_Tx线发送到收发器,然后由收发器把这个普通的逻辑电平信号转化成差分信号,通过差分线CAN_High和CAN_Low线输出到CAN总线网络。而通过收发器接收总线上的数据到控制器时,则是相反的过程,收发器把总线上收到的CAN_High及CAN_Low信号转化成普通的逻辑电平信号,通过CAN_Rx输出到控制器中。" [! l5 l. n5 k% ^  N7 r9 I! o
5 P( v5 }7 w$ u8 c5 g
6 Q9 j  i; Q5 C9 y
差分信号
2 Y1 B- F  T; `3 l3 ]4 s' [
9 G/ L/ Q  T! {' C4 Z. U7 I. ~差分信号又称差模信号,与传统使用单根信号线电压表示逻辑的方式有区别,使用差分信号传输时,需要两根信号线,这两个信号线的振幅相等,相位相反,通过两根信号线的电压差值来表示逻辑0和逻辑1。2 c' C1 i3 v) s* l  Z' ~
) _5 ~* d5 h  q4 q
相对于单信号线传输的方式,使用差分信号传输具有如下优点:' ]4 N& Q1 K+ \1 F! s

3 V0 X- I: X) J) K, i3 x* 抗干扰能力强,当外界存在噪声干扰时,几乎会同时耦合到两条信号线上,而接收端只关心两个信号的差值,所以外界的共模噪声可以被完全抵消。3 T1 {. I: H& S, |- s( i
* 能有效抑制它对外部的电磁干扰,同样的道理,由于两根信号的极性相反,他们对外辐射的电磁场可以相互抵消,耦合的越紧密,泄放到外界的电磁能量越少。
8 c- I0 q6 a3 ?6 n; m# P* 时序定位精确,由于差分信号的开关变化是位于两个信号的交点,而不像普通单端信号依靠高低两个阈值电压判断,因而受工艺,温度的影响小,能降低时序上的误差,同时也更适合于低幅度信号的电路。
* {, ^6 J6 |! Y) A* 由于差分信号线具有这些优点,所以在USB协议、485协议、以太网协议及CAN协议的物理层中,都使用了差分信号传输。
2 j% Z0 W9 [1 U& @) ]8 s+ f4 @6 d: K% z, L3 h
CAN协议中的差分信号
9 a: K+ s( r4 [8 G  y8 D$ F9 h' Q4 S* A1 O' D: Y$ h' |9 F1 t
CAN协议中对它使用的CAN_High及CAN_Low表示的差分信号做了规定。以高速CAN协议为例,当表示逻辑1时(隐性电平),CAN_High和CAN_Low线上的电压均为2.5v,即它们的电压差V H -V L =0V;而表示逻辑0时(显性电平),CAN_High的电平为3.5V,CAN_Low线的电平为1.5V,即它们的电压差为V H -V L =2V。( G2 [, g' h1 g& P; o3 ~

  u# Y: F" ~+ c2 h7 U PM9KOUVNXVZ[{5(VSX_KADJ.png
3 r$ m7 @' h" L6 P- n# b# z3 J7 i4 ?, l5 m1 U' F! o: n
+ U, D( Y: `* M4 B) r
CAN 总线的特点
) z/ }$ P( p! j7 [# G: |$ ~1 q/ o3 \6 B$ w' c" `6 U; g
CAN 总线网络是一种真正的多主机网络,在总线处于空闲状态时,任何一个节点单元都可以申请成为主机,向总线发送消息。其原则是:最先访问总线的节点单元可以获得总线的控制权;多个节点单元同时尝试获取总线的控制权时,将发生仲裁事件,具有高优先级的节点单元将获得总线控制权。2 [/ ~, @/ C, n& X" {
8 @: M( J4 `1 |2 ], x
CAN 协议中,所有的消息都以固定的数据格式打包发送。两个以上的节点单元同时发送信息时,根据节点标识符(常称为 ID,亦打包在固定的数据格式中)决定各自优先级关系,所以 ID 并非表示数据发送的目的地址,而是代表着各个节点访问总线的优先级。如此看来,CAN 总线并无类似其他总线“地址”的概念,在总线上增加节点单元时,连接在总线的其他节点单元的软硬件都不需要改变。
2 r+ [4 n" _2 p# D
8 B, W# M; y2 F  eCAN 总线的通信速率和总线长度有关,在总线长度小于 40m 的场合中,数据传输速率可以达到 1Mbps,而即便总线长度上升至 1000m,数据的传输速率仍可达到 50Kbps,无论在速率还是传输距离都明显优于常见的 RS232、RS485 和 I2C 总线。
+ i1 \, W  E, Q0 v& C7 m, K0 `, J6 Q8 g. O! i! G/ P
对于总线错误,CAN 总线有错误检测功能、错误通知功能、错误恢复功能三种应对措施,分别应对于下面三点表述:所有的单元节点都可以自动检测总线上的错误;检测出错误的节点单元会立刻将错误通知给其他节点单元;若正在发送消息的单元检测到当前总线发生错误,则立刻强制取消当前发送,并不断反复发送此消息至成功为止。
' o3 Q! e; [( c4 d* S
( \5 V2 @1 s( ]- W- I: ZCAN 总线上的每个节点都可以通过判断得出,当前总线上的错误是暂时的错误(如瞬间的强干扰)还是持续的错误(如总线断裂)。当总线上发生持续错误时,引起故障的节点单元会自动脱离总线。8 v6 X; S- L1 ?" I) s+ Q  T8 h
9 s4 _; I' ?3 k& n, A, ]& e
CAN 总线上的节点数量在理论上没有上限,但在实际上受到总线上的时间延时及电气负载的限制。降低最大通信速率,可以增加节点单元的连接数;反之,减少节点单元的连接数,则最大通信速率可以提高。
: d- ]4 `$ p/ l9 c2 l2 q! n, M1 P" I% P! w/ U8 Q" t
CAN总线的数据通信是以数据帧的格式进行的,而数据帧又是由位场组成的,其中每一个位又被划分为四段.即SS(SYNC SEG),PTS(PROP SEG--传播时间段),PBS1(PHASE SEG1--相位缓冲段1),PBS2(PHASE SEG1--相位缓冲段2).
1 N( e  V" u5 [0 s/ t
0 G, v3 B( s3 i* f* s3 y% d$ M. M数据帧的结构图:
; a5 w2 |/ l+ ?0 S# O2 P2 w2 d8 }# B6 L+ K( K  C: v( g8 [% n4 J
S6UF)GK2RRK{}`BL81DN.png   N4 o; P) r- S" P
) O" t1 g8 A; N& u
图中D表示显性电平,R表示隐形电平.* I5 d9 k  A5 S+ h* N

, E' x# C4 Q" j2 c6 C! ^7 aID:高位在前,低位在后。
6 e* \& q2 F* h- e+ _( Q
! i" O. w" [7 s: H基本ID,禁止高7位都为隐性,即不能:ID=1111111XXXX。* `! W1 c0 c+ I$ S9 I9 |5 J
( K" O  w0 h, E1 r( h" V  X
RTR,远程请求位。0,数据帧;1, 远程帧;# p$ a$ L% I; n5 Z% y& C

( x, W. q% D- }# F' OSRR,替代远程请求位。设置为1(隐性电平);6 g: J' ^6 e  O$ a1 i; {
4 R. O0 C' j, |" H- a* b+ I
IDE,标识符选择位。0,标准标识符;1,扩展标识符;6 e  r# z0 b; R( y5 d
" Y/ s; w6 Y! ~3 h: z/ I, [  I
r0,r1:保留位。必须以显现电平发送,但是接收可以是隐性电平。" g9 r( g1 K! t3 j& x
' M6 T, d/ o* r# i: j
DLC:数据长度码。0~8,表示发送/接收的数据长度(字节)。9 W( j6 W4 F' W% P# L0 K
9 L" `. W$ c/ g
IDE,标识符选择位。0,标准标识符;1,扩展标识符;3 B0 q' {" n6 Q! M& ]5 B

5 E8 t  ^* p9 ]$ v7 b5 g6 L! ?; a; E2 ?9 E8 w: G5 [6 B# A
  X6 \* z4 t3 v" b. C, H$ z
位时序分解

$ a/ R4 E  y" s
* ^9 D+ D+ K! c5 A* Q为了实现位同步,CAN协议把每一个数据位的时序分解成SS段、PTS段、PBS1段、PBS2段,这四段的长度加起来即为一个CAN数据位的长度。分解后最小的时间单位是Tq,而一个完整的位由8~25个Tq组成。# ^' B2 A4 P+ Q3 u$ n7 X8 b+ B( n
' m# y/ G3 `0 l0 b
$%EJZSSO{4ANCBIWX8BT3@L.png
, g& c: x! K+ W1 r: r; k
! p' F" E. P& ^3 `! `) d# D9 ^, `& o" s& }! n

6 ^4 o) n- `+ s7 j8 TSTM32中的CAN接口
7 H& I) h9 K( K  t, b  {
' M7 P0 D5 m$ }3 Y5 F2 RSTM32的芯片中具有bxCAN控制器 (Basic Extended CAN),它支持CAN协议2.0A和2.0B标准。该CAN控制器支持最高的通讯速率为1Mb/s;可以自动地接收和发送CAN报文,支持使用标准ID和扩展ID的报文;外设中具有3个发送邮箱,发送报文的优先级可以使用软件控制,还可以记录发送的时间;具有2个3级深度的接收FIFO,可使用过滤功能只接收或不接收某些ID号的报文;可配置成自动重发;不支持使用DMA进行数据收发。& ]) d. M8 L. X% P

( f+ e8 Z; H: {9 k0 ]* t, z1 ~ I@749X1@25IBIKX8HHSFJ)Q.png
$ W# Y2 R7 t. o: n& ^$ \' b# h7 J1 ^2 V8 ?: ~9 D3 O
1. CAN控制内核: j1 J, ^; p* A/ Z' J9 J
2. CAN发送邮箱
# i5 E& [! r1 h  ^' F3. CAN接收FIFO
; @/ a! v: q+ ~; k8 i$ T7 w/ i4. 验收筛选器$ t) m+ d5 i5 G: y$ X* {; F) M. k( Z
9 l% u8 `  J9 H$ @; f* [: W. e/ ?
STM32有两组CAN控制器,其中CAN1是主设备,框图中的“存储访问控制器”是由CAN1控制的,CAN2无法直接访问存储区域,所以使用CAN2的时候必须使能CAN1外设的时钟。
0 i6 @- o) a* d0 ]% n) Z/ G$ D
+ R% B9 A" n* r3 [8 U& V& H/ o3 MSTM32至少配备一个bxCAN(basic extend can )控制器,支持2.0A和2.0B协议,最高数据传输速率可达1M bps,支持11位标准帧格式和29位扩展帧格式的接收和发送,具备三个发送邮箱和两个接收FIFO,此wa此外还有三级可编程滤波器,STM32的bxCAN非常适应CAN总线网络y网络应用发展需求,其主要主要特征如下 :
3 R, h2 D, Y/ F* G4 y7 E4 j' a2 x/ \6 S9 r
* 支持CAN协议2.0A和2.0B主动模式6 Q3 D- a3 U. K# F0 i, |% f! X
* 波特率最高可达1Mbps
3 ^2 g# X& i. A  @* a* 支持时间触发通讯功能' Q* d: F( A( z5 L
2 A8 y5 ?, m( p. G- G/ b2 u7 D. F
数据发送特性:具备三个发送邮箱;发送报文的优先级可以通过软件配置,可记录发送时间的时间戳。5 `: \9 E$ }/ C2 o
* x: p0 {% L8 A" x
数据接收特性:具备三级深度和两个接收FIFO;具备可变的过滤器组,具备可编程标识符列表,可配置FIFO溢出处理方式,记录接收时间的时间戳
6 I  W6 [; ~$ N7 }, p, x% T# A/ q0 b
报文管理:中断可屏蔽;邮箱单独占有一块地址空间,便于提高软件效率。
+ V# ^8 ~' `. ?  `3 d& R7 B& ~$ V9 r' C. @# ?0 T5 m/ X: D
本文的实验设计将利用STM32 的bxCAN控制器的环回工作模式,实现bxCAN控制器的自收发过程,并使用串口设备跟踪监视数据收发情况。% U0 \( m6 H1 a8 |1 T0 z7 `

+ @4 @) |% w) H7 r程序流程如下图
2 Q4 L7 L: n% z" N# H/ Z/ _
; {3 R" o) d6 D# G5 b
O5OHNBE3)4RR3)7H)TCQZ2C.png
, N5 B7 L/ h- y- A0 `
, a+ E! a. m( n* O" n5 J) D, o8 E本程序设计主要围绕bxCAN控制器的初始化初始化配置展开,其要点罗列如下:
7 @( p% _0 d! [- l
" X4 w  [9 u* P3 e+ R  A1. 初始化RCC寄存器,配置PLL输出72MHZ时钟,APB1总线频率为36MHZ,分别打开CAN,GPIO和USART1的设备时钟。% `5 S! h& h% ^, m8 _
2. 设置CAN的Tx引脚(即PA12)为复用推挽模式,并设置Rx引脚(即PA1)为上拉输入模式,其中三个重要的参数如下配置:
" e$ |2 k" U- P5 L$ h
  1. CAN_InitStructure.CAN_SJW配置为CAN_SJW_1tq;
    : L1 X4 U0 s0 `4 K5 d# Y- l' }2 q; F
  2. CAN_InitStructure.CAN_BS1配置为CAN_BS1_8tq;
    2 U/ J" t2 G1 A3 A2 ?' Q# U3 }
  3. CAN_InitStructure.CAN_BS2配置为CAN_BS2_7tq;
复制代码
- D3 p. A9 ^. I. \% j1 S9 \) ?2 c
3. 最后分频数配置为5,配置接受接受缓冲区标识符为0x00AA0000,配置过滤器为32位屏蔽位模式,过滤器屏蔽标识符为0x00FF0000.
* V1 {, [3 S6 }( I+ B4. 初始化USART设备
/ u' Q0 a( w+ V1 T5. 使用扩展帧shu帧数据格式,ID为0xAA,数据长度长度为8, ^( t5 H' ]6 x, p5 ?

" h% f& B& a, m3 p' \+ t
& l: C, M) ~1 l8 `5 L, CSTM32的CAN控制器设计的重点集中在CAN寄存器组的初始化过程中,而CAN初始化的重点在于波特率的设置,过滤器的设置和位时序的设置,以下作详细叙述。
8 ]5 n3 M; M# }( _9 n
5 Z6 W1 F1 T( M  N5 P6 H: S8 L(1)CAN波特率的计算
( m4 M& ~$ n- g- m% f
6 b. n8 D0 m. l+ B' f; U
计算波特率是任何一种总线的zhon重要内容之一,CAN总线也不例外.从STM32微控制器的官方参考手册里可以查找到关于CAN波特率的计算公式如下.* [% J3 A% I4 [' D) {) q
  K1 l3 a; e8 p7 T. c7 ^, S! q% j5 X4 P6 j
通过配置位时序寄存器CAN_BTR的TS1[3:0]及TS2[2:0]寄存器位设定BS1及BS2段的长度后,就可以确定每个CAN数据位的时间:- _+ z( l* p/ P
8 [0 e2 J: a4 Z' N. t: ?& M/ g
BS1段时间:5 ~- s& C/ K" [. O" @/ S
' y$ s/ t1 R& A: J: U% z
T S1 =Tq x (TS1[3:0] + 1),9 ?" `) ~# Q2 Y4 {

6 L+ X& }+ G$ h2 eBS2段时间:
- L3 Q3 [7 y. B. d, F1 q; e( ^; a4 v5 W/ C  _. j
T S2 = Tq x (TS2[2:0] + 1),5 E* V% I7 V; ]- x& n

, g5 T" l- X' Z# i) h一个数据位的时间:2 L# q6 I, i0 L4 {( H% Q8 P
, s! f, g5 f* ?& R5 \
T 1bit =1Tq+T S1 +T S2 =1+ (TS1[3:0] + 1)+ (TS2[2:0] + 1)= N Tq$ p3 I& d( J( W5 `* S! c

9 E% `" f) ^* z/ P; p其中单个时间片的长度Tq与CAN外设的所挂载的时钟总线及分频器配置有关,CAN1和CAN2外设都是挂载在APB1总线上的,而位时序寄存器CAN_BTR中的BRP[9:0]寄存器位可以设置CAN外设时钟的分频值 ,所以:
0 Y+ z4 k1 @7 C: E# l, Q/ m
. i$ d6 d* r5 t0 D- C7 pTq = (BRP[9:0]+1) x T PCLK
  C+ c+ f2 h, W' ?; L' J/ w1 p; e9 w7 y; ?; w3 h
其中的PCLK指APB1时钟,默认值为36MHz。
% }% c: ?1 i0 B1 w0 s" \( T8 S( t3 f) F" }  s- h. w/ f
最终可以计算出CAN通讯的波特率:+ r4 @' H% I* E8 f# ?
9 T" r2 D+ ?% J; j& H  d
BaudRate = 1/N Tq, o9 J2 N; m+ m7 z
. L% h3 Y8 X, p5 x$ s
程序设计要点中强调的三个重要参数,其实是can总线物理层中所要求的位时序。共三个阶段,分别为SJW,BS1和BS2阶段,这三个阶段的时间长度都是以长度为tq的时间单元为单位的。这样可以逐步计算出CAN总线的波特率。因此要点提示中所要求的参数,实际上将CAN的波特率设置为450kdps。
+ m6 i( l8 a" t
' O3 \0 ?0 @3 [9 Y, o8 q/ V/ `4 ^7 E4 G# K# Y, i, A" N$ g% ^' g
过滤器的设置
% f! d- X# V+ L: S1 k& ^  y6 q* Q5 [- ~1 _' G; _9 O7 z& U; ]
can总线没有所谓地址的概念。总线上的每个报文都可以被各个节点接收。这是一种典型的广播式网络。在实际应用中。某个节点往往只希望接收到特定类型的数据, 这就要借助过滤器来实现。顾名思义,过滤器的作用就是把节点不希望接收到的数据过滤掉。只将希望接收到的数据给予通行。" y- U1 H# d9 A7 t1 }2 M

# F) ]( k& ]# c$ b4 N" sstm32的CAN控制器,提供14个过滤器。可以设置为屏蔽模式和列表模式对can总线上的报文进行过滤。当节点希望接收到一种报文时。可以用屏蔽位模式对can总线上的报文进行过滤。反之,当节点希望接受到单一类型报文时。则应该配置为列表模式。本机程序中使用了32位的屏蔽位模式。
( ?6 K; ^4 ]7 [# B1 h- c; I9 k; K% j6 c1 C  g: B
下面仅对这种模式进行解析。can控制器的每个过滤器都具备一个寄存器。称为屏蔽寄存器。其中标识符寄存器的每一位都有屏蔽寄存器的每一位所对应。事实上,这也对应着can数据。事实上,这也对应着看标准数据帧中的标识符段。" [3 v0 D! O( ~6 [- [/ P

7 I5 w5 b* _  `% \6 l如下图所示。
: y3 `( e/ ^8 m3 V
( y, Q. Y# U& b, p 3UR1U_CIM76FNU6]M9T0L98.png
1 L/ \; E3 ~; i: q4 V) J6 t3 k1 g5 R" M. v7 o
此处重点在于屏蔽寄存器的作用。通过查阅stm32微控制器参考文档可以知道。当过滤器工作在屏蔽模式下时。屏蔽寄存器被置为1的每一位都要求can接收到的数据帧标识符段必须和对应的接收缓冲区标识位相同。否则予以滤除。以本程序为例。要点中要求将节点接收缓冲标识符配置为0x00AA0000。过滤器屏蔽标识符为0x00FF0000。# ~) j* j  D9 w

0 s0 Y* J& v' i0 e该节点接收到的数据帧的标识符段的位[23:16],必须和接收缓冲区标识符中的[23:16]匹配。否则予以滤除。但若满足了这一条件而即便如下的位不匹配。则该数据帧仍不会被滤除。正如本程序而言。即can接口仅仅接收标识符段的位[23:16]为0xAA的数据帧.
/ d6 |: ?5 }# D* q' Y: ~; F0 B) |
. N9 c+ ^, e# J7 _5 U; a根据can总线物理层的要求。can总线的波特率和传输距离成反比关系。传输距离变化时,要根据位时序来调整can总线的波特率。. h1 W* t1 p% e7 B' `

0 R/ j3 P7 ~" q  T/ ~ E7CX_M101NWMIP139GWWRCF.png 5 D3 B* `( [3 X3 e. u$ e5 ?

6 Y: v( o* J& ^程序代码如下:
4 u: o% A' _' \) X: ~
  1. void RCC_Config(void): I7 c, n8 z6 q0 O  }0 t
  2. {
    . n- X7 X% }7 l8 H/ L5 Z+ I! h+ E

  3. ; m; r9 M* ]* f& f2 }5 ?
  4. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE)
    , M+ A0 T: o$ D& j4 N4 _2 K

  5. 1 P" c- X  M5 ?' X
  6. RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE)
    / p6 j0 ?4 f% q8 d/ o, O, G, @

  7. # S# b, V6 u5 `5 K4 ~" [7 e2 ]. d
  8. }2 L, ]$ e9 g9 K; }- ^! e! i
  9. void GPIO_for_can_and_uart_Config(void)
    9 M; H- R$ c, D6 ]
  10. {
    ; L* O2 E" U' D. w. l3 ?: f
  11. /*定义一个GPIO_InitTypeDef类型的结构体*/
    2 i+ r: ^; `  j& J  e/ v3 H; @& u
  12. GPIO_InitTypeDef GPIO_InitStructure;7 M1 C3 v# f6 b  R" e

  13. % m5 t) t  o" R- a0 G) o; D' l+ m
  14. ; u: O) F8 }$ t! N' U5 ~
  15. /*设置can的RX--pa.11引脚*/% y6 y, Z" ~3 d  O  d# j
  16. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    3 R$ V. J$ A! d4 r8 q
  17. . i# e6 w7 p7 v3 O( b! d: B5 l
  18. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;. X' u( k% d$ r" Q& |3 t
  19. $ h8 j& s( H! `4 Y" }$ k
  20. GPIO_Init(GPIOA, &GPIO_InitStructure);0 y9 ]' u% I4 z+ C# ^

  21. ' f3 e" M1 v1 n. u  Z
  22. /*设置can的TX--pa.12引脚*/! e/ O8 I- O9 c% |
  23. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    ! M% o; W0 m% e3 e" Q! o
  24. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    3 ]2 P) Y9 @2 W
  25. GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
    3 d6 n0 x6 P5 q9 g; J7 n, }' h
  26. GPIO_Init(GPIOA, &GPIO_InitStructure);0 _' h- m( c7 B$ `' |* M7 z/ Y2 B( ~
  27. /*设置usart1 的RX 脚 -PA.10为父浮空输入脚*/# N9 ~- e# F8 }& R+ }2 C
  28. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    5 }2 I, d. t0 b5 h
  29. * {9 w/ {" \* F* S6 T, U
  30. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    2 a& N; e* U, s- Q: q- W+ y
  31. # N; [7 ~  P' @% m2 [7 o
  32. GPIO_Init(GPIOA, &GPIO_InitStructure);6 l1 Z. j6 \! q+ f* w

  33. : Z! j, Q1 h  s: }4 ?4 O$ x! H

  34. 1 i4 _' j$ x# J8 a: f

  35. 0 o- X3 m/ ]6 E7 z" X+ b

  36. 5 K' q+ p  t; c
  37. }2 L7 _( b# d+ q3 b* _$ |

  38. 2 ~$ Z2 u+ S/ p5 m
  39. void Can_Config(void)+ y  A) z5 s' {
  40. {1 v- I$ f8 X" y3 z+ u0 E4 ~  C
  41. CAN_InitTypeDef          CAN_InitStructure;
      T3 `- b1 ~7 X$ O6 x  Y3 ^
  42. CAN_FilterInitTypeDef  CAN_FilterInitStructure;) K# X9 V' C) G

  43.   P+ V0 ^* e* f- k2 j
  44. CAN_DeInit(CAN1);+ G) Q2 e% Y/ [
  45. # g8 R& A1 B7 f& j
  46. CAN_StructInit(&CAN_InitStructure);9 d3 C4 B+ ^# y
  47. CAN_InitStructure.CAN_TTCM=DISABLE;
    5 ^( {% @1 g1 x* Y. w
  48. CAN_InitStructure.CAN_ABOM=DISABLE;4 i3 y$ R8 _# G% v) S4 h- K8 I
  49. CAN_InitStructure.CAN_AWUM=DISABLE;
    * l6 O! v# D- r0 p2 I
  50. CAN_InitStructure.CAN_NART=DISABLE;
    & X; _6 l% F- y" B& U0 y3 T
  51. CAN_InitStructure.CAN_RFIM=DISABLE;* F! m/ f/ j$ ]& R: T% d: A
  52. CAN_InitStructure.CAN_TXFP=DISABLE;
    * K4 L; e% h4 V- m% _( ]: O  Z
  53. / |; {% m6 z6 C& Z; `# w9 r0 b
  54. CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;& R4 j' T4 E& A
  55. CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;
    9 ]  D' N- X8 z1 J( Y
  56. CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;3 D( H8 m& x9 p+ v+ c) U3 Y$ E
  57. CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;! a1 Z" B) a9 T( T  G7 S6 \2 L

  58. 6 Y& f9 U9 g. Q' k% [7 E' Q) _! |
  59. CAN_InitStructure.CAN_Prescaler=5;/ z8 f8 J& J' p1 L4 S
  60. CAN_Init(CAN1,&CAN_InitStructure);
    9 ^. J0 o: r) ~4 \% k3 J
  61. 1 U4 E. t. A0 A
  62. CAN_FilterInitStructure.CAN_FilterNumber=0;
    5 i8 r4 v& F- I5 D
  63. CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
    ' I* ^9 e2 i  ^1 z
  64. CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;/ K  ~) H4 p9 f4 ?7 l; N/ u7 a
  65. CAN_FilterInitStructure.CAN_FilterIdHigh=0x00AA<<3;
    ! D6 a3 j( X3 o( \) {
  66. CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;  I' n/ G4 k. T
  67. CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x00FF<<3;0 `4 P- ]4 q4 u% g
  68. CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
    , U2 e  g' E# o& d0 P- i% T9 Z8 W; }
  69. CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
    9 k0 Z4 P+ y) s6 \9 G5 e
  70. CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;6 C1 Q; R2 _" W* O1 p) H
  71. CAN_FilterInit(&CAN_FilterInitStructure);/ ^' r) R8 Y9 Y) a( ?: ?$ \
  72. # _3 B1 M. n1 O  g8 }3 [& ]8 U
  73. }
    + w" g% A- R) h# O# |! [
  74. $ Q' j* U# l9 ?
  75. void main(void)
    7 ]# Z: X( ^% {; }4 N1 ]0 `
  76. {
    7 E3 G' `, p6 h1 n
  77. u8 TransmitMailbox=0;, ]2 r* F7 t/ V( i: L
  78. CanTxMsg   TxMessage;7 J/ V$ j- A3 y8 J- W! Z8 E
  79. CanRxMsg   RxMessage;% k* i- _5 v* m
  80. RCC_Config();
    7 n- G0 `8 A& T& w+ v
  81. GPIO_for_can_and_uart_Config();
    ! u6 |2 f4 Q7 n- S5 k
  82. USART_Config();
    8 x6 F. q6 `- Y& c* l
  83. Can_Config();
    2 L( w' V* E  j5 m9 i. ]
  84. 9 a3 k" M" v) C5 w( ?0 K
  85. TxMessage.ExtId=0x00aa0000;
    , S2 n" n# B2 H4 e1 P8 }' l
  86. TxMessage.RTR=CAN_RTR_Data;
    4 H1 U* y0 _+ z! N
  87. TxMessage.IDE=CAN_ID_EXT;
    / [9 n" g/ H1 K& p8 b  ]9 N
  88. TxMessage.DLC=8;' O7 U  z7 P: Q
  89. TxMessage.Data[0]=0x00;
    7 b) ^% i9 V& w8 \) k
  90. TxMessage.Data[1]=0x12;5 v4 ~5 J/ h$ |# g2 F; Q" u
  91. TxMessage.Data[2]=0x34;
    4 W/ x, e# b# _: Y/ y
  92. TxMessage.Data[3]=0x56;6 K+ P# k* b8 d3 Y" o
  93. TxMessage.Data[4]=0x78;  A7 f* z: g, {. p7 v
  94. TxMessage.Data[5]=0xab;
    # s2 W6 n2 K* e% g" ]
  95. TxMessage.Data[6]=0xcd;* @. o; \6 z1 @! ~  d
  96. TxMessage.Data[7]=0xef;
    ; T5 g$ ~: \+ C! o% G/ s4 l7 B) h
  97. # P) i% _, U  A
  98. TransmitMailbox=CAN_Transmit(CAN1,&TxMessage);
    7 w5 a7 t* h9 ]) K1 o* o
  99. while((CAN_TransmitStatus(CAN1,TransmitMailbox))!=CANTXOK);
    + F7 {2 N& Y% z7 E$ u: z
  100. printf("rnThe CAN has send data :0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,rn",9 e" \- M2 `3 @* G
  101. TxMessage.Data[0],TxMessage.Data[1],TxMessage.Data[2],TxMessage.Data[3],8 o. R8 f; g$ z# ^
  102. TxMessage.Data[4],TxMessage.Data[5],TxMessage.Data[6],TxMessage.Data[7],);
    + X- I& T3 z9 g

  103. # E8 |: A5 V/ R# V8 R0 E; T
  104. while((CAN_MessagePending(CAN1,CAN_FIFO0)==0));8 j+ n/ {5 h# q. ]( i
  105. / |0 Q+ H; i; P$ P# Z( n* k
  106. RxMessage.StdId=0x00;' z! c+ d6 Z, p* o4 @
  107. RxMessage.IDE=CAN_ID_EXT;
    ' w% D  t" V" X0 z0 \1 `
  108. RxMessage.DLC=0;, c' c: l7 _9 N! G! z& l
  109. RxMessage.Data[0]=0x00;
    8 _' d. W: {+ e, ^7 l5 k
  110. RxMessage.Data[1]=0x12;
    2 \+ j9 F5 ^; A3 U( t" L& Z
  111. RxMessage.Data[2]=0x34;- c. U% ~& _  j/ U
  112. RxMessage.Data[3]=0x56;$ k7 l5 M' z( c& a2 ^/ ^0 i* \
  113. RxMessage.Data[4]=0x78;/ G/ m1 ?/ Y3 I
  114. RxMessage.Data[5]=0xab;# c. w' l# g0 F2 R5 o
  115. RxMessage.Data[6]=0xcd;
    ! x( S/ w' b9 }" \
  116. RxMessage.Data[7]=0xef;
    * p% y- F: p0 f0 I

  117. $ t4 k' i5 u* N0 K  _, C0 f
  118. CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);
    * {9 X2 F3 c" x, p$ t! ^
  119. printf("rnThe CAN has received data :0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,rn",, K* @+ o% ?7 g
  120. RxMessage.Data[0],RxMessage.Data[1],RxMessage.Data[2],RxMessage.Data[3],
    8 I- y" ^8 w( J! o. m0 a
  121. RxMessage.Data[4],RxMessage.Data[5],RxMessage.Data[6],RxMessage.Data[7],);8 W6 W$ f# D  y8 @! ~8 l" J1 P: R2 a
  122. while(1);6 V' q! s% b% G/ j. \2 W) c
  123. , [) Z, U! G4 g
  124.   h, @/ m9 S! L7 A) H8 Y
  125. }
复制代码

  o/ Q/ ?5 p0 ]5 S
3 J+ k: ~2 ?0 i# g0 p6 U3 V+ r
收藏 评论0 发布时间:2022-3-16 21:00

举报

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