代码如下:
* Q8 N9 u; f5 L$ X# V; W) U1 o9 Y0 X
- #include "mycan.h"9 U) t5 k$ H( T; X
- & x |* {4 P8 A1 _8 r! k! A- x b
- //CAN初始化& C; i& i& b2 }5 f$ s# V. ~
- //tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
8 n& h9 L9 A. [) r# R& L; h - //tbs2:时间段2的时间单元.范围:1~8;) o$ P. `% K z" {2 M1 G
- //tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq
1 u2 E% s. u+ s* R - //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1! ]/ h3 O5 K1 }
- //注意以上参数任何一个都不能设为0,否则会乱.
, k7 t1 S. s/ g6 w8 E% i/ G8 C - //波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);1 v" ?) U9 r8 s; u1 H" ~* R @: J
- //mode:0,普通模式;1,回环模式;
6 c( S; m5 Z+ p* R! V7 L - //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1); `! e2 ?! Q! W# {
- //则波特率为:48M/((1+8+7)*5)=450Kbps4 N: y' p. g$ ?1 g: c2 b
% H7 ?1 b1 q# [6 `- void CAN_Mode_Init(uint8_t tsjw,uint8_t tbs2,uint8_t tbs1,uint16_t brp,uint8_t mode)
! k# i5 M( k0 I. k) c) S - {
: g9 S* _: M/ R0 z/ t
3 a3 k+ ~8 i6 b6 q0 }( G- GPIO_InitTypeDef GPIO_InitStructure;
5 t$ u# w! E( s6 H - CAN_InitTypeDef CAN_InitStructure;; v- f! s4 N) Q7 v" V
- CAN_FilterInitTypeDef CAN_FilterInitStructure;
7 B; D- t3 `8 T) ?2 Q( W - #if CAN_RX0_INT_ENABLE ' V5 C/ V+ o5 @9 e( _# E
- NVIC_InitTypeDef NVIC_InitStructure;. ]+ A$ E! t0 ]
- #endif
8 }9 r1 K' \( b, P/ W3 j, {6 Q) d - 5 s4 f3 `4 r% Q3 Y
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);9 D6 F3 }5 Q, |4 l# `
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能PORTA时钟
' E8 L3 w4 K/ W0 ?$ K - SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; //RMAP 0 p( P" i4 V" X9 E
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_4);
( @ ]0 p7 g* E: _ - GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_4);$ d# l2 [, c1 J4 }
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);//使能CAN时钟
) g+ R- ^5 q' u$ D* ` - 1 X m' U7 d$ `4 d& w
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;2 o9 f9 Q0 z9 B5 y4 m H) a
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
1 ?1 q( ?% {0 p/ @1 F% N2 {- x$ I& G - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
# k! y3 F- r, X% f& ?# e/ `! H - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;/ G- B' h. I' M+ D. S6 q
- GPIO_Init(GPIOA, &GPIO_InitStructure);6 l t2 {. }. F& X
- 8 X6 Z2 g0 u: r
- CAN_DeInit(CAN);
( v( e7 J X& S - //CAN单元设置+ f& y7 k! } W. A/ |/ b
- CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //* c5 ^+ j+ G" Q% |* c5 `4 z
- CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //1 e, @/ c- L; ?0 G1 D' q/ {
- CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//# a+ W2 b; y4 i! C
- CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 //
. p2 x$ Z }+ D2 B e/ p - CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 // 0 ]( ~- G% U$ ~. M" o+ l$ q, D" W
- CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 //' J* M* `, ~" q3 T7 `2 S
- CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; /// Y; }- [% G! u8 F; I* q
- //设置波特率! n5 _. ^, e7 k; g4 j% A" [
- CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
9 B! K! E+ w8 b* M% S7 ` - CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq. L& f- h2 O- Q2 q! @6 I
- CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq( j' f! d+ F/ d) w* g8 `8 e
- CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //' l9 j( A, W( ^7 ^3 r$ e3 s, }' ~6 j
- CAN_Init(CAN, &CAN_InitStructure); // 初始化CAN1 J9 P- D& R7 \' d' i2 ?! r
0 V) Y& `. T$ |- F, D; B1 o& m- CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
" j, h$ H8 i* E# B! t2 [, d& ?% k2 s - CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; " O) e7 |+ A3 l- G$ g* \1 S/ H
- CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
7 C5 Y x0 E- E! H" |8 I, Z6 V" j - CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
* V# I8 \' M! s, a1 r$ k - CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
! x% G( p$ g5 I; K- R. H - CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK' m' \- L! o1 i [& _
- CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
9 N1 ^& p# l9 _' ` - CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
' C; Y$ t$ I+ r4 h - CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器00 v6 u! Y; `6 W% N* Q
- " ^1 ]8 D/ {8 N) c7 B
- CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化 j+ X& |( b: s4 l2 K# N) [
- #if CAN_RX0_INT_ENABLE
7 f9 E% |% m2 B - $ Y4 }4 d- J( t) ^/ j% g# }
- CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.
3 M: B* P& I; k$ `; s6 L- k7 s2 D0 M
/ t, m: }0 W, R" P3 Q# j, e- NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
% }3 N1 ^1 Q1 m8 Y - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为15 W& ~" A) ]" d0 R [
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
9 g) a3 W7 Z+ a G4 D - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;0 O6 v4 l3 v* B: B/ _$ U
- NVIC_Init(&NVIC_InitStructure);
! ~/ u! }5 ^9 h, o8 [' c% L" A - #endif
! [* p* u( V( O& P; F - }0 b6 B5 E+ q( k
- #if CAN_RX0_INT_ENABLE //使能RX0中断* W4 }$ m! F6 c# K* q# ]. q, f
- //中断服务函数
9 W6 {/ E: l# s" y$ c3 p3 g: X - void CEC_CAN_IRQHandler(void)
) M3 g9 d& v8 e5 l: m - {* Y* [, s- n+ F. ~* `8 Q5 B# I
- CanRxMsg RxMessage;
1 R' M8 S) S) ^- T9 p1 g. D - int i=0;; H/ R# G. E1 H- O7 v- S
- CAN_Receive(CAN, 0, &RxMessage);
: G0 `8 G9 [2 y" y1 w) ]! u# ? - //for(i=0;i<8;i++)
4 [$ v6 F3 L! ]. M - //printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data<i>);</i>' x* _8 f1 d0 \" c( l$ f
- }+ A0 A, d- V, ]' r3 U5 h
- #endif
% ]& i" O: w' i - ) ?# q' M$ v$ p% k! e4 G
- //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)
6 ?" e* S2 a5 [0 Q - //len:数据长度(最大为8)
/ |* Z9 S. `- \' A - //msg:数据指针,最大为8个字节.( i, Y# G) d" o0 x8 e
- //返回值:0,成功;* _! G" \) L7 F ]
- // 其他,失败;
! g/ ^ {1 r9 f - uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)2 u2 [3 y* W& v& X6 O$ W: D) Q" n
- { 8 D8 S; R& x8 d% R
- uint8_t mbox;2 o3 h1 W+ L' _! B) J3 Y( N7 r
- uint16_t i=0;
8 R6 K* h* D$ G" i/ m: J - CanTxMsg TxMessage;1 i6 U( I" M9 j( d W8 t) r
- TxMessage.StdId=0x12; // 标准标识符为02 C" u Q" @8 y; ?0 i! p
- TxMessage.ExtId=0x12; // 设置扩展标示符(29位)3 n, J+ y( n# x6 L' s7 Z; U
- TxMessage.IDE=0; // 使用扩展标识符 g2 t: _3 |( o5 t
- TxMessage.RTR=0; // 消息类型为数据帧,一帧8位
2 V) L% n5 K2 d# E" D- C - TxMessage.DLC=len; // 发送两帧信息; B8 g! D3 @1 t# @* l i S
- for(i=0;i<len;i++)
; b1 R/ r4 W$ c/ s - TxMessage.Data=msg; // 第一帧信息 . q$ C2 {1 x& m9 J0 d
- mbox= CAN_Transmit(CAN, &TxMessage); $ |) O: v3 j4 R' ?( Q: O: ]
- i=0;
9 d7 r! s) t! o) I* v1 B - while((CAN_TransmitStatus(CAN, mbox)==CAN_TxStatus_Failed)&&(i < 0XFFF))i++; //等待发送结束; o* l. Z# S# U0 W
- if(i >= 0XFFF)return 1;+ l9 S/ p7 {* \ }/ |# r' c
- return 0; 3 a: g9 Q- B; M6 y
- }( U2 P3 v; V% h2 w
- //can口接收数据查询9 D9 }( g# @/ w1 m$ S$ u' W3 R
- //buf:数据缓存区; $ C& c: B* Z$ A" |
- //返回值:0,无数据被收到;
5 T9 h4 B d) v" D* ^3 W3 j/ ^ - // 其他,接收的数据长度;! q- s2 G+ p; `; ]# I: \) A
- uint8_t Can_Receive_Msg(uint8_t *buf)
: N3 x' D7 d+ a, m9 Q( h+ M- Z - {
2 [# f0 [ F! ]" ^/ C: A$ w; U - uint32_t i;
( T+ r5 w' D- Z - CanRxMsg RxMessage;
+ q3 A8 T' C6 j: Z# u6 D - if( CAN_MessagePending(CAN,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出
0 p7 v4 C6 I0 [2 I" h - CAN_Receive(CAN, CAN_FIFO0, &RxMessage);//读取数据 # s, M/ i1 E% p& W+ L
- for(i=0;i<8;i++)
3 ]: |- v" h6 |" i8 ? - buf=RxMessage.Data; $ q0 g" z# r9 ^( J( D M* G
- return RxMessage.DLC;
! K! Q2 \) `$ k1 ] C - }
复制代码 , t6 R. s- }( r) K1 I* d6 c
注意:一定要根据自己的封装来设置
* m: o8 [: v8 i# USYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;0 ]/ c( q( @! J9 Z Y. j, Z3 B
如果不设置 CAN_Init(CAN, &CAN_InitStructure);会初始化失败' z/ V7 A9 l2 i% {- H
. `7 ?% V0 _+ W; E
; b$ L& Q; ?' Q3 P& {% Y |