代码如下:: n( k! F3 @ i( [
x" B+ D7 U/ Z0 W, k5 W- #include "mycan.h"
% e. r% ^) e7 ~ t0 I8 J' u
2 ?1 H& Y4 @$ D, Y/ D1 `- //CAN初始化
@/ }9 `3 l' J/ ]' E - //tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
% Q0 h" K" v5 M3 Z9 k% S2 d - //tbs2:时间段2的时间单元.范围:1~8;% r% \1 A2 b* x' k) G
- //tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq
' Q7 i" o7 _' \( F7 z - //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1
5 b0 ?/ g$ n3 Z& d$ G A - //注意以上参数任何一个都不能设为0,否则会乱.
3 D" k- o2 f7 G! @ - //波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);! I' `6 Y9 Q# t4 z( Y' y+ B
- //mode:0,普通模式;1,回环模式;. a. W3 `7 ]% K2 S6 T) t
- //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);
: u# a1 N# c7 n0 p) n ~; C - //则波特率为:48M/((1+8+7)*5)=450Kbps
' g* c0 P% \. d4 R ^4 \* p
" o" b9 m3 ~; ]( l' h4 n- void CAN_Mode_Init(uint8_t tsjw,uint8_t tbs2,uint8_t tbs1,uint16_t brp,uint8_t mode)/ R. v' W) F: r
- {
2 Q2 L* v: W) S9 U - $ f2 j2 Z f8 f3 _, D
- GPIO_InitTypeDef GPIO_InitStructure; / g8 Z- S- w& ~# ?
- CAN_InitTypeDef CAN_InitStructure;1 e& d7 h2 p- F/ g
- CAN_FilterInitTypeDef CAN_FilterInitStructure;+ c+ s. h6 V# G8 b4 V
- #if CAN_RX0_INT_ENABLE
( i# b: J3 ~) i+ W. {& l1 X" P - NVIC_InitTypeDef NVIC_InitStructure;
: A! `- S$ C( p! ~/ G' h - #endif& P( P* H2 t0 Z) M& `
- ( L8 ], [ M- [2 I2 h; J6 }
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);" Q/ V7 [% U! v' p$ a% z
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能PORTA时钟
' J3 h9 i+ n! y! `5 x! Y( z - SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; //RMAP % {* I. J$ U8 i7 Q0 b
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_4);: e7 `8 z. h3 F
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_4);
. F% b q; ^$ I6 I - RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);//使能CAN时钟 7 `) s7 n3 N: N: c5 h$ ?2 f0 N
- * j& z7 t% q, [. I! w/ t5 q+ N( S; F
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;; r; A7 |3 F# ~1 B! v
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;) ]/ `2 c. Z( a3 w% h
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;/ [6 j6 q l* g9 E
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
8 G$ r& B3 D- J& _5 U/ x$ K - GPIO_Init(GPIOA, &GPIO_InitStructure);
+ Q8 F5 [. [0 o; `" v: w5 ?4 B -
, @0 R2 b2 o2 @. w4 C - CAN_DeInit(CAN);# V& I) i9 Y2 q: ]! A
- //CAN单元设置
, ?7 T( w1 k1 r - CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //3 C! H4 c! M1 d# L% P8 m! P
- CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //) j) U! O# p {; ?7 W( |: L' c$ F
- CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//
" Z+ B; q! ]8 {/ W- K. F& M1 |1 W' T% U - CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 //
- I5 s$ X' i) }1 V( n" i, N9 B - CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 // , \6 D2 P1 g# p. b
- CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 //
# T% i, O% h! w$ ]% ] - CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; //
, j: W" }' h8 M. U$ q/ t+ h O! O l - //设置波特率
- S. o$ Q) H# D \ - CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq( w9 D% u2 T8 G
- CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq. B C- O/ m& H# p5 l- n
- CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq, u4 z$ T; ]* \# a" D
- CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //& L; x! e" q9 e; ?" @$ r) I
- CAN_Init(CAN, &CAN_InitStructure); // 初始化CAN1 2 n$ b+ t" V! `" g
- 4 b# ?- C! a/ e
- CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
4 l1 r- a' p; V! ~5 m# C ^* A - CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; 6 S$ I( I; W8 M z, {1 T1 P
- CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
6 V0 \1 Z- W R! e - CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID- C4 [+ I6 l/ D% L# _
- CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;2 S2 \3 Q5 D) f. Q7 F7 ~$ S& @
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK! ^( ?- w: l* P, |. c, P
- CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
0 p5 y& @" E3 W. g$ G2 b - CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0; U ]" u0 E# E2 k
- CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0, D5 o/ L8 a* ]; `+ d: A5 _
- 3 Q, ^$ E+ C6 A1 V8 F: O
- CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
6 W, P6 K1 J) q* n- f& L - #if CAN_RX0_INT_ENABLE8 g" M9 M, F4 |' s, E( l
- / ?- D I7 v6 Z) [. p: \/ s3 T' w
- CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.
) p2 Y" H u9 L( G
7 e+ L) M8 I( e, a0 s; \8 [/ @- NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;: U& W/ Q g' U/ [7 W/ Y
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
9 s6 \2 P7 ]+ s7 d - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
1 v& x: A6 l1 G" K2 g - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
& X+ f! _0 i1 q; ?% ~; _ - NVIC_Init(&NVIC_InitStructure);
+ K. I8 z3 ?# z. ?+ c; _7 ^1 K! C - #endif+ t* {# [5 A! U( E6 k1 o' M
- }, q. _' J8 v+ ]( Y7 j2 P) B
- #if CAN_RX0_INT_ENABLE //使能RX0中断
# \ }. \1 j/ u3 \ - //中断服务函数
6 r: `' T3 r9 o# b5 ~ - void CEC_CAN_IRQHandler(void)
7 k' p" D2 Y* M( `, @/ E: ] - {
, H: F0 ?& h1 V; k' v# e2 ^ - CanRxMsg RxMessage;) ?' L* I- }* x6 h
- int i=0;/ a0 y5 I* n4 m7 u% S. q$ ]. ]$ O9 a
- CAN_Receive(CAN, 0, &RxMessage);
8 C4 E, q% h: q/ ~ O - //for(i=0;i<8;i++), F/ Y6 }. A* D* I) S
- //printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data<i>);</i>
9 m C5 D. c/ g8 ~# ~ - }
k; G7 W& z. g5 T - #endif+ l: J% D: z4 ~7 u
- 8 X+ s' I9 g6 v
- //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧) + E& i9 O m; o0 N# w$ J
- //len:数据长度(最大为8) ' C8 [3 u) Z m( k' T5 e9 u0 i
- //msg:数据指针,最大为8个字节.3 X% h& z/ u3 [3 j1 R
- //返回值:0,成功;1 ]& N% ?9 C4 {- b3 H
- // 其他,失败;9 P2 r6 |2 @5 `- z
- uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)
* g( b8 r1 E9 i: _. R+ C - {
! {; {" _4 r7 b N$ l- S - uint8_t mbox;
% C# {; |/ J9 O - uint16_t i=0;
+ e# Z' @: K u% X& b/ l - CanTxMsg TxMessage;) p' h- T9 \: I
- TxMessage.StdId=0x12; // 标准标识符为0
/ z4 |' A7 f" e+ E) c; V' N8 }( d - TxMessage.ExtId=0x12; // 设置扩展标示符(29位)
* T0 i2 B% J3 g, E) |. Z/ f& k - TxMessage.IDE=0; // 使用扩展标识符
1 L3 H( B9 m( z- I - TxMessage.RTR=0; // 消息类型为数据帧,一帧8位8 H: v w: ]' Y5 j- ^' B
- TxMessage.DLC=len; // 发送两帧信息
/ ^' g3 K0 o/ I5 D$ } - for(i=0;i<len;i++)3 @% N1 g* ]5 ^3 W. R2 P2 V) M2 u
- TxMessage.Data=msg; // 第一帧信息
/ ]# P; N" i' w2 Q' Q; s M - mbox= CAN_Transmit(CAN, &TxMessage); $ y6 ?) V7 b {7 S; P6 V' b2 h
- i=0;
+ a0 E1 Y! u! `2 k- o8 j# b - while((CAN_TransmitStatus(CAN, mbox)==CAN_TxStatus_Failed)&&(i < 0XFFF))i++; //等待发送结束
4 y; c! C) Y2 E3 U! |% f. @, W F - if(i >= 0XFFF)return 1;
+ [" N* M8 `0 o% v' I- g - return 0; + c' s5 ~: T# ]# Z# j
- } `( `3 T4 I& p. J- Y$ n
- //can口接收数据查询
, A0 L' U" v* r- A - //buf:数据缓存区; ' ?+ ]) {: Y; d9 S+ s
- //返回值:0,无数据被收到;( U4 {3 S; Y( ?3 V3 `) @2 A b
- // 其他,接收的数据长度;8 o! L* b# a6 y- |
- uint8_t Can_Receive_Msg(uint8_t *buf)
/ d1 T1 c' M( h - { 3 j6 p6 q* G# I9 ?6 W. f" _3 M
- uint32_t i;) `7 O: D% t. F5 B) e$ ]5 [
- CanRxMsg RxMessage;
* f( A2 _- ^/ s% A - if( CAN_MessagePending(CAN,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出 ) m% m% _- [- G' s
- CAN_Receive(CAN, CAN_FIFO0, &RxMessage);//读取数据
4 i+ O) W8 d" _5 A9 Z6 a! d- F/ P - for(i=0;i<8;i++)7 y M% p. v m. L6 Z$ Q7 Q
- buf=RxMessage.Data; 0 P' ^% y- O2 z5 b- u
- return RxMessage.DLC;
2 t7 u, o; p9 p* h - }
复制代码
$ w2 s: S% T4 H+ x注意:一定要根据自己的封装来设置
. m6 o7 {$ F" c4 YSYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;5 F: D) H" k1 V2 l/ B) R. x
如果不设置 CAN_Init(CAN, &CAN_InitStructure);会初始化失败7 Z! Z% z7 z1 _ Z% U* N
3 Z9 x9 d1 F1 E9 R! e1 N$ Y# b" w& l Y- t- I% _8 O W9 i
|