代码如下:* A8 Z6 r: N* t7 i( E
5 w1 ]& }4 s! v# g3 f3 ^/ b- #include "mycan.h"
' F* o% L2 M# @% g F( ^. M - $ Q& M+ u0 V' Y9 Y F% _
- //CAN初始化
$ P: K9 L6 A3 r( e+ @: W+ H' Q - //tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq' Y, T' x% a' ]/ T7 J8 [
- //tbs2:时间段2的时间单元.范围:1~8;
6 F4 p6 j5 V O" W - //tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq$ X8 e# D% z8 T- H3 t8 F
- //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk12 J! ^3 w) Z! f4 a# R$ j& ^1 q
- //注意以上参数任何一个都不能设为0,否则会乱.
* m, [6 _, A( M - //波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);
6 ?4 O9 R" W: f* q- Y - //mode:0,普通模式;1,回环模式;
' Q! o1 a1 C+ B - //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);5 B9 B2 `+ }1 |' y
- //则波特率为:48M/((1+8+7)*5)=450Kbps0 v" P( K9 f5 J$ \
: z6 W2 S4 E- q3 A) R6 }- void CAN_Mode_Init(uint8_t tsjw,uint8_t tbs2,uint8_t tbs1,uint16_t brp,uint8_t mode)
" Z8 x4 A1 O/ K2 S/ ~ - {
$ L: x @% K0 Y2 R - + |) d$ o* a& s! [
- GPIO_InitTypeDef GPIO_InitStructure; & S5 V; y$ G9 L* ]& U, X
- CAN_InitTypeDef CAN_InitStructure;
- q7 Q1 i+ q# K - CAN_FilterInitTypeDef CAN_FilterInitStructure;' k" y# w! j' u2 C! o% e' }
- #if CAN_RX0_INT_ENABLE ( M; B* O) V' i$ E+ j
- NVIC_InitTypeDef NVIC_InitStructure;/ @7 z0 a* [9 H
- #endif
7 w5 x2 [' u/ b# i7 ^% N$ z& M- i -
. j5 w+ S6 m# O - RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
# T6 C2 t5 a5 ~8 g; |: X u - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能PORTA时钟
+ M& ]2 K: ]- I* ~ - SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; //RMAP $ C6 ]$ r/ o* K; f- W2 v% E+ f& }
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_4);, `, o" y, F( C5 Q0 a" g
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_4);# @# d& }9 d- J$ R; @* j7 U, B
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);//使能CAN时钟
. ^2 ?7 l/ }. j! x5 ]0 z8 I
- }3 i! d% c% |2 \- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;% Z2 z% i% w+ z" b& l
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;" Q; M R: m9 C) J9 T3 s1 Y# }1 M
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
) j' `5 a0 }0 f5 n% w) c - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;/ h4 M2 b2 W5 j2 C7 b% O
- GPIO_Init(GPIOA, &GPIO_InitStructure);
1 m' [! k6 @# U J - 0 a5 u7 m5 O$ m5 K0 G
- CAN_DeInit(CAN);: d* }3 u3 |* o' r5 J
- //CAN单元设置9 {8 O: R( B/ E' O; Z" U# | s- f
- CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //; c T/ D' [! i
- CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //$ i, C/ C& n, A7 @
- CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//& z7 g: ^7 S" b) N& M
- CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 //1 ^7 Z }: O' \% B7 i4 m7 P
- CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 //
4 A h+ L5 Y9 [1 [ - CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 //
/ p1 S9 z" ]! s2 b( g$ ` - CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; //
& w& n6 G# h2 i! { - //设置波特率
" w `) ^" D; l6 C - CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
" X9 a1 E5 r5 l6 @ - CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq. k# W/ V I0 g+ S) I8 @4 M
- CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq }# [$ g( S$ q& G$ i! u$ m
- CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //
+ P# e/ y" e* P - CAN_Init(CAN, &CAN_InitStructure); // 初始化CAN1 # h4 r! H6 ~! s; I1 O- f! O
- ( \& ?" Z* U5 `0 n- r$ }' |
- CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0* v6 y$ l5 A& P0 V5 k! m1 a
- CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
% s( W7 `8 H/ H) w& u5 n - CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
4 P8 ?3 }. d% e+ j$ w - CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID% ?, {# ^) E J E6 h2 e
- CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
* }" P- Q' X2 X5 Y0 M- x! A - CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK4 F1 m: @! d) E6 z3 z
- CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;( _9 l5 q! X1 M. x: ?' @) f
- CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0% B% @/ ]8 u+ I8 k# G5 b
- CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0& c5 y6 e, s: c7 \( B! _( C
9 v* s6 A- D$ B" J5 s2 {# z- CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化; A5 D( ^ F# p( J5 _: _$ y
- #if CAN_RX0_INT_ENABLE+ F1 t8 R0 r2 d# F+ p; f, y" s
- + L9 Y( t/ y1 A6 X, Y2 j& T
- CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.
4 { s7 M/ y$ ^; G( [2 i+ f - + h% J; L' W8 u: ~/ b0 a& A' J9 s
- NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;9 Z( G* L2 l/ [/ e
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1# K$ n' q3 p( Y
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0: m9 V+ |. w x* b5 h9 M C4 K
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;) w! D2 Y3 M- q5 J4 C( p" ^0 {* u
- NVIC_Init(&NVIC_InitStructure);& D9 Q& J0 h6 I% M- j% |
- #endif
3 D# L4 c# ?% W4 o - }9 d1 \$ }3 h7 ~
- #if CAN_RX0_INT_ENABLE //使能RX0中断
) |9 [4 k+ E }% @6 n$ P - //中断服务函数 ( A# Z+ s/ L$ f$ X
- void CEC_CAN_IRQHandler(void)
& H- i) w c7 |/ G5 F' E - {
. |3 B" ^! Y$ ?; {7 M2 J - CanRxMsg RxMessage;" R' |1 \5 `1 U
- int i=0;
: }& A+ S$ f5 {. O1 Y - CAN_Receive(CAN, 0, &RxMessage);
1 G* y3 @' ?- Z- T6 R - //for(i=0;i<8;i++)
# i6 q% C J- U7 z3 k. H0 ^3 n: N - //printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data<i>);</i>
) @, m' W$ f$ m/ z& G0 U- V2 ]! e - }) c" Q9 u! P2 {" n8 b& f. x& F
- #endif
0 Q2 s, G8 p' C3 V1 B" }6 H) T
% C' S! `2 H$ z% ?! ]$ O- //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧) : \4 a) l# `7 q& h( G+ H y
- //len:数据长度(最大为8) 2 D3 ? k9 N5 x
- //msg:数据指针,最大为8个字节.' W% ^7 F! i, D* \2 M) L% r
- //返回值:0,成功;
' H$ s( }$ s2 ]! e - // 其他,失败;
( W% l, W' b+ }3 @% Y$ c - uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)
3 a& N) |! T& j1 o - {
! I4 x8 R- z; f. s( [3 f9 e8 F - uint8_t mbox;
, z0 \& y" A( y3 u+ q3 p; Y& j - uint16_t i=0;
- T2 c% o% }" P1 }8 \ - CanTxMsg TxMessage;7 s) ?$ X1 Q5 T$ o
- TxMessage.StdId=0x12; // 标准标识符为07 B" T' p% ~0 V5 v
- TxMessage.ExtId=0x12; // 设置扩展标示符(29位)
4 f* `* d: r, d w - TxMessage.IDE=0; // 使用扩展标识符' F8 S. K$ f# q1 K$ }9 ^" t
- TxMessage.RTR=0; // 消息类型为数据帧,一帧8位. g7 P5 _3 @3 o3 M# o
- TxMessage.DLC=len; // 发送两帧信息
X# F' j$ q/ r4 X7 W! i - for(i=0;i<len;i++)
% G, x; D1 \9 R/ R/ }4 Y# b1 a - TxMessage.Data=msg; // 第一帧信息
1 ]( Y4 ]) P. Z - mbox= CAN_Transmit(CAN, &TxMessage);
3 S" m$ F* H `# O d x$ ] - i=0;& D: j9 c9 a: ~% z$ m" n
- while((CAN_TransmitStatus(CAN, mbox)==CAN_TxStatus_Failed)&&(i < 0XFFF))i++; //等待发送结束
8 j4 t: E& g/ I5 J; T - if(i >= 0XFFF)return 1;
) }' O' }! ]: x" z! J, K - return 0;
7 H: ~- [: W- o6 |' R1 r2 [ - }
* ~! K" X! d# k) ~0 F - //can口接收数据查询! L, s9 }0 V( h3 E
- //buf:数据缓存区; ; r& Y0 r2 Y* k* b+ {0 m& i3 H2 r
- //返回值:0,无数据被收到;
0 A$ c/ \" {" P - // 其他,接收的数据长度;: }: @- L! @3 {( F$ q
- uint8_t Can_Receive_Msg(uint8_t *buf). V& E- K3 Z `' l( s |1 z
- { 4 {, ^) P2 d- N. p5 J( c
- uint32_t i;( X5 @0 }+ s; m! [6 w! | ?
- CanRxMsg RxMessage;
) F4 `( [" L, v* [% Y4 V - if( CAN_MessagePending(CAN,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出 , x0 f7 g5 F, O: W! | b$ a4 r. c
- CAN_Receive(CAN, CAN_FIFO0, &RxMessage);//读取数据 + F9 y$ x# o6 o8 ~
- for(i=0;i<8;i++)
% h* ~% y3 z( z5 B3 O/ E4 l - buf=RxMessage.Data; ( y k& f4 Q( c. U8 z* s
- return RxMessage.DLC; : T) M. U9 ~) s! K: P2 B& w) B& r
- }
复制代码 % n) O4 S, _) ~* N/ q4 E
注意:一定要根据自己的封装来设置7 S, z; h0 ^. l1 P, i# s4 d- N, x2 }
SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
. j( |5 m7 f* k& a/ Y3 U# b如果不设置 CAN_Init(CAN, &CAN_InitStructure);会初始化失败
9 q+ V# C" Y) c0 f( U4 G! h( A& f
; v5 a) E( A0 `' {" G# W
- W0 ~" K g9 g6 ^! s: D1 d! } |