你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

利用STM32F103精确控制步进电机

[复制链接]
STMCU-管管 发布时间:2021-6-25 13:30
利用STM32F103精确控制步进电机
一、用到的元器件
* y; z3 v* }0 `4 f7 \STM32F103C8T6
: k* b& P5 U: E. N8 ]42步进电机(42SHDC4040-17B)6 G% A/ h6 K/ F4 H5 _* _/ x7 J
TB6600电机驱动器升级版$ b8 q9 g' `/ i8 @" b4 J0 h
- H6 v0 V8 z, X- v5 @
1 z8 S  s1 A( O; \% K
二、42步进电机
  f3 J1 s) y3 B  d* ]1.步进电机的基本知识) P) ?& ]/ p" l1 I- z1 f" l% a+ Z
(1)拍数——每一次循环所包含的通电状态数(电机转过一个齿距角所需脉冲数)6 Z* N$ s0 X9 Y2 R" s5 V
(2)单拍制分配方式——状态数=相数
+ d. H2 Z0 p+ L* r  ~(3)双拍制分配方式——状态数=相数的两倍3 U  t: C+ l( e1 A. a% @
(4)步距角 ——步进机通过一个电脉冲转子转过的角度
1 `& C5 y! t) w' }0 Q1 ?! V
11.png
N:一个周期的运行拍数
; X: `" }- r1 e4 U5 t' lZr:转子齿数
7 K5 ^& X2 @: Z, `( Y& M1 g拍数:N=km
  e6 G5 Z! f( @, Mm:相数
) Q! W( [' _, `* {k=1单拍制
9 D  v1 o6 B' b  D% p7 dk=2双拍制
. X! j  L: K# @& d" d(5)转速! `4 B! F6 D* E0 P% b$ w' e. E
12.png
(6)角度细分的原理
" L) L3 @/ W0 u' o; O
' ^, s5 g; h& W! J; w  j
5 D. C. @& E  D& C% V- E
电磁力的大小与绕组通电电流的大小有关。
4 }1 Z( `- k+ f1 A1 M% f. F当通电相的电流并不马上升到位,而断电相的电流也非立即降为0时,它们所产生的磁场合力,会使转子有一个新的平衡位置,这个新的平衡位置是在原来的步距角范围内。
: s0 i2 }( H/ {4 N' z2. 42步进电机参数' |' o+ n1 y3 r/ l2 _- b9 L
无法查找到42SHDC4040-17B型号的详细资料,以通用42步进电机为例:
9 ?1 C2 u5 J4 I# c: o步距角 1.8°# @8 t1 [: _4 I. S
步距角精度 ±5%
+ t  y+ I8 {) U+ V8 ?相数 2相) @2 h! E# ~7 @7 H3 E
励磁方式 混合式! k/ O# N/ A3 }+ K2 T: `, Z
转子齿数 505 d* j: q, U/ k; a3 a9 m
拍制 双拍制. i. _, ?. Q- Q7 u, l! S- f' C
其他参数:无
1 v9 J5 F% p. X1 |由步距角=1.8°推算出转子齿数为50,拍制为双拍制2 V' e& F2 g7 i1 b* H' f. S
, Z4 c! }1 [& K
0 F2 N4 d4 `. c
3. 42步进电机速度与角度控制3 Q$ J0 V& q* _+ g4 i; F7 h
电机的转速与脉冲频率成正比,电机转过的角度与脉冲数成正比。所以控制脉冲数和脉冲频率就可以精确调速。
1 o& S9 v1 R. K4 L' f理论上步进电机转速 = 频率 * 60 /((360/T)*x)& p5 G: R. }3 B- u1 H: f. Q
21.png
  Q+ M4 r/ E, r8 Q/ b​        + V* I- p' }* J8 A
转速单位: 转/ 分
+ h5 |: b! z; W, e频率单位:赫兹* R5 W9 u+ n) {4 h* {3 T. A- r
x 细分倍数
) [9 }* y7 S0 i* ^% j5 NT 步距角
9 S# B" z+ H; p2 J6 `! W  D. s例如,在本实验中,32细分;频率72000 赫兹;步距角1.8°;套用公式72000 ∗ 60 ( ( 360 / 1.8 ) ∗ 32 ) = 112.5 \frac{72000*60}{((360/1.8)*32)}=112.5
) m8 B9 A4 c: f((360/1.8)∗32)# l- z, U% |+ H) ~& z
72000∗608 K+ S7 v5 l8 ~' L/ C1 e
​       
% [* f- ^  }8 z6 D. K9 a =112.5rad/ min,即1.875 rad/s.5 s: w: ]4 J( M* b% r+ `
13.png
三、TB6600电机驱动器升级版参数
7 Z. x$ n, H7 w* f7 V; ]5 uTB6600步进电机驱动器升级版是一款专业的两相步进电机驱动,可实现正反转控制。通过S1,S2,S3 3位拨码开关选择7档细分控制(1,2/A,2/B,4,8,16,32,),通过S4,S5,S6 3位拨码开关选择8 档电流控制(0.5A,1A,1.5A,2A,2.5A,2.8A,3.0A,3.5A)。适合驱动57,42 型两相、四相混合式步进电机。1 u7 \  l% n( P. g3 L. f

  T9 [" i8 p5 T3 Z% l- D; T

3 [6 q: P' H/ U; F1.信号输入端
3 j  f/ H2 [5 qPUL+:脉冲信号输入正。( CP+ )& T2 C5 k% z! `) ?) Z
PUL-:脉冲信号输入负。( CP- )# z3 Q9 J, h+ H( t- I8 k$ h
DIR+:电机正、反转控制正。
# r, T$ k1 l+ sDIR-:电机正、反转控制负。( l6 Q6 h* v( s  `# C) f4 [
EN+:电机脱机控制正。
- o' U* h; q* G5 B8 SEN-:电机脱机控制负。' K9 q1 w- P- u' Y
) p! J' U9 F1 g% C! Q
( @! P4 f, Z# o% A+ f) ?4 Z
共阳极接法:分别将PUL+,DIR+,EN+连接到控制系统的电源上, 如果此电源是+5V则可直接接入,如果此电源大于+5V,则须外部另加限流电阻R,保证给驱动器内部光藕提供8—15mA 的驱动电流。( g( b* {/ \' H/ K& Y
共阴极接法:分别将 PUL-,DIR-,EN-连接到控制系统的地端;脉冲输入信号通过PUL+接入,方向信号通过DIR+接入,使能信号通过EN+接入。若需限流电阻,限流电阻R的接法取值与共阳极接法相同。% S0 q% L2 H( f
注:EN端可不接,EN有效时电机转子处于自由状态(脱机状态),这时可以手动转动电机转轴。5 P+ ~9 w4 W, R$ L% Y% V/ x9 j( f
2.电机绕组连接. ^$ k& m* G6 }/ k1 m
A+:连接电机绕组A+相。
( M' v, n; |! l4 @$ BA-:连接电机绕组A-相。
1 i$ B1 n0 T" R  g4 M, ^: @8 T# fB+:连接电机绕组B+相。
+ H: L9 W4 w) [: `+ F# u+ ?B-:连接电机绕组B-相。1 [' I* D/ e" {$ f; ?
' s) E, [3 p6 B  m8 h$ n
1 c8 v! }8 z8 n3 \
3.电源电压连接3 S  b2 C9 t. w2 e* l8 y
VCC:电源正端“+”
; {( I# ^9 X! I, D) k; h% iGND:电源负端“-”
9 X* \9 ^9 @0 M3 ?  r: @注意:DC直流范围:9-32V。不可以超过此范围,否则会无法正常工作甚至损坏驱动器.* l4 M3 _: q: A
# s$ b( W3 E6 Q" A9 Q

9 J: V& Z. n& U7 K# i8 s7 r4.拨码开关/ B3 b0 A) A7 Z( e3 L
14.png
$ i' x( ?; Q- s1 P电流大小设定( P: a. H: M, s% Q
15.png ; C; ?4 X; @( P
三、STM32F103, }8 e  |6 d7 O1 a1 R
------说明:引脚部分在文章末尾有解释--------7 T+ T, i' Q" H9 ?( p

! p' F8 S2 v' @6 W* C0 G" m, i

# C; V8 l- T9 f6 ^4 A# v9 R5 ?* \3 Y1.引脚连接
1 Z- D' B9 C5 w& P5 D0 ?; y! @& rA 0——PUL+2 ]8 h% C! @1 l: b7 o1 R: y
A 3——KEY1——V3
3 o& b# Z2 f7 p+ y* g' z+ B2 }; a2 D! yA12——DIR+
! P  L+ s/ ^. T  ?6 ^9 L6 g0 XA11——EAN+1 ^( y* v- W& f
GND——EAN- ——KEY0: q" q' g& p) }# ^$ M
4 \: m, ~7 m) y( a+ a' h. u. x
0 d9 @$ l6 n. K! K
2.引脚功能' g7 R6 k, n& N; T
A0控制电机转速1 I, c6 U1 j$ E7 z! N
A3控制按键: g' J& ?/ n) e- e+ ?/ h+ V
A9
( r; Q7 K4 d) ?) B* P5 Z2 tA11
+ s$ j% N& {% y7 K# S2 TA11控制电机是否为锁死状态
9 e' A+ w. Y) M+ y  NA12控制电机正反转4 T, R4 s: S! w7 L4 D/ R& S

2 G$ h% L2 |8 ?' m
( y+ N6 x$ \) D8 u
3.定时器
4 h* x* |6 i, ?1.本实验利用定时器TIM2和定时器TIM3构造一个主从定时器,TIM2作为主定时器控制电机的转速,TIM3作为从定时器控制电机的转动角度。, M3 u0 i9 Z0 N& a/ f# k
2.电机的转速和转角还与驱动器自身的细分数有关,但是驱动器细分数是通过影响电机的步距角来影响转速和转角,而TIM2和TIM3是控制步进电机的频率和脉冲数来控制转速转角6 N! W: O8 D# k3 n' }! q/ ]) r
3.电机的转速和角度与定时器的关系(在不考虑电机自身的细分数下)& r( z. |; F( ~: @0 Z
# l% O( \2 X! i
0 J; Q* Y( r! i' ^
设TIM2的定时周期(即重装值)为nPDTemp2,预分频值为OCPolarity2
6 M( }" L: }" P TIM3的定时周期(即重装值)为nPDTemp3,预分频值为OCPolarity3,: E/ ^# l, H3 Q) w. I0 E
则单片机产生一个脉冲所需要的时间为:
) G; B) C$ I$ h! r* h- S 23.png & g2 y; T9 G* r6 u& M
​       
5 E& ~! ~1 k( A8 P5 O& d  本实验中设TIM2的定时周期nPDTemp2=72000/5000-1,预分频值OCPolarity2=999,TIM3的定时周期nPDTemp3=6399,预分频值OCPolarity3为0。即- D: e2 p# I# d
22.png
' U0 R8 ^& j! A! @! I  定时器共产生nPDTemp3+1=6400个脉冲,电机转过的角度为6400*1.8°=11520°,即电机转了32圈。0 p4 i  ]/ V5 |) _, Q
  转动速度" x; Z- m* ]" N5 h/ I! v
24.png
! L+ r$ D8 \% W1 r8 I6 d
& V0 `5 P% o+ y+ _- h  Z  l, ?

# h+ [; h8 T" X* B* Z3 {$ X% O5 u7 ~+ h4.在32细分的情况下电机1rad/s和转1°需要的重装值为nPDTemp2=11.25,nPDTemp3=17.7778。4 i/ U% P' R1 e. ^6 f; U

  C9 Y' |7 \+ @

/ d1 Q& O9 t! h" U/ L. Y四、程序实现
! i- B- S/ X" A0 `8 _1.main.c程序
% M+ Z  Y$ l* r: k3 B8 E
  1. #include "main.h"
    + t" [% I3 y5 o* U
  2. #include "sys.h"( h/ C% {% j; X5 r1 m: H; ]
  3. #include "usart1.h". V7 x+ n+ J$ X& R7 o4 n
  4. #include "delay.h"
    4 q3 i: }1 D$ h4 J
  5. #include "math.h"
    , I3 K7 r  d+ w: `9 C9 k
  6. 2 U6 U; y) @6 r, Y4 p. B
  7. u16 t;  , q5 r# H6 d+ |& h0 j
  8. u16 len;                    //接收到的数据长度1 \& h+ b5 u: m1 {
  9. u16 times=0;/ _2 e' `8 p/ H0 F
  10. char receive_data[60];        //接收到的字符
    " u1 H" N6 A7 J( j: s" w
  11. char state;                                //电机正反转标志位0正转,1反转
    ' |6 O! G! d* s4 }9 y$ ~) _/ g4 O
  12. int speed,angle;                //旋转速度,角度. q; J4 H; `3 p; S" e
  13. int a=0;                        //判断是否接收到数据
    " U7 T7 q. r& e: K4 e" \
  14. int r,data=0;                          //用于数据转换
    . M; q/ |8 \- p  Q
  15. int type;                                //转换后的数据   
    ' V2 ~) u3 R3 v3 I7 X- ]6 X
  16. extern u16 USART_RX_STA;6 [2 @: z* H  C+ V  c1 l1 `

  17. 1 U5 @: O( M  c  a
  18. /**************************) q; a( P3 I: e) l. h! ?5 {* P
  19. * 函数名:delay
    % W1 V7 Q2 |% `) G" P  p
  20. * 描述  :延时函数7 `  K/ @( n" x; _- U0 z
  21. * 输入  :无 - e* m  G/ w) C( a- G" k% ?
  22. * 输出  :无
    / |! I5 I6 x! m7 j
  23. * 返回值:无
    3 v' d. ?; E7 D6 g! W) P
  24. ****************************/
    - h5 P& T4 t7 }9 _
  25. void delay()//延时
    7 r! W" i; R: A  s1 U
  26. {
    5 ^9 M- S- s. i+ r* y7 v0 P
  27.          int i,j;
    # k: X$ x/ i; d  K* j
  28.          for(i=0;i<2000;i++)
    : [; a" E; u. N$ G
  29.          for(j=0;j<1000;j++);
    : ]; z# T( Q2 y8 i; |3 W9 V
  30. }/ a: a$ f2 d5 _, y9 B3 J
  31. + f! |  h# b- V3 Q. T9 y" m6 e
  32. /**************************; Z; C3 X! M; k" f- t2 r: w
  33. * 函数名:Waiting_receptio
    0 }+ I" p4 [4 ^7 E
  34. * 描述  :等待串口接收数据
    ) y: }& I' j/ A- p9 @; a4 q9 s) V
  35. * 输入  :无 $ r& J6 Z, L8 l$ F3 g6 E
  36. * 输出  :无
    5 k, u9 t9 j1 G
  37. * 返回值:无
    : g) v% v3 b8 @* n
  38. ****************************/
    6 k5 E1 u* j! [4 Z4 F. W% w3 U, Y* h6 k
  39. void Waiting_reception(void)5 Q. i( g7 M( H9 L4 T0 V$ ]
  40. {
    , x# \5 y* U; Y/ {( d
  41.         while(a==0)//等待数据发送完成7 ?8 }: e9 a5 x
  42.         {6 {8 C, ?2 m4 K6 H
  43.                 delay_ms(100);; Z5 A( [+ s8 Z
  44.                 if(a==1)//接收到数据
    % o- I% \6 Q* G5 s6 w2 t6 N
  45.                 {
    8 `) R- v" r6 n
  46.                         if(USART_RX_STA&0x8000)//(串口接收用到了正点原子的例程)7 A/ `* n: v  [+ l; E) f7 d8 ~; M1 ~
  47.                         {" t( _  `  L5 q" F
  48.                                 len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度/ ^$ Y/ ~2 h( h7 @5 [# }6 c
  49.                                 r=len;                                ' q9 y' J- ~7 [% }: Q7 W
  50.                                 type=0;
    ! H0 w; B/ M! z" Y9 W" v- f
  51.                                 for(t=0;t<len;t++)//拷贝数据,将字符转换为十进制数
    + A2 p( z" S4 v/ X  L! J  v# o2 F
  52.                                 {
      O! ?: I: \. q2 Z
  53.                                         receive_data[t]=USART_RX_BUF[t];9 v8 u" q' @1 g! F, z  R& W9 Y
  54.                                         data=(int)receive_data[t]-48;, p4 x" f$ D# s7 Q+ @
  55.                                         r=r-1;, _4 Z9 ~% J) L$ k% U- @) l2 ^; W; h) v
  56.                                         type=type+data*(pow(10,r));+ q  k6 H& d) Z" }+ S
  57.                                 }
    : n. v' m9 Q1 F% T' h( u
  58.                                 USART_RX_STA=0;" x6 I+ ~  c- j2 Y  x/ y
  59.                                 a=0;
    * q' [+ g7 [8 y3 |/ S
  60.                                 delay_ms(500);
    8 O% V" a& Q; k' {* M2 P
  61.                                 break;
    % m& _% U* }- @( c
  62.                         }
    ; n3 N3 W$ h8 f: S, W$ M
  63.                 }
    $ @" G( g8 D& s& m; v
  64.         }  X, t# _/ h" e: l& `' M/ y/ c0 Q
  65. }
    9 n8 t; N9 G' [4 G) J
  66. /**************************
    5 O/ j) N( u3 E' S# @+ ~
  67. * 函数名:KeyStates$ [- L3 ]: F% S2 c# m$ E
  68. * 描述  :监测按键状态0 ]1 {. b8 w6 F  Q! {
  69. * 输入  :无 7 Q: g( ^* N3 w: b0 |
  70. * 输出  :无
      X. `# G8 l: l: W- }& X% E
  71. * 返回值:0/1- e" {( b' t' z) u+ h
  72. ****************************// U- G! n: n. K3 l# y
  73. u8 KeyStates()//按键状态
    6 b* ~! P* F' a( k$ @
  74. {
    5 O7 m1 x, j( W; X) o0 Q' @  y4 W
  75.         static u8 i = 0;
    5 Y0 t, x# G; R
  76.         if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)- Z$ m1 D' h' {. i7 ^/ R
  77.         {
    1 X2 l, F$ u; Y5 F/ a9 p
  78.                 delay();
      c& A- l, E9 U
  79.                 if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)( _- P$ L  U" r
  80.                         while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0);. j: j- D$ x8 |, S  Y) J
  81.                         i = ~i;
    - ^: E% t0 ^# s2 I& W/ c
  82.         }8 G3 ]' v3 b, V) R2 W
  83.         return i;- A) d3 L. f  p  d8 _$ \4 g1 H. ]
  84. }9 I% s0 m3 \5 \) a
  85. /***************** }1 I' Q$ M2 e( x3 w
  86. * 函数名:main1 n* h0 s- X1 w5 g3 `
  87. * 描述  :主函数* S- i/ ]3 I2 ^3 u6 h$ r
  88. * 输入  :无 $ W: ?; u* M; F: |
  89. * 输出  :无6 a# [4 F) Z# N" p
  90. ******************/: H& l! G! N  ^! H$ Y
  91. int main(void)  b, i6 ^% Y2 b, d8 E) y
  92. {  J/ w7 x  S4 o4 z  V7 x( M7 o( z
  93.         NVIC_Configuration();                        //中断初始化  M3 A5 f  S7 j8 D/ B
  94.         GPIO_Config();                                        //IO口初始化
      A  C! N' r6 O& ]
  95.         USART1_Config();                                //串口初始化
    ( W1 I- f2 q5 E5 C: ^, [8 T
  96.     delay_init();                                   //延时函数初始化        9 X" m. }. e/ x2 ^$ p; J
  97.         GPIO_ResetBits(GPIOA, GPIO_Pin_11);//A11置零  A11——EAN+* Z8 v# Q, G. K% _
  98.         GPIO_ResetBits(GPIOA, GPIO_Pin_12);//A12置零  A12——DIR+  j/ t: _0 A4 Q; s, ^; w& P
  99.         while(1)+ X" q* H2 v. O, c& P
  100.         {
    + l1 A( A3 O) a9 _; N( ^8 O
  101.                 delay_ms(100);. S1 S3 U1 h/ s3 c. B9 c% x
  102.                 Initial_state:                printf("\r\n 请选择正反转,正转输入0,反转输入1 (以新行作为结束标志)\r\n");        / F" v5 l% I& ^- @$ _( b
  103.                 Waiting_reception();
    2 Y% ]  {5 x( K: Z: T8 U
  104.                 state=type;//将接收到的数据给type
    5 d( I5 a+ V5 Q' a* c, h9 c
  105.                 if(type==0)//电机正转1 h) u( {4 V( i; A# t$ R  d4 h
  106.                 {
    " l; g" b; S6 E( |! j
  107.                         GPIO_SetBits(GPIOA, GPIO_Pin_12);//电机正转* N( i7 K" b- q: k) _, d7 r2 p
  108.                         printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");4 k4 M7 }  w# }& S. F. w' ^7 E3 C
  109.                        
    - o$ ?. r3 \+ Y- l
  110. /*********************************************此模块用于配置速度参数********************************************************/( |* G; s4 f% ?8 Q: [# I
  111. , o) p  D5 p' [8 f% |( }3 ?0 [
  112.                         part1:Waiting_reception();
    $ C" a% F& q5 |0 S9 o0 c: S( @
  113.                         speed =type;//将接收到的数据给speed' ^; K9 i+ p8 T
  114.                         if(speed==0)goto Initial_state;//如果是0则返回初始模式
    3 U  m5 s! k/ ~/ Y. W7 E
  115.                                 else{( _$ n9 d# t4 ?8 f) p; v* ]( j
  116.                                         if(speed>=15)4 m( I* F8 W* [& H( r$ |+ ]
  117.                                         {' P& V0 n7 R( e9 b$ E" P* l( I
  118.                                                 printf("\r\n 旋转速度>15rad/s,请重新选择旋转速度。\r\n");- Q4 Q1 ~# B4 E: z6 W9 l, K( ?
  119.                                                 goto part1;$ q/ f7 i1 u) a' l& F
  120.                                         }2 B* h4 Q9 C9 _" M
  121.                                                 else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式 \r\n",speed);
    # Y7 `! }- R9 ~1 @
  122.                                 }
    / M( j. u- n' o+ \" M. J) E) p4 G1 A
  123.        
    - L& ]8 T0 c" b! d2 t5 E
  124. /*********************************************此模块用于配置角度参数********************************************************/                + i" e4 F, g3 U. P( C6 J

  125. ; j! k2 ?: f% J$ |
  126.                         Waiting_reception();
    6 y, B7 H5 b! S6 p( \
  127.                         angle =type;//将接收到的数据给type
    * X8 @+ m! N# {& X: D
  128.                         for(;;)
    + Z6 F% [4 h* a3 d$ F' i
  129.                         {
    ( v- `) O6 |- |/ a* e+ j
  130.                                 if(angle>0)//接收到的数据不是0: `( z6 t* P8 s8 A* p
  131.                                 {( M6 ^2 b: a$ M0 O0 @- k2 x
  132.                                         TIM2_Master__TIM3_Slave_Configuration(speed,angle);        // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度/ p. f8 ]. m! z2 Z7 W2 G
  133.                                         delay_ms(20000);//电机保护
    % a/ H# q; H: ]  n
  134.                                         printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式; \r\n",angle);
    " z" J/ x) M) _9 I1 U
  135.                                         angle=0;5 R8 W  W6 [& e/ _3 B6 D
  136.                                         Waiting_reception();               
    - Q" h5 P" t0 |- l7 }* @; y
  137.                                         angle =type;                                       
    # H+ f/ A' N- a) |. ^
  138.                                 }else{% k$ \7 ]" ?2 Y" X7 F7 a( D1 k
  139.                                         if(angle==0)goto Initial_state;//返回初始状态        ! I7 B  G( J0 Y- I- q- N8 _, I
  140.                                         else {
    4 ~; C3 y- B9 v
  141.                                                 printf("\r\n 角度错误,已返回初始模式 \r\n");               
    ! f0 _- D$ G# T( I( e! R" S0 @
  142.                                                 goto Initial_state;
    ! |# k( y0 w( Y5 D9 v: e8 |# F, v
  143.                                         }                                                / x$ H4 e* ]! x. W" ]' \; C
  144.                                 }
    8 Y( l2 s7 T4 j8 o* Y/ A. @8 M
  145.                         }3 b0 s" |  V" A& j+ {& d/ g
  146.                 }                # q& E: M# s) g
  147. /*********************************************反转模式********************************************************/               
    # a' n  S- [5 @: L$ v
  148.                 else{
    ! u! H0 z- D( _. ~3 F
  149.                         if(type==1)7 k! {2 B$ `0 \1 M. [. H; q
  150.                         {
    0 L# y- S2 O5 G1 ?
  151.                                 GPIO_ResetBits(GPIOA, GPIO_Pin_12);//电机反转3 A) c0 R2 F! i) \% p
  152.                                 printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");
    7 t" q8 O8 U, g8 c# {
  153.                                 * w0 c: i! ^- {2 @* A3 Y
  154. /*********************************************此模块用于配置速度参数********************************************************/1 G3 @7 R+ \9 [& ~- E) V
  155.                                 part2:                                Waiting_reception();
    * P3 E, ]2 \6 m8 Z# a
  156.                                 speed =type;//将接收到的数据给speed9 a3 C0 N. i+ m) ~0 H
  157.                                 if(speed==0)goto Initial_state;//如果是0则返回初始模式
    , U0 s/ [7 }8 d( A$ l
  158.                                         else{
    + v9 Y# {# ^7 {( Y6 _  t6 Q3 v
  159.                                                 if(speed>=15)
    4 r! w0 T6 ?  F3 Y
  160.                                                 {7 u- n4 e, ]; }1 l- m, I
  161.                                                         printf("\r\n旋转速度>15rad/s,请重新选择旋转速度。\r\n");: C- Q/ ]0 r6 S" J
  162.                                                         goto part2;
    , F9 Z+ }9 e. p5 ~: }; x. ?0 D
  163.                                                 }else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式  \r\n",speed);( A8 `- V: P: D8 J
  164.                                         }       
    % o6 B& \! J3 `3 y" V5 }
  165. /*********************************************此模块用于配置角度参数********************************************************/               
    + d* t- X" ]' A
  166.                                 Waiting_reception();# g! r  K& \3 s, H. y. S
  167.                                 angle =type;//将接收到的数据给type
    ' E$ Q% n9 y/ Z( R- D
  168.                                 for(;;)( `' v$ f$ D8 T4 Q
  169.                                 {7 n' L( q. M* J8 M; f, Y
  170.                                         if(angle>0)//接收到的数据不是0
    ' h$ l% x; [7 b# c8 x  q
  171.                                         {
    - V5 j+ g) d. g2 u; X- N
  172.                                                 TIM2_Master__TIM3_Slave_Configuration(speed,angle);        // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度
    : B3 }% T# a/ @
  173.                                                 delay_ms(20000);//电机保护6 a8 \2 t2 @0 N& R& y
  174.                                                 printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式;\r\n",angle);
    " F0 S3 K+ r, `! Z' Q3 x! a
  175.                                                 angle=0;( c1 A% _+ |0 f0 p
  176.                                                 Waiting_reception();               
    & N1 }' b& R$ ?' A% H7 ~. C
  177.                                                 angle =type;                                       
    ' F" L' Y2 a& H9 b5 I: @4 m
  178.                                         }else{
    4 X1 k  v# }5 m2 R: x* O
  179.                                                 if(angle==0)goto Initial_state;//返回初始状态       
    # T6 h6 J( r6 f* C2 |: X
  180.                                                 else {
    0 P- V7 B, l" }( f3 x! Q7 A" c+ R
  181.                                                         printf("\r\n 角度错误,已返回初始模式 \r\n");                / F  {5 z8 }% ^
  182.                                                         goto Initial_state;
    6 }: o$ k/ D0 @9 E3 r6 {! a
  183.                                                 }                                                               
    " J& |5 T; {9 M) X* b2 q7 j5 @$ o& L
  184.                                         }
    9 M4 G8 a1 d  D6 P) n
  185.                                 }: n. u4 z6 e% d: f/ e" A% Z8 a
  186. /****************************************************************************************************************************/                                        $ q# ^8 W2 S  c0 M
  187.                 }else{//if(a!=0)&(a!=1)9 S6 C' ^' C- F7 s& A
  188.                         type=NULL;
    $ s* J# ~( U6 L+ t+ N
  189.                         printf("\r\n 输入无效 \r\n");7 ~% B; A8 c+ X0 [( k
  190.                         goto Initial_state;//返回初始状态5 }  I8 W$ P' {! @9 Q
  191.                         }0 i+ n. u, h/ e9 y- j
  192.                 }
    : _$ L0 d) `1 `. ]' |
  193.         }
    ) \" V) m. m0 r* D, m9 ]
  194. }  m# h! Z. l7 C2 r( n
复制代码
2.main.h程序
* [2 j1 L. I/ q
  1. #ifndef _MAIN_H+ W7 A6 |/ B2 r% Q0 x" A
  2. #define        _MAIN_H
    & y( F! H4 w) e
  3. #include <stm32f10x.h>; s$ ~* S. r) _7 d- b4 ?% c8 g! \
  4. #include <usart1.h>
    8 _  r4 r! R9 _1 t! n; E" w: q
  5. #include <misc.h>
    ( k' N8 s9 e/ w/ ?% K) @9 G
  6. #include <nvic.h>! M/ R% _5 B+ j# u* g6 G; Y2 b+ I- ?
  7. #include <stdio.h>
    2 v# ]4 [4 \5 x6 Y2 Z2 G
  8. #include "stm32f10x_tim.h"/ \  C9 m* p5 N0 W9 i5 b) k
  9. #include "timer.h"
    2 c8 D) L2 f! o- v# w
  10. #endif
    ; l/ ]4 O3 p( u: Y
复制代码
3.time.c程序, t8 S  T+ k: u( r, O2 [
  1. #include "timer.h"
    & z$ Q2 B6 o8 J0 V% x6 ~
  2. /**************************  V, p0 ^3 d/ k
  3. * 函数名:GPIO_Config7 [5 B' H6 J) P6 ]
  4. * 描述  :无
    ( C6 N& A5 @% l5 Z1 X
  5. * 输入  :无 2 P( E6 _, M( P  ^; h
  6. * 输出  :无4 t& B) y: i* Q6 F
  7. * 调用  :主函数
    ! m1 T4 H+ f+ o0 C) o2 x7 @
  8. * 返回值:无8 ~$ O( ^3 m3 ^& n4 n5 s
  9. ****************************/* z7 D5 E2 v" a0 Q6 t9 B
  10. void GPIO_Config(void)
    8 f6 p4 C  F: a: D8 a7 N
  11. {
    / S! Z- [, J- E( W. ^' D/ h
  12.                 GPIO_InitTypeDef GPIO_InitStructure; : u0 y) e2 G$ [4 E% N) N
  13.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能IOA4 a& }8 f+ Y  `
  14.                 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE); //使能TIM2,TIM3
    + x- V' O0 R# k% A0 I
  15.                 0 X1 k- V& D, b8 q& V
  16.             /* Timer2 Channel 1, PA0 */ 9 i$ f' F) a" @% ~
  17.             GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0;
    # e) s2 [; x) R. G8 I; V$ Y
  18.             GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用输出8 q6 l9 ~) g4 {- K- j6 b6 @2 ?% H
  19.             GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; , C, y3 i1 f- v& f3 }2 Z
  20.             GPIO_Init(GPIOA, &GPIO_InitStructure);
    : v, J. I2 A6 v+ }6 |+ ^
  21.                  - ^; i/ h9 D: x% o
  22.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_11|GPIO_Pin_12;3 ?$ `/ a8 e  y. ]. z- W
  23.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式0 ^: D+ H9 o& `) ?) @7 A0 i( f
  24.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ
    9 w. \) x* J" V# O" L. B
  25.                 GPIO_Init(GPIOA, &GPIO_InitStructure);                   //2 ?3 _. p0 C+ z8 H7 k
  26.                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向$ G" p* n( U- J, U/ {$ Z
  27.                 GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能
    4 R% G& W9 V2 u
  28.                 GPIO_SetBits(GPIOA, GPIO_Pin_11);//指定引脚输出低电平,此时灯全灭,方向! W. |! W3 f3 \& }. [& f% j
  29.                 GPIO_SetBits(GPIOA, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能6 B" }8 t" T3 d0 P6 M! x
  30.         # B9 H2 U: q2 z/ I$ }/ J! R8 `
  31.          ( N2 M0 [2 ]; y. g& |9 `
  32.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    2 c2 M1 M  Z6 I; t! q
  33.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;         //通用推挽输出模式( \* {- ?& h: O& A. `% w6 c5 O8 l
  34.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ
    * k- ]7 K9 ?2 O: Z( ^, W
  35.                 GPIO_Init(GPIOA, &GPIO_InitStructure);                   //
    " x$ W0 q4 P! n' _+ ~5 {
  36.                 5 s5 ^. e, P7 D  [7 B+ T
  37.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); . U9 Q' y2 q. y/ ]$ h
  38.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    ; {' V3 p5 t% P( X, R" {
  39.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式& k" n! f% g7 N
  40.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ4 X1 J: v5 r0 h3 Y
  41.                 GPIO_Init(GPIOB, &GPIO_InitStructure);                   //" f( N6 Y1 A% r7 S3 D
  42.                 GPIO_ResetBits(GPIOB, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能. n2 a) V! K2 u. M) A- G% R& }
  43.                 8 z1 U- |+ O6 Q! K1 C1 s  }  ]2 W
  44.                 //GPIO_ResetBits  GPIO_SetBits
    ) J4 S. j: K! U( L: Q+ @  n$ B4 W1 K; [
  45. }
    0 Z/ C- E& D5 W
  46. 3 e( Y9 l# }; k
  47. //================================================================================$ z0 b8 j) C1 Y
  48. /**************************
    5 V& E5 ^$ g9 U
  49. * 函数名:TIM2_Master__TIM3_Slave_Configuration
    $ j$ S8 V* F+ u# ]
  50. * 描述  :主从定时器配置' J7 L7 |: q) H6 d, Y5 l- [! s
  51. * 输入  :电机转速speed,转角angle # W) s; y2 I# X+ J( u3 \
  52. * 输出  :无2 E' z# `7 r% M8 u3 J: m0 \6 Z
  53. * 调用  :主函数8 x7 q9 z. \5 z- c' j. J, f
  54. * 返回值:无6 {1 Y  @9 W, ?
  55. ****************************/4 Z0 H3 K2 P/ r- t9 q
  56. void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency, u32 pulse) 8 I" e% A0 X! x* q6 r0 J. Q9 I3 B
  57. {
    0 M2 J3 Y3 U& I0 \
  58.         TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    % @: {9 x- V9 z' C+ F% p+ \
  59.         TIM_OCInitTypeDef TIM_OCInitStructure;
      N8 b/ u+ S% z5 A
  60.        
    3 m  }- J- B" }0 s' a0 d
  61.         u16 nPDTemp ;
    0 m: y- g0 o5 j/ p* B& [$ r, m* S& w
  62.         u16 pulse_number;
    0 P( X5 g4 S) {$ K
  63.         float p=PulseFrequency;: e/ L( _: ~. X4 M- p2 j$ s
  64.         TIM_Cmd(TIM2, DISABLE);
    & A* O6 ~; h( g7 l- X9 U% Q
  65.         nPDTemp = (11.25/p);                            //TIM2重装值是11.25时1s转一圈(电机32细分下)
    7 G& z, R. u* e8 X
  66.         pulse_number = (16.7778*pulse);//TIM3重装值是16.7778时转1°(电机32细分下)
    1 ]# }5 _4 J& L8 f+ D2 y; t
  67.        
    , V/ Q4 T, D  R# ]8 n, C* Y
  68.         // 时基配置:配置PWM输出定时器——TIM2
    ! N% V7 I. z9 X: s. H1 s
  69.         /* Time base configuration */ & C' l; j4 C4 ^9 K; y  ~* t
  70.         TIM_TimeBaseStructure.TIM_Period = nPDTemp; //定时周期为nPDTemp
    ) K. F! T5 Y4 f$ ^" [# c
  71.         TIM_TimeBaseStructure.TIM_Prescaler = 999; //预分频值1000,即f=72khz5 z$ L. u/ s4 l" _* n# I/ a) ]
  72.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分频因子,会影响滤波器采样频率,与本实验无影响
    7 [& F8 Q# w7 V" r" c' _0 J
  73.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
    ' \$ p' J  n6 Q! r
  74.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //指定重复计数器值
    % X! Z! ]( U! D3 o6 F# V# ~6 s
  75.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    - R) X+ N' ~7 F' A& a, H* t
  76.         ' |0 y2 Y) C0 Q( a
  77.         // 输出配置:配置PWM输出定时器——TIM2
    % P# v( `# o) R' D+ @
  78.         /* PWM1 Mode configuration: Channel1 */    6 F1 D; Y  q7 u- N4 y' v  M
  79.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM 脉冲宽度调制模式 19 n: R% v- l% I. F
  80.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平有效" i# t# L1 }$ M* Q- L" \
  81.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出
    + V" [8 g9 W6 F) L; O& O2 I
  82.         TIM_OCInitStructure.TIM_Pulse = nPDTemp>>1;//50% //比较tim_ccr的值,输出脉冲发生跳变
    ; K' ]! W" Q2 L+ P6 B$ J) A
  83.         TIM_OC1Init(TIM2, &TIM_OCInitStructure); //初始化3 r" l7 C8 e" C0 h
  84.         TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能 TIMx 在 CCR1 上的预装载寄存器
    : B( C8 @' L8 z; J: o7 q5 \
  85.         TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能 TIMx 在 ARR 上的预装载寄存器
    - \9 G, e" _2 b; M$ q) c2 n$ w& z
  86.        
    9 I$ U7 K6 f+ }2 T7 @) t, K  w
  87.         // 时基配置:配置脉冲计数寄存器——TIM3
    ; h! b' @5 P, c' Y6 u
  88.         TIM_TimeBaseStructure.TIM_Period = pulse_number;      //0x1900是360°;//改变给电机的脉冲个数                     
    0 X) O5 p0 J7 l+ _. J
  89.         TIM_TimeBaseStructure.TIM_Prescaler = 0; + f8 s* t5 u3 [
  90.         TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    & V: n  ]7 W5 s8 N
  91.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 1 I* e( M; k& a: E4 [, j
  92.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    % Y+ F; H) ~: e
  93.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    * {( o* [: i3 A
  94.         // 输出配置:配置输出比较非主动模式定时器——TIM3" o# v  p- ^) n2 F- L$ R3 X6 A
  95.         // Output Compare Active Mode configuration: Channel1 & Z1 S, Q: E9 D% [6 c3 E0 F
  96.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; //输出比较非主动模式,(匹配时设置输出引脚为无效        电平,当计数值为比较/捕获寄存器值相同时,强制输出为低电平)      
    ' e0 N5 g2 i) l3 P# P9 r" y( S) l
  97.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; . H8 f. K1 Q3 r$ ]( ^$ d
  98.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 3 i* o% P* W! G1 j7 r
  99.         TIM_OCInitStructure.TIM_Pulse = 0xFFFF; // 这里的配置值意义不大   
    2 H2 J% e6 e" z* h; o! R
  100.         TIM_OC1Init(TIM3, &TIM_OCInitStructure); 9 J- D5 r% N5 u" r( D8 `  y
  101. 3 F$ U6 w6 y! Y: K. h
  102.         // 配置TIM2为主定时器
    6 A* S# K& {, h- U
  103.         // Select the Master Slave Mode
    ' @" |( B" \9 E+ y9 c$ l, f. g& w
  104.         TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //设置 TIM2 主/从模式并使能
    * N( B2 P% p" W9 W- q
  105.         // Master Mode selection  
    , p% m& G6 W/ Y5 N
  106.         TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); //使用更新事件作为触发输出7 Q/ I: T2 O8 J" _- C4 b
  107.        
    2 j; x+ y3 J! b# L
  108.         // 配置TIM3为从定时器
    - p: F$ F' Q, H  O$ g5 @
  109.         // Slave Mode selection: TIM3 7 G# N8 s! J4 d  d4 ]
  110.         TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated); //选择 TIM3为从模式   TIM_SlaveMode_Gated-当触发信号(TRGI)为高电平时计数器时钟使能2 O& k. B8 }8 t! B" r' z
  111.         TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); //选择 TIM3 输入触发源    TIM_TS_ITR1-TIM 内部触发 1
      d5 [# V. J0 Y) Z0 y
  112.         TIM_ITRxExternalClockConfig(TIM3, TIM_TS_ITR1);//设置 TIM3 内部触发为外部时钟模式   TIM_TS_ITR1-TIM 内部触发 18 o# F2 Z- w* ^) }: n# w
  113.         TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); //使能TIM3     TIM 捕获/比较 1 中断源          & r/ S9 D0 q  K* m; z# u* W' G3 a
  114.        
    & j9 g: Y& e! {9 d: t' H
  115.         TIM_Cmd(TIM2, ENABLE); 7 G; ~7 d( [3 X/ D* X0 E
  116.         TIM_Cmd(TIM3, ENABLE);
      r- g4 Q( I- h1 _$ O1 x* Z- ^
  117. }
    * o/ g. X) V1 p5 X
  118. * d) D' x5 B/ I( [
  119. /****************************************************
    , x6 h! X4 w: M* R" j
  120. * 函数名:Output_Pulse
    1 J3 U1 a2 U* ?, s$ j
  121. * 描述  :无- q3 B, J% u& s
  122. * 输入  :无 $ Z# r5 R8 z" `- j7 s
  123. * 输出  :无
    . e9 O/ A, |& i  H! p
  124. * 返回值:无* F, G5 J! ]5 b( v. |. S4 r
  125. ******************************************************/' Z5 N: J2 W, E$ |9 x, Z
  126. void Output_Pulse(u16 Num)( K% p$ T- W2 b" Z
  127. {6 u4 ]% z5 D; }* |
  128.                 GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能
    # [  e& N4 @, v8 S" G; n
  129.                 TIM3->CCR1 = Num; 8 @/ Q/ h7 S5 U0 ?
  130.                 TIM3->CNT = 0;
    5 i2 v3 g  y# u6 T6 r9 X) i
  131.                 TIM_Cmd(TIM3, ENABLE);
    ( [; k+ |2 m% a
  132.                 TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); 9 T0 l7 _; r( e# A9 ]5 T$ v. H/ n
  133.                 TIM_Cmd(TIM2, ENABLE); ' v7 Q: V2 H  c# n7 f1 k7 a4 p5 L  z
  134. }
      F1 C1 m9 A/ s/ X& w
  135. 2 ]) `1 h: Q8 p! Z$ R
  136. /****************************************************
    . R, {) a8 V& P) F3 Z
  137. * 函数名:angle_set7 w# ?$ X) U* `! C' ^$ G0 }
  138. * 描述  :无
    ; z- A9 o  f! M8 g8 N$ h
  139. * 输入  :无
    * |5 i7 r% ?/ x* t/ K5 Q
  140. * 输出  :无" ?  T0 L- X' C( e- q! O6 l( j
  141. * 返回值:无
    7 I3 E- P# Y- @8 k8 Z  K
  142. ******************************************************/
    0 m6 j' u1 ]  l
  143. void angle_set(u8 dir,u8 angle)
    $ I# z% N+ c8 R! Q) L
  144. {
    ) M, I/ F2 [/ |5 y4 m2 i% j
  145.         if(dir==0)
    # K5 K7 o) X; @5 p
  146.                                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
    . z  H3 r, L; m7 C3 {" m5 j
  147.         else
    ; k1 V1 _1 K; |3 L
  148.                                 GPIO_SetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向1 |+ g! F1 j- R/ A# N4 g7 v* p
  149.         / E, X# _( K* f% K; n$ _1 {2 j
  150.         Output_Pulse(angle*6400);
    / @) d8 O3 P6 v7 ]. T( u* U
  151. }* n+ B4 a+ _& ]( B0 S- z
复制代码
4.time.h程序& U2 y! y, M7 H
  1. #ifndef __TIMER_H: _6 C5 j4 L2 K" Q
  2. #define        __TIMER_H
    - n0 I0 o! h: `
  3. #include "main.h": H. [( `9 d3 S
  4. extern unsigned char Flag;
    0 B/ x! U# y6 ]9 s/ ]
  5. extern unsigned char TIM2_Pulse_TIM3_Counter_OK;# o& P- S8 c3 K7 P" P' c( L
  6. void GPIO_Config(void);$ d" C4 g' w  U: h2 S5 W( P+ @
  7. void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency,u32 pulse);4 F' K- _: P% R$ s# ?6 G" V/ L
  8. void Frequence_Setting(u32 PulseFrequency);
    7 C+ I# B6 g) r1 [
  9. void Output_Pulse(u16 Num);
      d$ s" [3 R* F$ P, I( H
  10. void angle_set(u8 dir,u8 angle);# ?2 }# P! \! R; R" ~
  11. #endif
    2 d1 K1 h& g# l# D  a
复制代码
5.usart1.c程序
4 `) E: o  a: H$ G
  1. #include <main.h>
    3 A, l* t# E  ~4 N: s9 v! H0 y
  2. #include <usart1.h>* i5 p2 i& }% P& W; y
  3. #include <string.h>
    * Z' ^+ E" f. [3 W6 j) v
  4. #include <math.h>
    1 Y+ C; [$ [- I  T; U: m6 L
  5. 3 E, k: Y) ?+ {  ?
  6. /******************************************************
    . R0 Q4 ?  o8 U" u# U
  7. * 函数名:USART1_Config8 E, d! k& U' L( j
  8. * 描述  :USART1 GPIO 配置,工作模式配置  t7 x& F9 y5 _3 }9 a
  9. * 输入  :无* j9 f. Y- z+ O8 o& H; }# f1 m
  10. * 输出  : 无9 J1 J0 w& N9 g: ~8 u  S
  11. * 调用  :外部调用
    ; ]8 P; G( t4 z9 h
  12. ***************************************************** */+ [, A! b+ _/ h& V5 Z* l
  13. void USART1_Config(void)* Z6 ~+ l0 H9 @
  14. {
    # v( d$ M. [# b. P7 i+ O7 c
  15.         GPIO_InitTypeDef GPIO_InitStructure;8 z+ |" P! K+ o) }/ r; m2 d
  16.         USART_InitTypeDef USART_InitStructure;
    4 j0 B: Z# T* Z7 p/ r
  17.        
    + q7 l$ Z( C! V% n6 u
  18.         /* config USART1 clock */
    / ?. K1 q5 S6 C2 r
  19.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    , }) R( a, M, E% z# Q& m* u" |
  20.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);4 K2 f- F- s5 a2 X

  21. & y; g7 N! }/ q  u
  22.         /* USART1 GPIO config */
    7 A7 N0 ~  f. a/ x5 Q) h$ A
  23.         /* Configure USART1 Tx (PA.09) as alternate function push-pull */
    : Q- q; n& X. h1 m; H7 K, U
  24.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    0 Q: N, d: Y& f. h4 f( q/ t6 R
  25.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;; n7 M& P0 N5 T& [, J
  26.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;6 e0 s" E2 P4 T9 F
  27.         GPIO_Init(GPIOA, &GPIO_InitStructure);    " G; s3 b8 L* o' O5 j3 R0 a9 s
  28.         /* Configure USART1 Rx (PA.10) as input floating */. v# G0 {& i; B6 T4 B" R4 O
  29.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;4 ?2 c; T4 {! x4 P) M, O
  30.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    % R! j0 ?$ W7 E7 ~
  31.         GPIO_Init(GPIOA, &GPIO_InitStructure);3 S; O, g3 l/ x1 A" O# c  \
  32.        
    4 J; K, J: X# G$ c+ \0 w7 `
  33.         /* USART1 mode config */# h2 o- s0 T, ~( R6 f; g
  34.         USART_InitStructure.USART_BaudRate = 115200;2 m6 h, N9 }8 G) z
  35.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;' I. _2 G4 D/ y$ H, M9 g  l% B5 F- d* u
  36.         USART_InitStructure.USART_StopBits = USART_StopBits_1;  ?* E* n! f: A/ a) G
  37.         USART_InitStructure.USART_Parity = USART_Parity_No ;
    2 [7 A& p4 A# _$ s' u
  38.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;) d. G5 V- T' e# H
  39.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    ! v. U' j3 H" V
  40.         USART_Init(USART1, &USART_InitStructure);
    : y0 _. b% K7 {' }2 M. e% m: P
  41.         USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
      Q  m2 D, w' o8 I4 Z( J; U# q/ m, J
  42.         : b/ f+ u& G( \
  43.         USART_Cmd(USART1, ENABLE);* k# D  Q( t$ \) M1 ^
  44. }% x4 {. X2 L5 U
  45. $ O9 ~& o, f7 d7 i
  46. /******************************************************* ~% g+ Y( }, @& o8 D
  47. * 函数名:fputc
      {# h" s4 `2 ]+ B
  48. * 描述  :重定向c库函数printf到USART1
    2 i) _" {7 [; x7 r
  49. * 输入  :无5 o  X6 X. [5 r  c4 n6 C* N* W4 w
  50. * 输出  :无8 C+ T7 U& y( p4 z: H. q
  51. * 调用  :由printf调用* D6 d7 Y6 E4 e8 D7 |4 `8 }& J
  52. ***************************************************** */
    % d9 T" V( L  E5 D6 _
  53. int fputc(int ch, FILE *f)
    5 u# n6 d/ n; T
  54. {' G! f- k' k0 L; \+ E. h% E, L
  55.         /* 将Printf内容发往串口 */3 _% b! m: N8 M0 l: X, H
  56.         USART_SendData(USART1, (unsigned char) ch);& L! B9 h5 G( n8 {! j2 x
  57.         while (!(USART1->SR & USART_FLAG_TXE));  `5 Z1 L  v  }! d4 s
  58.        
    5 g/ y- e2 ~8 {4 [5 p, ]
  59.         return (ch);2 H( D: [% E% D1 }' h" C1 }
  60. }
    0 K  h9 Y% {8 w" w, e

  61. * S9 K" C9 }+ p5 A3 o
  62. /*-------------------------------------------------------------------------------*/3 A& y( I6 E- Z# ]8 c
  63. /******************************************************
    . G$ E! v# G$ ?) A# a1 A: P* Y, p4 D
  64. * 函数名:USART1_IRQHandler
      L; E) H# u! I( p) D3 i
  65. * 描述  :USART1中断服务函数
    ) p5 E! _+ Z: `% H* u8 s; D$ ~
  66. * 输入  :无
    ' ^, Q, U' J  h& A- ?, a
  67. * 输出  :无
    9 [! ~4 F* N: n+ _
  68. * 调用  :中断调用
    & ]0 S8 j) u! N; o- j
  69. ***************************************************** */
    % V! Q+ b1 q$ U
  70. u8 Res;
    + I5 y+ c% V9 t) h, I
  71. extern int a;. l. W' J* n( T1 }7 N4 s1 R- @
  72. u16 USART_RX_STA=0;       //接收状态标记         
    " [7 N, }( v* w( \! i% ^5 K
  73. u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
    ( _1 J% \" Q- i+ Y
  74. void USART1_IRQHandler(void)                        //串口1中断服务程序' p+ q) u7 @( D5 T9 C7 m, x% v
  75.         {# [+ ~. W9 S# i1 V
  76.                
    ) ?, }, Q% q" \! R
  77.                 Res =USART_ReceiveData(USART1);        //读取接收到的数据
    7 h, T: r* t: g! B8 y
  78.                
    - c9 F+ f8 k+ n4 D# k; D4 P- `
  79.                 if((USART_RX_STA&0x8000)==0)//接收未完成8 ?; K4 R6 o  P) s$ U9 [; V
  80.                         {3 ?1 [% y# ~* u# N
  81.                         if(USART_RX_STA&0x4000)//接收到了0x0d/ q7 {. v* I, n0 L6 V
  82.                                 {
      t( N5 n6 E: k" I
  83.                                 if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始  W5 m& Y2 [$ `$ e8 e5 z0 v4 l& J
  84.                                 else USART_RX_STA|=0x8000;        //接收完成了 2 |, x, Q0 V. ]+ |
  85.                                 }1 Y6 w' ^* ~; }. C4 Z* K9 h9 W+ n8 {
  86.                         else //还没收到0X0D
    2 Y' [5 i: z6 C. k" q
  87.                                 {        ! B. e" v& Q6 V8 {( |
  88.                                 if(Res==0x0d)USART_RX_STA|=0x4000;) P, ?% H. E( y& y
  89.                                 else$ ?" [( D8 \% Z9 }
  90.                                         {
    / c: T( T# E8 l4 \. o
  91.                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
    : y& R  u  G* G& b
  92.                                         USART_RX_STA++;! b" F/ ~4 ^$ G# k, C
  93.                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收          
    ! S/ z0 o9 Z' i( k
  94.                                         }                 
    4 V" j- C) d4 J/ m1 O  m9 |! n
  95.                                 }9 W2 H$ a) R. E& C. E6 H
  96.                         }                $ X4 k8 W: |) U0 X& C6 a3 c
  97.                                 a=1;         
    " u& x. Z2 x0 I  \, t
  98.         } ' Z: R2 `6 d  S$ ^0 s+ O
  99. #if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.( s* [  U/ g: Q, g% f8 ~! Z9 b
  100.         OSIntExit();                                                                                           - m3 W1 F& C8 L3 i# A1 F9 a1 Q
  101. #endif3 s2 ~" ]+ c1 {8 B
  102. 4 _0 |4 b6 j* }, B: d% E2 y9 l
  103. /******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/
    ) v& {) m) S* ^8 t
复制代码
6.usart1.h程序; x: Z8 y2 ^# {* J
  1. #ifndef __USART1_H
    + V4 B+ Y! c0 U
  2. #define        __USART1_H# l+ |0 `) y" _# {
  3. #include <main.h>
    - i/ n8 M/ Q8 O4 G: m+ a5 [
  4. #include <stdio.h>
    * D1 b% Z7 l5 `: [
  5. 5 Q% h% O# C7 l' ]2 Q- h
  6. #define USART_REC_LEN                          200          //定义最大接收字节数 200
    4 F% a. z! B; V3 j
  7. #define EN_USART1_RX                         1                //使能(1)/禁止(0)串口1接收
    6 o+ N( Q6 [6 R  O
  8. extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 % s  @" R  s) Y. _
  9. extern u16 USART_RX_STA;                         //接收状态标记8 F% i1 e  I  _! @+ O+ J5 k
  10. int simple_atoi(char *source);
    . n' w6 y8 y) W' X4 }. H
  11. void USART1_Config(void);
    3 w/ u% g! q: U; Q$ j  t' S2 B
  12. #endif /* __USART1_H */
    - {8 D) `) b. r6 d' H: V6 x# p7 M; R
复制代码
源码:
$ T2 l+ r9 z1 v1 t/ I, i. L0 V 步进电机程序—串口控制速度角度.zip (4.75 MB, 下载次数: 132)
赞 收藏 1 评论0 发布时间:2021-6-25 13:30

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版