STM32F2-CAN通信-发送任意长度,调试好的,与大家分享- {. a$ \& X4 k9 v& y9 S- Q
/ C/ ]( e% X8 x( h; M8 o
- #include "include.h"7 W! `; W& }" P x" }
- //************************************************************************************************************************************************1 P7 f# a( a+ f" w5 m
- //20190611调试完成
+ V8 L W5 _, X: S. M - //By Wang
% E( Y8 [" O% r$ A& [& @: j - //************************************************************************************************************************************************, d- V; x& w( R3 A
' Z) B! {5 C$ G. `$ e: _' O B- CanRxMsg RxMessage;# N' w6 i2 G# Q3 t
- CanTxMsg TxMessage;
! V4 O2 G: t* E, }0 ~& L - //************************************************************************************************************************************************
8 l; c; o6 F! n. j4 r! h - //函数名:void NVIC_Config(void)
. W4 g& B! }7 g1 Q: Y - //功 能: CAN通信接收RX0中断配置/ M7 D0 Q; @- ^% M p$ \/ ?3 e3 a
- //参 数:无
2 w! b+ O# f0 W% \" i- D) U - //返回值:无& b* r* g6 T3 v1 r; V
- //************************************************************************************************************************************************
J$ U: Z' G9 o - 6 [0 x0 e6 `# F% h/ @
- void NVIC_Config(void)
% k$ f L2 b9 Y3 e/ ^6 L. H( l - {! M. b" Y6 ]7 }1 X6 X/ ^3 F( d
- NVIC_InitTypeDef NVIC_InitStructure;
0 a R% f I' P3 C$ Y - + K4 [) O8 }$ f3 O
- //#ifdef USE_CAN1
0 r% ?' m) y9 n
5 T8 V1 _$ g8 d6 R5 K: j$ `- NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;//与CAN1_RX1_IRQn;区别
3 P$ T6 a- {: p( n1 P0 J - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//不同的中断优先级一样会怎样0 O8 ^ k& C( G0 G) }6 T( f, v
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
* B+ A& Q% A! \; l4 X - 2 g! \# r. n( D) y$ r; {8 N
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
( S$ Q# H) ?, o; g9 H1 ~ - NVIC_Init(&NVIC_InitStructure);3 i9 X0 R, [& k/ z4 p, v
: \( v/ I# \$ \- }
t- b$ l/ F/ _% t& w: x
. q" R# y8 a/ A# t1 [- //************************************************************************************************************************************************
w! O4 z4 R4 U# k4 p2 o - //函数名:void CAN_Config(void), x5 r5 r& Y( ~ n# {
- //功 能: CAN1配置 PD0-RX;PD1-TX
7 p% P) L1 y4 X+ }, |1 _ - //参 数:无% }2 Q+ [4 E) b4 I
- //返回值;无
+ Q' L z" U5 V1 h2 T, Q - //************************************************************************************************************************************************
& }. ^: u3 D9 Z& j/ Z; t& n& z* k/ A - void CAN_Config(void): s/ G' f4 ]# f0 Y1 U1 q: _( h1 X
- {4 i. Q4 `: B9 R# x7 ?
- GPIO_InitTypeDef GPIO_InitStructure;; s( V( F3 M$ @) Q5 z
- CAN_InitTypeDef CAN_InitStructure;6 ?4 v/ I" |/ Z( j
- CAN_FilterInitTypeDef CAN_FilterInitStructure;
. `4 c+ A- f) @. H& D
1 M% m; Y+ n+ p l. R- /* CAN GPIOs configuration ***********************************/
& s, |! G3 S: A; D: V - /* Enable GPIOD clock */" M+ [: U$ u- x1 o) w8 P
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
. b: u1 K: s3 R) J9 h - - p* V5 \( k' |/ O
- /* Connect PD1 to CAN1_Tx pin */1 c$ P- T/ [* e- g6 H
- GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);4 H0 |1 n; U$ B, G4 G- f0 i
- /* Connect PD0 to CAN1_Rx pin *// M2 r! H2 ]/ B$ I, F2 X9 e& `! ]
- GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1);6 I) D/ g. j4 e/ o
; Z8 m' q4 J% A% g; Q6 p+ E- /* Configure CAN1_Rx(PD0) and CAN1_Tx(PD1) pins */ u( Y, H, D. I+ Y
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
) D- g6 \% V! j0 I# O' `5 ? - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
' A5 b# M! \/ A1 y1 H: b$ M" S- l# w - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
$ |" S( X y: e( s+ d8 K* e - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;- z, F1 m! y- H: u) w9 q
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;: V) Y* O/ m! u6 _, P
- GPIO_Init(GPIOD, &GPIO_InitStructure);
" ^5 P* |) I- U7 b - 6 ~. ]% @" a I M! }8 J% ?
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//Rx要单独初始化,否则进入不了中断,不能按照ST官方库来设定; [$ ~. d6 q# C4 D& v3 _) n
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
. I* Y0 T& J) U! ^- a - GPIO_Init(GPIOD, &GPIO_InitStructure);/ O( V8 B/ N- q, f8 \
- /* CAN configuration *****************************************/8 j# i; [; h/ ]; z# l0 y* F
- /* Enable CAN1 clock */
( {! y9 j( {" F" E$ K9 l! P7 W) I - RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);$ g5 O$ c$ A) {% _% w. m5 Y6 p" v& x
- : n+ K( {: Z; S( Q+ L* @$ _
- /* CAN register init */
- u8 R4 P% @& f: P5 T - CAN_DeInit(CAN1);* k5 R/ O* u% p! _
- /* CAN cell init */0 Q7 J* e8 y4 m2 P; D' G0 Z& P _1 o
- CAN_InitStructure.CAN_TTCM = DISABLE;
. h) G" y5 U: f2 z - CAN_InitStructure.CAN_ABOM = DISABLE;1 ^2 m; A7 ^0 V+ G8 B" f
- CAN_InitStructure.CAN_AWUM = DISABLE;
- P* B$ W7 ~8 h/ ~% D - CAN_InitStructure.CAN_NART = DISABLE;+ F) @! B5 U5 f3 i; m5 e
- CAN_InitStructure.CAN_RFLM = DISABLE;
% d, y+ H1 N% i+ \) B - CAN_InitStructure.CAN_TXFP = DISABLE;
R: j, Z* s( ` - CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
3 N; U9 E6 m5 S+ W" P - CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
$ Y& ?+ Z# I: b - /* CAN Baudrate = 1MBps (CAN clocked at 30 MHz) */ //30/(1+6+8)/4=500k
5 e8 o: x0 j, |9 M" m) p+ {8 r% K3 a" h - CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
- Y9 u o$ @) E - CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
- P7 B" L( O/ f, ~) q D; R# i* o; H% l - CAN_InitStructure.CAN_Prescaler = 4;" \2 I* f: b$ m) E% p
- CAN_Init(CAN1, &CAN_InitStructure);
s! ^5 q* h, c; Y - 7 [" [& o2 V2 A" z% m2 Q
- /* CAN filter init */7 r6 g2 f& | B
- CAN_FilterInitStructure.CAN_FilterNumber = 0;; l( }. X& Z3 P
- CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
4 u+ w8 { t4 X5 L$ |% R5 u - CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;2 ^, r! F; }+ S4 s! x7 v. r& |
- CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;2 u! {# \/ P2 n1 m
- CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;6 z: X6 z; W% {5 T& {8 ?+ V
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
# G% U6 K% k8 f - CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;% n9 Q/ a0 `4 y3 G' t" q
- CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;" D% y# O6 D6 m' s
- CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
6 U& o* |' n3 G9 L& ^ - CAN_FilterInit(&CAN_FilterInitStructure);
7 ?4 k, @6 X! f( y0 |. L- A7 g; ]# Q' G
, h+ s7 N% V# h: m- /* Enable FIFO 0 message pending Interrupt */ - q9 g8 C9 F1 G! r
- Init_TxMes();//发送结构体参数初始化
0 ~1 q* F' ?3 L) g - Init_RxMes();//接收结构体参数初始化/ k& O9 i; v( g2 K3 C
- NVIC_Config();//中断向量配置# z2 ^. P* V+ U3 y$ n; O9 d0 z
- CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);& [6 H* o; ]7 H) B
- ( l+ `! r9 @. E& f" Q) W
- }
4 i6 d u9 Y' c m - //************************************************************************************************************************************************
1 F+ M* f) q) K N c - //函数名:void Init_TxMes(CanRxMsg *RxMessage)8 ^3 d3 ~# z0 o* ^, R4 E8 c
- //功 能: Initializes the Tx Message$ e7 H+ G, k8 I- T4 @6 l# _. K
- //参 数:无
- y( y& n, w" D. N - //返回值:无+ y# `$ n6 Q) x* K4 u
- //************************************************************************************************************************************************
, R) j! @' y. h. \ _/ p - void Init_TxMes()
4 x! L0 A$ c/ ?4 t0 b1 `6 s; H' W8 r - {/ d4 u* _& J$ v: {4 I2 v
- /* Transmit Structure preparation */$ L% w, L) s6 G4 x1 k
- TxMessage.StdId = 0x123;//标准标识符,必须在( TxMessage.IDE = CAN_ID_STD;//标准帧)情况下才有效6 _/ r- Q7 E' I
- TxMessage.ExtId = 0x00;//设置拓展标识符(29位),必须在( TxMessage.IDE = CAN_ID_EXT;//标准帧)情况下才有效* }0 T1 y3 d9 Z# S7 d. q' V3 e
- TxMessage.RTR = CAN_RTR_DATA;//数据帧
[( j( w0 w4 T1 N7 n - TxMessage.IDE = CAN_ID_STD;//标准帧 $ P) ?) U( G2 v7 Q8 v
- TxMessage.DLC = 8;//发送数据长度 DLC=0-8
X% Y+ h7 q( v4 O! }" E) S! q - }
v, k3 H( ? r$ k1 Q0 F2 U - //************************************************************************************************************************************************
) x% W7 f& h. q5 V' v - //函数名:void Init_RxMes(CanRxMsg *RxMessage)6 P; d# U' U4 U7 _' c3 b
- //功 能: Initializes the Rx Message$ q, e9 M# r" b$ G. }4 H6 J* m2 {
- //参 数:无
$ P* X8 o: D) P3 o - //返回值:无
1 \# ~1 |1 o- X, [/ E - //************************************************************************************************************************************************, P, A) F+ k l. b; A
- void Init_RxMes()% D6 o, i h8 `; N, X
- {
2 J. N' \% b# P/ z7 Z0 [2 T - u8 i = 0;
; r, @/ k; s) n) H6 G - RxMessage.StdId = 0x00;//这个可以在接收中断中判断 如果RxMessage->StdId = TxMessage.StdId 接收正确
5 N3 [$ U% C0 o- [9 G. d - RxMessage.ExtId = 0x00;//这个可以在接收中断中判断 如果RxMessage->ExtId = TxMessage.ExtId 接收正确 3 k; |, x% L& y+ n$ p6 k
- RxMessage.IDE = CAN_ID_STD;//这个可以在接收中断中判断 如果RxMessage->IDE = TxMessage.IDE 接收正确 0 H( r# ^ e- c2 B3 D
- RxMessage.DLC = 8;//接收数据长度4 A, J Y; l3 r, Y" g
- RxMessage.FMI =16;//????????????????
2 m" k) [8 a, Q7 a. d - 4 j2 ]1 C2 |+ E- Q( z& G( n/ c: \
- for (i = 0;i < 8;i++)
( O' {* L# X* N8 R2 ^, Q - {
4 J1 F. P& o, I. S, b8 x0 V - RxMessage.Data<i> = 0x00;</i>, `. ~; B' e, {: ?. ^0 c' f
- }
5 [! Z4 d$ f; X - }
9 Q7 b- V0 J* C0 [. Z$ G, Z - //************************************************************************************************************************************************/ E" E( k/ O+ h
- //函数名:void CAN1_RX0_IRQHandler(): t0 C5 ^ w. M& h* b
- //功 能: CAN1-RX0接收中断服务函数8 ]- o* J+ y3 ^2 R. w/ c% }
- //参 数:无1 b$ N( P( K! ]8 `$ p6 B" `/ ~
- //返回值:无+ q5 A `% C1 j0 r2 i% }& U; g
- //************************************************************************************************************************************************3 }+ s- A; \: ]6 \' q2 n
- void CAN1_RX0_IRQHandler() //与CAN1_RX1_IRQHandler()区别
& A! g* H% ]2 p4 `& x' q! C" L - {
' B3 R) h$ L( [/ V - if(CAN_GetITStatus(CAN1,CAN_IT_FMP0)!= RESET)//判断是否发生CAN-R0中断
4 h; X; I4 ]( E Q9 v7 b, W) z - {* z B9 T0 O+ K5 L
- CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);//清除中断标志0 _9 Q& q$ C: i0 @8 f: x
- if(CAN_MessagePending(CAN1,CAN_FIFO0)!=0)//接收到数据
, D( Q" \/ P# s( J3 A( I) ~' ? - CAN_Receive(CAN1,CAN_Filter_FIFO0,&RxMessage);//接收数据最大只能8字节8 _( k/ l W" p
- }
6 m) j9 K+ L7 F, G% j2 t - Usart_Send_Buff(RxMessage.Data,8);//发送数据RS232通信 * F/ I. @. v2 F B5 |( Y2 h% s, R9 B
- }
: E6 N! |; e& x+ P - //************************************************************************************************************************************************
" w6 h5 Q7 `. u' K4 K* M0 s+ C8 C! E6 x - //函数名:u8 CAN_SendData()9 N. T$ }8 U* t' j+ w9 C9 T
- //功 能: CAN发送数据 发送第二步
) W$ W! V+ p1 |/ A$ w7 e$ |1 a& g5 ^# v - //参 数:Msg数据指针;Length数据长度
8 H* Z$ V1 t2 k. r. s, [ - //返回值:返回成功/失败标志
' F' B: J2 C9 n& h( F: \1 R/ n - //************************************************************************************************************************************************
( ^% u. O( f7 Z1 e - u8 CAN_SendData(u8* Msg,u8 Length)
: }" ?, n' H3 V0 {0 [8 J" j - {
r* }. \; |$ O2 E3 U - u16 i=0;* _( V; _3 H. I9 N7 c/ v
- u8 mbox=0x00; # `. z. w3 q+ F9 {; L, s$ S
- TxMessage.DLC = Length;//发送数据长度 DLC=0-8
, F+ i5 G% C, X$ ]9 q2 F - for(i=0;i<Length;i++)
3 S- g9 U. o" q6 f' Q! O - {
5 w* ~9 M" Z/ _% m6 j+ \4 B) X) G - <span style="font-style: italic;"><span style="font-style: normal;"> TxMessage.Data=Msg</span><span style="font-style: italic;"><span style="font-style: normal;">;! w4 ^( o, u2 \( Q' T3 ?
- }! |4 {3 x% B; \& K+ K. h1 _ u4 y* m
- mbox=CAN_Transmit(CAN1,&TxMessage);//发送数据 返回邮箱使用数量) Q, x3 T/ F+ A* E! d
( c' g. g4 D/ q4 M3 M! p- // while((CAN_TransmitStatus(CAN1,mbox)!=CAN_TxStatus_Ok)&&(i<0xfff))
6 m6 X/ G/ k8 w - // {! |& x- p# \, G' g
- // i++; K% }/ D% ]. H# m
- // }7 z7 C; h1 J ~* a% ]
- // if(i>=0xfff)
3 z; c& B2 M: m- {. v4 b# P - // {4 j* G1 x' N7 S+ p9 o: g
- // return 0;//发送数据失败6 o3 u1 i8 @! d5 v o% h7 a$ b
- // }% D7 |. o' Q! O0 k8 W( X% I( R
- // return 1;//发送数据成功
: l7 @8 m0 m2 J( f$ Z: r - }
" ~& L7 U) n2 G9 y& f* ? - //************************************************************************************************************************************************
8 B- ^ p9 j X& O3 T - //函数名:void CAN_SendDataProces(u8* data,u8 Num)# [& c" x9 e! V0 j0 ?4 M
- //功 能:CAN发送数据前期处理 发送第一步
v4 j, r! z6 k; M% q& F1 _, v - //参 数:data数据指针;Num数据长度
: a% r' K: L! w" `' Z! ^ - //返回值:无
" F9 [1 g' a, w# }3 ~6 x - //************************************************************************************************************************************************! P& V7 k. [ e* p
- void CAN_SendDataProces(u8* data,u8 Num)
, v1 [: Y- X+ S" v2 L4 }% M - {- h6 b2 \+ c) @! Z
- u8 flag=0x00,i=0;
8 l1 q( R/ V) z" b/ j* L - u8 Count=0x00,Left=0x00;3 Q# M7 d9 A; {8 E
1 D+ `6 K9 _3 p- K- Count=Num/8;//求多少个8字节倍数
2 u, p. u: s0 C - Left=Num%8;//剩余小于8字节的数量 \, I0 q9 Z2 Q- H; U
- for(i=0;i<Count;i++)" F9 \' Y) j5 [. K
- {8 O4 Q# T7 e3 j% l4 [$ T+ F) {* k
- flag=CAN_SendData((data+i*8),8);//发送整8字节的数据! \$ S6 i$ c) X0 P
- }
+ h2 O9 ]0 b5 p' w' r; n - if(Left>0)//有余数才单独再发送一次
! A Z5 w: a* Y& I$ ?$ X! E - {2 l. y; Y2 Q t
- flag=CAN_SendData((data+8*Count),Left);//发送剩余字节& t+ b* J7 v3 ^0 T# k! B( E' B
- }! U9 G9 u u* P: V
- }0 u; j+ {2 a4 C1 y9 j5 M
- //************************************************************************************************************************************************
3 \7 e& I. q% K0 S# B6 z1 c# v - </span>" G% S3 O1 P) x G, \2 Z- x# I
- </span></span>
复制代码 D+ ^! g0 A/ `( W" P' L$ K
|