一、CAN总线通信 发送# R# I/ D. I0 Z# i/ J$ `, h- Z. s
1. CAN总线通信发送配置流程+ i) X- z" ^. q6 V$ @! c+ T- {
1.写入标识符" Q; O9 {* ^& u$ w) a6 q$ h
2.写入标识符类型(标准帧/扩展帧)" r8 J4 S! n$ U/ u
3.写入帧类型(远程帧/数据帧)0 L( s9 b: g7 O5 l! [% L3 ]
4.写入数据长度
* t7 k+ r7 C8 J V5.写入数据9 C/ \- c, o% |7 ?* R2 z
6.发送数据- s' v& v" }) e- {/ x
2. CAN总线通信发送相关库函数! L1 b& N% K# D& S4 N
发送数据结构体:
3 N. F' O. _, R3 n: U9 U& F: H& ]0 ]# R+ @
- typedef struct) e) P' o. A/ c. Q! A& I( |4 u8 W W
- {4 U3 n% e" n: F' D, k
- uint32_t StdId; /*!<指定标准标识符6 ~% S* F: T9 n9 Q B! f6 x
- 该参数可以是0到0x7FF之间的值,11位数据 */
) E z4 Q) a5 j8 ]" R3 ~
/ R6 j# n# m3 _: ] j# l- uint32_t ExtId; /*!< 指定扩展标识符
" p7 r; d" g: J) v - 该参数可以是0到0x1FFFFFFF之间的值,29位数据 */' _: e# A3 d+ o% _
- ' J! z4 _/ z: |
- uint8_t IDE; /*!< 指定要传输的消息的标识符类型
/ _% q" i7 A: N9 l; w - 标准帧:CAN_ID_STD, i/ |" P( `" q' B$ S% y
- 扩展帧:CAN_ID_EXT */
' u$ B% P+ W/ G) h& |% s+ J
4 S$ R" ^$ z l1 Z$ m- uint8_t RTR; /*!< 指定要传输的消息的帧类型3 ^/ ], U. W1 E. H2 s( @- a: U
- 数据帧:CAN_RTR_DATA/ ]) G7 H- e" ^1 B8 v
- 远程帧:CAN_RTR_REMOTE */
% ^6 @* {; L6 Z* V C2 e: s - & A W6 o3 i& P, O! `
- uint8_t DLC; /*!< 指定将要传输的帧的长度。0 U3 a/ s( u& i! B
- 取值范围为0 ~ 8 */3 v. Q9 l% F& ?! `' z! d5 X
- , q; i: j; W% U+ K) @1 }$ \
- uint8_t Data[8]; /*!< 包含要传输的数据。
+ ?9 i8 ?% _" I- ?9 c& Z n1 t4 r - 取值范围是0 ~ 0xFF */* j+ V- J# l1 y: ~9 ]' m: [
- } CanTxMsg;
复制代码 8 q9 j- Z$ h% b. I6 j/ |7 J$ e* H4 }
发送库函数:
0 f1 d# }9 M! D. w% \+ _
2 R: g% w7 r3 C8 q- /**
2 p+ C4 D' |$ M* E - * @brief Initiates the transmission of a message.+ A# k1 ]. {9 r
- * @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
& w1 ?# N* o: |7 u @+ P - * @param TxMessage: pointer to a structure which contains CAN Id, CAN2 U/ E& K5 H, O
- * DLC and CAN data." K1 b# U: C- t7 B$ u
- * @retval The number of the mailbox that is used for transmission
5 Z; Y+ ~$ R# N. g A - * or CAN_TxStatus_NoMailBox if there is no empty mailbox.% j R) z% Z; g" b
- */
) }# b' Y+ ^; R$ S6 x
6 ]/ ~7 T p- e1 k& W v& I- uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage);
复制代码 4 M- c4 Z i' E J
3.CAN总线通信发送程序8 \5 I9 D7 B' e' v! x& d, p
标准帧具体代码如下:) [- D6 X, f# V) m4 f3 v. A! n
) f5 j; F" c, e! w2 v8 D* Q! n
- CanTxMsg TxMessage; //定义结构体变量1 N- n/ {6 |, e6 Z b3 R$ x( U# e
- /* 发送数据*/* I: b9 u+ M) ^ R: B2 W0 F
- void CAN_TX(void)# N0 {4 A; W' T5 i" x
- { : y* u; w- ?8 R8 F! ?
- TxMessage.StdId=0x01; //标准标识符为0x01
/ @* w/ f" w/ m9 ]( f, L: t( ^: M6 m - TxMessage.IDE=CAN_ID_STD; //使用标准标识符 CAN_ID_STD
; \3 F" P: O$ t. h% m- i" i8 _0 A - TxMessage.RTR=CAN_RTR_DATA; //为数据帧
6 h5 ^3 l# Z+ |! g# {; O. i - TxMessage.DLC=0x08; //消息的数据长度为8个字节
# j) P. Z3 S. R, E# e - TxMessage.Data[0]=0x01; //第1个字节数据
' F; p9 G- c, ~* A$ ?3 _7 h" n - TxMessage.Data[1]=0x02; //第2个字节数据
8 I. R9 Y( B- ^6 i" ?( t5 Y' n2 _8 U - TxMessage.Data[2]=0x03; //第3个字节数据
( T1 q8 ?! ^2 I2 \; {/ _. N - TxMessage.Data[3]=0x04; //第4个字节数据 n: O ?( ?! A" U- o& u, l
- TxMessage.Data[4]=0x05; //第5个字节数据
1 g7 Z9 a: I& V2 B& z& ~8 c4 s3 Y - TxMessage.Data[5]=0x06; //第6个字节数据
5 T% B- @2 V! J- j2 E" P/ P) z - TxMessage.Data[6]=0x07; //第7个字节数据
7 }5 q) R1 K; {- E* f - TxMessage.Data[7]=0x08; //第8个字节数据
0 d7 h( E6 f. E6 A* @ - CAN_Transmit(CAN1, &TxMessage); //发送数据
6 ]6 ^3 t% V2 X9 Q3 w - }
复制代码
4 u9 x2 ^ ~% L. Z- v' Y扩展帧具体代码如下:' d- r' Z1 W* u n. g$ o9 s9 W
0 ]( \. ~1 A3 \2 }3 B
- CanTxMsg TxMessage; //定义结构体变量- Z) |2 M9 |5 \' N
- /* 发送两个字节的数据*/ X% j7 @* v3 ~; ]
- void CAN_TX(void)7 I( E# W0 Z6 W6 N, g
- { / S6 P! o# D* M- Q9 H& k
$ C" O5 q/ `; T9 F8 [) D- TxMessage.ExtId=0x1FFFFFFF; //扩展标识符 0x1FFFFFFF
5 x, N/ u9 r& Q4 s - TxMessage.IDE=CAN_ID_EXT; //使用标准标识符 CAN_ID_EXT ! @% c- w6 H$ |- U) E
- TxMessage.RTR=CAN_RTR_DATA; //为数据帧
+ U8 p: ]7 X5 X) _ - TxMessage.DLC=0x08; //消息的数据长度为8个字节5 L- M1 _2 L# y
- TxMessage.Data[0]=0x01; //第1个字节数据 2 `4 r: V E* D. Y* o0 c# w
- TxMessage.Data[1]=0x02; //第2个字节数据 w) [' A6 u: [
- TxMessage.Data[2]=0x03; //第3个字节数据 % P u9 Q0 L0 E+ x {# F, m
- TxMessage.Data[3]=0x04; //第4个字节数据 ; W* n0 d3 U0 |- O) G
- TxMessage.Data[4]=0x05; //第5个字节数据
0 e" j# r1 p, r7 r" F7 l - TxMessage.Data[5]=0x06; //第6个字节数据 + ^( u- U# y* y
- TxMessage.Data[6]=0x07; //第7个字节数据
& S( M, \% c4 z) u* B, m* B - TxMessage.Data[7]=0x08; //第8个字节数据
0 t, ?' y' ~& P' }! q7 V - CAN_Transmit(CAN1, &TxMessage); //发送数据
- G' k2 m$ J: ` - }
复制代码
) k+ V* S0 _+ C$ \) \( x/ a. m$ n& r二、CAN总线通信 接收) I- B8 R" D1 m! \. b! }! a
1. CAN总线通信接收配置流程. X0 H% Q$ Z9 B; ^2 }7 e: r
进入CAN总线接收中断/ k8 j( g. o! p
CAN总线接收库函数接收数据' ?, A8 W' @2 X& |" o. P2 J2 w
解析接收数据
^# g8 A- H7 o. A实现对应功能
* @5 F @+ h" g+ e. W: I
& P) `1 v; E% \ }3 L9 x2. CAN总线通信接收相关库函数0 |- I8 H1 F( g# y( |; N
接收数据结构体:
, i: A% P/ R3 V& \. W
3 f3 X, J2 s' @& i6 x3 E9 Q- typedef struct
" i$ Y' l/ m" p2 d4 P' _# ?5 y3 Y - {
3 C- x) Z. U0 [$ O% ]9 r; V; ^- P - uint32_t StdId; /*!<指定标准标识符
- R) l+ M6 K! R* @9 I1 ^' f - 该参数可以是0到0x7FF之间的值 */
' t5 k( ^4 a0 T3 ~0 ]6 E3 {
, L3 `0 i, M S U& W0 R% B2 v- uint32_t ExtId; /*!< 指定扩展标识符
4 I: B3 _/ T% j* Z - 该参数可以是0到0x1FFFFFFF之间的值 */
4 s' s! [& j$ w* j8 g. `! Q- P
1 W4 R7 h6 h, J1 o0 c- uint8_t IDE; /*!< 指定要传输的消息的标识符类型# ]( a8 K2 x8 k4 b' g
- 标准帧:CAN_ID_STD
( T: O- l" b, j% t+ B - 扩展帧:CAN_ID_EXT */
{" {) V, P/ Y) _' ` - ' P1 w* g4 W' l, s: K+ r6 M5 @' P: T
- uint8_t RTR; /*!< 指定要传输的消息的帧类型
! Y1 y2 [% R1 l* O! }1 N. |* @ - 数据帧:CAN_RTR_DATA0 W7 S" r4 p1 F
- 远程帧:CAN_RTR_REMOTE */
1 k+ f" ?2 Z, T }9 {8 D
, u, I5 O% [9 t. X- uint8_t DLC; /*!< 指定将要传输的帧的长度。
& z1 k$ v E2 h Y" Q- v9 U - 取值范围为0 ~ 8 */
6 Q# g" G+ u& t# [
/ a: E5 B1 E6 M: ]2 x1 }1 `- uint8_t Data[8]; /*!< 包含要传输的数据。
2 S8 v# n) C, I0 ? - 取值范围是0 ~ 0xFF *// w- J2 G% v5 p- f9 Q. o: e
-
& U- o" p G' ?. ^" u. k" y' e - uint8_t FMI; /*!< 指定存储在邮箱中的消息所经过的筛选器的索引
* w, b' _' n' H: s- N& q1 [% S - 该参数可以是0到0xFF之间的值 */: D4 s, x, f. x2 X
- } CanRxMsg;
复制代码
4 L/ B% V/ F$ ?7 k接收库函数:
+ E# s2 `' j2 s3 @3 _
0 M+ D9 r3 J" }. _! D8 d- /**
. L# D* V# l/ _# R3 e9 T - * @brief Receives a message.
# C( W \/ x: p. e+ G: R- S - * @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
% F1 P) S9 K% O4 e% p - * @param FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1.' i; @' f: C6 p5 s# w5 l0 B( h
- * @param RxMessage: pointer to a structure receive message which contains 8 O! M6 I) B0 r/ [' _
- * CAN Id, CAN DLC, CAN datas and FMI number.
0 a& o& _5 c+ R2 Z - * @retval None.
+ }) H | h; R+ E - */
! n+ O7 B4 w0 n0 F# i - void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage);
复制代码
8 r3 F% b, d7 w3. CAN总线通信接收程序
0 U7 W& K! v. X' B标准帧:
- H: O% r$ G3 g. Q9 s, ]% ~& h" Q具体代码如下:
" u' f9 |" G; s6 t2 h. h# G8 |7 j- R" S' ]
) k/ H. Q. B" Y. q$ F: x- CanRxMsg RxMessage;//定义结构体变量
j* V) h2 \- u6 r' I1 Q& _ - //接收中断( R# x N2 X& G- c6 v
- void USB_LP_CAN1_RX0_IRQHandler(void)7 ^3 e* H* P( `& t( j( ]7 ~" g
- {
|. W/ P* P# C; f - CAN_Receive(CAN1, CAN_FIFO0, &RxMessage); //接收FIFO0中的数据
4 M% W" `+ ?- Y8 b+ o - get_data(&RxMessage); //接收数据处理函数- y8 _% O% h u( ? R% Z
- } ( e1 t/ A8 L- w! Z' ~" N+ u: m
- //接收数据处理函数4 D7 G! s' @2 u' ]* g; x& W8 p
- void get_data(CanRxMsg* rxMsg)
4 k( b0 Y; f( ], i6 K' Y+ Z* u% o - { F9 \9 f/ v1 k- X& L5 i @8 z& k
- switch(rxMsg->StdId) //判断标准帧标识符) Z2 _4 s, u" u' }
- {; u1 q7 ?1 t3 Y
- case 0x001: ! {2 R4 P) m0 G4 T' o
- //要实现的功能
5 ]2 U" k' p" A& \( y' k* p# ~* j - break;9 E& C& n8 R: u! f' A
- /*: x9 x" w& K: c% d9 ?/ X6 l
- *8 }- b* |! k9 X7 [
- 其他标识未列出
2 ~; `1 I. z* { k2 l - */
( {" O! H5 l8 [, b - case 0x7ff:
; Q$ S$ L2 x% ?, `% U3 l5 M - //要实现的功能
( ?/ R8 }* U7 L) b C - break; & |2 ^. I" Q! d, T: Y( ` F
- default :
6 O6 A; N t5 E4 { - break;
( e9 K& F3 | l7 G& } - }
! N3 U/ @+ {' U5 F1 S3 S% u - }
复制代码 . W p' ~ q1 K( A5 `! ?" x
扩展帧:
5 E1 P, K8 X6 I# X" T具体代码如下:; ^8 N) U; J2 E& w# {+ u
! Z6 T! E) v' C1 ^) N0 g- CanRxMsg RxMessage;//定义结构体变量1 [5 g: u! Q: }2 q; l
- //接收中断1 V7 M$ U% ?# D5 g3 t
- void USB_LP_CAN1_RX0_IRQHandler(void)
1 S/ w7 U3 N6 p5 e' r2 c - { . |9 r0 h, |5 r! G+ Q2 B6 ~/ O' I
- CAN_Receive(CAN1, CAN_FIFO0, &RxMessage); //接收FIFO0中的数据 5 P" m$ f% A1 q7 O( |
- get_data(&RxMessage); //接收数据处理函数2 T9 A7 k& U: @* w6 T
- } 0 ^ W/ J9 d L& r* Y! n0 i, N
- //接收数据处理函数. r; I c1 [8 d; \
- void get_data(CanRxMsg* rxMsg)
( i; c; Z1 x5 H, v2 T# ^ - {: T+ m9 b& Z8 f1 ~& m" Q7 F5 Q0 m
- switch(rxMsg->ExtId) //判断扩展帧标识符# O# I) I- A6 g; O2 ]: E. x! R* ~- }
- {
4 t8 f6 p! ^; h - case 0x00000001: # `! ~: y5 L8 t2 R& Z! F" c& Q8 J
- //要实现的功能
) N+ }, ^: v2 u' Z - break;( P8 t2 g; W& s) D0 m
- /*
$ K: ~8 q, S0 G& g - *
% T' f8 p$ L+ [' Z; y0 x2 v- l7 F - 其他标识未列出: B6 t5 P. V E# C& V
- */ 1 f5 u! K& E) y& I5 N, t O3 B
- case 0x1FFFFFFF: ' h( n* k5 I( e K0 G6 N% n3 U+ t5 n
- //要实现的功能 l7 H1 d* w0 D8 B1 d
- break;
3 r7 h9 c2 g% z5 m) V3 v - default :
2 O; K5 G6 _1 e/ ]3 H( ] - break;; s% y. I$ n" M3 V! k" Z! h, u
- }
0 b: J5 E6 _ H$ \3 @" ?8 n - }
复制代码
' Y7 ^) S( Z. K' B' Z
3 M' d+ P* p$ V" d8 S0 s0 T5 k+ r& t- q9 g% B( l) U5 A
- U1 }7 Y4 Y, j9 t, L5 d2 g
7 c/ z$ W! z4 ` |