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

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

[复制链接]
STMCU小助手 发布时间:2022-3-16 21:00
CAN协议基础知识
) j. t) t8 }3 _) G( |I2C.SPI总线多用于短距离传输,协议简单,数据量少,主要用于IC之间的通讯,而 CAN 总线则不同,CAN(Controller Area Network) 总线定义了更为优秀的物理层、数据链路层,并且拥有种类丰富、简繁不一的上层协议。与I2C、SPI有时钟信号的同步通讯方式不同,CAN通讯并不是以时钟信号来进行同步的,它是一种异步通讯,只具有CAN_High和CAN_Low两条信号线,共同构成一组差分信号线,以差分信号的形式进行通讯。
; ^% u8 l% \( s5 m
, ]' y/ L7 B0 `CAN物理层的形式主要分为闭环总线及开环总线网络两种,一个适合于高速通讯,一个适合于远距离通讯。CAN闭环通讯网络是一种遵循ISO11898标准的高速、短距离网络,它的总线最大长度为40m,通信速度最高为1Mbps,总线的两端各要求有一个* H4 b% w5 s- M  z5 A

8 B1 ]. K6 `/ |9 {“120欧”的电阻来做阻抗匹配,以减少回波反射。3 b4 v, s- F; C) ?

% \6 y3 ?8 t8 w( O; }: K( O
" v8 w2 y  g& ]9 J* b0 W* J. Q9 u闭环总线网络
( P% M0 \. F- _2 \8 E
, D# f: @. Z7 {. ~; [6 E
C6B_FO]A5AU2E3_C3N6QEUL.png
2 L: G) E% s) B' \3 O/ z! J% ]/ _- n. i7 z! e
CAN开环总线网络是遵循ISO11519-2标准的低速、远距离网络,它的最大传输距离为1km,最高通讯速率为125kbps,两根总线是独立的、不形成闭环,要求每根总线上各串联有一个“2.2千欧”的电阻。( ~  ?/ {% U0 O; H  f

: P6 V: X! b4 B9 z4 G/ ^8 M( {3 H% l3 i( h  s' h" |# i& d
开环总线网络
& w- P8 G$ l1 x, {7 l5 ?0 O
- x+ ]. f4 _5 p& |6 S! m
YY_5%7%S81V8L~8XYRASX.png
) v2 k4 B% S" b2 A6 {: F8 ^, O6 I& i3 H+ r& f9 e" e
CAN总线上可以挂载多个通讯节点,节点之间的信号经过总线传输,实现节点间通讯。由于CAN通讯协议不对节点进行地址编码,而是对数据内容进行编码,所以网络中的节点个数理论上不受限制,只要总线的负载足够即可,可以通过中继器增强负载。
( z0 Y0 n2 T4 a' ~' D( d+ X4 \; z, M0 F
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输出到控制器中。5 b) L8 [% b( w9 v8 z# p. S

2 Q! T& B- {+ L( Q8 W1 h) A) r  l9 v- N3 J6 M5 C: l
差分信号
4 Y7 C: Q4 `8 Y; I: Z. ~) d. R
4 @5 B! d: E% W* Y  G差分信号又称差模信号,与传统使用单根信号线电压表示逻辑的方式有区别,使用差分信号传输时,需要两根信号线,这两个信号线的振幅相等,相位相反,通过两根信号线的电压差值来表示逻辑0和逻辑1。4 j9 ]; |" V! E, M
! P; r7 Y, l5 ]$ S6 _
相对于单信号线传输的方式,使用差分信号传输具有如下优点:( _& w& }6 k; L" M! n

