代码如下:" w+ J" Z( A7 Q- j
V% u% d% L% e$ A
- #include "mycan.h"
" P; c% w# {" b) k$ K$ U/ J6 J - 3 D1 r% b8 b0 A
- //CAN初始化) t/ x2 h5 i/ w5 g) [) u" E, I
- //tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq9 O: m* T0 C3 s$ e
- //tbs2:时间段2的时间单元.范围:1~8; K4 m7 _) B/ w* ~
- //tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq7 `8 [! h7 x, x: C- w+ a! L
- //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1) m. }4 L3 V7 A6 x$ ]
- //注意以上参数任何一个都不能设为0,否则会乱./ {# a. p) U6 J$ c6 e7 H9 G2 X8 @
- //波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);
" N- s9 S4 @+ s& l4 U - //mode:0,普通模式;1,回环模式;
2 I6 b, ]! |/ J2 F9 ? - //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);* E+ p% |6 [) @" _4 B) [# B
- //则波特率为:48M/((1+8+7)*5)=450Kbps/ L+ H% r+ i" b
0 Y. e0 J I& I8 v, x3 `- void CAN_Mode_Init(uint8_t tsjw,uint8_t tbs2,uint8_t tbs1,uint16_t brp,uint8_t mode)
1 W- X) O9 c, ]/ ^- H - {
) ] g6 e0 k {- Q$ m2 N0 b" K
/ c1 Q" S" t. h- GPIO_InitTypeDef GPIO_InitStructure;
h" F" q4 c+ i5 j( v0 t5 U; i7 _ - CAN_InitTypeDef CAN_InitStructure;
% p3 Q! l+ s6 ^+ e& Q& ^ - CAN_FilterInitTypeDef CAN_FilterInitStructure;
/ a2 V& G. n+ r& s6 o3 o - #if CAN_RX0_INT_ENABLE 9 [. D8 E+ G- Z7 a0 w* _$ R
- NVIC_InitTypeDef NVIC_InitStructure;- @, V: q( B6 f8 L6 N
- #endif
6 ?0 Q% _! V L- R! X; I/ G$ k4 u- E -
4 Y8 M, \% {: M8 O& U6 V' I8 [ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
8 A8 [1 |6 o- s1 x h3 u - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能PORTA时钟 ( F% `7 D& Q# l8 Z% f7 v
- SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; //RMAP 3 ?9 u. J' t( m7 C. F$ z3 j
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_4);/ O' ^4 x/ k; g3 `6 T* {
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_4);6 q( L6 y, l3 H4 v; T
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);//使能CAN时钟
5 D9 w; Q6 _9 A6 |/ y, f2 v - ! d; r1 `6 Z% g% F( d6 g) l0 W& l
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;# G3 @: t2 ~1 ^3 M
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
' Y3 S# [5 W1 p& o0 D# H - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
" T/ c: d0 P6 T3 T - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
8 i0 l: K8 _: a7 | - GPIO_Init(GPIOA, &GPIO_InitStructure);
" Z2 Z* d6 Q/ t) h* Z -
2 I" W0 X0 \% E9 U. \' N, y - CAN_DeInit(CAN);
1 }) q8 G% ` C* N+ D! m2 \5 J - //CAN单元设置
5 b b8 Z0 {9 v$ N, e7 R - CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //7 ]& D0 R% `: h8 B9 K
- CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //; u: W7 ^4 g+ [- Q
- CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//+ r) v5 g3 n- r2 n/ J! G; c
- CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 //
; ?& j, `7 z; D3 ?+ H: @/ ? - CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 // & \5 K% H8 ^3 Q+ S% I9 m# b3 i6 ?
- CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 //
- d K# ]3 z* Q4 i. K - CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; //
5 {8 K5 j5 Z. p - //设置波特率
0 H6 w. X1 F) G; y1 N - CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
2 q2 z& ]3 ]5 p, @ - CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq" F7 W$ j1 D1 R& S! Q3 E! y
- CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq
+ v {6 [% [2 p/ E+ p - CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //
& }& R' Q4 V( M$ a- I0 M. W - CAN_Init(CAN, &CAN_InitStructure); // 初始化CAN1
: F$ D A4 W) |" M
' i9 E+ `/ |" e: L! V/ s- CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
5 ^' } S- u" M( f - CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; $ b1 W/ }; X$ x# `5 F
- CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
" Z3 i$ B0 i7 l( t6 ~ p( n" z - CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
& v' n2 F/ t% f% J4 b- Z - CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;+ D) ]5 v1 D1 @! [- K) @
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
- u, {$ J0 b1 f6 O$ S- f0 u* B - CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;
* c: ] ]2 W8 G5 `3 O. Y+ c3 r - CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0$ P: d" |( I9 R5 ~
- CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
7 n6 v' c4 g0 |7 d; _: t$ p - 9 C: n" N' G7 f9 G
- CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
+ [6 l: ]7 T8 D+ @: B$ |0 q - #if CAN_RX0_INT_ENABLE i: B' r! y4 B
- 6 f" y' t3 K9 d9 F: z m
- CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.
7 K$ t: C/ b k5 h) L; r
2 Y' j. a/ b7 [ m2 q, H' L- NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
" f2 m! Q1 P. c# I4 K - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1' X/ [" G5 i: g+ X) W+ u
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0 d D6 c) a: T y; c: k& J# T
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
0 F* V' h {0 Q) F/ t. V* }/ J/ c4 { - NVIC_Init(&NVIC_InitStructure);
: q, x1 F+ g% V% t9 Q7 Q9 [ - #endif# W: N' L. h! m* U! D2 ^
- }
3 D! r2 o; M: |$ U! l" _ - #if CAN_RX0_INT_ENABLE //使能RX0中断* C+ h9 i+ d" A2 M6 S2 F
- //中断服务函数
: S4 B) X o) n$ w( c3 U - void CEC_CAN_IRQHandler(void)
i: y5 X* a" M$ S" S9 T- T7 P/ h. g - {
% J" ~! g) ~2 \% n - CanRxMsg RxMessage;
. N! g+ \, ]: I: o* G - int i=0;
; q! m: Q: K4 T/ _6 j- L6 U - CAN_Receive(CAN, 0, &RxMessage);% U7 B8 P- o# S9 X8 x
- //for(i=0;i<8;i++)+ [6 R o X3 Q
- //printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data<i>);</i>
2 A1 R* W( Z; R$ { - }
9 L) x$ t. D- R p0 S* }' v - #endif
/ {' ]) |) l7 o$ ~; X( Y
) v8 }6 P; a4 K9 o- //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧) 8 M' }5 i8 r$ T6 T
- //len:数据长度(最大为8)
$ h/ J! j4 _( p4 @" R) m5 a - //msg:数据指针,最大为8个字节.
' N7 H' c& ~4 b$ f# q0 b - //返回值:0,成功;
' F/ }8 q% p3 m4 ` g: G) C# b - // 其他,失败;1 V8 t+ d" w3 w$ ~: ^
- uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)- G/ k8 k+ N2 \. L- Y7 `
- {
' L% I, v6 I" |7 w2 e$ v; A( N - uint8_t mbox; @$ d" K9 k) l+ M) O2 S9 t
- uint16_t i=0;
( A' @5 s1 K+ I* P9 X - CanTxMsg TxMessage;5 ^% K+ w2 a/ X+ g+ U
- TxMessage.StdId=0x12; // 标准标识符为0
7 ?! N% [' _/ I) H- B* V - TxMessage.ExtId=0x12; // 设置扩展标示符(29位)
- S, V( P; n# B* m- G; S% y% n - TxMessage.IDE=0; // 使用扩展标识符
! K- O" o; b: p8 h- d - TxMessage.RTR=0; // 消息类型为数据帧,一帧8位/ q' c. e5 h3 G u
- TxMessage.DLC=len; // 发送两帧信息& [. b! U, m4 W% h: w# J! B6 F
- for(i=0;i<len;i++)
* S+ I6 N7 m' O0 I, ?) \+ g - TxMessage.Data=msg; // 第一帧信息
6 o9 ], Y* E/ N) s - mbox= CAN_Transmit(CAN, &TxMessage);
. U; \( F' s- `( F* F; | - i=0;* b+ L/ N1 p! l8 ?2 `) _; N: x$ G8 V( _
- while((CAN_TransmitStatus(CAN, mbox)==CAN_TxStatus_Failed)&&(i < 0XFFF))i++; //等待发送结束
6 f d1 R6 [2 L, R - if(i >= 0XFFF)return 1;
! p( a" I* i5 y' F - return 0; . {% D6 b9 Y4 @3 D& {
- }
+ C% m' L l8 A9 m/ | - //can口接收数据查询; j' K; M) E9 N2 m! q' P
- //buf:数据缓存区;
, l5 V6 Z& x R; M' U - //返回值:0,无数据被收到; @- e9 Y' q0 Z/ o5 X' t* Q$ [0 ]
- // 其他,接收的数据长度;
% ?' P; G0 H ^/ C ?9 y, Y8 h5 \' b - uint8_t Can_Receive_Msg(uint8_t *buf)! \ G2 c3 X" N F1 T
- {
8 @+ U7 z$ O$ \. n: J - uint32_t i;
3 b+ c% r' l# L2 X2 A - CanRxMsg RxMessage;
! c- o* H, h4 h4 z/ D - if( CAN_MessagePending(CAN,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出
2 t4 {! K3 O0 Y+ `; Q - CAN_Receive(CAN, CAN_FIFO0, &RxMessage);//读取数据
- p3 @0 _2 |" i6 m, c& A: s6 w) T& f - for(i=0;i<8;i++)
8 h7 V. y: F7 U4 X& h+ C6 w - buf=RxMessage.Data; 8 w I& u" u" U3 s, n
- return RxMessage.DLC; 2 j+ S3 n4 Y! {% V+ _+ O
- }
复制代码
1 H7 H2 ?" S% h6 O$ ^注意:一定要根据自己的封装来设置
$ b+ |$ I! T" {0 C3 GSYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
) |0 ^6 l+ C$ j# B) I0 J+ c7 W如果不设置 CAN_Init(CAN, &CAN_InitStructure);会初始化失败) L* D9 y+ |! W
) @* d6 d [ u+ u4 y. d
' Z- Y; U- l0 B8 c5 @3 ?7 _+ ~" r1 d- @ |