代码如下:
6 c( k. F, G4 K. w) J4 x6 h$ S6 ^) h4 W: o4 N" K# ^
- #include "mycan.h"
; G9 k! Y( F" p; ]
" |# v2 H3 X" j- //CAN初始化
: {2 h1 ?! h0 o+ u$ F* P - //tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq: } `8 N, v4 T( @/ n+ X& v
- //tbs2:时间段2的时间单元.范围:1~8;
/ o" P: o! P2 J2 G! [4 H - //tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq
- [$ m# G" \7 Z' G" h - //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1+ y) |' h- Q4 I! I% p/ Z6 R+ Q5 _7 Y
- //注意以上参数任何一个都不能设为0,否则会乱.
. \* z. |6 N7 p- ^2 O; Y - //波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);- |9 @' W7 ]0 X1 j5 D3 Z* \
- //mode:0,普通模式;1,回环模式;
8 o9 X2 ^0 O7 h - //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);
! e0 a' t# I; L# J - //则波特率为:48M/((1+8+7)*5)=450Kbps/ c" a+ M& C6 Z7 ~8 h
4 j& H2 e2 a0 V5 ~% N- void CAN_Mode_Init(uint8_t tsjw,uint8_t tbs2,uint8_t tbs1,uint16_t brp,uint8_t mode)
8 e5 \1 ]3 `& r' H8 k! g - {5 Z5 O+ |: l* r; Y+ y
) K, v' _. B7 P, p$ o1 W- GPIO_InitTypeDef GPIO_InitStructure;
8 ^4 A. ?$ _, f8 Q6 _ - CAN_InitTypeDef CAN_InitStructure;
! k. U* i2 V+ v: [/ u6 v - CAN_FilterInitTypeDef CAN_FilterInitStructure;
# Q8 r$ T, `+ s9 M& g - #if CAN_RX0_INT_ENABLE
2 H1 j/ W- R i! { - NVIC_InitTypeDef NVIC_InitStructure;
7 X0 P; M# c% n4 V' \' a# ]# b% q - #endif
( d' c! W) f! A0 x" ~ - + o* f) ^ R5 I1 d2 F. ^* p8 f
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
3 F/ Z) H. o" c0 F6 F# g/ A8 \ - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能PORTA时钟 " e4 x5 {. q/ d' v$ t* j2 o; c7 i
- SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; //RMAP ; J" Q: s* ~8 B" M# B
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_4);
" s0 i: ?4 K6 D, V8 B/ c - GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_4);7 r) v+ n) K4 O! K+ N& J: S9 A
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);//使能CAN时钟 ) Y* _( i4 }: B& K; F1 {
) O) m$ [, D) t/ I! X( V- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;
# k/ h5 j- @9 t+ E* I* l - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
. |, V% f# {$ Q: k1 H - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;4 D. U. H. A0 u8 l
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
* H9 n" B! G+ D% Q6 d( ? - GPIO_Init(GPIOA, &GPIO_InitStructure);
( v( B( D' r k - Q4 O6 z9 \/ G2 f! E
- CAN_DeInit(CAN);) m3 \8 F ^6 K7 b
- //CAN单元设置% S# r v: v+ ]; w5 ~' ~9 ~( t; p
- CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 /// |( d( ?1 }$ {! `* L
- CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //
" Y4 x+ ~- m0 X) l2 f - CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//$ ?: D$ b% s1 P- F M
- CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 //
$ w5 l' O- q, R$ Q5 G - CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 // 1 L5 ~* R3 B& u) n3 n2 v. S& ~# {' U
- CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 //
0 G" h# a5 @$ x7 {* b - CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; //
9 P5 b9 A3 c* \" s6 a7 e9 ^. v - //设置波特率
: P' V+ u8 v% I/ u5 K8 ]* W - CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
0 O5 B4 n5 _3 C( j - CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq
6 i/ h( @( t) E# I9 ~ F* ] - CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq9 d0 j2 d4 w o( s, L) H# F$ ^
- CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //) v; M6 K. y4 o$ m7 x" H; s% W
- CAN_Init(CAN, &CAN_InitStructure); // 初始化CAN1 / b9 Y/ z# z, @4 g0 m) C
8 T$ a6 _6 G; V) y% x" c7 H4 K0 v- CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0: `$ {8 h( K# P
- CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; - A0 v% e7 F$ ^4 Z+ e" V3 G
- CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
2 `9 X- K& [% L: v4 \; b0 p - CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
$ e0 T! M0 B0 C( @# { - CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;8 f& i/ e) e z& ^; h( u& n
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
* b# } |2 [; n6 c+ D) a: ~0 E - CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;+ C) B4 S( h z) \
- CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
B, N9 d1 ^9 [: F5 i8 j - CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0; Y7 w' ^6 q' \" F. L' e$ P A
% g) {( f. [' G6 Q. e- \- CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化$ z* q3 k& Z) O+ {" k
- #if CAN_RX0_INT_ENABLE
& v1 c9 b7 _8 c3 x( ?+ n3 Q - 5 _8 f& O k: h4 \4 H% x$ A* q
- CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许. + m( C0 Q3 d) h& r% m0 F
- 5 S8 D5 T: V3 s1 ~5 m- n
- NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
9 Q9 |# A/ P! X0 | - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为1
" D* I* r r* P3 _) Q5 K9 k: \ - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为0( y6 P; H$ g. F5 Q- }9 K5 X
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;2 V+ D: K7 e) k# ~
- NVIC_Init(&NVIC_InitStructure);% Y; {5 R, a2 j& l0 y5 q" u
- #endif
3 {9 D1 Z. \) F( l8 i - }
% V2 E( U5 N3 w# M% M2 G1 _4 T5 ~! a - #if CAN_RX0_INT_ENABLE //使能RX0中断
* W7 O. C! i0 j3 ] - //中断服务函数
) Y' ~$ u5 {7 j8 f2 _4 I% B - void CEC_CAN_IRQHandler(void)
2 V& r& a6 ?2 [( u( y6 ? - {
) {" Y; l6 c$ F; B z; e - CanRxMsg RxMessage;! Q+ |% B4 E; t' n9 e# l. H
- int i=0;* q# h) ?" P1 F5 C+ p( g/ E" A
- CAN_Receive(CAN, 0, &RxMessage);. d5 a; @, g: z% ~
- //for(i=0;i<8;i++)
) h* L( h" ^3 I0 F9 M! u& K$ r - //printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data<i>);</i>! r9 ]* O6 b7 b) T) t! ~
- }. S0 n5 o; z+ k4 p, |) I
- #endif4 w; \4 R" C4 L* a3 ], [- g8 d6 y* ?' s
8 T v6 n/ C, l1 ~- //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧) 3 @$ M! v. y- e1 E* v4 w
- //len:数据长度(最大为8) 6 y- J) k$ @6 \ g: m. S
- //msg:数据指针,最大为8个字节.
! J o; D. M- P) O* L9 W. }; e6 q - //返回值:0,成功;
$ s( L* t2 Z* y: s) H* M4 j+ h - // 其他,失败;1 n7 O/ r2 f4 [& S. ^, ~
- uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)
* a/ [- e$ r# `6 e8 X0 e$ G' v/ P/ d - {
. L% u# O: d" d& t% U" b# N - uint8_t mbox;
5 H8 o& n8 P' D6 K( }/ D+ q - uint16_t i=0;
: k& v+ {, N2 q; K% J - CanTxMsg TxMessage;
9 ]7 \- s! l8 E2 E0 I: h6 M$ z/ t - TxMessage.StdId=0x12; // 标准标识符为01 B2 d. W8 H/ L4 }
- TxMessage.ExtId=0x12; // 设置扩展标示符(29位); G& u7 M9 ?) \7 M5 {$ X
- TxMessage.IDE=0; // 使用扩展标识符
1 r0 J9 @* w' \1 W4 Y& i# M _ - TxMessage.RTR=0; // 消息类型为数据帧,一帧8位
. b( @& }4 D) U - TxMessage.DLC=len; // 发送两帧信息
- {* I" S- J) |3 p" l - for(i=0;i<len;i++)
( J9 `( Z8 M, f- a9 H - TxMessage.Data=msg; // 第一帧信息 " j2 F# w, N5 k( B! b
- mbox= CAN_Transmit(CAN, &TxMessage); _' a6 V* f/ S2 m& M( J( E
- i=0;+ {1 X7 m# [4 _+ ~' \( Q j
- while((CAN_TransmitStatus(CAN, mbox)==CAN_TxStatus_Failed)&&(i < 0XFFF))i++; //等待发送结束
9 o" a8 j, ~& s8 E9 R; t- f: C - if(i >= 0XFFF)return 1;
: x+ y0 V _, S - return 0;
. L! S% x' i5 z5 M: i/ _/ o) l - }
8 R2 o( ?# b# b7 L - //can口接收数据查询' L( P$ b+ r( S: w& ?; e
- //buf:数据缓存区; ) K {$ f! y p3 z; f7 m$ h+ R
- //返回值:0,无数据被收到;/ z9 U" b* o2 Q- k/ H& v
- // 其他,接收的数据长度;" R0 f: j" ^9 ]4 ^( u
- uint8_t Can_Receive_Msg(uint8_t *buf)3 v' S/ y, u- W& w2 h7 K& s" u* ]; U
- { 0 v; w! A6 L6 j. W* F" x
- uint32_t i;
# c: U) v9 N1 S0 i - CanRxMsg RxMessage;3 o& z) h' g* Z E4 B
- if( CAN_MessagePending(CAN,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出
: B, P7 ~) V7 f+ F9 L/ k( P" n - CAN_Receive(CAN, CAN_FIFO0, &RxMessage);//读取数据 + }/ ?4 v7 f# Z! d7 Y" i1 d
- for(i=0;i<8;i++)
9 z% G+ B. H2 x( y, i3 U. r - buf=RxMessage.Data;
% C( t/ ^5 y0 i x$ Y7 C6 @ - return RxMessage.DLC; s) Q! }! ~" |0 ^
- }
复制代码
. [* {$ I! v7 d9 D% Q注意:一定要根据自己的封装来设置
+ R- n7 e3 q& N9 H5 n1 K/ pSYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
- a5 ` E7 i- _如果不设置 CAN_Init(CAN, &CAN_InitStructure);会初始化失败# d5 a/ i+ e( v8 M( n# T
. o3 W6 l, X3 V- c
. W: ]) @2 {7 m9 s" r) B
|