$ b# h/ }; L" F( h9 `7 E: A* 抗干扰能力强,当外界存在噪声干扰时,几乎会同时耦合到两条信号线上,而接收端只关心两个信号的差值,所以外界的共模噪声可以被完全抵消。
; V' S9 |* H) C) k* 能有效抑制它对外部的电磁干扰,同样的道理,由于两根信号的极性相反,他们对外辐射的电磁场可以相互抵消,耦合的越紧密,泄放到外界的电磁能量越少。$ G5 w. Y$ ^. F* p) G+ i% h
* 时序定位精确,由于差分信号的开关变化是位于两个信号的交点,而不像普通单端信号依靠高低两个阈值电压判断,因而受工艺,温度的影响小,能降低时序上的误差,同时也更适合于低幅度信号的电路。
3 L( D. c5 X0 }0 e/ n% T+ l* 由于差分信号线具有这些优点,所以在USB协议、485协议、以太网协议及CAN协议的物理层中,都使用了差分信号传输。0 B+ h' L: e) ]
9 @2 m$ z( H" C; b' r
CAN协议中的差分信号4 J, w: U9 v' L5 ]

5 C6 O. i7 e5 v; O1 a. F0 ?8 cCAN协议中对它使用的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。+ a. \3 T' ^3 d2 E$ A! Y/ }
& W/ K  d/ {+ j, B5 e
PM9KOUVNXVZ[{5(VSX_KADJ.png ! g6 [3 l: M, |% Z9 ~
! T6 A* m2 k- D$ T% U! J3 _+ O
( D1 u, J+ ]- e: D
CAN 总线的特点
' z0 R& j4 j( p+ r  H; W5 C! M- k5 _" I* d: e& b' n. @
CAN 总线网络是一种真正的多主机网络,在总线处于空闲状态时,任何一个节点单元都可以申请成为主机,向总线发送消息。其原则是:最先访问总线的节点单元可以获得总线的控制权;多个节点单元同时尝试获取总线的控制权时,将发生仲裁事件,具有高优先级的节点单元将获得总线控制权。
. E2 R0 g% s& ~& ^* [/ |
+ v! n- P. s; X" `, \CAN 协议中,所有的消息都以固定的数据格式打包发送。两个以上的节点单元同时发送信息时,根据节点标识符(常称为 ID,亦打包在固定的数据格式中)决定各自优先级关系,所以 ID 并非表示数据发送的目的地址,而是代表着各个节点访问总线的优先级。如此看来,CAN 总线并无类似其他总线“地址”的概念,在总线上增加节点单元时,连接在总线的其他节点单元的软硬件都不需要改变。  C3 Q  j% w- @* L
. o/ Q" A: j# S8 `) {8 j1 E
CAN 总线的通信速率和总线长度有关,在总线长度小于 40m 的场合中,数据传输速率可以达到 1Mbps,而即便总线长度上升至 1000m,数据的传输速率仍可达到 50Kbps,无论在速率还是传输距离都明显优于常见的 RS232、RS485 和 I2C 总线。
  `, S* Q0 F* |1 N2 s* V
; S  O# O0 }! C" l0 \% G对于总线错误,CAN 总线有错误检测功能、错误通知功能、错误恢复功能三种应对措施,分别应对于下面三点表述:所有的单元节点都可以自动检测总线上的错误;检测出错误的节点单元会立刻将错误通知给其他节点单元;若正在发送消息的单元检测到当前总线发生错误,则立刻强制取消当前发送,并不断反复发送此消息至成功为止。1 T' W0 C5 J& ~/ F

, i1 C, d' `0 J' NCAN 总线上的每个节点都可以通过判断得出,当前总线上的错误是暂时的错误(如瞬间的强干扰)还是持续的错误(如总线断裂)。当总线上发生持续错误时,引起故障的节点单元会自动脱离总线。
5 o' c  \$ H1 Q% A$ o' R$ k# c0 o+ \
( L- m' q6 {& J/ xCAN 总线上的节点数量在理论上没有上限,但在实际上受到总线上的时间延时及电气负载的限制。降低最大通信速率,可以增加节点单元的连接数;反之,减少节点单元的连接数,则最大通信速率可以提高。
! t. v8 x! z+ S7 K; X8 e
3 b) @. C2 x$ I5 v/ E) SCAN总线的数据通信是以数据帧的格式进行的,而数据帧又是由位场组成的,其中每一个位又被划分为四段.即SS(SYNC SEG),PTS(PROP SEG--传播时间段),PBS1(PHASE SEG1--相位缓冲段1),PBS2(PHASE SEG1--相位缓冲段2).
' Q- G6 f( N" v4 g8 U# z7 o0 C! i
% D. T/ V% w; J+ j5 a2 _数据帧的结构图:
4 Z7 T' j2 q/ J- V( D
) {) H4 K  U1 z+ H7 f S6UF)GK2RRK{}`BL81DN.png
4 `/ K: ^4 ?" }$ V- O, H& u5 y& j# u; W6 d& F
图中D表示显性电平,R表示隐形电平.
* B# J; O, _' w* W3 [" V* x4 n6 ^) G6 i! G( e9 w
ID:高位在前,低位在后。
6 z* q, L1 L) b- y$ r" Y) y5 ~4 K: i% b
基本ID,禁止高7位都为隐性,即不能:ID=1111111XXXX。
6 N& D9 w, Y$ R/ H
5 Q. m' _2 B9 D+ CRTR,远程请求位。0,数据帧;1, 远程帧;
8 i6 x! E0 N/ A& h
" h! @8 }' V6 B# R- ySRR,替代远程请求位。设置为1(隐性电平);
8 r: u2 Q% H- `4 h0 E" Z/ H$ N# I
IDE,标识符选择位。0,标准标识符;1,扩展标识符;
% ^0 ]& p4 j! U& z# J
: u% X  l5 w8 Z! x2 cr0,r1:保留位。必须以显现电平发送,但是接收可以是隐性电平。
1 n) M8 n: p9 ^0 l) `8 R  ^0 A' {4 c% C' C9 }4 X
DLC:数据长度码。0~8,表示发送/接收的数据长度(字节)。
6 i7 {# r( J% K7 F- U  T% X/ w7 n2 p
IDE,标识符选择位。0,标准标识符;1,扩展标识符;0 E* k& C3 `% E$ [# l# d

2 Q# A& G5 {# L' O
% V; J# k+ O: n5 Z9 j4 X. h
$ Y6 L: o$ }: j. ^9 R0 l位时序分解
' J' e2 S$ S# B9 J$ i1 T( O3 P

' ~  C( Y: u' s) V为了实现位同步,CAN协议把每一个数据位的时序分解成SS段、PTS段、PBS1段、PBS2段,这四段的长度加起来即为一个CAN数据位的长度。分解后最小的时间单位是Tq,而一个完整的位由8~25个Tq组成。
' p1 G, E' I$ C9 Q
3 }6 v1 v' i7 \1 } $%EJZSSO{4ANCBIWX8BT3@L.png
  H( x0 A9 @% ]: ]- x2 \$ G* s2 g. W: p
1 n3 S6 z4 Z/ `! n7 M' S4 C
7 `* X' s2 X0 z  ^, o) r% [* T
STM32中的CAN接口
4 i7 h+ v" `  M2 [3 `7 B! V, T# \
. Q, y- e7 N! Q8 f8 Z7 {STM32的芯片中具有bxCAN控制器 (Basic Extended CAN),它支持CAN协议2.0A和2.0B标准。该CAN控制器支持最高的通讯速率为1Mb/s;可以自动地接收和发送CAN报文,支持使用标准ID和扩展ID的报文;外设中具有3个发送邮箱,发送报文的优先级可以使用软件控制,还可以记录发送的时间;具有2个3级深度的接收FIFO,可使用过滤功能只接收或不接收某些ID号的报文;可配置成自动重发;不支持使用DMA进行数据收发。
& Z6 {4 c% G2 p' \
/ ~" ], R3 w5 M, R I@749X1@25IBIKX8HHSFJ)Q.png % X: t7 \/ `2 D

  @) T- \4 N) D1. CAN控制内核+ q" Z( \* B4 M& C" o  I
2. CAN发送邮箱
6 ~* D9 O  u* a( L5 b3. CAN接收FIFO/ {. l( m  |3 [
4. 验收筛选器
5 z( Q1 `0 y. _2 Q! n7 c, V! |; Y
STM32有两组CAN控制器,其中CAN1是主设备,框图中的“存储访问控制器”是由CAN1控制的,CAN2无法直接访问存储区域,所以使用CAN2的时候必须使能CAN1外设的时钟。
% y+ D. p' m0 C4 ~2 c1 S# S0 i* j. i9 `5 ]$ {# H% Z$ o
STM32至少配备一个bxCAN(basic extend can )控制器,支持2.0A和2.0B协议,最高数据传输速率可达1M bps,支持11位标准帧格式和29位扩展帧格式的接收和发送,具备三个发送邮箱和两个接收FIFO,此wa此外还有三级可编程滤波器,STM32的bxCAN非常适应CAN总线网络y网络应用发展需求,其主要主要特征如下 :
$ R2 \" _1 |* S* ~: {
9 ]+ d2 Y  \4 W  w* 支持CAN协议2.0A和2.0B主动模式5 v5 d2 Y0 L* E
* 波特率最高可达1Mbps4 t3 q' L5 f  Q2 E
* 支持时间触发通讯功能
( j+ ?: ]7 C9 y% C/ k* ]: a. ]
: K) h! F* ]- y+ Y2 o$ D数据发送特性:具备三个发送邮箱;发送报文的优先级可以通过软件配置,可记录发送时间的时间戳。
  ?$ n. u9 K! w; M: J& e3 W$ J9 Q
& ]5 W1 a- U. |& G; S$ J数据接收特性:具备三级深度和两个接收FIFO;具备可变的过滤器组,具备可编程标识符列表,可配置FIFO溢出处理方式,记录接收时间的时间戳
) `4 l6 x8 I) B, g4 x9 c1 H/ ?
1 Y+ G  ?' B7 k7 m报文管理:中断可屏蔽;邮箱单独占有一块地址空间,便于提高软件效率。6 X$ @* |* W1 x6 u3 e2 b
) m; U, Q; l6 e$ d6 g# U* ?
本文的实验设计将利用STM32 的bxCAN控制器的环回工作模式,实现bxCAN控制器的自收发过程,并使用串口设备跟踪监视数据收发情况。6 V% o/ `. v( H7 `4 O
+ i* s8 v  Q  G& v
程序流程如下图

4 d2 X/ o, p& X' V5 ?. c6 }+ j9 Z
! B' P7 r( K8 ^# q O5OHNBE3)4RR3)7H)TCQZ2C.png # q: Q/ h2 |; S8 F6 K6 c) l2 s

8 o7 |0 r0 `/ I# ]" q- T5 V( ^本程序设计主要围绕bxCAN控制器的初始化初始化配置展开,其要点罗列如下:
. v7 C" b* O; K9 o* O# u7 u  I! d' P2 a  l  _" e- N
1. 初始化RCC寄存器,配置PLL输出72MHZ时钟,APB1总线频率为36MHZ,分别打开CAN,GPIO和USART1的设备时钟。
7 t/ J* l2 M* K' s0 Y  E2. 设置CAN的Tx引脚(即PA12)为复用推挽模式,并设置Rx引脚(即PA1)为上拉输入模式,其中三个重要的参数如下配置:
# c2 T4 Z8 j0 A% l3 ]% G% P+ b6 Q" L
  1. CAN_InitStructure.CAN_SJW配置为CAN_SJW_1tq;1 p) L7 R9 G0 I' X$ ]
  2. CAN_InitStructure.CAN_BS1配置为CAN_BS1_8tq;2 \( z7 I4 ?. Z8 c# w
  3. CAN_InitStructure.CAN_BS2配置为CAN_BS2_7tq;
复制代码
! `6 B) B8 r6 l
3. 最后分频数配置为5,配置接受接受缓冲区标识符为0x00AA0000,配置过滤器为32位屏蔽位模式,过滤器屏蔽标识符为0x00FF0000.+ m# Z0 @( [# O4 r0 X* Q# d
4. 初始化USART设备% o2 X# P9 I1 Y
5. 使用扩展帧shu帧数据格式,ID为0xAA,数据长度长度为8! y6 g1 V& ?7 h+ D; V
7 y* H: j+ h5 p  C
# I# S( W# k( H3 L# R) c
STM32的CAN控制器设计的重点集中在CAN寄存器组的初始化过程中,而CAN初始化的重点在于波特率的设置,过滤器的设置和位时序的设置,以下作详细叙述。
! P  S6 C7 ^1 c1 |- r3 P, o8 Z# \% J
(1)CAN波特率的计算

8 Y: i  G% w7 b: w, W
- z" _+ g, y- S/ f2 M5 R' `# k计算波特率是任何一种总线的zhon重要内容之一,CAN总线也不例外.从STM32微控制器的官方参考手册里可以查找到关于CAN波特率的计算公式如下." @0 V7 x# v" i' k
5 c6 ~0 S( b+ Y6 O" ]" d3 K- r
通过配置位时序寄存器CAN_BTR的TS1[3:0]及TS2[2:0]寄存器位设定BS1及BS2段的长度后,就可以确定每个CAN数据位的时间:. X  z' p) ~  v* \4 A" t  p9 b3 u. c
. c2 e3 Y* R" ]& T8 {; L/ ]+ S$ a
BS1段时间:
: |! C. `% i: s5 H, R6 A1 a6 e# w8 ?
T S1 =Tq x (TS1[3:0] + 1),
5 M* O" `9 G1 `, O( o# V3 ?9 R# R5 f# x  n) P' v4 F
BS2段时间:+ O7 j: [! l2 @$ T, p% {. \
7 g6 d1 h. ^2 E* o! h( a
T S2 = Tq x (TS2[2:0] + 1),
% t5 J3 z+ p5 w! c! b4 I% D! S
! d  Z( J+ x! F+ g2 x  f6 \" Z  w一个数据位的时间:9 o* k1 U) W. O4 f( d
6 B: C# g; R: Z' n' o5 i
T 1bit =1Tq+T S1 +T S2 =1+ (TS1[3:0] + 1)+ (TS2[2:0] + 1)= N Tq* i0 ~* t3 v5 w- L

5 K4 H7 D+ Y6 a, y% U1 l其中单个时间片的长度Tq与CAN外设的所挂载的时钟总线及分频器配置有关,CAN1和CAN2外设都是挂载在APB1总线上的,而位时序寄存器CAN_BTR中的BRP[9:0]寄存器位可以设置CAN外设时钟的分频值 ,所以:& ?( C  |9 f/ e: |$ P0 g
4 q5 V! {4 j7 T5 u
Tq = (BRP[9:0]+1) x T PCLK
: `2 z( M; |" ?( i3 A
! D  F. X1 I4 l3 V0 K% `其中的PCLK指APB1时钟,默认值为36MHz。% z1 m; a0 x) R# ]

: s% N' ?% p; {  a2 ^* i最终可以计算出CAN通讯的波特率:
( a, Q- C) ]1 v* p& Q" [2 Y  e' V) R$ a
BaudRate = 1/N Tq
# K0 W5 t  `: p( C4 n
; ^& {  e* y9 K& o  T程序设计要点中强调的三个重要参数,其实是can总线物理层中所要求的位时序。共三个阶段,分别为SJW,BS1和BS2阶段,这三个阶段的时间长度都是以长度为tq的时间单元为单位的。这样可以逐步计算出CAN总线的波特率。因此要点提示中所要求的参数,实际上将CAN的波特率设置为450kdps。: o" B. i; N8 d- V( E

$ Y$ D+ p4 }/ E8 Y8 o% P  R# y! b- K( {" g% X0 d2 N# Z
过滤器的设置' J: q3 y! U) k8 j- J3 j

! c  h2 k4 ~8 \3 q% j. \/ T+ R" Q8 ?0 ?can总线没有所谓地址的概念。总线上的每个报文都可以被各个节点接收。这是一种典型的广播式网络。在实际应用中。某个节点往往只希望接收到特定类型的数据, 这就要借助过滤器来实现。顾名思义,过滤器的作用就是把节点不希望接收到的数据过滤掉。只将希望接收到的数据给予通行。6 Q  D9 m& p2 T6 s8 l

8 o! ~, O/ [  I5 w- s7 }stm32的CAN控制器,提供14个过滤器。可以设置为屏蔽模式和列表模式对can总线上的报文进行过滤。当节点希望接收到一种报文时。可以用屏蔽位模式对can总线上的报文进行过滤。反之,当节点希望接受到单一类型报文时。则应该配置为列表模式。本机程序中使用了32位的屏蔽位模式。) k, w" F; ^: ^% D' |
& p8 R+ b- \7 H: g, s
下面仅对这种模式进行解析。can控制器的每个过滤器都具备一个寄存器。称为屏蔽寄存器。其中标识符寄存器的每一位都有屏蔽寄存器的每一位所对应。事实上,这也对应着can数据。事实上,这也对应着看标准数据帧中的标识符段。
3 \, N8 H+ l) P( ^' O1 W* B7 ]1 c+ q4 E2 F; G
如下图所示。8 Q. @- g: R* Q3 x
0 l) o* }/ b% a$ D% U
3UR1U_CIM76FNU6]M9T0L98.png
8 @. M, ]0 m0 z0 Q- Q  p1 j
0 p6 ~4 E/ `% X1 r2 Z6 t" E. ]此处重点在于屏蔽寄存器的作用。通过查阅stm32微控制器参考文档可以知道。当过滤器工作在屏蔽模式下时。屏蔽寄存器被置为1的每一位都要求can接收到的数据帧标识符段必须和对应的接收缓冲区标识位相同。否则予以滤除。以本程序为例。要点中要求将节点接收缓冲标识符配置为0x00AA0000。过滤器屏蔽标识符为0x00FF0000。' L2 b" \- h2 o* J8 s6 y  R# X

  b, q* M# ~' z该节点接收到的数据帧的标识符段的位[23:16],必须和接收缓冲区标识符中的[23:16]匹配。否则予以滤除。但若满足了这一条件而即便如下的位不匹配。则该数据帧仍不会被滤除。正如本程序而言。即can接口仅仅接收标识符段的位[23:16]为0xAA的数据帧.: \; S; Y4 j4 K8 M

: o# @+ v2 B' R( y根据can总线物理层的要求。can总线的波特率和传输距离成反比关系。传输距离变化时,要根据位时序来调整can总线的波特率。
7 N  O- {) p$ g& B
' o* [& U0 I1 { E7CX_M101NWMIP139GWWRCF.png
9 v. X% i% p/ A) B) l+ K% k4 l3 J7 k3 j+ {( l) a- y
程序代码如下:
: g, i. ^3 L! n6 S$ m
  1. void RCC_Config(void)) q5 M8 T8 e' e2 j2 r( X; X
  2. {1 S6 w  W  Z4 X% g. L( {3 T  \
  3. ! A6 {' E, v- C7 T
  4. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE)4 _, L# Z8 V0 o* e2 W
  5. ! C* x1 w" U; m' c8 \
  6. RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE). H% e* H, }* [( T; z+ a
  7. 4 c' z+ P! h3 w" G+ g
  8. }
    4 g7 g! x3 k6 t. U. {- K% B* Z7 Q! e
  9. void GPIO_for_can_and_uart_Config(void)
    ( |) v: T' O0 w
  10. {& T) y% [* t/ G# ^" S2 B8 h0 s- D& j
  11. /*定义一个GPIO_InitTypeDef类型的结构体*/
    4 U% F  a. |/ X7 F0 K% I
  12. GPIO_InitTypeDef GPIO_InitStructure;
    ' _3 p8 i3 R5 l$ i

  13. 3 [7 L4 ^4 u6 d, n9 e

  14. # J1 v! O3 M8 m( H+ @
  15. /*设置can的RX--pa.11引脚*/
    ! C* a% o( O( n- O8 l; g- U
  16. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    : [2 V/ b( O! a) R& @
  17. ! y. [; J8 h5 B! q) S; s
  18. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    0 W* K( G9 e3 T; N

  19. 9 ?/ D& Z) E: b$ J
  20. GPIO_Init(GPIOA, &GPIO_InitStructure);
    : |" ^- |; U5 f7 L  z( K
  21. 8 v, h0 G( m5 u$ F! B, M4 [
  22. /*设置can的TX--pa.12引脚*/
    ! J( q1 n3 N* a7 J9 |
  23. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    ! z4 c4 a6 [/ S5 x/ v' V
  24. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    , A! S: h4 _9 Y/ X
  25. GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;# n) l3 w. |4 X) l6 W
  26. GPIO_Init(GPIOA, &GPIO_InitStructure);6 H! P' H7 C/ i, j
  27. /*设置usart1 的RX 脚 -PA.10为父浮空输入脚*/0 {4 M" X! ?$ i  p
  28. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    + _# V0 E/ M# S, k
  29. ! E* T% V: C& @' |$ @/ |3 v
  30. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    5 ]  J0 A' p& a! O/ L; _
  31. & U7 _- W9 P) ?7 ^8 u. n
  32. GPIO_Init(GPIOA, &GPIO_InitStructure);
    8 j1 n9 O) `5 u* G
  33. - n6 y# h" X" I
  34. - u. \2 J6 d" D/ y2 J
  35. 8 n' W. ^; }+ M& h$ r( E; ?' J

  36. # W9 k: h1 M! M  Y' V2 w. F
  37. }2 s5 e: P5 \! o$ s9 ?  q0 p

  38. 0 S$ Z; P) C, @& \6 U( D
  39. void Can_Config(void)* K" x/ t- t, |3 F$ j( D
  40. {
    . Q- H* u" W& k9 {
  41. CAN_InitTypeDef          CAN_InitStructure;
    , M: b  h! Z9 r! Z" L) H7 ^
  42. CAN_FilterInitTypeDef  CAN_FilterInitStructure;' H' C3 g" b" h. }% q

  43. ; u1 }8 ?( V2 L- H0 _4 s7 n$ Z6 D
  44. CAN_DeInit(CAN1);( S& V7 z' a5 j

  45. 5 s& U- o  K# f3 ?# X% K
  46. CAN_StructInit(&CAN_InitStructure);9 _( l# p9 x  k. V2 R  d% h
  47. CAN_InitStructure.CAN_TTCM=DISABLE;
    * D8 w' s6 z% G4 r$ i1 ~0 y7 B1 W
  48. CAN_InitStructure.CAN_ABOM=DISABLE;
    1 h  S& {1 {$ Y  c/ L9 s
  49. CAN_InitStructure.CAN_AWUM=DISABLE;
    0 ]4 H( b# Q  [9 k6 i" L
  50. CAN_InitStructure.CAN_NART=DISABLE;
    - \9 E% W4 h( Q% I. P6 ]8 c
  51. CAN_InitStructure.CAN_RFIM=DISABLE;$ k9 O4 C3 q& I: r8 `* o+ i& a+ w5 E
  52. CAN_InitStructure.CAN_TXFP=DISABLE;) H$ G) h6 \! E' f) T3 b- x* q; X% \4 y

  53. $ r( `( H9 K; v4 o
  54. CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack;
    : w0 _. |6 P' ]! k8 o1 o5 i7 @9 \
  55. CAN_InitStructure.CAN_SJW=CAN_SJW_1tq;2 U$ ]1 G- c! H
  56. CAN_InitStructure.CAN_BS1=CAN_BS1_8tq;5 c( W5 L  c+ h9 n# ^) l% o3 {6 z, l( d
  57. CAN_InitStructure.CAN_BS2=CAN_BS2_7tq;
    # A* c& V9 N* t7 L9 ^3 A

  58. 5 g0 N: H" S8 h7 w
  59. CAN_InitStructure.CAN_Prescaler=5;* h0 p/ }' _; Z7 @/ W
  60. CAN_Init(CAN1,&CAN_InitStructure);1 R3 x" F) J- ]8 P% j

  61.   @  z# b& c% s; j
  62. CAN_FilterInitStructure.CAN_FilterNumber=0;
    7 r" V# X. j" e2 z4 S; Q
  63. CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
    * |, a7 S& z) G/ e0 ~1 i
  64. CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;3 u- n3 t2 q6 h% Z9 ^8 M. }
  65. CAN_FilterInitStructure.CAN_FilterIdHigh=0x00AA<<3;
    3 l' s+ l, d  c, O+ z. d$ Q/ I5 U1 k
  66. CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;* Z1 Z" Y3 i. M  D9 s, S
  67. CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x00FF<<3;4 ?. B( O" R% e# i+ t5 W% d$ v8 i
  68. CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
    ; H  h# ]7 L) H( R: t
  69. CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
    % \* D- i) `( U8 A* W2 o  L
  70. CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
    0 v5 i! f* m3 v
  71. CAN_FilterInit(&CAN_FilterInitStructure);
    6 N5 h4 V8 T( j& H
  72. ( e6 _. a- N$ I/ A8 m" v
  73. }
    8 m" x# g7 E/ e1 B, m) Q

  74. + C1 ^6 v$ O( u  X$ K+ d0 {
  75. void main(void)
    & }; O8 |1 ~9 T) b# G
  76. {
    ' F6 k6 e& ~) W6 S
  77. u8 TransmitMailbox=0;4 G" ~2 F( r2 {& v9 \
  78. CanTxMsg   TxMessage;
    # U5 i. x( P$ m# B+ @9 V
  79. CanRxMsg   RxMessage;" c/ I1 T4 _& Z2 z
  80. RCC_Config();
    $ v$ q5 `- {2 }+ x  X
  81. GPIO_for_can_and_uart_Config();
    . \6 b$ e, u1 Z: }2 O4 S1 w
  82. USART_Config();
    ! k, V3 b( r- [' E2 p7 g
  83. Can_Config();
    4 n* T+ K  f7 p! S

  84. 5 b: [/ p8 g- x+ `, d4 ]# q
  85. TxMessage.ExtId=0x00aa0000;
    ) }) N7 c' H" c8 v/ |
  86. TxMessage.RTR=CAN_RTR_Data;  {" [* Y& D- _' i8 j
  87. TxMessage.IDE=CAN_ID_EXT;0 X2 ~) M6 k$ t& ^& E
  88. TxMessage.DLC=8;' g3 y3 t/ i; c. i, q
  89. TxMessage.Data[0]=0x00;  O$ O5 m+ _+ I* b
  90. TxMessage.Data[1]=0x12;3 {- ?8 `' J8 F6 z9 h
  91. TxMessage.Data[2]=0x34;" p1 {8 f1 a1 _1 q( R
  92. TxMessage.Data[3]=0x56;% C" c$ ]$ v9 x5 o7 H- j1 Y2 S
  93. TxMessage.Data[4]=0x78;
    5 w) d) X- _0 m- r1 D% I
  94. TxMessage.Data[5]=0xab;
    4 n# j6 `: S, j& ~) S# H3 T* N# ^
  95. TxMessage.Data[6]=0xcd;) H" l( O* r9 P
  96. TxMessage.Data[7]=0xef;
    4 a  b" c5 E7 f2 M5 S" ~& f" p
  97. . a6 L1 {! T4 B, o' i
  98. TransmitMailbox=CAN_Transmit(CAN1,&TxMessage);$ n  Z: N& ]# Q' @/ U
  99. while((CAN_TransmitStatus(CAN1,TransmitMailbox))!=CANTXOK);
    / H9 K* |3 x% D6 ~7 _9 p6 e
  100. printf("rnThe CAN has send data :0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,rn",
    4 u+ g4 o4 v4 g. m' E
  101. TxMessage.Data[0],TxMessage.Data[1],TxMessage.Data[2],TxMessage.Data[3],
    : x; H  b4 M7 H/ R
  102. TxMessage.Data[4],TxMessage.Data[5],TxMessage.Data[6],TxMessage.Data[7],);, }0 u: Z' l! M9 O) v- X# L

  103. * C0 J2 d% V5 I, Q4 g' Y
  104. while((CAN_MessagePending(CAN1,CAN_FIFO0)==0));, w4 O+ e0 A, m; s% n: @

  105. & ^2 {9 f# r% X3 F
  106. RxMessage.StdId=0x00;. b& g% a' g# e4 J- @" H& A  G
  107. RxMessage.IDE=CAN_ID_EXT;0 e/ t" h. A+ j- v2 p
  108. RxMessage.DLC=0;
    3 r8 w) I4 f  }' c1 v3 M# v
  109. RxMessage.Data[0]=0x00;
    ( _' _+ l  @( R: }1 f9 L
  110. RxMessage.Data[1]=0x12;
    : f% @0 |$ |& x7 L+ T5 y: _6 ^
  111. RxMessage.Data[2]=0x34;
    , ?: |; y/ \) I6 T9 J9 T
  112. RxMessage.Data[3]=0x56;
    4 \# i% e& H% R5 s/ [8 y
  113. RxMessage.Data[4]=0x78;
    * Y1 Z8 C' P" @$ j6 ^( h" M
  114. RxMessage.Data[5]=0xab;
    / f$ ^) r! R1 c9 J& K- G- E
  115. RxMessage.Data[6]=0xcd;
    7 ^) N  I1 h% q: C
  116. RxMessage.Data[7]=0xef;
    5 Q2 o0 A- l% ~

  117. ! X  `) f/ _8 L& E. s& X' A
  118. CAN_Receive(CAN1,CAN_FIFO0,&RxMessage);5 R: [/ m, e2 S  @; n+ ]/ b- v0 S
  119. printf("rnThe CAN has received data :0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,rn",
    2 M9 f5 y( M% x
  120. RxMessage.Data[0],RxMessage.Data[1],RxMessage.Data[2],RxMessage.Data[3],
    9 I; z# y8 O$ g  a  M  L' p
  121. RxMessage.Data[4],RxMessage.Data[5],RxMessage.Data[6],RxMessage.Data[7],);6 ?' e/ V) Q6 u! p" F- i# W" L# e* }' l
  122. while(1);
    0 }' j3 N  g& @; F7 b+ S. e) A

  123. : ^* A8 K3 S4 V# m$ u! i

  124. . l; D: k9 W6 B, S
  125. }
复制代码

7 d8 y' k% C9 I+ w" X0 S- @4 D  O) N0 g. c$ D8 ~1 T; x$ m- V

9 d" v" v9 C+ i+ c
收藏 评论0 发布时间:2022-3-16 21:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版