一、关于步进电机那点事
/ T: L$ \9 z9 A3 j这次使用的是二相步进电机,博客上也有许多关于步进电机的博文啊,质量也是参差不齐,今天就给大家仔细的介绍一下该电机,我主要还是继承以往的风格,资料方面我也讲的少,主要还是侧重实操方向,希望能够带给大家帮助! s, {7 P$ E. R+ Q1 E
8 L+ \ d+ C6 C7 t' ^
下面是图:
; O5 A/ s* M. t$ r$ L1 }4 e# J. }5 R3 [2 l0 l& n+ S4 y
% A& S, \, \& N [# ~- C
, }- {9 i2 I$ e: t; ^9 v' r$ [1 J首先要认识一下步进电机上的几条线:
, D, p( O( a! g4 ^. b1 B/ P. ?! c& C+ F3 Q7 x5 j; n' W
四条线(红、蓝、绿、黑)& T2 i! h; O, E, Z/ Y. ^- |
! Q! f7 w. y; q! H+ ]* u& f0 O6 ^; A/ P
正常来说对应A+、A-、B+、B-,在电机上基本上也都会标明代表含义,其实步进电机的原理其实都差不多,主要就是学会使用和了解原理就基本上达到我们的目的了,如果想要深入学习,那可以再继续研究······0 X& H! l7 V X2 q5 N7 ^* _
4 [/ F5 H" D* Q; W
那么怎么使用呢?首先就要搭配一款步进电机的驱动器了,网上随便都可以买到,如图:
3 b Q5 C- E7 [. [
! w3 ~& ~" }) Y
, Y1 x- U) ]4 f9 J6 A9 ]: l# R% w! d) v
这里我们很明显可以看到它有12个接口,这里再详细介绍一下如何使用接口:
$ k% R7 ^1 S2 w* p6 z) ~1 D
0 A# f9 e; N( A3 w' u7 G1 ^V+:连接电源正极(注意电压在9V~32V之间即可,过大的话你懂得)
4 e/ H$ F; u; n; K4 T9 Z: X" I
: x9 M; i/ O ^( V4 CGND:连接电源负极; ^# b$ l6 F, `/ t9 C
' t4 m9 X1 Y4 l% U' S( v" t: R" R( o
A+:连接电机绕组A+相
3 L+ }, h( k2 n& s1 m" c0 v
; O; `3 Q+ R0 I' p/ fA- : 连接电机绕组A-相
. p6 i+ \$ `& R9 m' b( U# Z. j
) i, h: f5 v0 ?6 E" mB+:连接电机绕组B+相5 F! r/ U) i5 k }
) K; g# ~" P4 V' q& u
B- : 连接电机绕组B-相
9 t8 z; i6 Y* w
; c( i( L( Q+ C8 V% x5 @, |CP+:脉冲信号输入正 ( PUL+ )(取决于共阴、共阳接法再来接线,共阴的话CP-接地,CP+接脉冲信号即定时器PWM输出)
, W: b/ q8 W, b2 w
$ |* ]' h/ P4 j, b' h% V/ jCP-:脉冲信号输入负 ( PUL-)2 x( Y8 o! `9 T0 h
0 h& T0 A. F/ W* w
DIR+:电机正、反转控制正(同样取决于共阴共阳接法). d5 V" R9 O- G- ^( D: q
7 z8 I4 l5 F- \/ O9 O
DIR-:电机正、反转控制负& W3 A3 R( z0 [) B
; Q {' B# o" `EN+:电机脱机控制正(可以不接)
$ A% N, B( r* t M# a, d" n) @& l/ _0 Y) t- x. {# r+ G& \
EN-:电机脱机控制负
) l; S+ R9 e6 w; \( h- a0 A9 G+ u$ Q8 j- y4 h+ s/ U2 F4 W
二、接线问题
t- {0 X! F4 v, i$ {上面到这可能对它的接线有了一个想法了,那么具体如何接线呢?嘿嘿,这里有共阴和共阳的常见的两种接法,具体参照下图:
2 _# |* E4 [& U0 }) m' x0 M) n5 n( t: N. ~% ]- O+ l
1 @( s- w& b$ [- z
- z( P4 W7 h9 N" E/ P! ]: }
. S( y" z6 |6 E, d# V* m- x" p. U6 m/ ~# O1 T
这里我采用了共阴极的接法
$ C) d6 K4 W( k+ F2 v1 c
3 Z$ e# k! L- s那么我的接线:, ~9 v- Q+ |+ T9 W3 V
9 Q; H2 Q+ g7 Y; wDIR+:PA8(随便一个端口即可)! h; t& I1 ?# G1 }
" X: y4 v; K3 Y3 ~9 C
DIR-:GND
9 M2 M- A* `, }, g8 J4 `% K
) v: B0 a( u- V3 g6 U. C: bCP+:PA1(TIM2通道2)8 y: Q% L, _, D6 D
k) l; Y& P% _* Y: r& a4 bCP-:GND' K' o6 X9 i, m! g
; W; d/ r4 y0 r! G" jENA不接& Y5 y. V6 H7 G$ b) d' U! A9 y7 l
8 ^: i% W( h8 S% W三、主要代码
5 p. R @- \+ F: a6 b这里的代码搬运后修改一些的,即可上手即可用6 f1 b: H M" d, [
7 \8 m* g& [( k3 c主函数 }" |/ C0 K& i
2 ?, t! n5 x) u. b+ A" K* {, H
- #include "stm32f10x.h", E3 b) C q4 y8 h, Q' y- J' k% V+ o7 i
- #include "sys.h"" F0 ~( @( g& E) S2 `
- #include "usart.h"9 B) y5 [+ W+ c# l: ?. z
- #include "delay.h"
9 G2 V) `( ?$ s; G9 V1 j - #include "key.h"
2 [: g3 G* F% g. F8 B - #include "led.h"
: h- v" s0 D; u- q# ~ - #include "usmart.h"
( I3 u# ?( F( {# Q6 ]. e) f$ `/ h - #include "driver.h"0 q8 M5 x2 ]) D
+ I0 D1 Q1 v4 n0 O5 {# `- //共阴
; J0 S% m. `) N$ G! t* \4 s# I - /*0 O/ M* k/ D# G7 K
- CP+->PA.1 CP-接GND
) q# x) C1 M! d2 g [ - DIR+->PA.8 DIR-接GND% ~3 Z' J6 X5 s* [
- */
6 i b: }# A0 ~/ o% d - ! N1 q) V k/ s% {9 \
- int main(void)
" x5 D7 ?. ~$ \8 Y. F3 \/ ? - { 7 v, r W7 j; m' J0 D
- delay_init();
: U* F# d& p& Q0 H) L8 s4 X - NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); ?0 P# p+ M, T* M( f% p
- uart_init(115200);
/ x' v$ I8 n) { - KEY_Init();
) n( @) S4 C% \) Z5 \( f: s) E - Driver_Init();
; a1 t0 g( K |1 K) D7 ?( F2 M - TIM2_Init(999,72-1);
5 z& s- `9 T% N: K j, F9 { - while(1)
& l* Y% B8 X+ v# a - {
- Z' l$ O+ {6 k4 O - Locate_Rle2(500,CW);
8 B( j5 l9 M6 G - delay_ms(5000);
! N/ o& g9 ?2 Q0 U - delay_ms(5000);
) ` y( X, ?: h; K - delay_ms(5000);' J, A% M7 J/ I1 P7 @+ N
- Locate_Rle2(500,CCW);
" z9 h6 `6 M$ o - delay_ms(5000);: Z m7 X* B: }9 A8 E6 S8 {
- delay_ms(5000);; K5 A4 d6 \, ?# {
- delay_ms(5000);
" ~3 O0 R) H3 |& B* ]! y# ^ - }* R5 r8 m7 H) g8 L$ E# b
+ M2 K. k% G4 ]; m$ Z A$ a- }
复制代码
' `: b9 F: j+ ` _$ g7 m 定时器函数:2 t5 c$ ^& B4 Z$ }/ L, z9 u* C
: F# O- d( z0 F" z0 k' N
- #include "stm32f10x.h"
: H- a2 a4 [4 S4 b - #include "driver.h"
* \, F! S, V' Q$ q# |% I% ^" ` - #include "delay.h"* U4 i/ e0 T) V4 E3 }
- #include "usart.h"5 |5 U7 x7 z' x6 e+ j
- 5 K$ r, L, \5 g# h% P
- long current_pos[2]={0,0};
/ J6 V( }* |1 l8 q+ k; p2 L$ h - int motor_dir2=0;
2 \, J: Z* q6 @( n% y# J - u8 count[2]={0,0};$ B' n- E- O3 `1 M& z
% x% n1 F$ N: B9 ?: B x" x- void Driver_Init(void)
r) t- h; V6 x# f& }. g - {
6 r0 f+ N9 T# W) Y+ b - GPIO_InitTypeDef GPIO_InitStructure;( K! _0 H0 I! |4 K# [3 D
- " z1 r+ O1 i/ f% c* x# m* i# V
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
, L8 A6 Y/ }$ p8 Q6 J; E1 h3 `
3 k4 F0 } m/ K8 i& {4 C* C! |5 A% ?9 [- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
( o2 `# K) D8 t% S - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
. m: e: j9 j1 C1 O' x; X* C7 A - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
* T( Q( M3 S, _! o" Q/ b - GPIO_Init(GPIOA, &GPIO_InitStructure);
* G" X$ N$ G b; M# Q - GPIO_SetBits(GPIOA,GPIO_Pin_8); 5 F; Q2 G; B% c% j3 B* J P+ i
- }8 O _/ v6 h/ U4 ]# R
- % b$ k" C& k7 Y
- ; D8 c9 ?$ [. O l8 o* y1 Q
- void TIM2_Init(u16 arr,u16 psc)
5 g( J* k6 O- Z* W3 ?9 n: { - { 5 |/ L+ s, C9 ?- x) r( e
- GPIO_InitTypeDef GPIO_InitStructure;
! C- C9 `7 _/ Q2 i8 z L - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
& E: I9 a# R8 B# i& E# Y) e" f- L - TIM_OCInitTypeDef TIM_OCInitStructure;# \* v+ |% X8 m
- NVIC_InitTypeDef NVIC_InitStructure;: r/ z+ O4 v6 F) F3 ]
- # r% \# a# E4 o: T$ v7 p {1 I
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); ; W% X% ?% `5 b7 w1 w
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); - u& L% z8 S9 d' {
" Q; p. F$ L' g0 I/ b q- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //TIM2_CH2
4 A' w# V( N9 v% v - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 6 x1 Z9 b& W1 S5 [/ `
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;% |) S @9 J6 B7 Z
- GPIO_Init(GPIOA, &GPIO_InitStructure);
' `* i6 p. W! l1 p$ c$ f - + Y& p4 R( b& z3 x; a% u2 _( [1 E
- TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
5 b J% t0 p- ]" z -
7 h9 ]' M1 L/ S2 F" R2 m, [ - TIM_TimeBaseStructure.TIM_Period = arr;
- r8 Y# _+ D+ Z- [, L1 n5 B - TIM_TimeBaseStructure.TIM_Prescaler =psc;
`; |; z: X. Z5 e - TIM_TimeBaseStructure.TIM_ClockDivision = 0; " S/ \2 D, w; m, B; o
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 1 o8 _7 C$ d4 I3 U. G; o, ~& J' i
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 5 A" K+ J+ Y9 o! K0 c# d {3 B2 x: S
- TIM_ClearITPendingBit(TIM2,TIM_IT_Update); % p* k. f: d- s( }
# Z* Z0 s4 S4 g# V- TIM_UpdateRequestConfig(TIM2,TIM_UpdateSource_Regular);
8 K9 F' ?4 p" e. d5 m - TIM_SelectOnePulseMode(TIM2,TIM_OPMode_Single);
1 O# H) N1 M2 k0 x' @3 |% s - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
. Z# e6 @# Z# w3 a* e6 r' T7 D - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; ) W. @) z- G) @ ]" [
- TIM_OCInitStructure.TIM_Pulse = arr>>1;
# \$ k: |) A' i5 I, ?2 v- Y @ - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
5 \$ {% l4 a0 h/ X4 G, p# N" m - TIM_OC2Init(TIM2, &TIM_OCInitStructure); ; X) y% c: {( N0 b
% J/ e" I! _( Z3 {- TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); 2 B( ]' N6 ?9 o
- TIM_ARRPreloadConfig(TIM2, ENABLE); * h$ h" a4 L8 @2 p8 z
- % k J; u% m/ W$ O1 ^6 d
- TIM_ITConfig(TIM2, TIM_IT_Update ,ENABLE); + z# _% ]# H" M7 w% }
- , M0 a2 X9 N: O
- NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; ! k, O Z. c0 Y. {5 {8 |' _/ P
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; % D0 }& L$ u& \% P+ T& o
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; * P$ R% z: z; S+ c
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 4 g: y# N* k* g0 y
- NVIC_Init(&NVIC_InitStructure);
- W5 H: ^& O. p- s7 | - 7 a" g7 L& @# D. d! R9 i# F7 h
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update); 1 B/ D6 N) T5 `" W
- TIM_Cmd(TIM2, DISABLE);
4 l9 j$ g. C5 x6 `6 [) x+ J - }
/ ]' F3 j+ h3 p0 A% E4 {: C - /******* TIM2*********/0 c1 W! y+ N: F" S4 N( G
- void TIM2_IRQHandler(void)
7 W. R5 y" n. f/ _) `. I - {
6 ?# I3 [$ C# h+ ]* ^ - if(TIM_GetITStatus(TIM2,TIM_FLAG_Update)!=RESET)% v# n J2 A0 A, X1 e
- {
% q# N: F! U& W- [ W - TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update); % z2 W) ]* J, Y1 O! A5 X
- count[0]++; 6 O+ L3 i* L% G& V6 b& i
- TIM_GenerateEvent(TIM2,TIM_EventSource_Update);
8 x5 a! A" t2 g# K - ; Y# l2 J% l. g6 o j* R p0 g2 [1 I
- TIM_Cmd(TIM2, ENABLE); ! ?3 Y) Z* O2 u8 w) n
- 2 o% w3 }3 q k( _" Y
- if(count[0]==200)
- t6 h4 M* [8 i C7 P. ? - {0 P/ g& z- C4 m) U
- if(motor_dir2==CW) % o9 n/ x0 B0 n
- current_pos[0]+=count[0];
) g# _' L9 N. _7 F3 C - else
* r6 ~( I1 }) |, a - current_pos[0]-=count[0];
/ f2 v* _2 {; [- O: } - TIM_Cmd(TIM2, DISABLE);
; G* q% M) r7 _! E$ C, s' u& [1 P+ i - printf("motor2µ±Ç°Î»ÖÃ=%ld\r\n",current_pos[0]);: \" o! j& d0 L5 h3 N8 _- \4 C
- count[0]=0;. c; J+ J" O; ]. ]) H
- }# L. e T c0 F' I
- + f5 o( A& c3 s: T& E/ o
- }+ A) p6 Q' r; D3 [3 O9 W+ Y, \; T$ j
- }5 ?$ l, Q8 G3 s
- 1 Q& m/ s9 m( i9 T$ \9 U; i
- void TIM2_Startup(u32 frequency)
5 x3 k, }! d/ A& @9 K3 |+ p - {
) ~4 u& @9 x g - u16 temp_arr=1000000/frequency-1;
/ P+ X" \7 N9 v& H% ^! w - TIM_SetAutoreload(TIM2,temp_arr);
+ B: ]$ v4 G! P5 \7 I+ J; R2 H4 s - TIM_SetCompare2(TIM2,temp_arr>>1); + r( R9 |0 U4 O& z
-
& Y$ e4 v$ F$ Y5 f) P" e1 z% G, ? - TIM_SetCounter(TIM2,0);
9 E) D* Z5 Q( `9 o" C - TIM_Cmd(TIM2, ENABLE);
4 l! ^# h5 t3 P0 c) r9 S2 z - }9 H. d" U( K2 s
* t% B+ ]" R0 p/ Q: Y- - _) e$ a; o# f- P9 i- ~) e6 t R
- void Locate_Rle2(u32 frequency,DIR_Type dir) 4 Z- o1 g! J1 ~* N4 @
- {
- Y0 J9 z5 T, o W5 S4 X -
( `, C: v/ Z# |( z; T - if(TIM2->CR1&0x01)
3 d" ]; Y( R1 B- X4 R - {
+ }" ^" U8 T# |- A6 e. ~ - printf("\r\nThe last time pulses is not send finished,wait please!\r\n");. R1 U( v8 S0 e/ p5 m
- return;
4 s4 M3 W, g6 [ - }
; d) Z$ N4 q: a' ~) [3 l - if((frequency<20)||(frequency>100000))7 J9 [2 {, d2 X& I* G! x: I! @
- {
8 h& z/ \; e3 U/ p - printf("\r\nThe frequency is out of range! please reset it!!(range:20Hz~100KHz)\r\n");+ _% q6 X& H# E' G- m0 b
- return;8 u* a7 o: q C$ \7 |9 \7 E
- }! z7 l3 {1 H0 k$ ~" ?
- motor_dir2=dir;$ H! b$ [# c @( i
- ( \/ _; T( O( T: q8 t- A
- DRIVER_DIR2=motor_dir2;
! m* [7 S7 a; ^8 H! s - TIM2_Startup(frequency);
; M. O0 I+ S5 o) o; q) Z3 T: G2 _ - }( Y# c& a& C: V: p2 p
复制代码 * M7 s6 F" k) j j: X8 _) a
到这里你就会发现其实原理还是相当简单的,剩下的也不再深入了,希望能够对大家帮助哈哈
+ b: h, R* N$ V) r0 o) p2 F6 [- @9 B0 w {# L, f/ A
实现目的:1 D6 d$ l9 L/ Y& }. S1 _2 b
6 e6 |5 s; p/ ?/ k! l6 n' u6 O# x6 z
该程序就是实现正转后隔一会再反转,大家可以根据自己需求设置到自己想要的转动情况,同时要让他停下来,只需要在自己需要的地方设置一个TIM_SetCompare2(TIM2,0)即可停下,可以自由设置。
, \8 Q% \5 x0 y; I
6 Z' ~9 F' c9 [7 Z, r( R. C四、总结! R* `: a+ b% q& I! o; j
今天关于步进电机就暂且介绍到这里,后面有需要会再特别介绍一下,文章写得还是比较简单,相信对于你还是可以很轻松入手的) E) o S, l* k8 [% R
. L: I p9 P0 c* ~$ o" X
) y% E( k4 u$ y$ b* V |