代码如下:
% e' l) E; r, ]. V6 |8 J- e! k* A
- #include "mycan.h"
3 ~+ l+ g6 ^8 m" D9 p# U - ( y7 ]) _3 P- r" S. l- T, P
- //CAN初始化
0 ^( R) w! z4 _. g+ N2 E - //tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq/ m! k+ V Y: b2 F; _
- //tbs2:时间段2的时间单元.范围:1~8;. Z9 B6 Q* i, h) c! i
- //tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq
( x" y! c* ]* A; d5 r - //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1
: p2 K2 E2 u* i. {- S2 u - //注意以上参数任何一个都不能设为0,否则会乱.
2 Q8 N! C- Z6 h - //波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);% F$ ~" s2 Q5 p$ {, R
- //mode:0,普通模式;1,回环模式;
/ m6 z2 _* s. x' e) m# P - //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);
# ?+ U$ @% }& H v( o4 M" _ - //则波特率为:48M/((1+8+7)*5)=450Kbps
) |4 e- p3 J* ]- E( b) H
" s2 D9 e1 {& s+ M0 {& g* e1 `- void CAN_Mode_Init(uint8_t tsjw,uint8_t tbs2,uint8_t tbs1,uint16_t brp,uint8_t mode)
. h& g8 f, g8 ?" K0 u, F - {
8 R# K/ S \8 O2 \$ i
9 ^3 ^8 o/ k7 o: a: o& v4 ?, {- GPIO_InitTypeDef GPIO_InitStructure;
+ y% U* D; h4 K X0 _ - CAN_InitTypeDef CAN_InitStructure;+ Q3 _4 U- G4 S8 v" S$ j
- CAN_FilterInitTypeDef CAN_FilterInitStructure;7 W9 a( a: }. Q4 B5 r H, H! |" l
- #if CAN_RX0_INT_ENABLE ; x8 y6 b: e2 P3 h1 r o9 B, S
- NVIC_InitTypeDef NVIC_InitStructure;
/ y/ t3 K/ i* J( X# s - #endif+ a9 ]0 ]4 u) D6 A
- 6 a3 g9 I# A7 X, W
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
# R8 n% t8 Q) F5 I3 ?- E5 } - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能PORTA时钟 * E+ I5 h) R/ a- R
- SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; //RMAP ( a2 G+ j, D6 W3 X; `1 R
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_4);! q) u' G& o9 s6 z
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_4);
' g, f6 p5 N; x: o! t. a9 e - RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);//使能CAN时钟 ; N: w. U+ t' V, m3 Z4 E! ~: E
- 4 j! o" A- W* u$ f
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
2 Z- @: s l0 d - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;- A, V) B8 w7 o& {8 }; o* n
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
# v7 c2 P6 l7 M6 O) R - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;3 {5 q$ F* i) c c9 b
- GPIO_Init(GPIOA, &GPIO_InitStructure);
" r7 j. q9 ~) ^ - / N) ]' J3 m8 ]# x
- CAN_DeInit(CAN);
1 ~' v: |3 c- G1 s" x3 v - //CAN单元设置- b2 X4 ^, L7 ^* ~8 e& H: G
- CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //3 Z y2 f+ @/ z7 t6 Q2 a
- CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //
5 R* V5 D8 V; A4 @ - CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//
4 j- o0 c1 r( Q1 U; F - CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 //- ^! E" J0 A3 B$ y% G% E
- CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 // 5 B6 A( E; g% n& L0 L1 E
- CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 //
( G% w# J! t, `6 C* Q3 ~9 D - CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; //
( e" U. D. y5 C# }5 H - //设置波特率
9 E, W6 A$ ]9 z% W - CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq( n2 v/ \$ R. I& y: J$ o- i4 V% {
- CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq# S5 y {( ~; W( c) J
- CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq9 M/ v) ]" T* r+ s9 o/ E
- CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //& L7 }% o% H* y/ c+ R
- CAN_Init(CAN, &CAN_InitStructure); // 初始化CAN1 7 _! {. f% i, A" r8 [' S7 H
! Y* }3 k+ u5 h( \! E- CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0) F) h* R4 v& k% P: \* L1 I
- CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
% G) s y* i( h9 v* p) A - CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位 7 l2 j1 ~) ?$ @
- CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID2 z3 p6 e: U$ g4 T! U7 l
- CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;
3 l$ p& u2 ~( R' M# \4 e1 q - CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK- y8 h W$ V( U! T
- CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;7 w8 Y# Y" O) ^6 J+ j( O: `
- CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
( r e4 A% ?3 v9 T - CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
' D2 u& H/ W4 @ - . P6 L8 H% X! T/ o: P( p
- CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化* B/ ?5 k/ i3 i- G# u9 O7 _3 `
- #if CAN_RX0_INT_ENABLE5 d( X2 z" k0 n+ P; J
-
8 H, F3 d0 Q- N - CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许. ( W& w9 s& H& B6 f6 L( g& W& I: B
- " A1 b6 A; V6 _3 W, }1 D$ @9 s
- NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
+ {7 K# I2 t3 Z4 u7 i; F# p - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1; }& Y- q' ]* F9 d
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0
* d+ G- ~! ?7 w% Z6 B* K - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
8 I) ?. d' H+ u! Z# F! B - NVIC_Init(&NVIC_InitStructure);; E1 q/ S: T. F; B o7 h+ M V
- #endif
8 z2 O5 U4 Y4 E2 B) k - }8 w- d% g$ l- ^
- #if CAN_RX0_INT_ENABLE //使能RX0中断0 _' ]$ q* v5 i8 N8 H
- //中断服务函数 $ z' {) n. {) h0 w- T' Q3 q
- void CEC_CAN_IRQHandler(void): a2 Y- k0 I" L3 S
- {
8 M' p4 [, ?, x, t( [ - CanRxMsg RxMessage;
) H- ?' g/ u0 ?$ { - int i=0;
8 q% B' s) w+ w# z f" K% b - CAN_Receive(CAN, 0, &RxMessage);( N3 C* p5 }1 C5 q' O+ D8 S
- //for(i=0;i<8;i++)% S/ y, _' B# J u& d
- //printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data<i>);</i>4 M2 R1 f+ Z4 ~/ q- ?
- }
0 k% G: h* H6 F; f n( A - #endif! l7 }: B7 K% Y% d- j+ ? b
- + x' I. k9 y; }0 H* ~) j
- //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧)
6 i) [, A+ |% w - //len:数据长度(最大为8) 9 w4 r4 |9 i& Q
- //msg:数据指针,最大为8个字节.1 |% a0 c6 _' x9 W( W' x
- //返回值:0,成功;
* R3 i+ ?7 T" G0 q+ |9 N0 m - // 其他,失败;
# _8 ~* g+ m3 x8 S - uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)- s6 q! e# J/ \$ A; f1 {
- {
; Y( o6 v* c) x/ b5 u - uint8_t mbox;
( P* X0 r5 K4 ~% c1 ^, W( x6 k - uint16_t i=0;0 i- j! V+ |% R& g& w
- CanTxMsg TxMessage;$ _5 i8 c# B* p! l
- TxMessage.StdId=0x12; // 标准标识符为0
+ g' ^ c$ y4 }& l6 K - TxMessage.ExtId=0x12; // 设置扩展标示符(29位)
. x* t0 c% V. E8 p6 t5 h - TxMessage.IDE=0; // 使用扩展标识符) `6 H0 y" h* w: P5 T) D: ~
- TxMessage.RTR=0; // 消息类型为数据帧,一帧8位1 Z8 ?$ c4 R! s" r& @3 ]: @7 W
- TxMessage.DLC=len; // 发送两帧信息4 N) E/ p4 u+ `, b9 a5 O
- for(i=0;i<len;i++)- L$ B3 |5 i4 q/ F& S3 `1 h. o
- TxMessage.Data=msg; // 第一帧信息
- V/ k% U, J0 A" s - mbox= CAN_Transmit(CAN, &TxMessage);
' v1 e0 w3 r: O+ Y - i=0;3 L$ i6 N }* o
- while((CAN_TransmitStatus(CAN, mbox)==CAN_TxStatus_Failed)&&(i < 0XFFF))i++; //等待发送结束
6 k" a9 ?/ V7 V/ G4 T7 U: I - if(i >= 0XFFF)return 1;
5 N* u; V2 w, K/ m2 K - return 0;
" ^5 A* c, ~3 @ ~5 Z - }
" }+ c3 y/ ~+ u8 O. I) C4 r& z Z% X - //can口接收数据查询
( _! R% t$ p4 Z' o - //buf:数据缓存区; & P, k. g: r8 x1 A" }1 V
- //返回值:0,无数据被收到;
$ X# R9 Y7 F! O9 |9 Y - // 其他,接收的数据长度;
1 Y+ i: x- M" J/ Z6 } - uint8_t Can_Receive_Msg(uint8_t *buf)2 p6 p+ F5 `, G" D6 y' ^
- {
( k7 Y: R1 U5 j) t9 R1 e* w - uint32_t i;
! e. o6 Q$ d- K& W$ v1 A - CanRxMsg RxMessage;
* u! l6 i3 q& i- j - if( CAN_MessagePending(CAN,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出
3 E, a+ i0 g3 A( X3 Y - CAN_Receive(CAN, CAN_FIFO0, &RxMessage);//读取数据
, d! D1 o: d! c) p - for(i=0;i<8;i++)% F: @& r" ]& J! \
- buf=RxMessage.Data;
- V7 _) Y. D$ n2 T - return RxMessage.DLC;
, b* j1 j! ]7 |/ Y - }
复制代码
$ V& j1 w* n$ [注意:一定要根据自己的封装来设置) F# w* C7 L( A0 z7 v0 `) i+ y
SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; R; {; x- c3 |& {( A
如果不设置 CAN_Init(CAN, &CAN_InitStructure);会初始化失败" @# j4 u: A4 z6 {3 ~% i7 c
1 Y% l, ^$ ]2 J1 G! @+ `' q) \$ l {2 Q! M5 r9 D
|