代码如下:
# c f4 P( g5 b+ k
0 P% F& Z) k0 K& g( h+ \2 E( w0 _- A- #include "mycan.h"
+ o! d: \2 I' W( E
1 ~) U! M. y9 F4 i" ]+ r- //CAN初始化' f6 a, `! f% V$ H" A
- //tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq5 T" p. l M. f9 e: s' J& v. o/ D3 L
- //tbs2:时间段2的时间单元.范围:1~8;
4 ~% t2 G$ f! F! b3 X - //tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq5 i5 [+ @( Y7 J7 r' _0 `" n8 }
- //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1
# P7 D$ @3 T2 e3 {3 } - //注意以上参数任何一个都不能设为0,否则会乱.7 A; g( S- j! E1 s% g+ I/ T2 J7 M
- //波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);
2 i+ M% |3 Z6 q$ ?& e/ p - //mode:0,普通模式;1,回环模式;- N: |8 ~! v* O8 M& Z% \
- //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);
) N( `% h8 V( E4 i1 U* ^2 `3 g8 q - //则波特率为:48M/((1+8+7)*5)=450Kbps
7 Q2 q/ |* W" |9 z# N* M" w
& X; A/ H) w+ t- void CAN_Mode_Init(uint8_t tsjw,uint8_t tbs2,uint8_t tbs1,uint16_t brp,uint8_t mode)
& M" m, g; s* \% L C& ^ - {
" i1 i5 b! x! U- R8 O* V0 U
. o, C4 {% G8 j5 o) N( K- f/ Z s1 k- GPIO_InitTypeDef GPIO_InitStructure; * T _' M( u* x$ u" s$ ]
- CAN_InitTypeDef CAN_InitStructure; H6 L2 d0 s( q5 [6 `' I1 n
- CAN_FilterInitTypeDef CAN_FilterInitStructure;
+ V# T7 t3 E7 n7 S# F1 J/ s) ], L! [ - #if CAN_RX0_INT_ENABLE % U! w5 b4 [& N3 d& f! ]. f
- NVIC_InitTypeDef NVIC_InitStructure;
' m- S3 C+ t' O9 [, E( f6 I - #endif' v: ^! s( e+ O
- 1 s& ?* p& b* V% o7 ?. K
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);7 f# Z# E8 R* l; R
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能PORTA时钟 3 u \3 E3 b0 g" Q
- SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; //RMAP . w" i! @" `7 s
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_4);
: P/ b9 P/ a3 S/ Z - GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_4);
: m7 Q' i1 \: J( D6 @ - RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);//使能CAN时钟 ' k% d* X6 e7 K
- - C& D' ?6 [! K
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;) Q! x& e% y1 b# r! n; c
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;4 `: A/ f+ O! k. y; i, V
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
, }( H! H- g* I8 t/ ~; k9 s! Y' V - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
! V, ]: l" F+ M( o6 | - GPIO_Init(GPIOA, &GPIO_InitStructure);: z( N9 B7 ~, m
- / z3 ~/ p* D6 U) c: s0 R
- CAN_DeInit(CAN);' e @, M H- G
- //CAN单元设置0 s5 c1 Q& p: G# _
- CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //
- u. J! f* p/ K - CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //4 t$ h6 A( V. l9 t( X1 _3 c) m, T
- CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//
0 z: ?; y4 ^: R% V - CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 //
% f' e! l% A8 I0 k) j& z* x - CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 //
% ]; R5 I: \7 r) x6 Y5 D% h+ S - CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 //
5 @! M: `2 N5 A: U - CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; //' a+ F4 t# m7 F7 J
- //设置波特率
. B8 g# s# L' N* N4 R0 X - CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq& F8 _/ z9 F) a, b7 H+ n# E8 o* e
- CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq' m7 E- u& b8 m" S, ^ w, Y
- CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
2 w2 \% n# i. ]5 I& n0 u# @7 O) F - CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //
7 Q( h3 k v5 U; Y7 ] - CAN_Init(CAN, &CAN_InitStructure); // 初始化CAN1 ) S" y. B$ g- J5 w# H
- # w3 a/ e- L- O' i" o0 k
- CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器06 F" @* B$ f k$ f- ]
- CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
. n& T- Z4 V" s; J& [5 w" L - CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
1 M& J& [, K8 e6 G - CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
# v a9 x; \, S7 z - CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;! P- y$ ~7 R. c1 G
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
3 S1 _8 H% l2 f+ w3 M% ?# ?- K - CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;! o, l6 n, c- l6 `3 Q. d
- CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO06 [! e7 F. f* G/ g! j; u4 S
- CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
# b% E5 M9 R8 y0 Q o+ o0 C - 3 w3 Y3 |) a4 x3 m A1 l$ h& j
- CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化! ^2 I4 {3 v7 l3 h, i
- #if CAN_RX0_INT_ENABLE: T5 Y7 s( V7 R+ }: x6 L4 n' |
- / u$ j, L' [# F4 F* H; j# u# B
- CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许. 9 `, l1 b: {4 v0 T! o
- $ W% C! e( z: R* H- o- H
- NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
0 s' b3 q/ m: W3 s' x - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1; n* }9 ~' s! g6 J4 D
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为02 x8 j/ P# o) W1 o& Q
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;4 [+ f, [" c/ l. s% c: q! h
- NVIC_Init(&NVIC_InitStructure);
, c4 j ~+ ~* A/ [) M8 F+ w - #endif
* @) ~3 |0 [# ^' w& w5 ~ - }. N; n3 g" o! g# o* I5 l+ d+ U
- #if CAN_RX0_INT_ENABLE //使能RX0中断- |) A: n! _/ V( ]3 {- _4 T
- //中断服务函数
; n% A4 N0 v! C+ ] - void CEC_CAN_IRQHandler(void)6 T0 J& Z$ y d4 q
- {8 m4 C& F1 }2 L$ T% H
- CanRxMsg RxMessage;6 N a" ~6 Y. s4 g0 v! S
- int i=0;
1 e, C2 Z5 r+ ?8 Z - CAN_Receive(CAN, 0, &RxMessage);. k" Z) Z0 k0 ?& S
- //for(i=0;i<8;i++). w- ?% I. }+ ^' ^4 `
- //printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data<i>);</i>
; r' c$ @9 B. |% | a4 ^& b$ Y - }( S P/ u2 i, G) q
- #endif
* O- V# N4 v7 k5 R* E) v! B4 M - + f- E, m" F8 g7 R! }
- //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)
& K* D+ [: _ R/ n4 j4 \' ^5 s - //len:数据长度(最大为8) % e( T9 s$ X7 c
- //msg:数据指针,最大为8个字节.
! Q, G% u) o# r$ g0 a' n5 f - //返回值:0,成功;
9 V8 Z# z6 E. X' x' u - // 其他,失败;
6 N7 k1 w$ ?- d - uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)
( z/ f, O- x7 _* i+ B2 f - { " C8 A# o9 ]& N' ^2 A
- uint8_t mbox;
/ Z6 Y8 ]! [' j* S" J - uint16_t i=0;
, U5 V" O3 M4 \& `! j - CanTxMsg TxMessage;
9 ~8 j% W6 F, f - TxMessage.StdId=0x12; // 标准标识符为0
+ N9 i; ^8 r) \; M/ e3 q E3 H - TxMessage.ExtId=0x12; // 设置扩展标示符(29位)
- D# s% d3 G o; H - TxMessage.IDE=0; // 使用扩展标识符) D5 U. j. l6 q/ O6 c- A
- TxMessage.RTR=0; // 消息类型为数据帧,一帧8位
/ d4 U- L: f7 L' W/ t# f4 B - TxMessage.DLC=len; // 发送两帧信息
; ^6 n b. Q3 [1 n1 | - for(i=0;i<len;i++)
8 G r4 q; @$ B) n* B+ E - TxMessage.Data=msg; // 第一帧信息
1 O2 v. T' A1 R$ |& D. z - mbox= CAN_Transmit(CAN, &TxMessage);
1 l+ M* {% z4 u- g# B3 t - i=0;
( G2 w7 V' o. Q; w, h - while((CAN_TransmitStatus(CAN, mbox)==CAN_TxStatus_Failed)&&(i < 0XFFF))i++; //等待发送结束
9 e7 M% i* D! r* G* q - if(i >= 0XFFF)return 1;4 T! C# W) N8 O) Q) f
- return 0; 8 S, G6 R/ L( G$ ~) I" T, e
- }) V i& l2 E7 \- a. N: M
- //can口接收数据查询
8 E( s( V7 d- T, E+ o; a2 }9 W - //buf:数据缓存区;
) Y* l- @6 l! k( G - //返回值:0,无数据被收到;
$ U+ e% e) l+ C t! w- p - // 其他,接收的数据长度;
5 v6 @/ a4 g6 p7 X' p - uint8_t Can_Receive_Msg(uint8_t *buf)
1 V, H9 P- }) F1 [: a0 e' m - {
6 j. k, _( V- J6 M9 ~& q2 M8 ] - uint32_t i;
* s6 w1 E) n" ^$ [ - CanRxMsg RxMessage;# Y0 w4 j, Q% _3 _
- if( CAN_MessagePending(CAN,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出 $ b2 u2 U9 s# x* m7 r7 e8 A! v- f- q
- CAN_Receive(CAN, CAN_FIFO0, &RxMessage);//读取数据
R0 N8 m6 {+ q+ l' y - for(i=0;i<8;i++). c5 d7 v- i/ T( {* g2 n" ^/ i7 R
- buf=RxMessage.Data;
k! u. d5 ]" e( T; r, b; ~ - return RxMessage.DLC;
3 v0 d- H/ @+ _7 w( M" T3 R$ b6 D - }
复制代码
8 S7 f7 t/ k6 O y+ X+ p注意:一定要根据自己的封装来设置
6 l3 r5 V* q& Z" u3 aSYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
# w: _# I9 P- J6 H% f如果不设置 CAN_Init(CAN, &CAN_InitStructure);会初始化失败7 S N- @4 h: Y8 G" B& @
" ^/ z- h1 _3 v& n0 E# m" t+ n0 a
" V* h" ]# G6 H, d" r
|