使用芯片:STM32F103C8T6/ H& E* n5 Q2 O3 Z6 Y# P
cube软件版本:5.10
, S& Z0 [# E3 [( ^软件包版本为:STM32Cube FW_F1 V1.7.0
6 I3 j3 o$ O( v3 ?$ W1 T/ ?
, x6 p5 H# d( k; g" ?一、配置时钟为使用外部晶振,并配置为72M. D1 {8 t( j6 q- f: \% O6 B
9 |, W( q( y+ E& h3 T
7 i9 ~, s {6 S( R+ Z/ l
, w! V1 w r+ k7 p
% p! r' p# b8 F% b0 |7 e二、使能 can,并配置参数8 g* I$ h% G7 t* a" d* t
设置can波特率为500k,并设置为loopback模式,波特率计算方式为(systime/(pre*(bs1+bs2+sjw))),can时钟为36M,则36/(12*(1+2+3))=500k。8 G% t( P' P* B
- c$ t3 E: B' a3 Q
o4 a# H% _) I4 R
# q8 K2 N1 T2 Z$ m' A! Z3 z三、开启can接收中断; S; ]4 b1 r2 ?
' n H' s$ @& r7 a; T
7 J' u" K; N% Z: ~
' W/ g$ U& Z3 L% g' F8 o1 u四、设置生成代码,在生成的can.c函数中增加过滤器配置代码如下9 P& n5 @7 ?; \' E* Z1 J: o) W
8 r9 k1 h8 D9 a1 S: u
0 O+ t& d# k; P1 x4 m( o
8 z/ h; ?" ]9 `% YCAN_FilterIdHigh和CAN_FilterIdLow组合成一个32位寄存器,用来存储将要过滤的ID
3 a' c) D. i; C5 N) f: S
5 V f0 I/ W" V# Q! kCAN_FilterMaskIdHigh和CAN_FilterMaskIdLow组合成一个32位寄存器,用来表示这个ID的哪些位必须符合(置1),哪些位不关心(置0).
7 F2 C# l$ M' W- Y: H* S( w例如要过滤的ID为0x1e000000,则CAN_FilterIdHigh、CAN_FilterIdLow、CAN_FilterMaskIdHigh和CAN_FilterMaskIdLow配置为
7 x! u5 N5 g$ w% n+ o! |9 i- z
& X3 n$ ^5 { }8 k4 E- uint32_t EXTID = 0x1e000000;
3 ?0 ?) Z0 m' c; |' D - CAN_FilterType.FilterIdHigh=(EXTID<<3)>>16;
8 V1 e- g. c/ ` - CAN_FilterType.FilterIdLow=((EXTID<<3)&0xffff)|CAN_ID_EXT;//只关心扩展帧,标准帧为CAN_ID_STD: a1 O6 w! e D3 D
- CAN_FilterType.FilterMaskIdHigh=0xffff;
8 A( z9 g1 y3 h0 P' G0 T" \ - CAN_FilterType.FilterMaskIdLow=0xffff<<3|CAN_ID_EXT;//每一位都必须一致,只关心扩展帧,标准帧为CAN_ID_STD
复制代码
& l+ H, @0 e8 a7 ~9 q% s以下配置代码,有列表模式和掩码模式,二选一
) P4 H/ D, j8 a7 W" w1 I" E+ |1 Y" [9 G, ^9 r* ^
- /* 列表模式只接受0x02200000和0x1e000000 */
* H2 v* K& M. J2 j - void CAN1_IDLISTConfig(void)$ t6 U4 R* {' r% i, h" H/ [5 H
- {9 @0 I# \! I2 x, b
- uint32_t EXTID = 0x02200000;
+ A( f: @+ k3 B+ [" g. C - uint32_t EXTID1 = 0x1e000000;
+ m7 C: u+ k' V5 S+ K6 S! a - CAN_FilterTypeDef CAN_FilterType;' @1 Y, _2 q# y# o6 |
- CAN_FilterType.FilterBank=0;6 Z& B1 i- s# G; [5 P' ]* E2 {
- CAN_FilterType.FilterIdHigh=(EXTID<<3)>>16;
' I% z$ z2 m& j# O2 L - CAN_FilterType.FilterIdLow=((EXTID<<3)&0xffff)|CAN_ID_EXT;6 [5 [& U1 u6 b. A
- CAN_FilterType.FilterMaskIdHigh=0xffff;
( H$ U j# h- h) i% _ - CAN_FilterType.FilterMaskIdLow=0xffff<<3|CAN_ID_EXT;
% L- N% w& Y# N. b* s; E( ~ - CAN_FilterType.FilterFIFOAssignment=CAN_RX_FIFO0;- i( X# K. z+ V1 j2 ^+ _' i
- CAN_FilterType.FilterMode=CAN_FILTERMODE_IDLIST;; s0 C1 o( ]. j
- CAN_FilterType.FilterScale=CAN_FILTERSCALE_32BIT;
/ X* a0 }7 ~, P) y, q2 ~" D - CAN_FilterType.FilterActivation=ENABLE;
, G: S7 j) n0 k# ?( m, K$ R* E1 Y - CAN_FilterType.SlaveStartFilterBank=14;3 ~- Q4 `& V, v6 L o; Z8 W
- if(HAL_CAN_ConfigFilter(&hcan,&CAN_FilterType)!=HAL_OK)7 e4 P/ b- `& g3 W# w
- {8 H& Q7 h$ _) y. s, M& ^
- Error_Handler();
+ B- q8 {3 N0 a ~ - }8 y$ K& G8 R' K- l+ I
- CAN_FilterType.FilterBank=1;9 O- V/ u. o+ X' ~' q
- CAN_FilterType.FilterIdHigh=(EXTID1<<3)>>16;
6 @& `. G+ m$ |( ?+ d - CAN_FilterType.FilterIdLow=((EXTID1<<3)&0xffff)|CAN_ID_EXT;
* Z9 l$ e1 h/ o+ k, W6 n5 k - CAN_FilterType.FilterMaskIdHigh=0xffff;7 E1 B0 q" k! t1 y* \1 A
- CAN_FilterType.FilterMaskIdLow=0xffff<<3|CAN_ID_EXT; Q9 s. R6 O3 U" i2 A# ^
- CAN_FilterType.FilterFIFOAssignment=CAN_RX_FIFO0;- ^. C r9 `" d/ m i; q: ^ _3 w1 g
- CAN_FilterType.FilterMode=CAN_FILTERMODE_IDLIST;//列表模式
9 |/ x' z( O: [, j' ^ - CAN_FilterType.FilterScale=CAN_FILTERSCALE_32BIT;" G# L( @% q* y, O% f( L8 b
- CAN_FilterType.FilterActivation=ENABLE; e; K Y% d) Z R# U/ s
- CAN_FilterType.SlaveStartFilterBank=14;
, s/ D N# Z; V# j) E/ E! { - if(HAL_CAN_ConfigFilter(&hcan,&CAN_FilterType)!=HAL_OK)# h* ^# `( q; E+ I/ f4 `
- {3 O- C5 R4 x6 n% ?1 {3 k, N
- Error_Handler();1 I- C0 b, z( }, l8 B) q' E
- }; C# W" n) O2 \8 j( g; s- [
- if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING)!=HAL_OK)( R! f6 D3 F* e) N
- {
- p; J! g+ S! }* x- ^ @% l$ V0 D. U - Error_Handler();3 q% g/ r; N$ V0 B) M
- }
+ a9 ?. I W$ R1 |! t: T - if(HAL_CAN_Start(&hcan)!=HAL_OK)
" e; x2 [5 P. s7 @* p# b* a% { - {0 ~* n5 J! H \" ~) @
- Error_Handler();
0 \3 p6 P) B& f7 M) x5 M, E7 M - }
+ @# |5 Z4 t# q' Q6 W- X# ?( G - }
8 L& V, J% b6 k6 u. c5 K' _ - /* 掩码模式全部接收 */
* v9 f3 N+ |) j' Z) \ - void CAN1_IDMASKConfig(void)* u* R# h7 ]2 {4 N8 h0 r1 B
- {
) g3 i6 g6 \# A* A: i! t' y, [+ U - CAN_FilterTypeDef CAN_FilterType;' v: _5 A- U4 p, }' ]# l* H1 `$ @
- CAN_FilterType.FilterBank=0;
! t/ q& l5 J, @, W- U& S - CAN_FilterType.FilterIdHigh=0x0000;% ^% U" c% X! i0 r& X6 h1 ]; ]
- CAN_FilterType.FilterIdLow=0x0000;
8 t* K" E0 ?4 ]! ^/ g+ ? - CAN_FilterType.FilterMaskIdHigh=0x0000;1 N7 @: P8 v l M1 Z) Q: S) t- {. D
- CAN_FilterType.FilterMaskIdLow=0x0000;
4 S! _0 w5 s1 a- H1 g - CAN_FilterType.FilterFIFOAssignment=CAN_RX_FIFO0;6 {* F' R" D3 z# |8 `
- CAN_FilterType.FilterMode=CAN_FILTERMODE_IDMASK;//掩码模式3 n& `* n5 u1 b" L3 B: g( W
- CAN_FilterType.FilterScale=CAN_FILTERSCALE_32BIT;/ s- N% p' n# N9 o G
- CAN_FilterType.FilterActivation=ENABLE;
?: i& M3 |8 v - CAN_FilterType.SlaveStartFilterBank=14;
5 D9 q' T0 _4 N - if(HAL_CAN_ConfigFilter(&hcan,&CAN_FilterType)!=HAL_OK)
8 b! D6 A% P/ g7 V# x* d7 f - {0 @$ q% b1 Q4 T5 ~! M
- Error_Handler();
( ?; ?2 d" {/ m e - }
1 o5 z- x! m2 _8 t$ T8 E, O6 D$ k - if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING)!=HAL_OK)
' g/ g1 H* G" _- p8 w) { H9 X - {0 G# [# f3 ]5 ^' Y+ s
- Error_Handler();
$ a) G; q" ?9 R/ T - }
" f9 M$ [* x5 o5 A; R5 ] - if(HAL_CAN_Start(&hcan)!=HAL_OK)
5 S2 v4 a3 F+ n$ A# h - {& H, Q# `$ j* E2 p0 ]7 N
- Error_Handler();9 x' v! \* k* b4 X2 a2 w+ `
- }
& L$ d7 q" K# S5 U9 k' M) h9 P - }
复制代码
# X" [' o T( ~五、增加can发送函数! z. T/ {* Z2 y) V% n1 Y
- /***********************************************
8 m) P3 U2 F$ k/ f' E9 R) {8 y - 函数功能:can发送数据) x# P, f# n( F8 @9 e) B
- 入口参数:% G1 ]4 ]/ V4 s! ?" l6 r
- ide: 0:标准帧
5 F% w3 ~! E: G1 S! A - 1:扩展帧
3 W; T% j4 C1 S( j% B - id: 帧ID: _' {& C7 C" v. i- N% ?( Y
- len: 数据长度
h( u9 C' V' v- Q - data: 数据; h2 y, e! Z2 j: X1 f& ]+ H. N
- 返回值:0:成功。1:失败9 u+ D' [" j3 p. {: h8 C
- ************************************************/
' k$ ~& k) [9 s- t - uint8_t Can_TxMessage(uint8_t ide,uint32_t id,uint8_t len,uint8_t *data)( J% P0 b0 K, B+ i, o0 Y2 e- I
- {1 y" a( d. j) y0 e: g2 f
- uint32_t TxMailbox;
9 g, r; e8 J! x6 n" w# k a: L - CAN_TxHeaderTypeDef CAN_TxHeader;
& u& q/ H2 A! ~# h, b+ t - HAL_StatusTypeDef HAL_RetVal;
: I( V* u3 Q/ z: g) X - uint16_t i=0;
1 B" `/ v4 e m8 e' C5 e - if(ide == 0)2 t) P7 @# n& ~' V" C. U& o/ f! n
- {" `! Q/ |' E( e1 R, F. }
- CAN_TxHeader.IDE = CAN_ID_STD; //标准帧! D; f5 E& ]) ^0 f D: [( l
- CAN_TxHeader.StdId = id;
9 K) r' R' m9 L; o: E, v1 U - }3 t0 _* K' J) h' Q; Z
- else
$ `8 ]- I4 V5 |5 M; {9 l - {
* s0 `+ N# {" M/ J1 ^6 \ - CAN_TxHeader.IDE = CAN_ID_EXT; //扩展帧4 b+ ]3 n0 `0 X9 y; D- l2 S# Q
- CAN_TxHeader.ExtId = id;% ^8 v) E% r$ o' {
- }
; Z, ~0 P7 ?/ ~4 w* \ x - CAN_TxHeader.DLC = len;
6 E1 h! \% D4 X: y0 [+ } - CAN_TxHeader.RTR = CAN_RTR_DATA;//数据帧,CAN_RTR_REMOTE遥控帧
& K) N, ]8 p+ A! T3 W4 a7 p3 a - CAN_TxHeader.TransmitGlobalTime = DISABLE;, Q7 y. {* l( f3 W
- while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) == 0)+ V+ C. p. m' R# d9 A
- {: U' Q- h8 N! K: D0 k3 I
- i++;& u7 x/ v# n% ?/ N0 U
- if(i>0xfffe): X" }$ C( K6 d% d$ H) x
- return 1;( D6 b6 z5 K- Q; e2 ?
- }) w* d8 E, F: `! h; o1 F0 ]3 r
- HAL_Delay(500);
( x- Q, w- v1 M" e! @ - HAL_RetVal = HAL_CAN_AddTxMessage(&hcan,&CAN_TxHeader,data,&TxMailbox);
1 H* m3 F) s; f# W - if(HAL_RetVal != HAL_OK)6 ]5 M- K3 Q' ]7 x# X, V8 {9 C
- return 1;3 ^# S5 x+ ^$ s
- return 0;5 l# P/ s/ c8 D3 U
- }
复制代码 ! ^$ c! b8 n( E8 E N
六、增加接收中断回调函数+ N# |. e% s! i' _3 t
- void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
# n* T2 ^8 o6 `; g& ` - {5 x) N, h6 s# ~# }; }' A; [; ]
- CAN_RxHeaderTypeDef CAN_RxHeader;* m+ [9 ?# P% n& d8 c; B
- HAL_StatusTypeDef HAL_Retval;# X n! A( G7 d1 z! J
- uint8_t Rx_Data[8];, N6 q2 I% J2 F5 j& l, p
- uint8_t Data_Len=0;
U' ~# \, ?9 X+ @* ?, O% o& [! b - uint32_t ID=0;
" h1 x: _9 I3 `4 {" |1 N4 x( E( C - uint8_t i;
: \% F& Q! F3 s+ T3 ` - HAL_Retval = HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&CAN_RxHeader,Rx_Data); j5 O9 ?8 ?! W* n% g2 G
- if(HAL_Retval == HAL_OK)
5 k! N& H- j* l. Q P - {6 @* k7 ]. V, U- F: L
- Data_Len = CAN_RxHeader.DLC;
% w* o5 q4 K5 X9 c E9 U( `, L8 V - if(CAN_RxHeader.IDE)
& C: v, n+ o l; U - ID = CAN_RxHeader.ExtId;
) E' i5 f; ]% F+ c/ O, l4 w0 D8 c M! P- Q - else) Y* x4 }% I9 \& D
- ID = CAN_RxHeader.StdId;/ | }& x N4 u0 R
- printf("id:%x\r\n",ID);3 H7 T& V' C& o+ d1 Q
- printf("Data_Len:%d\r\n",Data_Len);
$ R# c( O6 k. y" p# p - for(i=0;i<8;i++)
. E% z$ u) e8 P$ ~* W4 w - printf("Rx_Data[%d]=%x\r\n",i,Rx_Data<i>);
) N& ~0 m+ [6 a( a) R6 J( m - }2 ]: r& I! K5 N" Y: }, r2 I! M
- }</i>
复制代码 8 ~/ W3 {9 @! d
8 ~5 g# `$ G7 x* t8 @! S7 F七,在main.c函数中增加函数,最终如下:4 t8 {4 y( y" t4 A+ W9 a1 K
- int main(void)7 ~0 i) k8 \+ S" }
- {
9 `( O2 ^! i! U0 h! @, d9 u - /* USER CODE BEGIN 1 */5 H$ c9 J* j+ X3 f
- uint8_t data[8]={1,2,3,4,5,6,7,8};
3 Q T+ [9 W# S; p1 p6 J - /* USER CODE END 1 */' C2 o. _2 T3 l* g9 z6 G
- 2 G& _! S7 D& @ f5 s L
- /* MCU Configuration--------------------------------------------------------*/
! ]! S, C; q; l8 I: k1 n8 C
/ g: l! t- q* O2 `0 Y( l$ {6 t- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
2 l- e9 |; p) f& z; J+ e! ` - HAL_Init();
8 ?4 q4 G5 o5 e - # ^; O. J+ r, ?0 M, J3 U
- /* USER CODE BEGIN Init */
- P' m* Y" }* D% H! s9 T - ; v0 [/ u2 l1 D. Q8 M5 e: R
- /* USER CODE END Init */
- P1 m7 L( K9 Y0 T- T6 `: Q - # y$ q3 N+ t8 y6 I
- /* Configure the system clock */! n( d r- ^- ]) H
- SystemClock_Config();" [3 S* x* d& K" ]1 Y1 j8 H
, P5 L: ^9 }( `, C( n- /* USER CODE BEGIN SysInit */0 }! e5 }) X8 F
3 p x. S! H6 m% b$ X- B- /* USER CODE END SysInit */+ T+ j( w( Z% k% j3 R. h
- 4 R9 }' D& g2 }$ Z; }
- /* Initialize all configured peripherals */& n: l$ r, {5 T5 V* F/ \1 h0 Z* w$ r
- MX_GPIO_Init();, @* w9 q5 Z* Y: j" s* J
- MX_CAN_Init();
; j5 N" d7 h8 @* i: g - MX_USART1_UART_Init();
7 h) ]" m/ F( d/ }- ?# m. Y - /* USER CODE BEGIN 2 */
' C3 O, r) ]* Q) ~: D! T - CAN1_IDMASKConfig();//过滤器配置& V2 d. `, I7 G- z
- /* USER CODE END 2 */
2 J4 n5 `: R1 p8 } x( B - /* Infinite loop */
4 ]# M% j' q& K$ W0 H - /* USER CODE BEGIN WHILE */
/ M$ z5 Q4 w2 ?( A5 n - while (1)2 W8 Z4 G/ W2 {) v& M# _. h; H
- {
+ N. S4 s1 C' _& d% [$ b! K - /* USER CODE END WHILE */& n5 \* O& M* S) I: \
- ) c' c/ i7 `4 c. p
- /* USER CODE BEGIN 3 */
) _( Y8 I" f7 A( t - Can_TxMessage(0,0x222,8,data);//CAN发送
3 C+ a) v2 w! t/ S$ M' { - HAL_Delay(1000);
4 j0 v: x. g, y: g" J! T6 j6 U7 F. z: j - }# z9 c+ `9 g( q2 d/ O) a* k
- /* USER CODE END 3 */3 Q W, q% W/ r0 N! _
- }
) x# I6 P/ S0 m1 k7 J' ~- U
复制代码
) `1 W$ e. t7 z3 Y: o每隔1S,通过can向标识符为0x222的设备发送一次数据,因为本例程设置的为loopback模式,所以不需要接任何外设即可,通过串口调试助手查看接收到的数据,与发送数据相符
* W- ^1 z3 {8 @3 c& H! ^) S5 v, J7 a6 X2 y/ u2 G
# q. Y! _& A( b# I, O. t% k# W
& F# F1 x6 `# Z3 ] |