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

利用STM32F103精确控制步进电机

[复制链接]
STMCU-管管 发布时间:2021-6-25 13:30
利用STM32F103精确控制步进电机
一、用到的元器件8 z* M* g# ~# @# T9 u
STM32F103C8T6
6 T/ C1 D/ M3 f" t42步进电机(42SHDC4040-17B)$ @) v) i7 q# h
TB6600电机驱动器升级版# L' Z" z, R) P: S6 B
' l4 X$ ]: C# P( Y- B  y" G" m
" K0 ~0 {3 i+ O8 R0 \
二、42步进电机
( _# w5 A/ E5 e6 z- X/ s3 q1.步进电机的基本知识5 d! u  g0 ?+ x6 {7 q% S
(1)拍数——每一次循环所包含的通电状态数(电机转过一个齿距角所需脉冲数)2 N3 i3 L; u; ?* i: ~
(2)单拍制分配方式——状态数=相数
, l* G0 L+ w5 Q6 b(3)双拍制分配方式——状态数=相数的两倍' b- }6 N, m1 P! w/ J
(4)步距角 ——步进机通过一个电脉冲转子转过的角度! \# z7 E/ y: t
11.png
N:一个周期的运行拍数. z- o$ [! d- ^! E
Zr:转子齿数
* y$ a5 N4 w4 z0 L1 P6 O拍数:N=km
9 I$ a: |7 o/ }/ m) X" V  ^m:相数
8 Y+ S7 V* g0 i9 B7 v, i8 xk=1单拍制
! f+ w7 {- I: X9 {/ h" O+ x$ E; hk=2双拍制
+ A  A& I1 T( M(5)转速
# Q, l4 y( m3 ?8 e
12.png
(6)角度细分的原理- w( x% t: t% q! D& }& D

4 d: a: Z: B, g5 c. D( P

( U# s$ U' p1 w9 G/ S& o* x电磁力的大小与绕组通电电流的大小有关。3 y* T' e6 o+ u% A6 t  o
当通电相的电流并不马上升到位,而断电相的电流也非立即降为0时,它们所产生的磁场合力,会使转子有一个新的平衡位置,这个新的平衡位置是在原来的步距角范围内。
6 J* x6 U! [' m; O7 ?, F2. 42步进电机参数
3 I; B. A: d' w. X9 B  [/ O无法查找到42SHDC4040-17B型号的详细资料,以通用42步进电机为例:
$ l5 [, Y+ l' ?" @步距角 1.8°
( l$ R, i* U* h" U步距角精度 ±5%
* o( y  @! j, i4 o相数 2相
& r2 G1 G- ~, k" i励磁方式 混合式2 t$ i( F7 W, L4 }& d2 P/ W" e
转子齿数 50. p6 G  A8 x: {
拍制 双拍制% z6 D4 J/ f3 F5 O
其他参数:无
% e, W" s6 k  |( n/ }2 \由步距角=1.8°推算出转子齿数为50,拍制为双拍制
6 e9 ^8 o) I9 _' j9 b" ?2 S* w( y2 C
3 w" t( h) s5 L
3. 42步进电机速度与角度控制9 G: q, w! v: O! F! F+ M# z
电机的转速与脉冲频率成正比,电机转过的角度与脉冲数成正比。所以控制脉冲数和脉冲频率就可以精确调速。
* o6 @  L7 @/ o6 S2 p! ~1 v3 N" D理论上步进电机转速 = 频率 * 60 /((360/T)*x)
% C, ~3 _5 e! K2 k: l5 g 21.png 6 q4 W& ]9 N6 M3 C3 ^
​        ; b, G1 [9 u: F5 d7 g6 |$ Y
转速单位: 转/ 分
4 p% @6 V6 h) y% |6 J1 B) X" M频率单位:赫兹0 U1 r0 E% C( \# N
x 细分倍数
5 X" Q3 ]5 {0 T2 `+ {$ mT 步距角9 K1 }$ u: I# a$ Q
例如,在本实验中,32细分;频率72000 赫兹;步距角1.8°;套用公式72000 ∗ 60 ( ( 360 / 1.8 ) ∗ 32 ) = 112.5 \frac{72000*60}{((360/1.8)*32)}=112.5 # h( D0 \2 @3 e6 C1 f1 o
((360/1.8)∗32)+ L4 F0 ]! C8 I6 M* L4 V* O2 F
72000∗60
& D1 W5 \7 j/ V; h! H2 S​        2 Q# }& W! }( [$ v
=112.5rad/ min,即1.875 rad/s.( b: `  L8 Q0 {/ f5 V' b
13.png
三、TB6600电机驱动器升级版参数) Y! P; S' G: R8 P( e* V: D
TB6600步进电机驱动器升级版是一款专业的两相步进电机驱动,可实现正反转控制。通过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 型两相、四相混合式步进电机。" t9 L0 V9 x7 F/ {* ?
* h! w- N: v2 R3 L! P

1 h  p+ B4 f) c2 V1.信号输入端0 E6 d' r0 C- l9 e% l0 c9 t
PUL+:脉冲信号输入正。( CP+ )
/ o$ P7 g/ p% [PUL-:脉冲信号输入负。( CP- )0 y( N' V% |/ V' \& |  A6 Q7 z% J' W8 I% u- N
DIR+:电机正、反转控制正。
% k! l: p  n  n1 k7 bDIR-:电机正、反转控制负。( M- p9 f; r4 ^9 r
EN+:电机脱机控制正。7 S, t' T# A' R7 d" k6 S& V4 R" i
EN-:电机脱机控制负。9 }4 V, {  I7 L0 t

7 @7 |( P( m( G8 H2 U

' Q, y  L5 ~, N" a" E共阳极接法:分别将PUL+,DIR+,EN+连接到控制系统的电源上, 如果此电源是+5V则可直接接入,如果此电源大于+5V,则须外部另加限流电阻R,保证给驱动器内部光藕提供8—15mA 的驱动电流。, l. \) `( Z* {+ O* I8 c! v$ b9 ]8 D7 y8 G
共阴极接法:分别将 PUL-,DIR-,EN-连接到控制系统的地端;脉冲输入信号通过PUL+接入,方向信号通过DIR+接入,使能信号通过EN+接入。若需限流电阻,限流电阻R的接法取值与共阳极接法相同。, o; _$ Z4 g! v2 k2 x5 S. t& d7 G
注:EN端可不接,EN有效时电机转子处于自由状态(脱机状态),这时可以手动转动电机转轴。
# b0 }+ i8 ^; I6 B2 q/ f2.电机绕组连接
, ~+ I) U4 q) D0 D/ m; VA+:连接电机绕组A+相。5 a) Q8 l% Y, ~: v! I5 p$ r
A-:连接电机绕组A-相。' {$ q  V; ]# o
B+:连接电机绕组B+相。
5 B# J! O! u0 @- |' ]B-:连接电机绕组B-相。
: S- r0 D: O& Q8 Z
  L1 u( s! l2 w- s8 Y
: b0 j0 A4 J- [
3.电源电压连接
# c, v* J; M0 L1 s; jVCC:电源正端“+”
) @# b% s( e0 a% JGND:电源负端“-”+ X% H+ ?" [: Q
注意:DC直流范围:9-32V。不可以超过此范围,否则会无法正常工作甚至损坏驱动器., @3 d1 k+ R/ Y, p" A0 N

& ^1 B; Q" R) l9 P

$ u! ^; Z7 c/ q4.拨码开关
/ h# _+ D" H8 x  G0 v- {! A  R 14.png ( B0 o) w. P2 P% u8 m! h
电流大小设定' q, ~; Q- w3 A9 h: ^
15.png ! Q# H7 J1 `8 q% z" }  q
三、STM32F103
0 C% V6 G5 e" J% G" H------说明:引脚部分在文章末尾有解释--------
% x" l9 p5 @+ ]9 x$ P
7 y* o& D5 z4 L6 X8 b6 u% ]

$ B! }7 V, \0 }- O5 X1.引脚连接
2 T  H2 L# q" P" U2 p9 V1 yA 0——PUL+: I- m: z% b3 A1 R% v- O$ e* `
A 3——KEY1——V3: Y8 u2 `" e9 E5 d
A12——DIR+  E1 G' H" O0 q
A11——EAN+0 B, Q, b2 e% W% p
GND——EAN- ——KEY0
: G* r7 L) {8 a4 j9 I7 m7 v) {9 {  d1 V& Y8 {
7 j1 q9 c3 [; T- T  m
2.引脚功能
+ v3 h: w: T) }7 Z# g: [1 H. |; cA0控制电机转速( l7 ~0 [' F; L" z' a/ H
A3控制按键
' g# t' P' t# D- r6 E$ yA9
$ t# @! z% M. O% HA11% }  Y9 k" Z$ I" Y
A11控制电机是否为锁死状态
( {3 b7 ~4 _" j5 O6 E% ]& uA12控制电机正反转
* t: P6 A0 h6 A$ k  B* B
: _) U6 N1 E9 S! y& H! I! y
. B4 i! |8 X$ q( D
3.定时器+ U! Q+ [% a; |0 E7 h. A& P
1.本实验利用定时器TIM2和定时器TIM3构造一个主从定时器,TIM2作为主定时器控制电机的转速,TIM3作为从定时器控制电机的转动角度。
( ^, j! |$ b- |' V% `; Y2.电机的转速和转角还与驱动器自身的细分数有关,但是驱动器细分数是通过影响电机的步距角来影响转速和转角,而TIM2和TIM3是控制步进电机的频率和脉冲数来控制转速转角! L( |3 f  B6 B8 k; B: _/ j
3.电机的转速和角度与定时器的关系(在不考虑电机自身的细分数下)& _# A) \9 X, ?* |) x- \5 m2 _. b, L3 W8 N

1 Y. X4 u+ I/ F) i: r) g% f

0 U0 \6 D& p6 R( l. [1 F9 A& o设TIM2的定时周期(即重装值)为nPDTemp2,预分频值为OCPolarity2; x+ j* F. X8 Z" A" _5 Y. z% Z. g* O% y
 TIM3的定时周期(即重装值)为nPDTemp3,预分频值为OCPolarity3,( Y3 t) ]# ]4 |& X6 ]
则单片机产生一个脉冲所需要的时间为:
; x( o. x1 h5 q$ r8 ~ 23.png ; [$ i1 l! {- q! a& m  I+ I! Y/ t
​        3 l/ S- H8 o' W7 q2 L  |
  本实验中设TIM2的定时周期nPDTemp2=72000/5000-1,预分频值OCPolarity2=999,TIM3的定时周期nPDTemp3=6399,预分频值OCPolarity3为0。即
& y* {6 x  O7 m% Q1 E6 D 22.png
* m& {, p& h! I8 s! P3 S9 q/ N  定时器共产生nPDTemp3+1=6400个脉冲,电机转过的角度为6400*1.8°=11520°,即电机转了32圈。4 p% ~' Q  q  T" j
  转动速度
8 X2 j9 T8 R+ U, v, d 24.png ' F. N& _2 p+ W$ |. H! S7 c! Q

, T" b4 b: w$ U4 t. P0 N& h, y

7 L. o8 d. ~) F- b4.在32细分的情况下电机1rad/s和转1°需要的重装值为nPDTemp2=11.25,nPDTemp3=17.7778。
8 D- P* s. s" W  u5 N  V* S; E+ @; G# a6 K
* B# i/ m! O- N: P2 P: l
四、程序实现* |* N1 L4 W, {
1.main.c程序3 \) M+ v' M3 }' C8 L3 R
  1. #include "main.h"
      \  N/ n; N- F6 y$ b$ t1 `9 x. z
  2. #include "sys.h"; M8 n( m& x8 B1 c5 d
  3. #include "usart1.h"
    5 M$ [: l  D7 c' Y
  4. #include "delay.h") l+ e3 Q0 a0 h8 k: c
  5. #include "math.h"/ P5 v, q0 u$ n% h

  6. - D. }' l- a5 T9 [! Z1 |; j
  7. u16 t;  1 `+ y9 H- d* y! ?7 Y. n4 m6 ^
  8. u16 len;                    //接收到的数据长度
    1 w6 E9 n& @' q, f, D, n, T% a
  9. u16 times=0;: V; U0 I- l4 e8 @5 Z! G$ \# U
  10. char receive_data[60];        //接收到的字符 - M( S; N7 E, T6 f
  11. char state;                                //电机正反转标志位0正转,1反转
    5 a' C+ F& P2 N9 z8 R+ M8 V
  12. int speed,angle;                //旋转速度,角度
    4 @+ m3 l% g5 i
  13. int a=0;                        //判断是否接收到数据  L. h6 n# w) ?( }* k0 c
  14. int r,data=0;                          //用于数据转换% P9 J2 ?# |) [, G' f8 h+ O8 G  w
  15. int type;                                //转换后的数据    % K1 V2 C8 _, {: Z% b& Y( s2 X+ X
  16. extern u16 USART_RX_STA;
      p  ?6 D) a8 f, \4 \; @
  17. 0 W/ Y0 q2 }: P3 x  P7 N: T
  18. /**************************$ g8 h* \. M. A7 n
  19. * 函数名:delay
    2 t! n$ g2 R. ?
  20. * 描述  :延时函数
    $ o8 f7 x' r) A) ?" Y
  21. * 输入  :无
    / {, _* T7 _! k& ?; ?/ c- h
  22. * 输出  :无
    ( b% l7 _* C* a% Z2 b3 Z0 T
  23. * 返回值:无7 A( t; Y& c3 v# n3 ?
  24. ****************************/* B0 J, v; u) ^' A; x9 k
  25. void delay()//延时3 q& _  o' b+ U
  26. {
    & P& I* W8 j$ u% b2 Z0 H
  27.          int i,j;
    ! b% C4 T& a6 A) \% d7 y
  28.          for(i=0;i<2000;i++)
    . u$ B' Y' ^# d0 p7 J$ z7 q
  29.          for(j=0;j<1000;j++);) b7 K7 v! T+ N/ R9 i, g' h9 [
  30. }- J5 f' N/ u' ^6 Z

  31. * ?. t9 n8 c' x0 X, \
  32. /**************************3 A+ f( Q6 @1 U% ?) E
  33. * 函数名:Waiting_receptio
    0 B1 I$ s2 @$ ]) `% j
  34. * 描述  :等待串口接收数据
    ; t  V% M4 {5 ^+ {8 u
  35. * 输入  :无 7 R# e+ @3 J# |+ o) S( k
  36. * 输出  :无
    ) M0 T, d% ?. R7 [) W
  37. * 返回值:无
    % K7 x* R2 X: |
  38. ****************************/
      |7 Y  r2 V& I5 V" k+ _% A
  39. void Waiting_reception(void)& `0 b+ G) _8 \+ d# I* g5 I1 ^, T
  40. {# c6 C9 y: R( z
  41.         while(a==0)//等待数据发送完成) C1 K( X4 n* ?) ]9 A
  42.         {
    : t6 ^8 r+ l% G
  43.                 delay_ms(100);
    $ x! Z6 v2 ?- I4 A' ?+ [
  44.                 if(a==1)//接收到数据( m& k$ Z1 R+ h5 {, ?; A# A
  45.                 {* e( z" L0 K& h- t0 R( `
  46.                         if(USART_RX_STA&0x8000)//(串口接收用到了正点原子的例程)) b7 d; ^0 }2 _1 p7 y
  47.                         {2 y9 [7 S5 s$ T5 k* x. V
  48.                                 len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
    2 j* l3 [6 {5 R" `2 v5 W7 I" ^
  49.                                 r=len;                               
    3 k. z# \2 w: b' O% f
  50.                                 type=0;2 G8 M. [3 m  F% _2 z
  51.                                 for(t=0;t<len;t++)//拷贝数据,将字符转换为十进制数
    + I2 `0 L7 z- d/ h6 r! v; k
  52.                                 {
    ( r1 z1 ?+ E! G+ E
  53.                                         receive_data[t]=USART_RX_BUF[t];' U; u0 q7 y" V
  54.                                         data=(int)receive_data[t]-48;- e; q* ?2 W" @
  55.                                         r=r-1;
    - _* C4 b/ y) [+ `+ }/ m
  56.                                         type=type+data*(pow(10,r));
    , U8 e3 b3 {% r# n& Z( U- K
  57.                                 }
    # F5 o9 \1 R: X9 W+ F, h& r
  58.                                 USART_RX_STA=0;
    ; R# @7 h' @2 \/ A- b
  59.                                 a=0;- q' i$ t* a/ L( |. @0 O4 p' Q
  60.                                 delay_ms(500);
    $ |; q' Z% l3 @9 h* @5 m
  61.                                 break;
    ' R% p8 H: H; V) q  v& F
  62.                         }: h" m6 X$ l2 N
  63.                 }
    ( B9 O. R1 f7 T( Y' F% K* w
  64.         }
    " k4 F  S& k; b
  65. }
    6 @9 W7 h0 }4 }' v2 L
  66. /**************************
    . W/ r; k0 W% @9 V. r. o2 ~
  67. * 函数名:KeyStates! M8 Y- U* M% Z5 g
  68. * 描述  :监测按键状态5 ^/ e0 R8 j+ _8 @5 v
  69. * 输入  :无
    3 G6 W0 I+ o0 A+ A
  70. * 输出  :无3 Q7 V; F) h4 r6 a) ?5 Y  R
  71. * 返回值:0/14 |! \4 p, x  h9 t. S: y/ S1 h
  72. ****************************/$ S/ V- d5 g0 x4 |8 U+ _
  73. u8 KeyStates()//按键状态
    % q" Z* S5 f8 |6 n5 ?; m- f3 n. ~
  74. {
    % M4 h# i- T" r# t; R# ?+ p. r
  75.         static u8 i = 0;7 g- }6 {, ]+ }+ B$ X
  76.         if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)
    . g  j: y# K2 M/ o
  77.         {
    3 a% q8 V$ x6 O# r
  78.                 delay();
    " t& \, ~7 A1 E8 k  h$ n
  79.                 if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)
    $ p, _3 }4 _$ f5 s: r; j4 K
  80.                         while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0);
    + v( n! L+ I& D6 l& U/ l) \
  81.                         i = ~i;) r! Q+ X& z3 d5 D( \1 B; Y# [7 ]( `
  82.         }1 a7 r% k# f$ i1 \' ?$ l
  83.         return i;) i) A& g' l- M
  84. }, e' E, |0 c' ]* Q! s' e: A( Z2 L
  85. /****************: b; e# W, l, ]7 K* o* |
  86. * 函数名:main
    3 N/ J4 V% O1 T9 H- o* b& b7 g; ~6 {
  87. * 描述  :主函数& x* p. v! T* }1 k
  88. * 输入  :无
    % z9 c) Z7 p) l, V8 k, U% Z
  89. * 输出  :无; `9 F$ M' o" b; Z% @3 i
  90. ******************/2 J$ _9 I. L5 ^
  91. int main(void)+ v$ J3 C& [+ w- d% @
  92. {
    8 n" s- l+ n/ W: c1 E
  93.         NVIC_Configuration();                        //中断初始化
    % Z0 P8 P0 d, P" q6 g. X& m  O+ ]- c
  94.         GPIO_Config();                                        //IO口初始化, J6 L1 Z7 w9 C2 \' [- ^
  95.         USART1_Config();                                //串口初始化; @9 L6 X* x4 T3 ^) K, p( x
  96.     delay_init();                                   //延时函数初始化       
    ' q  l' b8 h. S5 d2 q
  97.         GPIO_ResetBits(GPIOA, GPIO_Pin_11);//A11置零  A11——EAN+& r1 a4 Z# M! G, ~  y
  98.         GPIO_ResetBits(GPIOA, GPIO_Pin_12);//A12置零  A12——DIR+
    7 n1 H) f2 L& k  M& P, Y- j
  99.         while(1)
    ) k1 L! q  N' i& E
  100.         {
      W, K) L1 u- }" w: L1 g
  101.                 delay_ms(100);
    # U  |. K! d0 R
  102.                 Initial_state:                printf("\r\n 请选择正反转,正转输入0,反转输入1 (以新行作为结束标志)\r\n");        6 }  W+ ^# k% q
  103.                 Waiting_reception();/ B; ?2 K7 `* o
  104.                 state=type;//将接收到的数据给type/ ]# x; p' R* D7 [5 M
  105.                 if(type==0)//电机正转+ w$ @3 I0 |- K: a
  106.                 {1 z4 M5 `1 Z$ W- z
  107.                         GPIO_SetBits(GPIOA, GPIO_Pin_12);//电机正转+ J4 ]! ?4 A. T1 i( B
  108.                         printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");
    . L  `7 b7 H4 N& B+ Y
  109.                         , ^  s  R& [3 t3 g5 R
  110. /*********************************************此模块用于配置速度参数********************************************************/; e8 y! @2 Q9 c

  111. 1 f  l, {2 O- P3 a" L6 u
  112.                         part1:Waiting_reception();
    ; M% n% Z6 k- Y
  113.                         speed =type;//将接收到的数据给speed5 I6 w# K$ n2 W# b$ x) ~# l
  114.                         if(speed==0)goto Initial_state;//如果是0则返回初始模式+ d4 y( n8 r$ i) }+ C, _; }9 }* V
  115.                                 else{
    8 A& q; K3 t% S; U! A& J, x
  116.                                         if(speed>=15)
      r' S0 [3 X; C1 c" z+ C4 X
  117.                                         {
      N3 |/ K2 _3 b- d4 G( D
  118.                                                 printf("\r\n 旋转速度>15rad/s,请重新选择旋转速度。\r\n");
    : a6 q4 v7 `  k2 F* a+ h3 @
  119.                                                 goto part1;
    4 k" ?" I3 ^' B
  120.                                         }
    - Y" Y7 w* A- M# D6 L- S0 I6 k' @
  121.                                                 else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式 \r\n",speed);
    / F9 e+ _5 n/ _* N! z' H+ d
  122.                                 }: E2 q5 y" p! u' b. W' }
  123.         1 c8 S, c  T! `
  124. /*********************************************此模块用于配置角度参数********************************************************/                7 j0 e3 |$ x1 f3 |$ y2 X' X; |1 y

  125. 7 k& T; {; X: O) F6 t# W
  126.                         Waiting_reception();
    4 ?1 p  w* P2 e  A& D2 i  d
  127.                         angle =type;//将接收到的数据给type7 a" h, G# j: r0 y' X
  128.                         for(;;)
    % {  M! n: H5 {# [+ Z; v: K
  129.                         {
    ' W2 M7 O% p8 i  R- e3 f9 X
  130.                                 if(angle>0)//接收到的数据不是07 B6 x3 ^) u9 e3 {" M* K$ x
  131.                                 {
    , i6 O$ p8 @+ ^' s8 d- t. [
  132.                                         TIM2_Master__TIM3_Slave_Configuration(speed,angle);        // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度
    . W3 m3 W( m2 V6 K% R, t* l+ r
  133.                                         delay_ms(20000);//电机保护- I- D8 v& O; X
  134.                                         printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式; \r\n",angle);
    # Q$ ^6 ?+ D! s
  135.                                         angle=0;
    * D, Z/ a0 q/ ~
  136.                                         Waiting_reception();               
    + O; c4 Q; V. ~( l2 O- B6 H% W
  137.                                         angle =type;                                       
    1 ^% k  r; d# d/ Z
  138.                                 }else{
    . {. ^% K' h+ V- S) M! }
  139.                                         if(angle==0)goto Initial_state;//返回初始状态        , j8 W% D& X9 _! t
  140.                                         else {# I0 ?! G* f! A+ V3 T: P6 D# g1 z
  141.                                                 printf("\r\n 角度错误,已返回初始模式 \r\n");               
    ) Y2 j+ l0 w" N) m6 v' {
  142.                                                 goto Initial_state;
    $ U4 G/ f0 T. z; N4 f
  143.                                         }                                               
    ( j/ k& R- r- {( P8 T! |. g
  144.                                 }
    + H; j8 ~# k9 z' ?! p  M' ~
  145.                         }
    9 y% c* n1 ]6 X' |$ D% m7 K( {, y
  146.                 }               
    8 j: J2 N1 m* d3 u  _! f
  147. /*********************************************反转模式********************************************************/                5 c/ H0 n. x* j
  148.                 else{
    3 ~7 h: e# h& ]
  149.                         if(type==1)
    $ w( _+ y2 Q3 p1 {. f
  150.                         {
    : z% o  ?' D! Q0 d
  151.                                 GPIO_ResetBits(GPIOA, GPIO_Pin_12);//电机反转. {. d* K* @* L& F$ T, `+ A
  152.                                 printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");- U% r$ @& w+ `& P- |% q- z
  153.                                
    - Q5 d0 K& b2 X. M! t0 o
  154. /*********************************************此模块用于配置速度参数********************************************************/( C4 j" i, K# N# w6 h; v4 {
  155.                                 part2:                                Waiting_reception();
    ' w- ~* y, P& i$ T' G( p
  156.                                 speed =type;//将接收到的数据给speed# F3 K$ [% E4 w# O9 u8 l; U' }
  157.                                 if(speed==0)goto Initial_state;//如果是0则返回初始模式
    6 W7 b  g: \- n1 O$ z% b1 x
  158.                                         else{
    5 t7 y# R/ V) [' O& _. D9 H7 J
  159.                                                 if(speed>=15)
    ' V$ c( I: K+ v1 u- q  p2 z& U3 E
  160.                                                 {
    * G  k: _( p, B" j$ z$ L
  161.                                                         printf("\r\n旋转速度>15rad/s,请重新选择旋转速度。\r\n");$ P" \- I6 d$ {8 R) G! _" A) O6 f
  162.                                                         goto part2;% Z5 H$ a3 n2 T: U! p0 s7 \
  163.                                                 }else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式  \r\n",speed);
    3 V8 ~2 G# |0 H: @# |2 w9 @6 w
  164.                                         }       
    7 s$ y& R% l% }) [
  165. /*********************************************此模块用于配置角度参数********************************************************/               
    5 z" o1 c. ^* f3 T3 X; M
  166.                                 Waiting_reception();
    4 K7 g2 f, o6 G& w, `! S* [0 m7 E
  167.                                 angle =type;//将接收到的数据给type
    $ ^4 M$ r+ ]: y: R+ G$ D- E. d0 e
  168.                                 for(;;)% e5 d  \2 e' r0 r1 R
  169.                                 {8 G5 J+ ^+ k( x
  170.                                         if(angle>0)//接收到的数据不是06 G7 V) T+ ^2 @" c& V1 ^
  171.                                         {* C# G; P. n/ ?+ N- V5 g' P
  172.                                                 TIM2_Master__TIM3_Slave_Configuration(speed,angle);        // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度
    6 j! r7 O1 @  G! I1 q
  173.                                                 delay_ms(20000);//电机保护" c  n% j& {! n
  174.                                                 printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式;\r\n",angle);
    ! ]2 K! j$ f$ O  _3 ~0 e
  175.                                                 angle=0;2 x: M# o2 J& N, k
  176.                                                 Waiting_reception();                ) c: |. S9 J7 s9 z
  177.                                                 angle =type;                                        / J6 i7 R& s/ a7 n7 n
  178.                                         }else{" H; a6 P! x6 K$ D% S: U0 N
  179.                                                 if(angle==0)goto Initial_state;//返回初始状态        - V6 S' O. e& X3 \: |$ w
  180.                                                 else {- D, K; u# ?+ A/ t; G9 T
  181.                                                         printf("\r\n 角度错误,已返回初始模式 \r\n");               
    7 p9 k$ e" n/ O# d! n: [
  182.                                                         goto Initial_state;
    2 d& [1 E0 }6 J% {$ E  E% `9 |
  183.                                                 }                                                               
    8 u2 K9 d: L( b- R
  184.                                         }! K' o$ ^+ Q* K; w+ c7 x
  185.                                 }
    $ [4 ^( ^4 @1 ]' c# j. U- z
  186. /****************************************************************************************************************************/                                       
    ! S7 U( }, I3 r! L$ X
  187.                 }else{//if(a!=0)&(a!=1)
    5 i' v0 |+ @6 K! i3 E
  188.                         type=NULL;; k: t/ Z) a) d  i$ ~# w  G. E
  189.                         printf("\r\n 输入无效 \r\n");; `$ }, i. C! u1 L
  190.                         goto Initial_state;//返回初始状态2 p" N) i! W( C! |
  191.                         }
    7 \* l9 a' T" L
  192.                 }
    4 T: Z9 Q8 R- a- B! D6 q
  193.         }1 R; }( Q7 p9 [" d/ F2 F
  194. }
    % x& O+ q5 G" e9 `/ M; q
