STM32F2-CAN通信-发送任意长度,调试好的,与大家分享
% X; s. l: z; w5 i
" L6 L1 E2 u& v- #include "include.h"& X" p3 L; n* e2 d3 E1 X, k
- //************************************************************************************************************************************************
; u+ A7 d$ ?4 X - //20190611调试完成) O. W- [# ^! p( W0 U$ H# Y
- //By Wang
0 u Z/ u n7 o. y - //************************************************************************************************************************************************' {: u" C4 X2 \ ?$ ^8 @9 j! ^
3 s8 N$ Z6 E) _9 O- CanRxMsg RxMessage;
! o8 w$ s$ l7 v - CanTxMsg TxMessage;' V) r3 _- I4 e
- //************************************************************************************************************************************************- W1 ^4 g, \! g
- //函数名:void NVIC_Config(void)
. f& U" ]2 G- |- {& @ R L: E - //功 能: CAN通信接收RX0中断配置3 t9 a1 F; y+ Y/ F( D
- //参 数:无
6 t; n) j8 ^; Q+ \" b - //返回值:无
) m: f! ?- g. q* { - //************************************************************************************************************************************************9 O1 n# `, \" x) o
$ `9 L g. _% v- l, M: f- void NVIC_Config(void)
% b" T9 D1 z( Q. S7 I - {' n2 u! J% D: w; j" q: A
- NVIC_InitTypeDef NVIC_InitStructure; S7 U- L; z3 i$ K6 \) h8 W
- & E) e5 N3 a1 N7 K9 ~0 `8 L- Y
- //#ifdef USE_CAN1 & ^1 ]# I# W+ l' u: {1 q
* ?0 z N3 ?! w9 G- NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;//与CAN1_RX1_IRQn;区别5 I0 U( s9 p4 e
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//不同的中断优先级一样会怎样( p& G* @6 U1 ^3 ?5 R/ V( @7 B! {2 \
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
& x( j1 ?8 `$ I4 o8 C - + I, C& c: ^0 D6 I6 w* m% d3 ]
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
3 q9 c, [( @ Z: o& Z - NVIC_Init(&NVIC_InitStructure);( N- e/ x0 m" u* p3 {
) D* v9 f3 ]0 c/ g- A. t- }+ s* T1 Q# k8 O6 b8 ~
* d1 ^( f! K- r+ k1 g- //************************************************************************************************************************************************
) W# v0 O" m9 b. M5 N- P: G+ w0 {' J - //函数名:void CAN_Config(void)3 f4 ~6 E# T0 p w* e
- //功 能: CAN1配置 PD0-RX;PD1-TX( w; F* R2 t6 }: ~) `" a) g6 q: P
- //参 数:无8 a; ?1 o# L, x
- //返回值;无
( N. L+ }* X( r. C2 U$ I - //************************************************************************************************************************************************/ Z3 s$ K) u* G6 {8 T" [6 Z4 @
- void CAN_Config(void). P$ U( G+ {4 u6 m) O& f$ i/ m8 P
- {
3 D) c- b+ ~ Q9 q6 n7 ? - GPIO_InitTypeDef GPIO_InitStructure;! i+ j1 Y) A* m% O! I" A
- CAN_InitTypeDef CAN_InitStructure;
, u8 ]! L8 ~7 M! y% X P# f0 F - CAN_FilterInitTypeDef CAN_FilterInitStructure;
( l' z& u4 {% a7 r. N$ T
8 M# V) k- F/ ~: B4 }5 G- /* CAN GPIOs configuration ***********************************/
- a* Z% U! U: h' v - /* Enable GPIOD clock */
: V+ E) M. {3 V9 l$ p# l1 q - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);# h1 B, I: Z) B+ X- F- J( K3 L
( i# C% B+ D {- /* Connect PD1 to CAN1_Tx pin */# F6 A- f, Z* J7 C
- GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);
1 ^; Y7 _$ u9 h! z( a - /* Connect PD0 to CAN1_Rx pin */
0 l* C9 Q# x+ x8 Z- z: a2 z - GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1);
5 b4 ?! W! w+ N' J
4 g" ~/ b9 u. O- /* Configure CAN1_Rx(PD0) and CAN1_Tx(PD1) pins */
6 {$ } g, P e9 m/ s- p7 D, _6 b - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
& Q& W P: h" t( @- Y - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;) z# ` L8 R& M; _' I
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;, o) I+ P: Q9 t1 l* H" E
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
9 `- U s5 X6 |0 a" R - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ y3 o8 i/ h! [; A1 T - GPIO_Init(GPIOD, &GPIO_InitStructure);4 {) p# m% J* Z* D+ [1 L i+ E
7 r" S2 f1 J9 ?6 H, `( l- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//Rx要单独初始化,否则进入不了中断,不能按照ST官方库来设定& @& W0 K5 P5 ^$ U5 J, V6 y% u$ p
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;% C( `/ R- G" S( Z6 b9 k# U
- GPIO_Init(GPIOD, &GPIO_InitStructure);
- l$ ~1 y8 Z! a - /* CAN configuration *****************************************/( p8 l6 |2 d) ?
- /* Enable CAN1 clock */
% L$ `$ a. l6 z- ~% ~ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);6 [* O" g& g0 O2 M/ B
4 P* S. C+ q) {. R& Z( j, s- /* CAN register init */
1 f; i* e; U1 V3 k0 M% T - CAN_DeInit(CAN1);
" R! |' B; v' x, J9 Q - /* CAN cell init */- w' S7 E0 p8 {
- CAN_InitStructure.CAN_TTCM = DISABLE;5 |6 g) E; m0 x5 Q. R6 z% Z$ z( T
- CAN_InitStructure.CAN_ABOM = DISABLE;6 m9 S1 {) Y; |, D1 ~0 @
- CAN_InitStructure.CAN_AWUM = DISABLE;4 [$ |. s' k. W
- CAN_InitStructure.CAN_NART = DISABLE;
0 G( T: M o8 M9 l$ @; ?- ^# I0 {& B - CAN_InitStructure.CAN_RFLM = DISABLE;
" a/ `/ G' l" Z* t. g0 _ - CAN_InitStructure.CAN_TXFP = DISABLE;
' A; |( h+ p2 O* v) { - CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
7 c2 I F- E3 t7 S h) G" X7 U - CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
: B+ E: j3 C. A( y# R- S- G3 Z3 Y - /* CAN Baudrate = 1MBps (CAN clocked at 30 MHz) */ //30/(1+6+8)/4=500k
4 Y$ [8 \; l a \8 r& ? - CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;) C% c% E- N# l9 R4 T4 j. a) U
- CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
d' ^/ y, M- \3 N - CAN_InitStructure.CAN_Prescaler = 4;
0 z {# e& N7 \7 e/ {+ D0 ^' Q# p# [! H - CAN_Init(CAN1, &CAN_InitStructure);
# l) ]( v8 n4 X6 q+ r( C - 5 ?6 ?2 \# d! W. J% y
- /* CAN filter init */
4 M. j& n- i8 x) @- G8 B* t1 s1 v a% F - CAN_FilterInitStructure.CAN_FilterNumber = 0;
: B; _% c: ~- ]4 d% g - CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
9 L& q5 T) F4 s$ ^ - CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
7 J8 Y: s5 J4 C - CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
r; o( z4 V: e7 t7 L - CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;$ c2 i/ _6 z7 r8 _; s
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
% Z" Z3 u8 R( `% t# q3 E! B - CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
* ~ G/ |- Q- Z5 I' c - CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
5 F6 M3 Z8 `% ?. C9 S) \5 g8 o9 e - CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;* O, n1 r3 B. ^1 f9 ]
- CAN_FilterInit(&CAN_FilterInitStructure);
2 g3 r7 i, |# ?; V; b - , h9 I) g& b* w ^. W% i
- /* Enable FIFO 0 message pending Interrupt */
8 a) T6 A. ^: Q - Init_TxMes();//发送结构体参数初始化
% I$ Z7 t' G* F- h( x9 m - Init_RxMes();//接收结构体参数初始化( k8 |$ y( D6 Z/ L: |2 z5 d
- NVIC_Config();//中断向量配置0 b& o; X) h3 {
- CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
0 `2 ? F$ V9 D3 e) Q8 C! @1 u& e. B, c
& r% [4 H. |6 |- }
7 g( h# D4 I) x0 t% ^/ ?5 c! Z - //************************************************************************************************************************************************
2 \1 u( A D$ ~' C& o - //函数名:void Init_TxMes(CanRxMsg *RxMessage)
, }# v$ F; |, J- K: i' G$ W - //功 能: Initializes the Tx Message
2 k+ O9 c8 V) e* U5 q - //参 数:无
4 q2 L/ p O/ y' Z7 V8 P+ v - //返回值:无
/ \' j3 S! y( V; X, I8 z5 U - //************************************************************************************************************************************************
5 J( J& `! A$ R! c! L0 J - void Init_TxMes()
& |# j# ^' o) x - {+ p$ _$ H7 b) [0 i) L: B
- /* Transmit Structure preparation */
: u+ c Y! d6 t3 C- `, C7 R - TxMessage.StdId = 0x123;//标准标识符,必须在( TxMessage.IDE = CAN_ID_STD;//标准帧)情况下才有效
9 h* M/ F" S0 |% M6 p( Z- y0 F - TxMessage.ExtId = 0x00;//设置拓展标识符(29位),必须在( TxMessage.IDE = CAN_ID_EXT;//标准帧)情况下才有效" i# M' E5 V& @, \" B3 [ R4 i& o
- TxMessage.RTR = CAN_RTR_DATA;//数据帧0 T$ E$ x% z+ u' s7 \7 T) A
- TxMessage.IDE = CAN_ID_STD;//标准帧 ) t: }5 J$ }5 R1 Q
- TxMessage.DLC = 8;//发送数据长度 DLC=0-8
1 K, ]8 r2 w/ S% F$ L# p3 s - }
/ B1 Y0 ~8 s5 Z( l+ m) T - //************************************************************************************************************************************************8 b( h9 p% y) `* I3 K8 _
- //函数名:void Init_RxMes(CanRxMsg *RxMessage)+ I8 G$ s3 u( a1 s
- //功 能: Initializes the Rx Message
* o' r9 S) e Z' X4 k+ F8 M1 S - //参 数:无
_- }5 H. g5 j - //返回值:无
# F1 p% j5 }6 v1 @3 l - //************************************************************************************************************************************************
/ P$ O/ i3 s% s! Y - void Init_RxMes()
; R# Z1 |) U, W, c+ ~7 A% V% i6 m - {
T3 r) b) t# r- u/ s - u8 i = 0;- R9 F1 a I; f' s( g* n
- RxMessage.StdId = 0x00;//这个可以在接收中断中判断 如果RxMessage->StdId = TxMessage.StdId 接收正确 x* P4 ]; H# G) K
- RxMessage.ExtId = 0x00;//这个可以在接收中断中判断 如果RxMessage->ExtId = TxMessage.ExtId 接收正确
4 I J3 l' M3 `6 Y - RxMessage.IDE = CAN_ID_STD;//这个可以在接收中断中判断 如果RxMessage->IDE = TxMessage.IDE 接收正确 & W7 x$ _4 S9 X3 E5 O6 W# E
- RxMessage.DLC = 8;//接收数据长度
! b. P8 |! M" [, j+ Z - RxMessage.FMI =16;//????????????????
& [; ^4 \; j8 I' V# O. x K - 9 k$ p! s8 [8 C0 \
- for (i = 0;i < 8;i++)
/ R" ~$ l8 ] ]) v8 b - {
- X% V: b0 T5 ~9 b - RxMessage.Data<i> = 0x00;</i>
2 F0 Z' ]2 b6 W) K' B6 Z - }
- W8 W6 N5 O" U - }
4 N9 j3 l# k5 a - //************************************************************************************************************************************************
! I7 s$ W+ h$ n$ V) ?7 O - //函数名:void CAN1_RX0_IRQHandler()
# u" |5 }! A) V) T% ^ - //功 能: CAN1-RX0接收中断服务函数- {8 l. a! `- q; F% [! m) }
- //参 数:无
& ~9 _( @, F' t6 g7 L+ h - //返回值:无5 P8 g) p" C; k
- //************************************************************************************************************************************************
' Z- q9 v% h; m/ k" J/ Y - void CAN1_RX0_IRQHandler() //与CAN1_RX1_IRQHandler()区别
& E2 _. Z: p2 ~; D p - {, f+ s2 h' I- m9 m, d
- if(CAN_GetITStatus(CAN1,CAN_IT_FMP0)!= RESET)//判断是否发生CAN-R0中断- ^' }! ^5 L, ?* K* u9 C; }
- {: w* z9 m1 G5 i; n9 O: e
- CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);//清除中断标志
' q( z) a8 {( c. |, T" S% \+ x, o - if(CAN_MessagePending(CAN1,CAN_FIFO0)!=0)//接收到数据) z& p, b$ S2 Y! d0 T1 N
- CAN_Receive(CAN1,CAN_Filter_FIFO0,&RxMessage);//接收数据最大只能8字节
4 p. d& F* o3 G - }
9 L, }' f5 W# v* @( q1 f2 ]6 ^ - Usart_Send_Buff(RxMessage.Data,8);//发送数据RS232通信 6 z+ s$ |: J& S6 s
- }
. Y4 C/ @+ q* L+ [: E - //************************************************************************************************************************************************7 I( u# r1 }5 w. I7 N1 U
- //函数名:u8 CAN_SendData()
$ |* d% F$ F' R. X' g) x - //功 能: CAN发送数据 发送第二步: F9 X7 J: K% D- s# d: T
- //参 数:Msg数据指针;Length数据长度) R$ I6 n: ~5 @( z; E3 c! [
- //返回值:返回成功/失败标志
. X: i' l) I T* |8 N% W - //************************************************************************************************************************************************
c6 O3 T& J; G# F3 @- d - u8 CAN_SendData(u8* Msg,u8 Length)
8 R' V9 r" X/ _8 y - {
" R* }( t3 Q) V. U3 K* k9 d - u16 i=0;
' V$ U( | B& c% d& q4 N5 m& [+ | - u8 mbox=0x00; , v# E! M4 n+ M! u
- TxMessage.DLC = Length;//发送数据长度 DLC=0-8
7 ~5 V7 y9 h5 }0 w4 h. Q. e - for(i=0;i<Length;i++)
8 k$ U: q' e- H6 G7 Y! x - {1 K2 r: W3 N' J! R( A" I
- <span style="font-style: italic;"><span style="font-style: normal;"> TxMessage.Data=Msg</span><span style="font-style: italic;"><span style="font-style: normal;">;$ B z, q8 Z4 ]. G6 y! Z( t% `( L
- }
$ z; ^4 j. F; R4 w - mbox=CAN_Transmit(CAN1,&TxMessage);//发送数据 返回邮箱使用数量
; [% J6 D: ^" ^3 g
" O6 M; a5 R. ]4 Z0 o0 F5 L4 ] G: Y- // while((CAN_TransmitStatus(CAN1,mbox)!=CAN_TxStatus_Ok)&&(i<0xfff))+ l9 [- \2 M B$ g/ @4 s& k
- // {
# u* t& D; h! X. D, u& ` - // i++;! G) N5 _( G7 e
- // }; h& B0 T6 e- N1 U
- // if(i>=0xfff)
0 A: h& }1 Z. Z+ t h5 y - // {
8 d# }0 @: j2 |# D - // return 0;//发送数据失败9 R+ g/ O4 [9 W+ J' e5 S( B4 M6 C+ [! S* ]
- // }
( U/ q' j8 e3 r/ C# o - // return 1;//发送数据成功
0 C8 [2 C2 c7 E2 x - } O" y: d* b' h
- //************************************************************************************************************************************************
/ `1 _8 _6 U( L5 A5 f: K - //函数名:void CAN_SendDataProces(u8* data,u8 Num)$ b+ o) _! o9 s
- //功 能:CAN发送数据前期处理 发送第一步
. M# l2 i7 o4 o - //参 数:data数据指针;Num数据长度' T0 n+ \ [0 T$ U% X$ J5 I- n" Z
- //返回值:无
$ y& i a8 i% E5 P s, } E) X% K1 r - //************************************************************************************************************************************************
# h, g8 m2 S0 x( z4 l - void CAN_SendDataProces(u8* data,u8 Num)6 d! ~ T$ |! v3 K4 @) K4 v
- { Y; L/ [3 Y- g f' g. m
- u8 flag=0x00,i=0;* j4 `$ L, b6 {) I& H" P0 H
- u8 Count=0x00,Left=0x00;9 w- z( z# h9 ^ I; I
- [+ u% A6 A: I9 O" B& U; ^" N1 [- Count=Num/8;//求多少个8字节倍数5 w5 W: S* t k1 `# F# s: }
- Left=Num%8;//剩余小于8字节的数量
3 M- x9 u3 g" @! ~# i$ o - for(i=0;i<Count;i++)
4 K8 q8 A# o. S7 {3 E! C - {
/ Y, A7 U! q3 E+ _1 c C4 j6 S8 W6 b - flag=CAN_SendData((data+i*8),8);//发送整8字节的数据
' ?9 v' A6 f; Y' M, W6 U2 j4 B - } % Z7 y8 W. t, s2 W8 a
- if(Left>0)//有余数才单独再发送一次$ X# X4 S s l- C; H
- {
' v7 Q6 Z# `1 `* w+ b5 m& i& a) ` - flag=CAN_SendData((data+8*Count),Left);//发送剩余字节
* ?# f/ A8 K+ G7 i( F6 j( D. q - }% T4 p& I/ c7 I/ g9 L7 S# n' P1 k
- }
7 Z3 E, Q0 J' h$ N0 V - //************************************************************************************************************************************************! }9 O1 w+ h' b3 P: Q- [9 R; D7 g& T. B
- </span>
3 X. ]: ]9 Q9 ?1 s$ | - </span></span>
复制代码 ) T- O. f" `1 F' k
|