代码如下:; H2 @/ ]6 S" y) I1 d0 b3 T; V
/ G4 R P7 g$ V, s' D" B
- #include "mycan.h"
) c; X+ Q# y6 \8 {6 N# Z3 @) d - 4 E- j' T h+ y7 r( f( w
- //CAN初始化7 f& z6 F+ L: y) l+ X% Z* s" m
- //tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
7 d: f5 f8 y6 c; F7 K5 u' B - //tbs2:时间段2的时间单元.范围:1~8;% T# ]' a& @+ z( k
- //tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq
8 V5 g- t, h' s+ l1 H - //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1
, S3 J" G# U {7 y - //注意以上参数任何一个都不能设为0,否则会乱.
0 O) y$ y. z0 S - //波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);) F+ K x5 s) E0 x9 b
- //mode:0,普通模式;1,回环模式;
) x- g4 W9 [" x0 u& w - //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);$ j, z1 M: o m' r
- //则波特率为:48M/((1+8+7)*5)=450Kbps @& @8 f6 _$ k/ P' |
- 3 A4 o" f' F; h/ @0 f
- void CAN_Mode_Init(uint8_t tsjw,uint8_t tbs2,uint8_t tbs1,uint16_t brp,uint8_t mode)! l% f a. m) d/ p
- {8 ?1 N' c. `- Y0 J- P4 b% s# D) P; R( Z
- 9 s# R9 v0 l( f: g9 [
- GPIO_InitTypeDef GPIO_InitStructure;
. t- [' f% c$ m% b6 t - CAN_InitTypeDef CAN_InitStructure;/ i4 B! x2 V# n* w
- CAN_FilterInitTypeDef CAN_FilterInitStructure;7 }4 H9 R( r' t$ y
- #if CAN_RX0_INT_ENABLE
0 V5 n$ W! |+ ^ - NVIC_InitTypeDef NVIC_InitStructure;
$ m$ P- Y- Z( x+ F/ m - #endif
+ Q# q6 Y* m5 r! } - ( Q) ~& t* c% ~$ Q3 l% A, H
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
; h8 F8 V! I% R - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能PORTA时钟
6 B& s' ~( s1 H - SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; //RMAP , N. N' k& L# w) v$ W' k) p/ d
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_4);
Q9 c% }! e8 m$ p) W - GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_4);
3 I$ V- C# F Y" |7 d4 i, m - RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);//使能CAN时钟
, }1 X$ ?! B! `& X* V- V9 o! j - 7 h; B$ e6 Z7 t; S" C
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
?/ x& Y& e& B& ?/ G- v1 Z. j) Z - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;) V0 Y* ~+ l. V; T5 a7 i Q+ {& i
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
8 d4 e5 n' e4 C - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
6 T2 i- L3 r) l6 U0 W4 g- e, ]/ ] - GPIO_Init(GPIOA, &GPIO_InitStructure);; E1 d; y2 ]0 D" A2 S
-
: p' ~& c- F3 U v' V; X, X - CAN_DeInit(CAN);" C) H0 W* F' Y# d( t
- //CAN单元设置% `/ O; B- ]' i! _
- CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //
3 n. U3 O6 ^9 k8 a3 T$ _. o' t - CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //, q' c& e7 y1 T7 I4 s7 x
- CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//
8 }3 U$ K/ V0 ^) j# M - CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 //
( r2 p* f7 t8 a, r& ]/ R E - CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 // ) F6 K, `. R4 z& t* n
- CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 //) j- Z# j8 H7 u0 z" N
- CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; //4 D& L2 a& v7 \; g2 }2 A
- //设置波特率
, d' G0 J) s. I/ m1 w0 o - CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
. g$ ?0 e1 {% v$ o7 c - CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
$ z" V6 M' i$ ?# T - CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
: m8 c1 _! z& n; P1 l. i4 U - CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //# {) l5 x; b0 q: O0 U" m
- CAN_Init(CAN, &CAN_InitStructure); // 初始化CAN1 . H9 @2 S8 P1 |1 m2 C/ K
- : {. L: K& d M# R$ k: p Y
- CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
2 g5 e3 G% u% I - CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 4 a; [) ~4 V. h0 A |8 M
- CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 * e5 M0 T# u n& Z
- CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID7 j& E) V/ q: ^4 m& {! m$ P3 b
- CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;" S: P# w; [" P8 `! \6 k4 u
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
) }, M% S; J' O - CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;% c" ?, B; `: p) z
- CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO06 i! H6 r2 j6 c+ g# E
- CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
6 k* r3 `3 j; I( c( U& ~
! \, T7 F: I. o8 r) ]- CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化& _8 _& V* W7 r- A% w2 q3 Z# ^
- #if CAN_RX0_INT_ENABLE( |1 o0 R* l C; O
- % ~, b. ]3 E2 [/ E+ J
- CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.
2 {1 F' i h0 Y0 M
7 k. r! T2 g8 R% J" L# w- NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
0 @/ B+ O% D* D" u6 @. [ - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
0 r* c( d; u' D8 P0 D; @* d) t - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
' Q9 C- g# a. t8 } - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;' ]' Z& c3 y/ I* p' [/ K
- NVIC_Init(&NVIC_InitStructure);
/ i1 q& }2 [* M4 R - #endif# Y: _* W f' m7 `7 s
- }9 E, m* }6 b: ]9 P& O2 [/ k
- #if CAN_RX0_INT_ENABLE //使能RX0中断
! K6 t) J* G+ D% {9 V - //中断服务函数
7 E7 w* g' Q( v J' e& _3 q - void CEC_CAN_IRQHandler(void)
6 l8 P( Z: U$ T1 A; ]$ ]' ^ - {
_) R' c2 Y7 r8 G8 z' ^( B - CanRxMsg RxMessage;5 J7 {; B8 z% P; n$ W
- int i=0; W% f" `/ h; K" ?/ p$ G
- CAN_Receive(CAN, 0, &RxMessage);4 U5 N8 l/ R7 ?
- //for(i=0;i<8;i++)
8 I; O( m" P( b6 J - //printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data<i>);</i>
8 B& k6 s5 W' V9 e$ [3 p* g3 Q - }
% X: X8 i' @! g( b% f - #endif4 K$ d: H/ V5 s3 A$ F1 F
8 U+ Z4 z7 i5 Y* C" R- P: `- //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧) % B, i. m# F/ o2 w1 s* E% ^) p' l
- //len:数据长度(最大为8)
0 N: n8 h7 {/ v! A - //msg:数据指针,最大为8个字节.
3 }+ s$ i/ @5 X" h) T - //返回值:0,成功;7 J+ A6 n$ J( X" V' m
- // 其他,失败;
( V) r3 k0 b2 W. X4 I - uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)( U( Z- `1 F5 R% E% ?
- { . _* f: A' ]9 L5 i4 X- |5 E
- uint8_t mbox;& p; Z2 N0 k) E& J( a- l" z7 F9 b
- uint16_t i=0;
) r) K# |1 H8 B! v - CanTxMsg TxMessage;
, q% u0 |' {8 j7 \0 } - TxMessage.StdId=0x12; // 标准标识符为0
7 J1 l$ j2 w5 ~: Z7 p - TxMessage.ExtId=0x12; // 设置扩展标示符(29位)
4 ?; Y7 T" l8 z" B - TxMessage.IDE=0; // 使用扩展标识符! a( B% D/ I/ w
- TxMessage.RTR=0; // 消息类型为数据帧,一帧8位
. {. G: g3 A# T+ d o5 ?' `8 M$ R2 c - TxMessage.DLC=len; // 发送两帧信息3 p, X0 t: K7 P. o) Y2 f4 `+ c
- for(i=0;i<len;i++); p" m/ R9 b- \
- TxMessage.Data=msg; // 第一帧信息 ) v9 k+ {! Y& o* L8 { R3 _2 q; c
- mbox= CAN_Transmit(CAN, &TxMessage);
3 J5 Y# y6 B7 s' a - i=0;: _/ \- \. `- b+ o4 s
- while((CAN_TransmitStatus(CAN, mbox)==CAN_TxStatus_Failed)&&(i < 0XFFF))i++; //等待发送结束
8 _! Z- k6 j3 R/ i2 y1 c! _, { - if(i >= 0XFFF)return 1;) I" w* K7 y% s) M
- return 0; ; H7 H+ x9 y/ T7 r4 l) v
- }
+ z2 |' U/ V# B8 |- k. K - //can口接收数据查询
) }; S: w+ s1 x1 u6 A& p; O - //buf:数据缓存区;
2 \- k% T+ |- r! K% s4 G - //返回值:0,无数据被收到;
: v; Z/ K# c5 b7 X" ?7 o9 h4 W - // 其他,接收的数据长度;
% `- r1 I# }- u9 O - uint8_t Can_Receive_Msg(uint8_t *buf)
2 V, o0 R; q- a: ?9 z; I - { : X) R" u$ k3 q( C8 W& X! b6 ]( Y
- uint32_t i;3 s$ \# S+ w0 k4 t
- CanRxMsg RxMessage;
, N) r& `1 w( x% D/ f' P - if( CAN_MessagePending(CAN,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出
; u$ b9 y" |6 s/ x4 g - CAN_Receive(CAN, CAN_FIFO0, &RxMessage);//读取数据
' c% M V3 ~2 l - for(i=0;i<8;i++)
) j1 @- x, V1 }$ V9 q - buf=RxMessage.Data; ; A+ _9 Q* f4 Q" C" X0 H1 X8 ]
- return RxMessage.DLC; 9 s1 _! @- B$ g. n4 s
- }
复制代码
1 x3 D. }0 B4 b- v9 M% Y5 E8 Q! L注意:一定要根据自己的封装来设置
& ^. q0 H4 v8 Z3 y- i2 x6 NSYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;/ R4 \# j& z& z0 ]$ x
如果不设置 CAN_Init(CAN, &CAN_InitStructure);会初始化失败( i/ g8 x7 O1 B( h6 k0 P2 c
& @6 s( u; g! V: J# G- i; ~
! x7 n5 o: a7 R1 m. y* g
|