复制代码
2.main.h程序: z  J! |6 d* J
  1. #ifndef _MAIN_H' t/ }8 g( f8 S, o) H" x$ U+ q
  2. #define        _MAIN_H
    7 D3 S' k" \+ M( h& B
  3. #include <stm32f10x.h>
    8 Q- n% Z5 w* d
  4. #include <usart1.h>
    2 u1 _. o) e9 c: b, }9 t# n5 ?+ h
  5. #include <misc.h>
    5 Q% q! g8 Z* `' g. K- a. n! ]3 B# M
  6. #include <nvic.h>
    ! V1 A& L& b7 s. K- I& f
  7. #include <stdio.h>0 `: m( e4 }% p6 E- {" X
  8. #include "stm32f10x_tim.h"
    ! W" I3 Q: T' c( D8 B1 ?6 W- Z' I
  9. #include "timer.h"
    2 u' V$ i% K) }6 q
  10. #endif( w. U: s/ t7 i& T( A
复制代码
3.time.c程序
5 Z; Y4 d* t/ Q/ w$ ~
  1. #include "timer.h"
    - p7 r' ]: S8 P2 u
  2. /**************************% f9 n: B( [8 C% w4 s
  3. * 函数名:GPIO_Config) O4 R" \! b! \( [
  4. * 描述  :无
    6 P) f: }! p6 {  Y9 e  a
  5. * 输入  :无
    * A0 ]4 }/ Y* P! H! b9 c) |
  6. * 输出  :无+ ?' ]6 Q+ c; k( {. [5 |/ A
  7. * 调用  :主函数! }& q( x- D7 L7 I
  8. * 返回值:无
    ) B) l% n) i; x
  9. ****************************/: ^/ B1 b0 V8 T
  10. void GPIO_Config(void)
    " C" u0 T& k' N/ F9 Z2 P
  11. {
    # b" C, ^; J5 Z8 G
  12.                 GPIO_InitTypeDef GPIO_InitStructure; 8 h. t2 n/ z5 W$ L" x* p
  13.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能IOA! g4 i) ?9 n7 w' |) m$ C/ r! k/ ~
  14.                 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE); //使能TIM2,TIM3
    ' S! Y; j( M/ M# o6 A9 ~
  15.                 3 x/ x0 |- ^* o2 [9 w; @' v
  16.             /* Timer2 Channel 1, PA0 */ 9 O  j& i6 v& x! O
  17.             GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0;
    " x; {7 f( y8 C' Z! X
  18.             GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用输出+ U; C7 b( U* j
  19.             GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    , G: k) Y# P: e' r3 r7 S3 z
  20.             GPIO_Init(GPIOA, &GPIO_InitStructure);
    2 z# y2 `- I; i6 y' X5 u1 `
  21.                  
    ; l. {3 H; T2 o
  22.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_11|GPIO_Pin_12;  I8 l4 R# ~/ i$ F
  23.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式
    6 q5 f- h9 L5 t* w1 ~# }' E3 m
  24.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ
    2 [  k4 G2 l- [: P9 ]
  25.                 GPIO_Init(GPIOA, &GPIO_InitStructure);                   //( {4 k4 O8 b/ y' n0 x
  26.                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
    " L! J+ `4 c! W" T; D
  27.                 GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能( }7 J( p/ k( \4 w; F4 V2 L1 J
  28.                 GPIO_SetBits(GPIOA, GPIO_Pin_11);//指定引脚输出低电平,此时灯全灭,方向
    % x* _) A6 Z! }0 F% d
  29.                 GPIO_SetBits(GPIOA, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能
    . |+ S. `5 x4 D9 h% S, k1 A
  30.        
    9 P0 j! \) d  Q* k
  31.          0 B4 @5 Z5 @2 a3 W2 c
  32.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    1 j( t0 c$ q( I0 c* v  ~
  33.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;         //通用推挽输出模式- u; {) t1 k% d( o" S9 v8 i, `5 J
  34.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ3 _( @: U( }8 j0 ~: Y& X
  35.                 GPIO_Init(GPIOA, &GPIO_InitStructure);                   //* `% B* P1 D' o9 z% B
  36.                
    ) v# Y' P, J) A! c) `6 b& a0 r5 L6 G9 V
  37.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 3 V  h( A0 b8 o( @6 E' f9 B8 m3 w
  38.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    3 {5 P; x/ @" }/ h+ x" U- c7 [, N( B
  39.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式
    ; \1 z# D% ^$ g7 J2 D) I
  40.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ- a; c, ?( R, H
  41.                 GPIO_Init(GPIOB, &GPIO_InitStructure);                   //
    0 p( Y1 y1 }  D0 Q* n+ D
  42.                 GPIO_ResetBits(GPIOB, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能
    6 y$ v3 i& }' [( E/ w- b
  43.                 7 {: O0 ~  O8 k
  44.                 //GPIO_ResetBits  GPIO_SetBits) }1 R( U! I4 J$ W1 _
  45. }& t8 b8 {% U) u

  46. , k1 @8 c6 L; x$ f7 {; N3 u1 V# o! n4 `
  47. //================================================================================8 ?* W: Z7 _1 P
  48. /**************************
    ) z3 V* @4 w% Y5 J8 K/ h* a. w  d
  49. * 函数名:TIM2_Master__TIM3_Slave_Configuration
    7 l/ U0 J  u: E/ U
  50. * 描述  :主从定时器配置& a3 i; R" u" i: ~
  51. * 输入  :电机转速speed,转角angle
    5 R' U; H; d4 U
  52. * 输出  :无
    8 ]( d8 e+ s+ n% g8 T+ n
  53. * 调用  :主函数
    3 y/ }9 O4 ^. D6 j6 C% @5 c
  54. * 返回值:无
    3 A& R* i; v/ ^! a1 r
  55. ****************************/  k, E; C2 g  G: f
  56. void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency, u32 pulse) ' ~0 Z4 G* Y" J) F
  57. {! e8 G- t# Z+ o4 R
  58.         TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    ) ]1 P! e$ w, U1 ~9 ^1 U' d7 {
  59.         TIM_OCInitTypeDef TIM_OCInitStructure; 6 S5 e" N( w$ \, p5 t7 f* e
  60.         * n2 d+ t% T  i& r
  61.         u16 nPDTemp ; : w# Z$ U- K% ?1 B% g5 @
  62.         u16 pulse_number;
    ( o) ?9 C# \4 y3 E: S) v& m+ W
  63.         float p=PulseFrequency;
    . b; D2 I/ }$ d( v6 k* g% B  X
  64.         TIM_Cmd(TIM2, DISABLE); " h9 q0 c" @/ P5 \& c5 M1 ]% q
  65.         nPDTemp = (11.25/p);                            //TIM2重装值是11.25时1s转一圈(电机32细分下)
    5 W0 l" }; |& s# Y6 V3 P0 r5 Y; h
  66.         pulse_number = (16.7778*pulse);//TIM3重装值是16.7778时转1°(电机32细分下)
    ' n8 \  P/ C( j  ?/ O. k8 Y
  67.         ' n8 E' M* d- b1 G$ d* z
  68.         // 时基配置:配置PWM输出定时器——TIM2 , n" ?! }- L3 d7 \3 b  H
  69.         /* Time base configuration */
    0 L1 c3 i; A  ]4 M  d* U
  70.         TIM_TimeBaseStructure.TIM_Period = nPDTemp; //定时周期为nPDTemp
    8 h3 j8 w* j) |, V( y
  71.         TIM_TimeBaseStructure.TIM_Prescaler = 999; //预分频值1000,即f=72khz/ }' i8 z0 k/ C' P; r
  72.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分频因子,会影响滤波器采样频率,与本实验无影响
    & K* E5 K" i) l1 C6 y
  73.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
    + c( F% Q0 n6 ~5 d" z* `+ o, n
  74.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //指定重复计数器值
    8 _8 n( v2 [+ X) i: O" r1 q
  75.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    : _5 S( b9 O9 Q! e+ Z+ _8 n
  76.        
    / p- W8 |  D6 G4 t  C9 m8 Y! V
  77.         // 输出配置:配置PWM输出定时器——TIM2 4 }1 f1 ~; ^8 g! C
  78.         /* PWM1 Mode configuration: Channel1 */    7 q7 ~  c- h1 L
  79.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM 脉冲宽度调制模式 1
    8 d$ F0 k, t' w& D0 B' e8 m+ n
  80.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平有效
    * `  G5 w& d4 N( J) F  R
  81.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出$ Y3 A/ J( r' P9 U: B. E; e
  82.         TIM_OCInitStructure.TIM_Pulse = nPDTemp>>1;//50% //比较tim_ccr的值,输出脉冲发生跳变
    , _* a) G" ?7 d5 G8 t6 a1 s6 [
  83.         TIM_OC1Init(TIM2, &TIM_OCInitStructure); //初始化/ n  H, R! _  @
  84.         TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能 TIMx 在 CCR1 上的预装载寄存器3 k3 e7 H1 [- R( ^) R
  85.         TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能 TIMx 在 ARR 上的预装载寄存器' P' h2 Y8 N5 L1 Q8 O
  86.         ; o1 N- o( h# ^7 n) X
  87.         // 时基配置:配置脉冲计数寄存器——TIM3 ( t5 S' w. q4 q8 f! {. Q
  88.         TIM_TimeBaseStructure.TIM_Period = pulse_number;      //0x1900是360°;//改变给电机的脉冲个数                     4 b$ _% n; a7 n( t! X3 h
  89.         TIM_TimeBaseStructure.TIM_Prescaler = 0; # M5 J6 h5 O2 Y& i2 p9 A9 b
  90.         TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    - F/ w, a; V: Z/ B: G
  91.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    $ K% F3 H: H1 ^9 E9 S4 D9 I
  92.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    * p( T3 A6 X+ G6 m3 x9 H
  93.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    : N, x% }9 w5 I) k4 V2 p* |
  94.         // 输出配置:配置输出比较非主动模式定时器——TIM31 {' k1 {3 u! h1 P$ W( n( s6 X) J
  95.         // Output Compare Active Mode configuration: Channel1 " G9 s* b, M: l+ \$ F
  96.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; //输出比较非主动模式,(匹配时设置输出引脚为无效        电平,当计数值为比较/捕获寄存器值相同时,强制输出为低电平)      ' k6 G6 M4 k$ \0 U
  97.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; + ]9 {: G  \, N: Y5 Z2 |
  98.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    8 r5 @; ?1 e" B% k6 b# R8 }
  99.         TIM_OCInitStructure.TIM_Pulse = 0xFFFF; // 这里的配置值意义不大   
    + `3 i2 s  G; b" F% \
  100.         TIM_OC1Init(TIM3, &TIM_OCInitStructure); * I' F7 ^: Y" L/ l

  101. + y2 l( Q( y5 Z3 y3 P# C
  102.         // 配置TIM2为主定时器 , ^5 C8 {# o  p% f: D
  103.         // Select the Master Slave Mode 7 ^2 U1 |! d) q1 f7 ?1 R$ i
  104.         TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //设置 TIM2 主/从模式并使能1 r, H% Z3 H5 O, A7 S0 l, ]/ W
  105.         // Master Mode selection  
    # L2 f* N* }- v# G5 d/ G. A+ l3 B
  106.         TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); //使用更新事件作为触发输出/ q1 r! b( @* Q  V6 _- c) P  ^1 j, Z2 n
  107.        
    7 ]4 ?/ o* h# i( k
  108.         // 配置TIM3为从定时器 $ p) Y4 l+ Y5 \0 U. f
  109.         // Slave Mode selection: TIM3
    , T& ~/ }& ^* x9 H# b. L6 G. }( {! V
  110.         TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated); //选择 TIM3为从模式   TIM_SlaveMode_Gated-当触发信号(TRGI)为高电平时计数器时钟使能
    % w4 D2 v& a* z2 c8 y* \0 G2 \" H
  111.         TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); //选择 TIM3 输入触发源    TIM_TS_ITR1-TIM 内部触发 1
    - j! t5 s( G5 A
  112.         TIM_ITRxExternalClockConfig(TIM3, TIM_TS_ITR1);//设置 TIM3 内部触发为外部时钟模式   TIM_TS_ITR1-TIM 内部触发 13 z0 l9 ~5 L' t9 Z& Y2 k6 m
  113.         TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); //使能TIM3     TIM 捕获/比较 1 中断源          
    6 V2 F8 k" E; l$ F2 o
  114.        
      S2 j: w& y0 O0 C" e( D4 B0 i
  115.         TIM_Cmd(TIM2, ENABLE); ) Z; D7 h( h8 T# n- S6 R
  116.         TIM_Cmd(TIM3, ENABLE); / n7 Y9 N6 @4 x/ {- t6 S
  117. }
    * e, B" o- l& ~6 Z, D, ^) J+ b4 C
  118. ; ?! M3 \* W+ h
  119. /****************************************************- n# V& n* v* g  T% j# l; b3 T
  120. * 函数名:Output_Pulse
    6 J, v( p$ Y9 l+ v8 z/ W
  121. * 描述  :无- {: l7 V$ v7 k6 ?$ M' \
  122. * 输入  :无
    / N+ S9 A  i% u/ e0 {
  123. * 输出  :无8 T8 Q  o, d8 E" B3 {9 h
  124. * 返回值:无- ~6 h9 R, X; G1 J$ R
  125. ******************************************************/  k6 i/ p* j& `0 K/ Q& Z
  126. void Output_Pulse(u16 Num): D8 q- i& U$ u/ y# j
  127. {
    3 F/ W& Q- G% c# I9 B
  128.                 GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能# ^2 b' i) c  y' I  [, I
  129.                 TIM3->CCR1 = Num; 8 W: c! W# g$ @: Q2 {' {% W
  130.                 TIM3->CNT = 0;
    " E, X8 @8 v' ^. ^/ }/ q/ L' D% {
  131.                 TIM_Cmd(TIM3, ENABLE); $ {0 u& ]; \6 q8 p) E
  132.                 TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
    ( b* G4 }( F& Z# w
  133.                 TIM_Cmd(TIM2, ENABLE); - F) [% v, I  W: \
  134. }8 o' e$ u. g, g; W1 ^& I# A  P
  135. " g* j# G3 ~6 E/ L6 e4 F6 r/ ]
  136. /****************************************************+ \7 E9 O* b) Z  X
  137. * 函数名:angle_set& J5 M5 }6 e, Z. i/ L  j
  138. * 描述  :无2 P/ V  t; [- F% a# r
  139. * 输入  :无 & }- l9 W( `/ T8 e) D& @: R6 r5 C
  140. * 输出  :无
    ! Y4 I7 @$ Q8 @; J* J, j% O' ~
  141. * 返回值:无; }$ A9 i' R: P3 E# H. O
  142. ******************************************************/  I, H  r/ Z; @3 k
  143. void angle_set(u8 dir,u8 angle)/ a+ X" I+ p; Q0 g  z4 f6 ?
  144. {. T: {9 N5 u6 `& Z
  145.         if(dir==0)* V! v2 n/ ]9 q, n* h1 a+ S. J
  146.                                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向; n' |8 g0 |( C; X* o1 u0 n/ [
  147.         else4 t; y/ T& e3 E( p% }% a
  148.                                 GPIO_SetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向6 n# D# `- P; ~" \0 b# [+ A2 K
  149.        
    ) x% U: d7 P+ I. C1 m  j
  150.         Output_Pulse(angle*6400);; i7 y( l" ~/ _7 W
  151. }( t- e" s. b! O0 z* B* L
复制代码
4.time.h程序
' ]  q, ~& D8 \$ X
  1. #ifndef __TIMER_H
    , u  ?. E/ F% m. v% s3 r! h9 o" Q
  2. #define        __TIMER_H1 ~  R4 X$ q" v) {' i8 A  r4 M* ?4 z5 g
  3. #include "main.h"0 w7 w( A6 e8 G0 x2 q/ u
  4. extern unsigned char Flag;9 }1 ~3 s* e5 L6 j- H5 |/ J, t
  5. extern unsigned char TIM2_Pulse_TIM3_Counter_OK;! O4 C' e7 o0 b, {3 j0 D$ Z
  6. void GPIO_Config(void);
    3 x% I, D+ Q% `  o
  7. void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency,u32 pulse);$ c7 Q! p) g4 D& P
  8. void Frequence_Setting(u32 PulseFrequency);( V/ p- y5 V2 l& e5 }6 k7 G
  9. void Output_Pulse(u16 Num);5 \8 f0 d7 H, z4 ]* o4 M) Y
  10. void angle_set(u8 dir,u8 angle);
    % I8 ^8 E/ a& V( [7 ?
  11. #endif" h' }* M. x4 C; @
复制代码
5.usart1.c程序. V! R8 z/ B$ `1 V" h; I
  1. #include <main.h>
    ) B9 {( N3 \% U2 c, i4 o! }
  2. #include <usart1.h>
    2 f; p+ }: y; A
  3. #include <string.h>1 f: T" N5 g# c9 H0 M7 f  ?" U% P
  4. #include <math.h>! @! s6 F. A7 A  j/ Y( G7 c# a! I

  5. - [0 q" j# N$ \) ?9 O3 x% a% P. ~9 {
  6. /******************************************************5 ~; d: d' p+ Q1 R! b
  7. * 函数名:USART1_Config
    4 N) P9 s1 O9 c9 s% X- A  T9 [% k
  8. * 描述  :USART1 GPIO 配置,工作模式配置* P- }/ k# h* R: S  q2 N
  9. * 输入  :无
    3 P8 u! h2 E. V( |* Y
  10. * 输出  : 无
    2 K4 C% F  {) p
  11. * 调用  :外部调用1 [  v: k7 {; s: C* E' ]$ u) L& y( f
  12. ***************************************************** */
    7 @6 _1 n4 l5 @# ]% E, Y
  13. void USART1_Config(void)
    6 T8 o4 W: R% ^1 j
  14. {
    3 v9 F! |3 k+ T
  15.         GPIO_InitTypeDef GPIO_InitStructure;
    : J, n, e- F: ^+ l& E
  16.         USART_InitTypeDef USART_InitStructure;
    : g/ l0 D- e4 E2 z5 t6 w
  17.         - R7 D& s6 G. E
  18.         /* config USART1 clock */) C, b0 a3 F2 W5 w# r/ t
  19.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);0 R  |* t; B" O- X$ A/ x+ M
  20.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    + f0 r' U; ?( p* v  Z3 V1 o+ R
  21. : k2 D5 c3 n* B! P! G
  22.         /* USART1 GPIO config */. k) f1 [* G9 S* X; S
  23.         /* Configure USART1 Tx (PA.09) as alternate function push-pull */' ?; _1 {' q" w  j
  24.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;# G& b' P6 ^# H9 _
  25.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    $ ^: w% C; H8 \) ~7 h
  26.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    1 j$ m% K. q+ k( b% R
  27.         GPIO_Init(GPIOA, &GPIO_InitStructure);   
    # P+ {, I* e, e+ e+ N: F" z1 E
  28.         /* Configure USART1 Rx (PA.10) as input floating */; ^9 n4 o) k" ?8 y. N: a( h1 O
  29.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;5 Q9 d6 w) T  `" [9 a( Z
  30.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    ( U( y; p/ L# }/ f- w
  31.         GPIO_Init(GPIOA, &GPIO_InitStructure);0 N# s! f4 o6 N5 @* |9 v% y
  32.        
    6 C% _- Y. ]2 P4 s1 J+ k* @
  33.         /* USART1 mode config */
    * Z( T$ Y. c8 A, ~1 d3 f
  34.         USART_InitStructure.USART_BaudRate = 115200;
    8 ^( w4 D' x% v; q* ?9 Y! Q
  35.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
      Z$ }. F/ a* U  s/ R
  36.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
    5 P5 U1 t8 u, ?/ x
  37.         USART_InitStructure.USART_Parity = USART_Parity_No ;
    ' F* A) x5 Q! t" }# I+ s5 }+ q6 r
  38.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;5 b, b# a& ?3 W
  39.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    . ]8 f9 f7 n0 l+ g' m* _
  40.         USART_Init(USART1, &USART_InitStructure);
    0 J: q! M( n5 g
  41.         USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);1 _' a& K* @' R; V) Z6 b
  42.        
    ' d# T  S  H$ C
  43.         USART_Cmd(USART1, ENABLE);
    , _5 _$ K6 O" b& h  q' y( {
  44. }" @+ C) G$ T8 W% s

  45. ; c1 g5 b5 i4 u: g
  46. /******************************************************$ m: ^, a; t) U) S: v
  47. * 函数名:fputc. \0 q8 I: r+ e/ e9 B9 u* h
  48. * 描述  :重定向c库函数printf到USART1
    ) p$ [* K* H. J7 x+ n  e- ]
  49. * 输入  :无4 e4 U% D: H' p* x
  50. * 输出  :无
    / |+ o/ ]* O- a+ @
  51. * 调用  :由printf调用
    ' F" Q0 _6 i, a1 l9 a, J3 J8 G
  52. ***************************************************** */
    # y$ R& k. O( {. C
  53. int fputc(int ch, FILE *f), x5 A) ^6 m. r
  54. {& v) x3 w, p$ j) n
  55.         /* 将Printf内容发往串口 */
    ( j; ^7 f" `$ `( Z
  56.         USART_SendData(USART1, (unsigned char) ch);
    , ?& o4 v$ _( x
  57.         while (!(USART1->SR & USART_FLAG_TXE));
    . r2 ~7 r: T" w! B
  58.        
    ; O0 G/ n3 Q! A2 m9 z2 `# K
  59.         return (ch);% _  k$ T0 Y, `/ ?8 H0 `
  60. }
    3 ]& U4 t* q4 |. }* y" o
  61. + U, \; i( k: u5 @( v
  62. /*-------------------------------------------------------------------------------*/( Q& N- V  e; u+ [
  63. /******************************************************; X8 c7 U- z; S, O% b- V
  64. * 函数名:USART1_IRQHandler
    ) O5 d. I& h1 b' Y7 w5 G. l4 z
  65. * 描述  :USART1中断服务函数
    / c7 x' `5 f6 k% S- q3 \2 {8 B( y
  66. * 输入  :无
    0 Z$ U6 m/ `$ d) B
  67. * 输出  :无1 ~4 V% H! g; V6 t
  68. * 调用  :中断调用
    ' A! K- V9 t5 r7 s% l. l$ c4 I
  69. ***************************************************** */
    ' u% H, `6 K& t4 p
  70. u8 Res;
    " s. O4 V# r$ i1 v* v4 J
  71. extern int a;
    7 T- Q5 k$ `1 Z! K' D
  72. u16 USART_RX_STA=0;       //接收状态标记         1 S$ u& W. d/ g% ~1 G
  73. u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.1 X% V1 v) N, Y
  74. void USART1_IRQHandler(void)                        //串口1中断服务程序
    & X$ `# \4 n2 _5 U' W& \$ h2 [
  75.         {
    ! @% U! h/ F! c4 T) J% `/ O
  76.                
    $ \2 m' z& V* e
  77.                 Res =USART_ReceiveData(USART1);        //读取接收到的数据
    - m) v- J+ j! I
  78.                
    ( w0 u& K% [, O' S
  79.                 if((USART_RX_STA&0x8000)==0)//接收未完成
    ' k5 N/ }' d& N6 y
  80.                         {
      |7 ~& W% Z  q; {
  81.                         if(USART_RX_STA&0x4000)//接收到了0x0d
    * y/ t5 p+ o: x; X1 v6 M
  82.                                 {
    3 e5 \  P, t1 L3 P" ~$ _' r5 I
  83.                                 if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始1 k- ?3 _: D' f3 T$ v
  84.                                 else USART_RX_STA|=0x8000;        //接收完成了
    . p0 k& C4 a1 e" w) r
  85.                                 }
    6 ^( F, D  H; g8 S0 P$ i- n% }( \
  86.                         else //还没收到0X0D1 u1 ?& a) j1 |2 ^  Q! d6 N% a
  87.                                 {       
    * f( q) v1 Z( c( A( N
  88.                                 if(Res==0x0d)USART_RX_STA|=0x4000;' B% `' l! j3 |+ u
  89.                                 else$ L9 b8 [: Y& P
  90.                                         {3 F( T" g/ |3 y
  91.                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;* T9 z$ t9 p' X3 K. g
  92.                                         USART_RX_STA++;1 j+ x. _4 w0 K. o( J2 p) x7 {% ^
  93.                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收          % F: s3 e* `1 e) v3 |6 t9 D
  94.                                         }                 
    $ G& }5 I; E+ |
  95.                                 }
    & ^& _/ L$ b( i& Y9 ?& H- T
  96.                         }                # S# Z. t7 r5 W3 W3 q
  97.                                 a=1;         
      ]3 v$ v( Y  S0 X
  98.         }
    " }0 j( ?0 |( l, \, q1 J2 k
  99. #if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
      N4 s2 x7 r' V5 v
  100.         OSIntExit();                                                                                           
    2 C, F4 W- u0 V. j3 S
  101. #endif- W' o* O# u$ K- x8 z$ S: _4 Y
  102. . K% x+ X/ ^  s% ?* m* O. b- ?
  103. /******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/
    % A+ i7 `! C  {! }
复制代码
6.usart1.h程序* T. g1 C0 U8 H) s
  1. #ifndef __USART1_H
    : C* k. K7 V5 N2 u1 M
  2. #define        __USART1_H
    4 |8 r& Y& f5 v2 A! \0 J' s0 [
  3. #include <main.h>4 B- u- C6 M  Z! v2 Z7 M4 m- H. M4 r
  4. #include <stdio.h>2 n5 J+ J& b7 q! F, `
  5. 9 R" z8 v* z  s1 H5 J/ U, L
  6. #define USART_REC_LEN                          200          //定义最大接收字节数 200
    0 K: o: o7 o% A) Z" a) `
  7. #define EN_USART1_RX                         1                //使能(1)/禁止(0)串口1接收
    ; X4 d1 S' ~! `& i3 {
  8. extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 ! k* }3 n1 p$ I
  9. extern u16 USART_RX_STA;                         //接收状态标记
    # R0 X9 a) _' C) I3 U1 F: ]& n/ r% K
  10. int simple_atoi(char *source);. ^* C, T" P" t5 b9 c! I
  11. void USART1_Config(void);# b: U: N9 g3 a2 W" L9 G
  12. #endif /* __USART1_H */
    % D3 _+ |: u1 T9 S( P" J) D0 e
复制代码
源码:/ Q5 t) Q4 |. q/ y& x
步进电机程序—串口控制速度角度.zip (4.75 MB, 下载次数: 113)
收藏 1 评论0 发布时间:2021-6-25 13:30

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版