STM32F2-CAN通信-发送任意长度,调试好的,与大家分享
+ t- _: ]+ U8 P% A
% q( g( ~' C) x. M% \+ U- #include "include.h"+ _* z7 m1 U8 n
- //************************************************************************************************************************************************
4 P* G" D6 K! U% e. k9 j/ j( i - //20190611调试完成
3 t6 o! V; \. ~& v) e- h2 R - //By Wang# j8 r" R+ J8 e" d0 g
- //************************************************************************************************************************************************
9 `0 X0 j& Y! ~8 }9 Y+ o$ X - # S/ U- J# A! l
- CanRxMsg RxMessage;
. w& ?1 E+ ]4 T8 P) y. H9 S - CanTxMsg TxMessage;
9 r" Y3 x5 X6 m$ M0 v - //************************************************************************************************************************************************2 f# [5 n& N* p
- //函数名:void NVIC_Config(void)
1 }% f0 K3 \5 r5 L - //功 能: CAN通信接收RX0中断配置
! C4 X8 a+ W* G8 T" H+ U. i - //参 数:无
( s' g( h# O4 q7 L$ r - //返回值:无
/ \) S0 @; [0 L4 e5 @ - //************************************************************************************************************************************************
0 G3 s4 w! @; F; t1 m U
6 P( `% z7 G1 E- r) @- void NVIC_Config(void)
/ ?3 L1 [& |( J5 O4 m) [6 d - {. C; R$ I1 r' g, |! h# G
- NVIC_InitTypeDef NVIC_InitStructure;
, g |6 [2 H. e5 N9 ] }
" n6 r# ?0 J% z7 m, N" N- //#ifdef USE_CAN1
3 N! c' {0 t+ q2 M
: G2 o$ {! {! d9 ]! l3 |- NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;//与CAN1_RX1_IRQn;区别
# z" F( c7 w2 I4 } - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//不同的中断优先级一样会怎样
' U3 g& Y! M3 X# I! {( O - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;( n: S3 ?2 |4 s
+ ^7 L; U( S) S- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;0 ^- d4 g+ I. U% e
- NVIC_Init(&NVIC_InitStructure);
* u$ s( B, f" t8 d& o) K - , h$ C2 w! `, C) Y+ m( \0 N2 y/ ^' M
- }
v$ f: v6 P5 A2 m# M) _9 ~8 f; |3 @ - 5 x; d6 W: _/ }& o* g
- //************************************************************************************************************************************************. H# ^" F. V6 @. _/ I
- //函数名:void CAN_Config(void)! k7 Z7 E8 q# W
- //功 能: CAN1配置 PD0-RX;PD1-TX
) p/ M" G* _6 E: _7 n; }" w2 o - //参 数:无) U. ^: o1 {) r/ Q: M
- //返回值;无9 |3 z9 M6 S5 t& T8 J
- //************************************************************************************************************************************************ k& v4 B J' X% |3 K8 z1 U2 d
- void CAN_Config(void) ?4 t( w6 q) _$ y- ?
- {
, h6 S( H! t* Q s3 H - GPIO_InitTypeDef GPIO_InitStructure;
. n9 D+ {: M& j - CAN_InitTypeDef CAN_InitStructure;' x0 h* j' [+ i( Z; [0 c
- CAN_FilterInitTypeDef CAN_FilterInitStructure;( k% b2 l5 [$ F
- $ L+ j" W) t1 o y: B+ j& u8 j+ T
- /* CAN GPIOs configuration ***********************************/, X D3 K8 o6 l
- /* Enable GPIOD clock */
4 F8 Y; R4 W6 k8 D* x, { - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);7 L) l* M4 a* P6 Q; N+ y2 L3 U
/ |0 t# b4 `4 ` {( |- /* Connect PD1 to CAN1_Tx pin */
; U; X5 h$ \ L" { - GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);
9 O3 k+ Q* \7 |) W) A7 q - /* Connect PD0 to CAN1_Rx pin */
6 {1 F8 F0 w' f" i - GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1);
1 S2 M4 I3 A/ y: i
5 i0 w8 i6 S; y7 A- C e( ?, V- /* Configure CAN1_Rx(PD0) and CAN1_Tx(PD1) pins */* j2 I1 _. b+ T( E6 m
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;, o! [6 q4 N3 q) `
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;# W( ?+ I0 V2 r( m7 _5 u
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
# b0 O. L4 }+ G. @ - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
0 \! |- K( X3 s& g* s: C - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
3 i! u4 B0 E) Y2 i! D6 _ - GPIO_Init(GPIOD, &GPIO_InitStructure);
7 G/ p& R2 z) f% p; S1 ?" T - + c; s1 O2 m# w% m% k: u3 T# g8 a
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//Rx要单独初始化,否则进入不了中断,不能按照ST官方库来设定
( D2 ^' K, P) Z. X9 s - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;& j, y) ^' G/ I2 Z
- GPIO_Init(GPIOD, &GPIO_InitStructure);" e& G7 R, n' o1 n2 d. o
- /* CAN configuration *****************************************/
% `1 w5 x3 n" o) d2 F - /* Enable CAN1 clock */$ j! q! Q9 e! j' ~6 ]
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
( X8 L' b+ t a8 A
6 y0 [# h5 F3 b* l. E0 c- /* CAN register init */
3 R" ~+ [9 z8 G! Y, G - CAN_DeInit(CAN1);1 a A0 J; N) F8 C% x" A! x
- /* CAN cell init */
+ f: e3 l+ |6 Y3 U! D. w - CAN_InitStructure.CAN_TTCM = DISABLE;, u1 U! L3 F, ]( T" h8 w/ n- R* s
- CAN_InitStructure.CAN_ABOM = DISABLE;+ n. I3 Y* h- N5 |( G, E& Y" X1 Y4 \
- CAN_InitStructure.CAN_AWUM = DISABLE;8 R( d" {% U! K& ]4 {# K
- CAN_InitStructure.CAN_NART = DISABLE;, m4 X7 z5 J2 D+ G2 Y( ^- u
- CAN_InitStructure.CAN_RFLM = DISABLE;
7 z6 Y( X; u6 m' J - CAN_InitStructure.CAN_TXFP = DISABLE;! }3 p' x/ a4 ]
- CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;9 O4 {3 R0 ~$ D4 r+ ~
- CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;: O: S6 t+ B$ k0 n- M5 }! W
- /* CAN Baudrate = 1MBps (CAN clocked at 30 MHz) */ //30/(1+6+8)/4=500k2 H2 u2 Y G# B% a6 X5 G! C5 W
- CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
_0 m% W v8 G- T3 L) l2 V7 K6 m5 ^$ } - CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
& N n, E: M/ o* F3 q/ o - CAN_InitStructure.CAN_Prescaler = 4;
4 o+ X5 U& f+ J- k; m* { - CAN_Init(CAN1, &CAN_InitStructure);; c$ e& M/ P" W7 a! c0 `
- 0 i" Q- _6 V6 j' K X5 N0 \) J6 e% x
- /* CAN filter init */
" {0 L6 j7 g2 d$ C& W - CAN_FilterInitStructure.CAN_FilterNumber = 0;3 \5 m( r% n2 D/ L' j
- CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
! R7 I% S* {: z9 k9 I) C - CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;& f q" `' h2 a( z
- CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;( H* @- ], t' V* f% p$ Y4 R* ~! k
- CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
/ \! _ ~9 a; W9 x ]( f - CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
) w* r _! u; } l9 s - CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
" f1 |# `! u6 E& [; D5 L - CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0; P, m) k, B8 k |. i# F
- CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;7 k+ V8 B& W/ v* ^, p, W( U
- CAN_FilterInit(&CAN_FilterInitStructure);
7 r- W0 K& O% t8 R2 F - 0 J0 |! f. V5 @; L7 {0 {
- /* Enable FIFO 0 message pending Interrupt */ 2 w) c( X% f. w; W7 Y) `3 A. {
- Init_TxMes();//发送结构体参数初始化- c3 u# J" t8 m3 r8 [, N0 s( T
- Init_RxMes();//接收结构体参数初始化; s6 r- F% J) r/ _1 o8 |$ g
- NVIC_Config();//中断向量配置 p0 h+ a4 {6 a$ U/ A" e
- CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);' X. V X4 S0 y! Q4 h- g
4 h& F1 c7 {( R& |3 r- }; ^- t5 K" T. G) K( Q
- //************************************************************************************************************************************************
, ]4 J" z, i. h5 P$ E% A - //函数名:void Init_TxMes(CanRxMsg *RxMessage)1 B0 |4 k& e# L y* L9 C3 C
- //功 能: Initializes the Tx Message D& _% k) W5 s8 o8 _
- //参 数:无7 O, D. \$ J! _# J2 F1 d7 x
- //返回值:无+ R3 w4 D) J" h6 S
- //************************************************************************************************************************************************( t, G' d" M+ q8 x& G1 O8 l
- void Init_TxMes()
' d% o0 v- v5 Q6 x. Z - {
3 C5 r* r- Z' _0 _* P - /* Transmit Structure preparation */
& n+ }# V7 j, [* t3 m$ F - TxMessage.StdId = 0x123;//标准标识符,必须在( TxMessage.IDE = CAN_ID_STD;//标准帧)情况下才有效
1 W% u7 R% I7 j! B% p - TxMessage.ExtId = 0x00;//设置拓展标识符(29位),必须在( TxMessage.IDE = CAN_ID_EXT;//标准帧)情况下才有效
& u4 w* w8 {& t$ N+ P7 u - TxMessage.RTR = CAN_RTR_DATA;//数据帧) |0 a* n% `* t v- \
- TxMessage.IDE = CAN_ID_STD;//标准帧
5 J9 w. g% S: \% ^+ v/ F - TxMessage.DLC = 8;//发送数据长度 DLC=0-8% _4 [% m, |+ g: ^( ? X8 c
- }7 M/ Z1 p u" r8 ^
- //************************************************************************************************************************************************
! \9 I3 T3 x4 }& U2 {" u% [+ O* Q! c - //函数名:void Init_RxMes(CanRxMsg *RxMessage)
2 H- t# J; F# n+ s2 U - //功 能: Initializes the Rx Message; r' C: `: k p( g; _5 h! t: F
- //参 数:无
0 L( r$ A5 ~0 K1 \" V4 c" m - //返回值:无
% d( l$ c, h( n9 C - //************************************************************************************************************************************************6 Q% \% r2 N+ V# k
- void Init_RxMes()) |- C0 e% ^: H, F& n
- {
9 \! I6 [. Z9 J! M/ ~ - u8 i = 0;
8 O: m, j5 p" G* O2 s - RxMessage.StdId = 0x00;//这个可以在接收中断中判断 如果RxMessage->StdId = TxMessage.StdId 接收正确 & I% U. Y% [5 Z& }3 j! ]/ T
- RxMessage.ExtId = 0x00;//这个可以在接收中断中判断 如果RxMessage->ExtId = TxMessage.ExtId 接收正确 : V) i$ n$ |+ |/ W1 c3 c8 z0 a0 b
- RxMessage.IDE = CAN_ID_STD;//这个可以在接收中断中判断 如果RxMessage->IDE = TxMessage.IDE 接收正确
. ^* W( ?9 |( C0 Z! o0 [) A; U6 q - RxMessage.DLC = 8;//接收数据长度
1 o0 a, r4 G; l' j - RxMessage.FMI =16;//????????????????
; E! Y: V# o/ h! y1 |( S+ P - 1 n* ]5 G+ G3 H
- for (i = 0;i < 8;i++). l5 l8 Z; x0 Z: U" l
- {( F5 a" U3 s7 W
- RxMessage.Data<i> = 0x00;</i> m- K1 p5 r# C1 D" Z
- }, a1 u: W" v, c7 ]+ B
- }
0 @, {2 h; P/ ?5 L8 |+ Y+ v/ d - //************************************************************************************************************************************************
$ h* X4 ]$ h+ H9 J - //函数名:void CAN1_RX0_IRQHandler()
2 n4 R2 }0 |% q0 j6 n - //功 能: CAN1-RX0接收中断服务函数
5 o. k6 u/ F B- ?$ e - //参 数:无0 e# ~1 j- N# `) I" ~6 W8 e
- //返回值:无" a H. Z {8 _$ Y+ B) F, l
- //************************************************************************************************************************************************9 B0 K- \% V5 H
- void CAN1_RX0_IRQHandler() //与CAN1_RX1_IRQHandler()区别
) E1 H; |! d' w6 f* u - {1 J# X, g3 ^* p
- if(CAN_GetITStatus(CAN1,CAN_IT_FMP0)!= RESET)//判断是否发生CAN-R0中断( L) w' T# r/ I3 I# R( l
- {
9 P& u3 m3 _' q r8 k# N - CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);//清除中断标志; ?. k* M3 f* r: m3 n
- if(CAN_MessagePending(CAN1,CAN_FIFO0)!=0)//接收到数据' w3 k0 Y/ v) a" T
- CAN_Receive(CAN1,CAN_Filter_FIFO0,&RxMessage);//接收数据最大只能8字节4 R/ D o7 U9 _0 G" G, }8 a
- }' W. K o# {& F+ w
- Usart_Send_Buff(RxMessage.Data,8);//发送数据RS232通信 # R" r: P6 ^, y% f) a1 P
- }4 j M" i- E9 q3 G/ ~/ w
- //************************************************************************************************************************************************
( G, l: b, O% W$ r - //函数名:u8 CAN_SendData()
M% E& M7 P: L4 `. Y8 a! t - //功 能: CAN发送数据 发送第二步
! M3 g# ?4 w4 ` - //参 数:Msg数据指针;Length数据长度8 ^" N O$ u0 {
- //返回值:返回成功/失败标志1 r! m. p3 u `# g
- //************************************************************************************************************************************************$ R% m, a0 D4 j" ^
- u8 CAN_SendData(u8* Msg,u8 Length)- H/ t7 H8 s7 F( q" W) b
- {
5 F% y$ \1 I& S4 t" _( O4 h! s$ ? - u16 i=0;
; A8 X5 s/ @. F. n- }+ r* `6 | - u8 mbox=0x00;
! P" i9 \0 I+ @& T& G - TxMessage.DLC = Length;//发送数据长度 DLC=0-89 W$ Z- Z% m0 H0 h' x0 Q# K
- for(i=0;i<Length;i++)
+ E. X0 {( N% c - {, m0 c+ a. q0 `+ \0 N+ y& `* q3 |9 e
- <span style="font-style: italic;"><span style="font-style: normal;"> TxMessage.Data=Msg</span><span style="font-style: italic;"><span style="font-style: normal;">;7 ^* `1 C$ p% M8 c
- }' | ]( l7 ]$ ^; M
- mbox=CAN_Transmit(CAN1,&TxMessage);//发送数据 返回邮箱使用数量
- }" ]/ T: M! j" f" G' r% F
7 Z: {+ f7 Y; P) Y# Z, w- // while((CAN_TransmitStatus(CAN1,mbox)!=CAN_TxStatus_Ok)&&(i<0xfff))) r1 f( A# S: g/ u9 C* m
- // {" J4 D" F( x- [
- // i++;( D" s* v3 O* `( T- d% B
- // }
, q$ b) K$ j3 m( ^0 ^4 E$ ` - // if(i>=0xfff)
6 w& Y* S: y, s4 ]( i - // {3 \. M. Y/ u, z& g5 o a1 V
- // return 0;//发送数据失败! e& f$ H' x- A, n. @
- // }) p; @. n' @$ w! n; M0 d: H
- // return 1;//发送数据成功
8 }# ?* d/ R' V9 W7 i- ] - }2 K9 r; x8 l7 z3 @% s
- //************************************************************************************************************************************************+ C. q& T5 K- ~ s6 |
- //函数名:void CAN_SendDataProces(u8* data,u8 Num)
9 U; s8 e4 a7 m) B4 s2 l+ c - //功 能:CAN发送数据前期处理 发送第一步
& g$ z! p' `8 C+ M - //参 数:data数据指针;Num数据长度
; Q% M- \7 P2 R9 G( x - //返回值:无 U: ^% y0 t3 ~: _7 b( Z6 f9 Y/ {
- //************************************************************************************************************************************************ q- j. ]) W- I4 E2 W
- void CAN_SendDataProces(u8* data,u8 Num)
2 i* i* o3 {$ S) W - {2 g1 c+ }6 b8 F. ]/ n6 i
- u8 flag=0x00,i=0;
- E7 T- H9 N' L - u8 Count=0x00,Left=0x00;( Y. D' a" M) q: @- ^# R
- % R' V; h) q# u+ R+ X7 L
- Count=Num/8;//求多少个8字节倍数3 c2 E5 x# M! a4 ~* @
- Left=Num%8;//剩余小于8字节的数量
6 R: c1 ?8 ?: _3 v) r - for(i=0;i<Count;i++)2 c6 V2 v$ ~1 f F5 V2 V
- {
2 k7 E$ G) Y# h5 }. n1 I - flag=CAN_SendData((data+i*8),8);//发送整8字节的数据# d( t+ K% M" I6 y5 M: J
- } ( |, U0 T- F& c9 v' I# ]
- if(Left>0)//有余数才单独再发送一次
& T8 {0 G4 T2 L- n& U8 G! J8 s - {
6 I; d4 r( s; t1 h: M2 L% ` - flag=CAN_SendData((data+8*Count),Left);//发送剩余字节
3 c# q& `. o- k) H7 i3 } - }
' I8 m' Q" F0 j1 c* \, V$ h - }
) X: [5 E/ q4 X% h8 W% d# d0 m - //************************************************************************************************************************************************; z8 V0 [$ d& a6 d
- </span>
: \1 X4 `( S# C7 t - </span></span>
复制代码
; T. R5 [7 v# j9 t6 k: T0 T |