代码如下:
( {* r, n! I9 v Z/ B! r3 k: ^0 I
9 \! ~# p0 I( d! R7 V- #include "mycan.h"
5 j& j0 w) N9 m# i" t8 q& p" Q - : N% R$ b; v; O* ?
- //CAN初始化
5 A# O. ]) ]- @" N, o9 ^ - //tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq' r7 y, p6 p7 _* ^3 H- a
- //tbs2:时间段2的时间单元.范围:1~8;
1 e4 j" |) ^) i/ E* l8 X - //tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq% P( s4 \1 M: t
- //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1
1 K" U& i- L' i9 z8 n - //注意以上参数任何一个都不能设为0,否则会乱.5 F9 V4 I7 f0 r4 n; J' }/ l
- //波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);
& u4 t. V7 ~7 v' p! P- m( I - //mode:0,普通模式;1,回环模式;6 Y& [! P2 g6 s7 X
- //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);! @: }$ D1 N+ w! O3 _
- //则波特率为:48M/((1+8+7)*5)=450Kbps
9 m; G+ e% K" e' r" ]6 Q' U
2 r/ Z. d' V; g4 T0 j5 c- void CAN_Mode_Init(uint8_t tsjw,uint8_t tbs2,uint8_t tbs1,uint16_t brp,uint8_t mode)" m3 g, {1 _0 _5 s3 L" D2 T8 @
- {
) U v0 c- N) C. | - % o$ B8 A* b" J. U. E+ g, J% h
- GPIO_InitTypeDef GPIO_InitStructure;
" i) e* I. d! @: q- z+ [ ~ - CAN_InitTypeDef CAN_InitStructure;
/ W! z, |" B# h$ z - CAN_FilterInitTypeDef CAN_FilterInitStructure;& m- O2 A0 }0 c, w4 T# j: u/ Y
- #if CAN_RX0_INT_ENABLE % n! w# K, b* k. [2 x3 J
- NVIC_InitTypeDef NVIC_InitStructure;
, H4 v) b7 @; N% U# k+ U. X - #endif
$ y& t) Y p) y& y B -
0 k) ]' C2 u) O- A! a" q$ \4 U- B1 } - RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
5 P3 a8 N, U0 g8 i' r. \ - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能PORTA时钟 ! c" t. F1 r3 w/ V& u% m$ y+ X- d
- SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; //RMAP 6 ]" p1 x3 Y# M& j" s7 t6 ~
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_4);
- z! J! W( u4 @* C: b; Y0 j3 e1 F+ A - GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_4);
9 T5 ?$ t5 n0 J3 I9 i* H. y2 o - RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);//使能CAN时钟
1 C) w6 y2 F0 ~" M
4 }2 \8 a( J* H# x8 |0 k- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
' I6 [( }% S" a - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
' l7 v# K: e$ y7 O: J- k - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
: G5 G/ O9 @& e- {# s6 _ - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;+ x" T8 [6 N1 T m
- GPIO_Init(GPIOA, &GPIO_InitStructure);
4 F9 t" r( D: R1 o. L Z1 g - 1 s+ ]! V4 W# f! p# v) p
- CAN_DeInit(CAN);
- s& B2 X* s: S - //CAN单元设置- O6 Y, P! |5 {( ?2 V8 O9 P
- CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //3 d2 W; i% @* ]3 |3 u4 S& q& Q
- CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //
5 |5 w# k% {6 g5 h+ T - CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//( k s- b! j, f; |
- CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 //
5 P6 u( \! h* F" \ - CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 // " f7 v! q4 V+ m' E @+ z4 F4 {
- CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 //6 O0 n* g+ @& Y- ^
- CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; //$ r. r$ {( S6 U
- //设置波特率# n3 u# J) b3 S( ~: m! o. U6 a4 Z
- CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
# ~4 {4 W; Y3 b- h: n4 ^4 J, T) k - CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq# F5 Z2 \+ x3 h6 i' |3 X$ t. i, J
- CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
; C: F; R7 G- G* [& f- k# [2 [ M - CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //
D3 [8 C# [/ y0 v4 y7 P - CAN_Init(CAN, &CAN_InitStructure); // 初始化CAN1
* ]( q4 g) F) K/ w( m; q7 |7 X
5 q+ f4 _; v' j% u& f1 X0 @- CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
3 W* j: r$ D, h; ?; q, [* Z# ` - CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
, ]3 w E% S g8 f/ Z - CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
/ M' D) a; I* _6 j5 G - CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID; Y% V- F- I' g" a4 W
- CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;" B) g, ?- v0 I& m* C8 G: G
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
8 `1 n8 e( J8 Y8 ~- J0 W - CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
- C& g( l0 B, y* S# y G4 I! ~ - CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
5 u z' o) ?9 m8 k( m - CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0) y+ P. n( s1 ?/ a9 c V
( Q! n+ c# u+ G, n- CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
0 c0 _" Z7 `/ B4 T2 L - #if CAN_RX0_INT_ENABLE L6 {1 N" S+ g
-
( B- f. r% F' i) I$ u) L - CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许. : B- l! |! I. j8 {, H* H, |' n
- - ~7 p( J+ C9 h
- NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;5 H* D6 t2 i Y. B
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
. v% N/ a9 v* K9 h& f/ K0 m - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
7 w) v$ K2 P) g - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
) G4 j: i& s" s5 c - NVIC_Init(&NVIC_InitStructure);
; X- F. e5 t+ [5 p; t' W - #endif
6 ?, {- G3 w0 W7 h0 N; x - }! z* h6 r4 B( p" O7 y- _5 a* M
- #if CAN_RX0_INT_ENABLE //使能RX0中断
' P @9 c2 o" M3 `8 I6 ]& u( K9 K6 F) l - //中断服务函数
8 s% | U5 S0 g3 C+ e# U - void CEC_CAN_IRQHandler(void)
: G2 O' }" [( e/ j& m! t7 n( f! z - {; @/ B5 l/ ^ n: U
- CanRxMsg RxMessage;
8 v( B! e+ J, ~( c# g6 G - int i=0;
" ^7 N& b0 F2 m# d - CAN_Receive(CAN, 0, &RxMessage);
0 p+ f2 E- {7 A) y# ?/ R - //for(i=0;i<8;i++)$ Y: x5 U5 A, u# @- {* i% y
- //printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data<i>);</i>
) u7 ?( }( z" [5 M1 Y+ y - }
) `1 L8 ]4 D# M t' Q, I - #endif
# R9 t5 `9 ]4 e6 r# x- T
) u! o7 `/ d+ O1 @/ |: H* C- //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)
9 d9 S7 J2 h" V - //len:数据长度(最大为8)
( I, Z' I3 j! T - //msg:数据指针,最大为8个字节.
3 F8 J' R0 K/ q9 F* f2 R8 N' S - //返回值:0,成功;( p7 D' N* Y9 k( a; W+ O9 K7 k
- // 其他,失败;7 {! f5 n0 _% o1 L6 Q
- uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)
: J- i) O3 i0 ?9 ] - {
0 g3 d; H) f' s9 B, \( X9 r - uint8_t mbox;
1 X! B/ i) \8 s$ T r6 a, J - uint16_t i=0;: E( f: }1 c/ ?1 p, A7 D* V7 Z
- CanTxMsg TxMessage;
- y C; ^: E# h& {2 r3 h - TxMessage.StdId=0x12; // 标准标识符为0& q. K& A: }! z. T; h7 j' c
- TxMessage.ExtId=0x12; // 设置扩展标示符(29位)
* T0 D$ I0 N( v2 s - TxMessage.IDE=0; // 使用扩展标识符# v. q' Z2 F5 E( r2 `: O5 `
- TxMessage.RTR=0; // 消息类型为数据帧,一帧8位: k( }, g2 D" N& y
- TxMessage.DLC=len; // 发送两帧信息
2 q1 _6 ?6 ]8 J3 I, T( g - for(i=0;i<len;i++)6 r5 x* c+ n6 ?6 A" [ C
- TxMessage.Data=msg; // 第一帧信息 / B. z+ m5 Z! F" d4 Y
- mbox= CAN_Transmit(CAN, &TxMessage);
2 c$ ]; z: W. Y8 k7 Y - i=0;# X9 M S! u3 G. e
- while((CAN_TransmitStatus(CAN, mbox)==CAN_TxStatus_Failed)&&(i < 0XFFF))i++; //等待发送结束
6 O3 a! M3 c7 V( F8 l) y ^9 h& b - if(i >= 0XFFF)return 1;
" i( _9 m( C) k$ a- C$ I# t1 ~. ? t - return 0; $ y' m5 b- w& J+ ]7 M
- }
: x I! @6 G e6 p4 O# ?8 b - //can口接收数据查询
. X y& ^% j* B1 \1 K/ [/ A8 |. @1 q - //buf:数据缓存区;
& Q, f4 W5 k0 f4 t5 F - //返回值:0,无数据被收到;1 B' Y2 {1 Z, H) S, i% e
- // 其他,接收的数据长度;, [; g* C8 O4 I/ ~( ]
- uint8_t Can_Receive_Msg(uint8_t *buf)
f g' @. ~0 V6 V - {
/ x8 t( L T4 o3 B* U' z+ w/ N/ V - uint32_t i;
0 h1 p5 d; F, q - CanRxMsg RxMessage;
, L4 r" P. v z( E - if( CAN_MessagePending(CAN,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出 4 z8 `0 X9 I* F' w/ t4 [+ _
- CAN_Receive(CAN, CAN_FIFO0, &RxMessage);//读取数据 8 o! ?1 q: {2 `8 q7 ~8 {
- for(i=0;i<8;i++)
, p* L: }4 n3 n$ f2 W8 v5 B - buf=RxMessage.Data;
1 @: W" p# X6 L8 P0 Y - return RxMessage.DLC;
3 c6 y, e7 x# D9 W$ f - }
复制代码
6 |# c# b" Y. z6 G& ]% u注意:一定要根据自己的封装来设置6 S( L0 d* z& v* [
SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;6 P. i% ^' P! T: w" M3 X3 u
如果不设置 CAN_Init(CAN, &CAN_InitStructure);会初始化失败7 t7 r4 w8 d5 _# n7 X
! E9 f2 ~$ O T: z0 I7 p6 p1 U9 Y" R; |# U
|