一、关于步进电机那点事. y* q% f1 ?6 ^6 i. U
这次使用的是二相步进电机,博客上也有许多关于步进电机的博文啊,质量也是参差不齐,今天就给大家仔细的介绍一下该电机,我主要还是继承以往的风格,资料方面我也讲的少,主要还是侧重实操方向,希望能够带给大家帮助
) V2 @/ @6 \( M, G/ J
# J+ E# y: O3 i4 @" d5 i下面是图: * G5 ^; ?: h' |8 y' {% \& N9 t/ Y
5 i1 i- y' N7 A- X5 p! I
6 d8 L1 h, {; a. T6 j
4 z5 N$ B! O+ n2 ^7 g6 {
首先要认识一下步进电机上的几条线:
/ F; _$ ^' N* z# s! p
- C; O! F, c! E* u6 l1 t" N1 c* ^ W四条线(红、蓝、绿、黑)/ `" x" c) [& k. e& D" \, E+ O( m
4 Y1 B9 O* g! ?8 F正常来说对应A+、A-、B+、B-,在电机上基本上也都会标明代表含义,其实步进电机的原理其实都差不多,主要就是学会使用和了解原理就基本上达到我们的目的了,如果想要深入学习,那可以再继续研究······7 E1 z8 L d: z, A2 d
* M/ P# N3 K7 c" ^' m6 N3 z% P
那么怎么使用呢?首先就要搭配一款步进电机的驱动器了,网上随便都可以买到,如图:
! G$ H6 }# s- o: T
- c0 s, \% ?4 C
) q0 s! l/ f; `" t+ N- f. K8 P9 x4 u
这里我们很明显可以看到它有12个接口,这里再详细介绍一下如何使用接口:! q3 ~8 N$ s" {; ]; _, F" E
$ u6 u/ ^$ c |+ {! r7 i
V+:连接电源正极(注意电压在9V~32V之间即可,过大的话你懂得); s; K3 m' i% C2 Y0 h9 a2 x
# u6 g; m" j% l3 G5 o
GND:连接电源负极
( b9 K5 r' g- Q
+ q# j) u% M, }. Q8 x) V( ?* I4 k" mA+:连接电机绕组A+相& ]1 ~- w2 @2 m
$ Y+ K+ F" P+ h; p- A2 sA- : 连接电机绕组A-相
' d; K ?/ ~$ y3 { O$ T( |* @* s+ y- |6 V
B+:连接电机绕组B+相( a. _0 N6 z' V+ }- v a
; l8 L6 B, Z, J& ]; c7 h
B- : 连接电机绕组B-相
& k5 o$ z3 x. A; M# x; r+ }/ D8 ?5 L$ B+ z
CP+:脉冲信号输入正 ( PUL+ )(取决于共阴、共阳接法再来接线,共阴的话CP-接地,CP+接脉冲信号即定时器PWM输出)8 F' H& u% m2 `
; D6 L& @. R8 U5 G8 c
CP-:脉冲信号输入负 ( PUL-)
/ t+ q. U+ i* n j% y
- ~" w1 @! ~; y! Y1 |& G" V* vDIR+:电机正、反转控制正(同样取决于共阴共阳接法)
5 h& f3 V- w0 ]
% u `, ^% u2 G$ y+ q6 x" ADIR-:电机正、反转控制负3 V$ m' f+ a" d3 R% W
( [7 ]$ v( @, @# y
EN+:电机脱机控制正(可以不接)
0 B2 Q+ k8 c* N L0 C" `( q: Q( w2 j
EN-:电机脱机控制负
1 f2 U q6 O0 K( f! i0 g H8 n- G+ x: Z, _4 e
二、接线问题9 P0 |, I, j: J- ~- G: ?8 Q
上面到这可能对它的接线有了一个想法了,那么具体如何接线呢?嘿嘿,这里有共阴和共阳的常见的两种接法,具体参照下图:
4 n, ?( j- ~6 n) s: I. B/ k! u" N1 D4 y5 Y$ i1 d
# i; D6 a r8 m
. ]5 q) u% i, R) h, i& X1 S
! F- v4 s2 n5 [0 Z
& ?4 Z* O% N$ h- E8 k d 这里我采用了共阴极的接法6 [* ~. M5 W" r9 H) I+ C
$ l$ D% b8 t$ P/ c那么我的接线:
" J: }" q+ L& y5 i& c% t: g, y u1 |' z0 l
DIR+:PA8(随便一个端口即可)8 t, P1 N8 i1 I" B! [( ^
1 d# }5 @, q5 K5 r8 D' ` @DIR-:GND
9 g8 ?4 Y& o" h/ r; t6 q( d( L6 C# r. T- y6 L6 h
CP+:PA1(TIM2通道2)
l5 [$ h; u& W9 e& x- p& u# q. j S
5 u1 K' K1 h r. B$ K c% I# }CP-:GND
6 f' f0 j/ G# N6 b* ~6 M5 C( j) C8 ~3 }1 g8 K. @
ENA不接
5 a- F. n8 p: a, r9 |+ k8 d: J0 u/ V W- K6 N8 |0 H
三、主要代码
8 b, r0 {* Y& G- p s4 H这里的代码搬运后修改一些的,即可上手即可用
5 { |, R' C$ R* {* p- w# O5 Q7 v
! D- t% J' q4 ?) n1 o1 f主函数
+ L' L Q% \; ^- R- U3 `9 R( _# H' S0 A6 s# @7 m' u1 X
- #include "stm32f10x.h"
! @% M- X C. H! x - #include "sys.h"4 C, t! z: _5 w; R) V
- #include "usart.h"- ~+ G$ O9 E, B ?, _
- #include "delay.h"! s- E; v+ r: F* ^( l
- #include "key.h"3 h$ ~: ?8 b2 L, ?, z) U
- #include "led.h" # w/ a& O ]9 v( \. k0 j3 @
- #include "usmart.h"
* l# | n; B3 l; {* P1 i: s - #include "driver.h"7 \ L5 P) y/ p+ g6 ]* d
- " c1 I* D8 l# M' d# T
- //共阴* k4 h# @% C. }9 c. g
- /*
, a- {/ R& V3 o$ {7 E - CP+->PA.1 CP-接GND
1 ]3 {9 P) O6 S) L) p5 B3 d' H - DIR+->PA.8 DIR-接GND
* B2 ^! H. H$ }. R6 D2 n. t( [ - */" u9 e( ? e1 z- J G
8 v. b; J9 h/ U- int main(void) U1 A) k; F; ]; f; o
- { - o% W. u# C% l/ S/ G- t+ V: O+ a
- delay_init(); $ L3 t# k; o4 f" N% D2 R* j
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
5 w* i& w1 T' J6 J - uart_init(115200); 8 @5 J; j9 N4 o( P
- KEY_Init();
5 K/ ?; s0 }# b, y1 V$ x - Driver_Init(); 2 \& S8 w% }* {: }$ y& E" d6 d& ?
- TIM2_Init(999,72-1); % z" ~0 Y; }! _
- while(1)
0 X/ n1 }# ?/ D& v" a+ E - { ; U, i* n& Q8 ?. h) |9 Z
- Locate_Rle2(500,CW);3 Q3 j. F! U# O# {' G$ y0 P* Y
- delay_ms(5000);
% G. d$ m7 d3 [+ ~" X4 z - delay_ms(5000);
: ]* {. Y- f% `# J5 X5 L - delay_ms(5000);
" H) I& g" U! z: n. r - Locate_Rle2(500,CCW);
+ p& C8 q9 y; S- G - delay_ms(5000);
8 b: [5 c# m' Z! i, o8 X - delay_ms(5000);
[' `! T- U: G- |% |. Y - delay_ms(5000);
* {9 ^9 _# J4 {$ I& a% \! X! [) r- _ - } H2 u! J2 b9 _3 {0 w; f, T
. ]/ o' M9 N9 i; L2 v0 z- }
复制代码 2 e8 g& k. P$ {2 q: P7 x9 W
定时器函数:
5 E4 c) u6 y, t( q
! X+ m1 M! l' T1 V2 \- #include "stm32f10x.h" B) n& Q+ n( [7 n
- #include "driver.h"( \7 N- G' h+ Z. z2 @: `
- #include "delay.h"
9 D( l4 m' U& c- }' Z - #include "usart.h"" q9 Y/ d. Q2 H' y2 M
' \/ _1 u8 @ ~9 `% ]- long current_pos[2]={0,0};
[0 _. Q5 f0 L# L) I- z+ N8 y; k - int motor_dir2=0;/ n$ H: M4 G! A5 K9 |6 z
- u8 count[2]={0,0};
: t+ j5 I/ f. I9 u+ {' O7 Z$ S
4 K% }2 M* E) D& [& F- void Driver_Init(void)" T( y+ I+ D8 y0 \
- {9 Z. r6 @0 u K5 K# S
- GPIO_InitTypeDef GPIO_InitStructure;
. z0 ^; r; Q! e2 Y - 9 X4 x0 C) E# l- |! e
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); b5 T# i' p( v$ R
; i) ]! V- Y' e/ l0 Q- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
) C/ p0 U4 O7 | - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
0 Y+ _! }4 O. [3 `6 S4 w - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
; ^8 C" R- v0 J1 p5 v - GPIO_Init(GPIOA, &GPIO_InitStructure);
) H t6 @! g3 C - GPIO_SetBits(GPIOA,GPIO_Pin_8); 4 ?/ S( s( D j* |
- }* N+ \. d! P% E% x- f
! e/ K) M" x9 V) e8 h
6 R' W& L( F( O5 g- void TIM2_Init(u16 arr,u16 psc)' E* _6 Q' ?( R# L% j$ _ j2 B
- { 8 o; f9 S( E. @+ A; b; @3 L
- GPIO_InitTypeDef GPIO_InitStructure;# f" \$ f7 N; P( x' F
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
0 X2 K( h* A) ~4 J - TIM_OCInitTypeDef TIM_OCInitStructure;# [7 g! X4 r* d% a+ c; {
- NVIC_InitTypeDef NVIC_InitStructure;2 e1 [( k% i2 j! n( Q
- ' b1 y. v5 A0 I! e
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
" o: a1 J" N7 D1 K4 @6 P+ E0 T5 H - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); % Y! \5 W$ t0 q2 p a- Y' y8 q7 ?
- " ]8 @( I1 T2 f9 L
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM2_CH2! Y N1 y& o0 N
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
9 Q; Q7 I7 r+ c, Q+ \ `. G, T# C - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;2 H4 F$ g7 x5 [. p5 T
- GPIO_Init(GPIOA, &GPIO_InitStructure);, g& L# h: K; j o: [: x* [4 J V
-
5 g* m% E) g$ p3 i _& a, | - TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
8 m: s# b% `& U* X7 N - . `2 N1 |" H# r% V9 |9 p
- TIM_TimeBaseStructure.TIM_Period = arr; 7 K9 }2 ^) v3 ^8 t4 o) L8 a
- TIM_TimeBaseStructure.TIM_Prescaler =psc;
4 Z2 Q. o, N9 l* J; @2 f0 D8 g - TIM_TimeBaseStructure.TIM_ClockDivision = 0; / _0 \7 m6 Y1 E9 M T
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 3 z; W3 }! o0 w# Z6 v5 |* A
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
. J' Y, b/ L& n; ~ - TIM_ClearITPendingBit(TIM2,TIM_IT_Update); * k0 Q( ]% r6 B$ t2 D1 F! v
" c5 A0 m+ a6 T! }# B$ m$ F$ r- TIM_UpdateRequestConfig(TIM2,TIM_UpdateSource_Regular);
7 t+ H+ ~; L4 S0 I6 k% v7 Q; W0 r - TIM_SelectOnePulseMode(TIM2,TIM_OPMode_Single);
6 j: u" F' V2 U( m6 C8 Q - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
! j# C* ]$ o4 i$ R; F - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; # s/ {$ x9 \% `1 S( S$ U
- TIM_OCInitStructure.TIM_Pulse = arr>>1;
8 ~: A0 g, Y6 f, t! P( @ - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 5 g8 P5 A# i) i
- TIM_OC2Init(TIM2, &TIM_OCInitStructure); $ E5 T6 x' v+ x8 P. C7 h
9 C9 R+ i8 F" V n6 z- TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
/ N0 b) T! c7 z/ N" {7 d$ E7 o - TIM_ARRPreloadConfig(TIM2, ENABLE);
. A, v; ]6 z; a0 K9 p4 j! U - ) k' B$ E' h+ d2 u$ l! e% O# A
- TIM_ITConfig(TIM2, TIM_IT_Update ,ENABLE);
: h4 G# j: | \6 u: |" G
, ~8 M- h5 A: ], x- NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; + b0 b4 T: n4 r& P& }
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
/ I" g; m& f5 V. f& l! w% v - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
3 h3 v4 b7 @" g2 f" n( S - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; / F! @ v) D f# n6 v: \
- NVIC_Init(&NVIC_InitStructure);
5 e2 N, O o$ }6 S - 1 W4 V. h0 J7 s$ V* ?& q3 K
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update); . i; q, {8 O% A, A( t/ U- f6 u, h9 F
- TIM_Cmd(TIM2, DISABLE);
: O2 k+ o: a9 u: }/ m/ W- n, V. W - }
1 W N8 B# z g - /******* TIM2*********// W5 t- w% z G# H! a* ^
- void TIM2_IRQHandler(void)9 N% l1 Z- t9 @) W
- {3 M2 R: s7 u; U; r' H! r) _$ c$ N' C6 T
- if(TIM_GetITStatus(TIM2,TIM_FLAG_Update)!=RESET)- `" e5 w$ q6 u- g" X' O! c
- {
- Z9 F; _$ L* G - TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update); 4 S2 Q7 J @( p, x2 V% v/ B8 n
- count[0]++; ; X5 }: ]& }+ u1 N
- TIM_GenerateEvent(TIM2,TIM_EventSource_Update);
' U% O! a6 @: P0 }' E - ; o Q8 w4 b3 M6 O. h; s6 \
- TIM_Cmd(TIM2, ENABLE); # v W' F/ O) a* K p$ P
- " q4 i: `/ C% r+ X
- if(count[0]==200)( e) [1 I$ T5 n7 Z6 ^
- {/ R9 C3 ~+ S9 w3 H( u. U
- if(motor_dir2==CW) ) a( i+ T& s% l4 e& [% Y) `8 X
- current_pos[0]+=count[0]; [+ y- V( E! h( Y
- else * e3 B- g8 b. c; V
- current_pos[0]-=count[0];
`$ K& |+ x' U* g; P. _* U - TIM_Cmd(TIM2, DISABLE); 2 Z' s1 T/ G6 U/ a+ S4 c4 N& [
- printf("motor2µ±Ç°Î»ÖÃ=%ld\r\n",current_pos[0]);6 b3 L6 t/ D2 w$ A
- count[0]=0;! M+ e# [+ H0 k1 @6 B
- }# ~: ^+ ^0 |# Q! d E! B4 P" U
- % ~' l4 k1 G9 F
- }- i7 r8 x1 o/ f l4 C! O' G5 f
- }/ ? y# G( p3 Z% P
- 7 T- j1 r1 D7 i9 I& a) X
- void TIM2_Startup(u32 frequency) # L- b. i1 C5 ]& n% p
- {' N+ u' ^" ]6 f+ V* O
- u16 temp_arr=1000000/frequency-1;
, V }8 B" |; b& _% C$ D - TIM_SetAutoreload(TIM2,temp_arr);
# c2 K' A5 g; d3 O+ r3 y, ?- {7 H5 U - TIM_SetCompare2(TIM2,temp_arr>>1); 7 E! m2 p5 ~. `! X7 ]
-
% W! e2 {. Q& X/ _ - TIM_SetCounter(TIM2,0);' k) L# u/ Y( U/ X x( C
- TIM_Cmd(TIM2, ENABLE);
* V: X$ `1 M" ^. `8 S5 i - }4 p5 U$ M+ @& X8 H D% g1 r
, t/ R. m) b' H+ k. ~# r& h2 A
2 [1 Y" r3 f# }- void Locate_Rle2(u32 frequency,DIR_Type dir) 4 \* y7 M0 S7 m0 ]: ^# }
- {! L* m$ L V8 S! ]8 X
-
- ]5 O4 G) I% O/ R' j - if(TIM2->CR1&0x01)! } ~' T5 T8 ]: p
- {
; ?/ L& H9 n/ ]! F7 V - printf("\r\nThe last time pulses is not send finished,wait please!\r\n");
6 }) l/ Z4 y3 s/ `5 \/ d A - return;8 F" u+ k) @4 Z* y
- }" t$ a8 ^9 h) |( d8 p. U0 u
- if((frequency<20)||(frequency>100000))! `5 n! N M' x& m* Y' ^ w
- {$ R4 u( Q7 `* ?8 {# x5 k
- printf("\r\nThe frequency is out of range! please reset it!!(range:20Hz~100KHz)\r\n");
$ L' S+ h9 f9 Q; E$ {, A' H* H - return;& |2 I; ?9 ~/ j/ ] D; W
- }: `7 @5 c3 N: Z3 O: F
- motor_dir2=dir;2 ?1 L% \4 z8 S- R
- " ^2 |3 `0 u7 Q
- DRIVER_DIR2=motor_dir2;
/ p( A& D4 e4 u5 z" t* E - TIM2_Startup(frequency); 7 e- i w' [: \7 Z: Z3 M
- }
/ c8 r0 A: O# m
复制代码 4 N# V4 I; H; z3 W: X
到这里你就会发现其实原理还是相当简单的,剩下的也不再深入了,希望能够对大家帮助哈哈7 y0 b4 }$ _; N* K$ f
) i) k, T! Y1 g. c6 E实现目的:
4 F5 q- U$ m( O3 B9 x& o% I
+ c3 g# ~, g% i2 S5 e8 z0 l5 y该程序就是实现正转后隔一会再反转,大家可以根据自己需求设置到自己想要的转动情况,同时要让他停下来,只需要在自己需要的地方设置一个TIM_SetCompare2(TIM2,0)即可停下,可以自由设置。/ z x- N! q) G2 Z, V
4 J+ s/ v+ h$ Q4 Y四、总结4 _ W. W4 Y1 [4 y0 {! @3 H
今天关于步进电机就暂且介绍到这里,后面有需要会再特别介绍一下,文章写得还是比较简单,相信对于你还是可以很轻松入手的5 i' f, i9 C Q/ \
5 a! t: x! d( I/ J" W
: ]* {2 q; J7 i |