代码如下:$ q5 v0 q. { I8 ]. C* ^! ]" l
6 s" }% V! h1 g; l: t% G% C- #include "mycan.h"2 O1 T# }+ z' o+ K* J7 ?
- / I: B) N8 G+ y C: j. j
- //CAN初始化
7 z1 p! I9 v; t& l( r) E8 [/ x4 v - //tsjw:重新同步跳跃时间单元.范围:1~3; CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq
3 a% w8 K. H! I- q2 D% W - //tbs2:时间段2的时间单元.范围:1~8;
% V" j6 x: ]; W3 O3 E; Z: Y - //tbs1:时间段1的时间单元.范围:1~16; CAN_BS1_1tq ~CAN_BS1_16tq# c) ~& ~, _2 m! }; a: h) m9 n5 s8 V8 W
- //brp :波特率分频器.范围:1~1024;(实际要加1,也就是1~1024) tq=(brp)*tpclk1
& [3 ~' ?; f% k - //注意以上参数任何一个都不能设为0,否则会乱.1 s Y0 T* e @0 t8 b/ Y
- //波特率=Fpclk1/((tsjw+tbs1+tbs2)*brp);: k; L1 @( }5 R- V0 f) x
- //mode:0,普通模式;1,回环模式;
- I( ?4 ]. l6 M% T. H - //Fpclk1的时钟在初始化的时候设置为36M,如果设置CAN_Normal_Init(1,8,7,5,1);& K; u3 ~5 }- o
- //则波特率为:48M/((1+8+7)*5)=450Kbps
$ x& @6 f7 G( k$ J: ^1 W5 ?% g7 E/ ^
$ i! m0 S' }# Y, g% w" e6 J- void CAN_Mode_Init(uint8_t tsjw,uint8_t tbs2,uint8_t tbs1,uint16_t brp,uint8_t mode)+ q! p; E. a: {/ ]% ^: k
- {0 J' V) M( R0 e
3 {* ?: e+ G3 V7 G8 b$ i: k( ]- GPIO_InitTypeDef GPIO_InitStructure;
: [" e+ T* j* n& ~ - CAN_InitTypeDef CAN_InitStructure;9 q/ K$ M# o1 o; d( A1 K* O6 k: ]
- CAN_FilterInitTypeDef CAN_FilterInitStructure;% m, w3 ~7 ^5 k9 V" e
- #if CAN_RX0_INT_ENABLE 7 ~ \9 {9 Z) h: N5 |! l
- NVIC_InitTypeDef NVIC_InitStructure;
5 x9 V S9 ]+ g" A+ r1 h - #endif
5 _" `* r6 t7 y+ ?3 W2 C4 D - $ _. @% |0 l4 g( C+ O1 F7 j1 S
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);9 ?+ x. r. Y2 ^0 [
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);//使能PORTA时钟
* ]1 \0 P) I" `& g - SYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP; //RMAP 8 ]/ l0 C$ u y) b# E# h7 y
- GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_4);
7 ]! S- q* x4 g3 v- y0 C* i - GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_4);: q8 ?) g6 V' o4 G
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);//使能CAN时钟
7 V; f$ [; D4 v: c' H - ' m5 a8 D/ m: N) e
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12;2 G8 n# Z. i* [0 J+ {" k v' `
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
. C o' g ` H. _! f - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;; ?, `3 O$ K; r5 }
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;! |2 D/ E9 V! ~5 H, m" j; c3 j
- GPIO_Init(GPIOA, &GPIO_InitStructure);, n0 l4 K' Y, N4 R, j, w1 b
- 7 B+ x) D/ U. H8 B
- CAN_DeInit(CAN);, m- N; j' \, Z6 a5 F
- //CAN单元设置
$ Q" s* U- N4 V$ g - CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式 //2 v6 w& ]& w) g3 K
- CAN_InitStructure.CAN_ABOM=ENABLE; //软件自动离线管理 //7 R( Q# u' @# \
- CAN_InitStructure.CAN_AWUM=DISABLE; //睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)//, ~" x: n2 p5 \ l7 i8 _7 U+ z
- CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 //
8 e, d( E8 ?% w# I) Z. ^6 n - CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的 //
f! C4 {! U; r. s8 L0 A, E; X - CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定 /// d' i: V U: ?! d
- CAN_InitStructure.CAN_Mode= mode; //模式设置: mode:0,普通模式;1,回环模式; //7 E: k7 _- k$ s( ~- ^! L& C
- //设置波特率; w/ {( c( r2 i2 b# t2 z5 `$ g
- CAN_InitStructure.CAN_SJW=tsjw; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 CAN_SJW_1tq CAN_SJW_2tq CAN_SJW_3tq CAN_SJW_4tq3 d8 c3 o2 q' z0 e7 }+ g( ]% f, |2 c
- CAN_InitStructure.CAN_BS1=tbs1; //Tbs1=tbs1+1个时间单位CAN_BS1_1tq ~CAN_BS1_16tq! N8 D, ?( A4 q5 P( Y5 O
- CAN_InitStructure.CAN_BS2=tbs2;//Tbs2=tbs2+1个时间单位CAN_BS2_1tq ~ CAN_BS2_8tq& X( J) O0 ~, p( B* P0 j" u
- CAN_InitStructure.CAN_Prescaler=brp; //分频系数(Fdiv)为brp+1 //
' M& H* S; U; |" l - CAN_Init(CAN, &CAN_InitStructure); // 初始化CAN1
# p" q: x8 |7 w9 e* |1 Q, {
1 H7 i2 Y- ~; h7 k& G- CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
& P5 X. q, a' A- _3 W q# V$ u - CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; ; ~8 j% V- P8 F
- CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位
$ [ h5 _- c g. ?, l - CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000;32位ID
{3 R# R% J0 J# i - CAN_FilterInitStructure.CAN_FilterIdLow=0x0000;8 G& v* a* S: ^; w) s% Z3 t; l
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000;//32位MASK
$ E( J! n5 w; H6 \* R4 ]. w - CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000;2 G( P9 c3 \, B) d4 p
- CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
/ Y$ ?% f9 R, a3 u3 M% d% r! n - CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0. R. v: z3 Q; [. u9 z0 g
- 1 u! u- {( _. B
- CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化2 w( b' ` h% ^ G0 G. d* z
- #if CAN_RX0_INT_ENABLE$ ~2 |' n5 ~( h. ?* b7 r/ a M
-
/ R9 t! |" V. X - CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.
+ s* _& D' i) h4 T0 h9 u
9 T0 `+ x" ~) w3 n3 g r6 z6 g5 W- NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;/ k1 @9 e* t( }2 {, p
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 主优先级为11 A) s3 C z. {8 X$ g8 w
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 次优先级为01 P' X6 c' p b6 i, \& B5 R
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
1 q; ?5 ]$ z: ^ { l9 ?: j: Z - NVIC_Init(&NVIC_InitStructure);, ^; m2 c) O% n6 c7 U4 G8 ~: G4 q! M
- #endif2 V x1 ?7 I1 x$ p, C2 D9 O
- }
. m, l5 @/ U6 _" M - #if CAN_RX0_INT_ENABLE //使能RX0中断1 x, F* U1 A7 g6 ~' Z% N' |' {
- //中断服务函数
6 y% \' l f# Z - void CEC_CAN_IRQHandler(void)
# y, Y, r$ @; C% k8 B' W; \) b4 Y - {
2 `% ?. p2 k2 p( F' U: Y, p - CanRxMsg RxMessage;, w/ d9 `: D0 n: B
- int i=0;
* [* s; e; c4 ^1 c% K8 o* U4 R - CAN_Receive(CAN, 0, &RxMessage);- ~% C& a9 M1 R8 k) x( g
- //for(i=0;i<8;i++)& ~2 M4 j/ ]2 g6 z
- //printf("rxbuf[%d]:%d\r\n",i,RxMessage.Data<i>);</i>
& b @6 u8 l F9 n" r& H R% ` - }
^/ h# j% ^* m) I: S4 v+ y+ ~ - #endif W. q* z4 X( G; a3 O q9 E9 H) \+ |0 v1 n
- 4 S# Q2 s R4 F- C
- //can发送一组数据(固定格式:ID为0X12,标准帧,数据帧) 2 n' n* J6 q, p9 k9 Y2 j
- //len:数据长度(最大为8)
$ y% m- x6 ^, a, ?9 O1 M' ` - //msg:数据指针,最大为8个字节.
' |6 g+ ~$ E) R! b. E% T. g - //返回值:0,成功;+ s2 A5 R- \& G7 x* v& V
- // 其他,失败;
! v: k4 i) T+ t, ?) M) h E - uint8_t Can_Send_Msg(uint8_t* msg,uint8_t len)) R6 S- M7 S5 H/ I( m# G
- {
: _+ m) h$ d s; K/ P! F& z3 A- | - uint8_t mbox;' e5 V% W0 q1 I; z1 w
- uint16_t i=0;& ?8 ^+ ?" `$ \8 Z% S6 |
- CanTxMsg TxMessage;) z* D! P% M# R( a9 [
- TxMessage.StdId=0x12; // 标准标识符为0$ B- ^& G+ a% P, Q
- TxMessage.ExtId=0x12; // 设置扩展标示符(29位)) q, N/ ?& V/ I, L8 `4 {
- TxMessage.IDE=0; // 使用扩展标识符, t6 ]* }. d8 U5 G' M0 [
- TxMessage.RTR=0; // 消息类型为数据帧,一帧8位
% u5 _- j# L" M; i! R' i/ |* i( C - TxMessage.DLC=len; // 发送两帧信息0 q6 m/ Z6 h7 d' K& @( b
- for(i=0;i<len;i++)" A) Q. L( b" \; ~, b2 q5 A: u9 r
- TxMessage.Data=msg; // 第一帧信息
8 u7 [* ~3 v+ S- d7 A! Z - mbox= CAN_Transmit(CAN, &TxMessage);
! P! _7 K( K# h' I2 w9 n - i=0;
9 ]4 X5 _0 S# t+ M! U' Q4 i6 w9 Y - while((CAN_TransmitStatus(CAN, mbox)==CAN_TxStatus_Failed)&&(i < 0XFFF))i++; //等待发送结束
* b- z: o: e2 ^5 e& r - if(i >= 0XFFF)return 1;6 X4 y9 K2 Q4 X
- return 0; 5 u- Q6 v$ i/ f5 U4 V8 x
- }2 y: b9 `5 O1 a! |$ P
- //can口接收数据查询
: D! ^' ~8 [( o8 k: ~) [/ _9 H - //buf:数据缓存区; , h. T. s6 l( o% E, X3 h) m
- //返回值:0,无数据被收到;9 V+ `/ B/ j7 v( }9 b
- // 其他,接收的数据长度;9 j4 D' E) Q7 L: t- r8 V
- uint8_t Can_Receive_Msg(uint8_t *buf)7 I4 Q4 l+ l- [) `( Y, v% R
- {
& K3 Y, m8 w2 i - uint32_t i;
% n: @& r) }! `: Y - CanRxMsg RxMessage;
+ v) W7 K2 a: B3 \ - if( CAN_MessagePending(CAN,CAN_FIFO0)==0)return 0; //没有接收到数据,直接退出 ( r6 Y7 b1 r! L( X% h7 K
- CAN_Receive(CAN, CAN_FIFO0, &RxMessage);//读取数据 . w4 |' a- p3 u
- for(i=0;i<8;i++)7 u6 k+ Y: ~( a3 ]# a4 A8 \& T
- buf=RxMessage.Data;
8 D" f! Y2 E1 i+ S# k - return RxMessage.DLC; 6 m) K" Q H9 k
- }
复制代码 ) A. G- L/ T! X3 J: J
注意:一定要根据自己的封装来设置
+ I0 c/ g/ v; P% h% B) p7 CSYSCFG->CFGR1 |= SYSCFG_CFGR1_PA11_PA12_RMP;
3 d. Q7 f7 C" h, |如果不设置 CAN_Init(CAN, &CAN_InitStructure);会初始化失败
1 G; q- q2 \3 `) r) }1 ^: E' c4 ~) u, V* s6 u
' }4 c7 y9 j: {- ?! h
|