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

利用STM32F103精确控制步进电机

[复制链接]
STMCU-管管 发布时间:2021-6-25 13:30
利用STM32F103精确控制步进电机
一、用到的元器件
3 t* _  q- K4 p2 TSTM32F103C8T6- J2 W; v; O! f3 Q- }( N6 j0 n$ m5 }
42步进电机(42SHDC4040-17B)
3 x) ]. ?: n/ X" ?TB6600电机驱动器升级版
0 S8 d$ g+ x  a# T- D! c  S3 E' A- g; B; G( F

5 V( c1 H$ ^$ D二、42步进电机
9 U, |3 L. u' \5 P# A9 s* x3 A1.步进电机的基本知识
& c! ^, f% d0 c  |(1)拍数——每一次循环所包含的通电状态数(电机转过一个齿距角所需脉冲数)
) U! @+ A* Q0 J; ?" W(2)单拍制分配方式——状态数=相数
; \! h! Y1 K8 ](3)双拍制分配方式——状态数=相数的两倍
* ]; n2 y) z' r5 c% l(4)步距角 ——步进机通过一个电脉冲转子转过的角度6 K/ X& C# D" j7 `
11.png
N:一个周期的运行拍数
0 O8 U0 g, `& {( FZr:转子齿数# j* E% L6 N' `. ]
拍数:N=km
6 t/ x. }- L# P3 m6 Bm:相数
; e9 X1 O8 v# a4 Y, U5 [k=1单拍制$ S, t, p6 C1 r7 o
k=2双拍制
# t! A* c7 u7 c6 E5 C(5)转速6 h4 o4 v  D5 H5 f# s0 f
12.png
(6)角度细分的原理7 a3 e0 t1 e2 L: W! V
6 k7 ^8 c- X% S

+ o  Q( C7 }: W, H" {7 z电磁力的大小与绕组通电电流的大小有关。
; ?7 q$ ^1 x) [6 T0 @: L当通电相的电流并不马上升到位,而断电相的电流也非立即降为0时,它们所产生的磁场合力,会使转子有一个新的平衡位置,这个新的平衡位置是在原来的步距角范围内。
  N9 Z1 f2 L+ A2. 42步进电机参数
; p0 j4 _6 M" o. }% E无法查找到42SHDC4040-17B型号的详细资料,以通用42步进电机为例:4 O' J8 a8 ~7 k  }8 V6 t, @
步距角 1.8°
" i4 v4 E# A% V' @, l步距角精度 ±5%
6 i5 ?8 R$ x2 p+ ?3 U相数 2相0 s2 K. k. Q0 v  E+ \" M. }- E
励磁方式 混合式
+ _( o( Y# U8 \( N2 ~# @转子齿数 50  U7 ?3 ^  L3 W' \7 a
拍制 双拍制
  z; U1 {1 n; x8 r9 M其他参数:无
6 P& x7 }3 G7 t5 r+ c由步距角=1.8°推算出转子齿数为50,拍制为双拍制' B6 a3 r! I2 Q0 q# w2 J6 t3 B

& e4 S% C0 r5 X- r5 B% k7 Z: p
2 h! X; M( |$ o/ j4 ~# o# _0 B
3. 42步进电机速度与角度控制6 b) c4 o- i6 T+ g0 l
电机的转速与脉冲频率成正比,电机转过的角度与脉冲数成正比。所以控制脉冲数和脉冲频率就可以精确调速。
3 P6 d! q) q5 M1 I/ n9 ~: F' @理论上步进电机转速 = 频率 * 60 /((360/T)*x)- Q  ?" s5 P; ~2 L: `3 S
21.png
) f0 ]+ ?' o4 i, j/ @6 ^- \​        4 H' `# c* J5 s! j
转速单位: 转/ 分+ a; _  `8 |3 H( M
频率单位:赫兹/ L3 k7 Z) |8 g" E) G! c9 C
x 细分倍数
  K1 R: d" s% L% t- oT 步距角
7 w* M; z  T/ I4 n7 I* Z例如,在本实验中,32细分;频率72000 赫兹;步距角1.8°;套用公式72000 ∗ 60 ( ( 360 / 1.8 ) ∗ 32 ) = 112.5 \frac{72000*60}{((360/1.8)*32)}=112.5
# E" z) R5 p& V+ z((360/1.8)∗32)
7 S% l- D! C; M4 ]0 V* T72000∗60
# W/ h0 C: ^" f! O% S8 \& C) I​          X( Z8 X. ?+ Z/ `
=112.5rad/ min,即1.875 rad/s.
( I& Q0 C: j* N1 m4 i4 R
13.png
三、TB6600电机驱动器升级版参数
- S6 q6 v/ s$ KTB6600步进电机驱动器升级版是一款专业的两相步进电机驱动,可实现正反转控制。通过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 V$ u& \7 Y5 w: d

1 Z4 g# g( S/ I9 B% J5 t. G2 E0 S0 C5 @
+ _, w4 s4 v  d7 A3 J) N
1.信号输入端5 t/ ^3 |. V2 d" C& N9 U1 u& {
PUL+:脉冲信号输入正。( CP+ )
6 N# }( O% Y& o# F$ MPUL-:脉冲信号输入负。( CP- )3 p4 y  t' o. F/ H
DIR+:电机正、反转控制正。
* t9 c2 _/ K8 F- B7 qDIR-:电机正、反转控制负。
  G  L% F3 U4 mEN+:电机脱机控制正。
& u7 E# X7 h# ~; n6 WEN-:电机脱机控制负。0 m$ y) f( d/ r. [* ?
" \0 h6 w* }, ]+ B7 V

- ?# ?$ Z; }4 K共阳极接法:分别将PUL+,DIR+,EN+连接到控制系统的电源上, 如果此电源是+5V则可直接接入,如果此电源大于+5V,则须外部另加限流电阻R,保证给驱动器内部光藕提供8—15mA 的驱动电流。( C) v: t" _4 N1 z/ M7 d
共阴极接法:分别将 PUL-,DIR-,EN-连接到控制系统的地端;脉冲输入信号通过PUL+接入,方向信号通过DIR+接入,使能信号通过EN+接入。若需限流电阻,限流电阻R的接法取值与共阳极接法相同。
# Q# O) W7 p- m% \$ R1 U注:EN端可不接,EN有效时电机转子处于自由状态(脱机状态),这时可以手动转动电机转轴。* R3 {* b- l  l! N& Z' p
2.电机绕组连接1 O' i9 {9 x+ `8 Z( p/ r5 o
A+:连接电机绕组A+相。
# v2 W- Q1 I; {) QA-:连接电机绕组A-相。3 g, z) U1 |8 W, B/ J' Z( }
B+:连接电机绕组B+相。0 ]. X' {2 J; C
B-:连接电机绕组B-相。- B( p# ^& d8 M! D+ S$ W

. _, Y7 l* }2 T& }

, ?+ x, y* `0 Z# i  b3.电源电压连接1 h" ]  I* H+ G
VCC:电源正端“+”
/ D# m$ u; W8 V9 `  K9 hGND:电源负端“-”
  j$ o7 S2 c# {; e注意:DC直流范围:9-32V。不可以超过此范围,否则会无法正常工作甚至损坏驱动器.
- @" u4 o! r& g3 @" D% z
! S7 X, F# T8 e5 n4 D: F

- r1 s0 h' h) O4.拨码开关
: \- Q) f- o( ^ 14.png
4 M2 ?3 ]8 v+ U% F1 U2 q/ g电流大小设定- [" i6 g* _) L- S/ [
15.png
5 Z- w$ Z6 q$ l" I1 V* v4 q4 w( i三、STM32F103( T; z( V, ^2 O5 y; R2 R8 J
------说明:引脚部分在文章末尾有解释--------5 X, u* D* d$ E) e+ }, W# x
: o3 m/ S% W7 p% {7 a
/ j& w! O3 _- {8 G' t9 i
1.引脚连接- F: t6 e3 r/ C5 x# b7 J, |2 g
A 0——PUL+' F0 n  V% E) l: ?- q
A 3——KEY1——V3
/ Q1 F- `# |& B( R1 A$ nA12——DIR+
  k- Q7 a/ f2 |4 L: r4 b+ MA11——EAN+
& F  E! p  B' b6 jGND——EAN- ——KEY0
: u9 z* g8 G! Z9 S6 o$ @- O: k. o; _9 W1 k  B5 h0 K* G. u% G

5 A: c! U; s* M! [2.引脚功能
8 L9 @5 Q. ^% K! R+ KA0控制电机转速, F% T( a: p% L+ j: |3 g
A3控制按键0 R; D4 i/ j% [# l$ B: [
A9
$ s- c) O# G8 o) h0 }. uA110 u5 w4 N7 D" K. b) n$ ]5 |
A11控制电机是否为锁死状态
' x$ V& E9 a  q& D. w2 Z$ P/ mA12控制电机正反转9 \9 ]6 P% J# L1 @6 R* d4 C2 ~

  j5 b/ j' u3 ~! r- r6 Z

# ~8 E+ K# h8 S4 m7 r5 j/ N9 b3.定时器9 `% ]% i7 m1 V7 i/ ~4 Z3 K
1.本实验利用定时器TIM2和定时器TIM3构造一个主从定时器,TIM2作为主定时器控制电机的转速,TIM3作为从定时器控制电机的转动角度。0 J& z! R/ \# o  _: P
2.电机的转速和转角还与驱动器自身的细分数有关,但是驱动器细分数是通过影响电机的步距角来影响转速和转角,而TIM2和TIM3是控制步进电机的频率和脉冲数来控制转速转角
* \, r, P: n, @; C3 [3 F5 }+ e- b3.电机的转速和角度与定时器的关系(在不考虑电机自身的细分数下): R" y7 m9 ~( X7 L* U2 D. I; [2 Z5 D, o
! ?# m) o0 C# t* Q0 W

! [7 G& j4 a8 C# ?+ q' ^" \设TIM2的定时周期(即重装值)为nPDTemp2,预分频值为OCPolarity2" H- g/ a# |8 @
 TIM3的定时周期(即重装值)为nPDTemp3,预分频值为OCPolarity3,2 z) Y, q  H9 o$ w0 U/ }
则单片机产生一个脉冲所需要的时间为:
1 z4 |" F1 q6 H  s& Y5 m 23.png
: W( |/ G8 ?& F# k- F: o​       
) N* ~$ q" G; _  x+ l' {  本实验中设TIM2的定时周期nPDTemp2=72000/5000-1,预分频值OCPolarity2=999,TIM3的定时周期nPDTemp3=6399,预分频值OCPolarity3为0。即# Z% x7 p% A  h# e# o. Z
22.png + ]! o4 ?3 K, C4 ^
  定时器共产生nPDTemp3+1=6400个脉冲,电机转过的角度为6400*1.8°=11520°,即电机转了32圈。
2 L% B  [; |# U6 P$ Z  转动速度
$ g. O3 K) B/ c& C7 {' X0 }4 ~/ | 24.png
/ a9 i) c" p/ w6 Y  V  g1 s4 H. A' R* Q  a. _! G% H5 M: i

$ m9 \4 }4 L; V/ d6 z# G4.在32细分的情况下电机1rad/s和转1°需要的重装值为nPDTemp2=11.25,nPDTemp3=17.7778。- d: w: @8 R1 N$ a

: ?2 u( G4 q# V6 ^& G1 g9 s
0 w2 \; ^& v+ v. m/ f+ l) g
四、程序实现
0 ?1 r$ _: E3 e3 L! r  w1.main.c程序
  G* Z8 ~4 |  d0 G
  1. #include "main.h"
    # T5 Q3 n5 V+ ?0 l: W. _; {
  2. #include "sys.h", c) \7 U! g9 b3 g# U) e
  3. #include "usart1.h"
    & `5 s  x3 I6 g8 M) m$ K
  4. #include "delay.h". A. h% C3 ?* v' @4 o
  5. #include "math.h"
    1 W5 A# ]* A. I2 C% @
  6. " A' |! {! G/ m! Q
  7. u16 t;  
    3 ^$ P9 h' a/ K* M8 M1 Z: l
  8. u16 len;                    //接收到的数据长度
    ' N/ A, p; {  I3 X; j
  9. u16 times=0;
    7 a: P) m6 a0 r8 [
  10. char receive_data[60];        //接收到的字符
    3 U$ o( G% q( n+ P2 g
  11. char state;                                //电机正反转标志位0正转,1反转$ r# ?3 Z& Q1 m) W) [# x
  12. int speed,angle;                //旋转速度,角度
    : h6 c, H5 L/ b2 c- _' n8 _
  13. int a=0;                        //判断是否接收到数据6 p. c3 F$ i9 |7 v0 a4 r
  14. int r,data=0;                          //用于数据转换
    , h7 v6 a  n; Z# r0 O6 n& P
  15. int type;                                //转换后的数据   
    1 m% p2 R( P- R% u
  16. extern u16 USART_RX_STA;6 L2 K5 X- m) a

  17. 9 v# N. [$ o" p* C6 Y7 U, g
  18. /**************************# U( O, L/ E! P* j
  19. * 函数名:delay
    8 A% E# v: m* G9 t5 E* Q
  20. * 描述  :延时函数
    ! M" C, t) D" N1 B; |, s6 Z6 v1 D
  21. * 输入  :无
    5 T- q3 X6 Z7 o# s# M3 e
  22. * 输出  :无
    , Y$ e) \! U" c! ?9 B/ x& E; E
  23. * 返回值:无/ t8 h) w( v# S: S
  24. ****************************/$ C5 D, |9 Q& X
  25. void delay()//延时- e7 c/ s/ Q% e+ e. H' o! Y
  26. {
    + t- |" u6 P$ W
  27.          int i,j;
    / ~% \# }" F4 e2 M. A6 v
  28.          for(i=0;i<2000;i++)" e3 W! H9 S+ W# R$ ?/ u) z
  29.          for(j=0;j<1000;j++);- H, G- t9 S4 h6 I) I4 C! m
  30. }; y2 O' \3 J3 \8 J

  31. ! ~1 U$ \4 Z  R0 f( E& I) N/ M
  32. /**************************
    $ y+ q: F; |7 F% }; M9 K
  33. * 函数名:Waiting_receptio
    + {- ~3 m# V) q" \
  34. * 描述  :等待串口接收数据
    9 @3 V1 J, t5 A+ r
  35. * 输入  :无 $ ]& B6 K9 J% n6 L. T$ T5 `5 K% |, l
  36. * 输出  :无
    / B: F1 e* W) p* Z/ P
  37. * 返回值:无
    # g2 L4 m! M' l  S
  38. ****************************/4 d  Q; w0 [' I7 ?7 L/ |: c1 d
  39. void Waiting_reception(void)3 k9 m+ t; M8 s' r8 g2 @9 z
  40. {
    2 u, j3 W; @. k' I# ]
  41.         while(a==0)//等待数据发送完成# j- L$ b' T* r/ k
  42.         {
    : M2 o/ k5 ]# E7 W! ~
  43.                 delay_ms(100);
    1 S9 ]$ l& F" J9 b5 {, i
  44.                 if(a==1)//接收到数据8 B% u5 ^, p9 N( p
  45.                 {% U0 K0 ^: R, @' G
  46.                         if(USART_RX_STA&0x8000)//(串口接收用到了正点原子的例程)
    5 @, y. y5 c& H/ g& N( e
  47.                         {
    ) n. x. C0 z( o4 a4 B  w
  48.                                 len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度  _  \6 ]. v/ `6 n
  49.                                 r=len;                                ! j; h2 P( [/ n- e
  50.                                 type=0;
    ' c; R: ~! t2 j5 @
  51.                                 for(t=0;t<len;t++)//拷贝数据,将字符转换为十进制数9 z# F9 F, v7 M, s
  52.                                 {
    % z# ~( C( a/ J, m8 }
  53.                                         receive_data[t]=USART_RX_BUF[t];; [. e% q$ f' k6 P) N
  54.                                         data=(int)receive_data[t]-48;
    - b/ ~0 l$ ~& N! Q6 I% d
  55.                                         r=r-1;! }5 y! s; c3 r
  56.                                         type=type+data*(pow(10,r));
    / P$ [" a6 a4 Z: K+ l# K
  57.                                 }
      ~5 W, n0 ]: u- O/ C( b
  58.                                 USART_RX_STA=0;
    & D9 Y/ G) U( I3 X
  59.                                 a=0;
    8 c) s2 ?; O$ a( D
  60.                                 delay_ms(500);
      k! P6 c" L! F) R: s2 h  x; O
  61.                                 break;; `9 k/ }1 v# x' W0 q
  62.                         }
    8 g! i& y4 F$ W0 E
  63.                 }
    , |! X" H7 C8 e/ [& R! ?' ]
  64.         }
    , s0 e  @# C( C+ y
  65. }% {) R' U# z1 T, n
  66. /**************************
    ' O- F3 {( f+ i: p4 x' R  R8 u
  67. * 函数名:KeyStates, [4 L7 Q2 s6 V  U
  68. * 描述  :监测按键状态+ f' E% g$ }) n* ?
  69. * 输入  :无
    # _9 c" i% p0 `9 S
  70. * 输出  :无6 N6 l8 T/ f: r! H
  71. * 返回值:0/1- h6 \( r) r  V- h1 g; r
  72. ****************************/
    3 l4 a4 o) @0 d8 w& e
  73. u8 KeyStates()//按键状态3 B0 P, a& m3 K3 U
  74. {2 C9 v! ]0 r4 y
  75.         static u8 i = 0;
    . l0 d$ t8 ]) C( E2 e: h
  76.         if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)( N! B( q9 h" Y
  77.         {
    2 p8 n% s& }2 |1 v
  78.                 delay();' C; x0 v+ j: [9 L5 U
  79.                 if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)
    - Y# |8 @; E4 B, T, S& x1 `
  80.                         while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0);$ X' J0 m+ w; F# S# |" ?# j/ |' S: h
  81.                         i = ~i;, [/ c2 s  _' [( O
  82.         }3 W" _" S! V6 t. J6 ]2 X( P$ C
  83.         return i;& @! R1 q  ~) Z9 m; p1 Z
  84. }& V) A3 _% y) v6 ]
  85. /****************) T7 G5 W: F7 u  s
  86. * 函数名:main2 F  n7 _$ H4 U7 M$ k1 Y- U1 q
  87. * 描述  :主函数7 p2 U; O; [6 j  g2 O
  88. * 输入  :无
      k$ l2 M( j( J$ W. c4 X
  89. * 输出  :无$ p/ g8 g: ~/ M" p% S: }( t$ T
  90. ******************/2 \7 r$ `0 f. M2 G
  91. int main(void)  V+ p  j) i) b' @8 A
  92. {, L, z: _- E) ]% A3 v
  93.         NVIC_Configuration();                        //中断初始化
    0 a- T; P6 M3 N6 ^" a% P" u' X
  94.         GPIO_Config();                                        //IO口初始化: C4 T4 r0 X0 j7 Z5 Q
  95.         USART1_Config();                                //串口初始化1 E8 \: o+ y* D! G$ N4 I
  96.     delay_init();                                   //延时函数初始化        ' y8 T. ?: E$ o- [" m3 D
  97.         GPIO_ResetBits(GPIOA, GPIO_Pin_11);//A11置零  A11——EAN+7 A4 f- M% A4 K1 H5 ?3 W# T) P
  98.         GPIO_ResetBits(GPIOA, GPIO_Pin_12);//A12置零  A12——DIR+7 j; p  C. f6 o7 t" @3 g
  99.         while(1)
    9 S& j2 L, I7 J2 V4 D- p
  100.         {' c# L# N* ?& a# p) o. B+ L
  101.                 delay_ms(100);. e5 s( b) C- s$ M5 G
  102.                 Initial_state:                printf("\r\n 请选择正反转,正转输入0,反转输入1 (以新行作为结束标志)\r\n");       
    # j( E3 v! j7 e$ F$ b8 ~' y
  103.                 Waiting_reception();
    # c, ?3 Q! Q2 b* q( l
  104.                 state=type;//将接收到的数据给type4 ]1 W% y$ D+ ~) a; S
  105.                 if(type==0)//电机正转* C' O% H- u: M0 H7 S; M5 C
  106.                 {
    6 f) N  B9 W( Q& D, G
  107.                         GPIO_SetBits(GPIOA, GPIO_Pin_12);//电机正转  s; @( c& _( t; p: B
  108.                         printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");0 n# I. h9 [( p' G6 ]7 c
  109.                        
    4 c# L) o) K: B. G  W
  110. /*********************************************此模块用于配置速度参数********************************************************/
    ) R& w% m/ Q* ^
  111. & Z: Q5 L! B3 C. x/ {% {$ C' A% z
  112.                         part1:Waiting_reception();% h( S* @) I# H
  113.                         speed =type;//将接收到的数据给speed/ a8 |2 L1 e% s4 _" M
  114.                         if(speed==0)goto Initial_state;//如果是0则返回初始模式
    5 a% Z4 q8 V7 E% M% x
  115.                                 else{+ |  R2 i! b) F
  116.                                         if(speed>=15)
    6 U% x. X- y' [! v+ q* n
  117.                                         {
    ! F. Z; N/ k; m; {* G
  118.                                                 printf("\r\n 旋转速度>15rad/s,请重新选择旋转速度。\r\n");  e. b8 n% ^# H5 ~  T7 {/ i& }
  119.                                                 goto part1;1 i. Y2 D, \7 ]2 C5 d; S4 ?
  120.                                         }
    4 C1 x0 W1 ^5 G& p2 q
  121.                                                 else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式 \r\n",speed);8 n0 U7 n3 D6 x" L+ d5 p) M
  122.                                 }
    . M5 J; }2 t7 p1 q4 J% r  U
  123.        
    4 H4 b) e1 {9 L8 E+ b
  124. /*********************************************此模块用于配置角度参数********************************************************/                ) \$ Y& C/ F9 u; k; l- W3 E

  125. ) E. T/ L4 |2 T6 B) [
  126.                         Waiting_reception();
    1 f7 V9 o. K0 T. H1 z. H2 e
  127.                         angle =type;//将接收到的数据给type
    ' k  s1 q1 L- I9 m8 ?- L3 x  A' i& z
  128.                         for(;;)
    : q+ q4 _1 N5 T* p, X
  129.                         {
    , _4 _: S) j; |, w  C
  130.                                 if(angle>0)//接收到的数据不是06 o1 N" H$ M' i  P, M7 p6 {" G7 J
  131.                                 {
    , f+ }; }9 H- ?' E* o
  132.                                         TIM2_Master__TIM3_Slave_Configuration(speed,angle);        // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度4 N( O+ z9 B; A
  133.                                         delay_ms(20000);//电机保护0 j- H$ F  y# c2 A9 \
  134.                                         printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式; \r\n",angle);# B/ \4 K; X- w: ]+ a$ G7 r' U
  135.                                         angle=0;
    ( K! n4 F0 @. X2 e* Q
  136.                                         Waiting_reception();                & r6 }) w5 b3 ]! u/ X
  137.                                         angle =type;                                       
      ]# t! M- L& N8 M0 y' G
  138.                                 }else{( P# e1 Q4 ~$ l
  139.                                         if(angle==0)goto Initial_state;//返回初始状态        7 n0 T) e7 s/ p' f+ M' _
  140.                                         else {6 w6 w, X+ _7 N! l
  141.                                                 printf("\r\n 角度错误,已返回初始模式 \r\n");                ! `2 M4 j* h, f) h$ R. S& X
  142.                                                 goto Initial_state;8 p: e4 I9 O& k: S) x, X
  143.                                         }                                               
    # b% C, p4 W- y1 j
  144.                                 }
    " ~( P  K) r8 h
  145.                         }+ G( a: u' z* `3 T+ z" t" \
  146.                 }                : H: [2 i7 A# `6 p# R/ C' @9 B
  147. /*********************************************反转模式********************************************************/                . n, |4 T3 s. M) x" D
  148.                 else{2 d  m8 F) h( W* L
  149.                         if(type==1)
    9 D% `/ P% S4 T5 V6 [: |# v5 E
  150.                         {: f* \3 I1 \& R8 x$ d& I+ r3 ^
  151.                                 GPIO_ResetBits(GPIOA, GPIO_Pin_12);//电机反转. s/ }6 G5 _$ e9 [
  152.                                 printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");
    9 Z/ L: m' K0 ]) C8 b
  153.                                 ! r  A9 g9 E7 U+ e( z, e! u7 ~  B
  154. /*********************************************此模块用于配置速度参数********************************************************/
    , \/ K; E0 E# N! x: m2 m! h
  155.                                 part2:                                Waiting_reception();
    - {8 ^7 Z7 ^/ C- H( W4 x
  156.                                 speed =type;//将接收到的数据给speed
    5 E) m$ ]& M. G: u3 x4 e+ b
  157.                                 if(speed==0)goto Initial_state;//如果是0则返回初始模式- S: r1 n$ H/ F6 m
  158.                                         else{  E  r1 I# p" G
  159.                                                 if(speed>=15)& l3 r- }7 a) Z3 U: V( H$ a
  160.                                                 {, M  u# u6 l& F, o  ]6 W
  161.                                                         printf("\r\n旋转速度>15rad/s,请重新选择旋转速度。\r\n");3 u" u1 @0 F! d9 {! i
  162.                                                         goto part2;
    % O( u* T+ h& F5 Z
  163.                                                 }else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式  \r\n",speed);, N) Z: z3 B: h6 i* Q% l
  164.                                         }        ) Z% q! e# H) S1 H4 x1 ?7 j" h+ c/ @
  165. /*********************************************此模块用于配置角度参数********************************************************/                + b7 u$ I9 c9 b. v
  166.                                 Waiting_reception();( V+ C% ?3 O  Z9 A8 N4 n" k
  167.                                 angle =type;//将接收到的数据给type2 R. D" w4 R" Y; ]5 M# J+ E: c" J5 ^
  168.                                 for(;;)
    $ Z" I  }8 v/ p8 {6 H1 b4 r* N
  169.                                 {
    4 p+ G8 T. U# c- ?
  170.                                         if(angle>0)//接收到的数据不是0' E: W- k* r4 u- T" @
  171.                                         {
    , d! Y- L5 x( d5 F  e& F) V
  172.                                                 TIM2_Master__TIM3_Slave_Configuration(speed,angle);        // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度& x# ^1 a. s2 ?. t3 O) H5 p, N3 D
  173.                                                 delay_ms(20000);//电机保护
    5 v. M8 _& c" T  F$ A% s" }
  174.                                                 printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式;\r\n",angle);
    9 {0 F0 e% F# ?. e/ x; ^& G
  175.                                                 angle=0;0 V! c9 ?" O0 b6 d, u
  176.                                                 Waiting_reception();                  g9 E6 ~% U9 J  n' p3 E# _1 A
  177.                                                 angle =type;                                       
    0 q8 f6 f- h. E
  178.                                         }else{4 I. s# }; m* g6 T" H4 j- E
  179.                                                 if(angle==0)goto Initial_state;//返回初始状态        + O+ h% u7 z) M8 L8 P: D
  180.                                                 else {
    ) I9 x2 d9 @0 F& W9 \6 W8 }9 H4 t0 K
  181.                                                         printf("\r\n 角度错误,已返回初始模式 \r\n");               
    ; [7 Z( g, V/ S* ~; S
  182.                                                         goto Initial_state;
    0 y8 c2 S( M) m/ p% f* w, o9 j% i
  183.                                                 }                                                                8 Y7 _2 t: Y& e- u1 g& e& z5 b
  184.                                         }
    2 }, h- ~! s/ m" Z1 ^: o
  185.                                 }  N+ y' ~+ P1 \
  186. /****************************************************************************************************************************/                                       
    , }+ `: W# `, e0 A& g. w# U$ i% T' x
  187.                 }else{//if(a!=0)&(a!=1). a. E# Z* D0 Z! N
  188.                         type=NULL;
    - L/ c* r5 R4 C& L7 j2 _
  189.                         printf("\r\n 输入无效 \r\n");* L5 v1 I7 C7 P6 Q! k
  190.                         goto Initial_state;//返回初始状态. @; D0 @& @) V6 w  c# V& x! H4 g
  191.                         }* V  a8 B* T9 }( m, l0 f
  192.                 }4 X" S1 ^8 e; ^  b
  193.         }
    6 T5 T" a4 ]5 J2 i; S
  194. }' `. K1 Y1 v- Q8 L6 W& U
复制代码
2.main.h程序
/ P* \& b) V; G8 O7 f: h; ^! S6 ]  o7 d# n
  1. #ifndef _MAIN_H& I+ `5 w/ K! J4 g. o- Q
  2. #define        _MAIN_H
    ' A4 M3 K; U. Q
  3. #include <stm32f10x.h>6 T+ E  A0 G4 Q) B+ M9 e
  4. #include <usart1.h>7 G- j8 G* Q0 R* r4 ]4 o1 Z; H+ s
  5. #include <misc.h>' H  b) R4 ^$ C* P  c3 M2 ^* f
  6. #include <nvic.h>
    : `# W! V: t: h" ~" b  k
  7. #include <stdio.h>- A# I9 i( q3 j: ^
  8. #include "stm32f10x_tim.h"
    8 `8 A/ U% u% L$ O& K) u" Y
  9. #include "timer.h"
    / c6 c6 Z% q2 L$ B% O' C" f7 T; D
  10. #endif
    ) W0 s3 S# Z# @/ Y& X* ~2 U% U
复制代码
3.time.c程序2 p1 y# g( C! B+ Q
  1. #include "timer.h"/ m4 R) O6 Y6 F2 @# E/ s6 H
  2. /**************************9 G" j+ H9 i+ ^% A
  3. * 函数名:GPIO_Config3 f3 A: X7 L0 U
  4. * 描述  :无0 k* o2 Z, B+ C* |
  5. * 输入  :无   N. N7 B9 ]8 e2 \" H
  6. * 输出  :无7 k# X, }& C( F
  7. * 调用  :主函数0 }. {2 o: p" a  v; x9 x; Z
  8. * 返回值:无+ T+ p, O  J/ u1 Z" E1 K7 j  V
  9. ****************************/
    % T0 S2 r$ C/ k+ j+ V
  10. void GPIO_Config(void)7 t- `1 v2 W( |& x+ {8 e- `/ K
  11. {
    2 V1 c6 m3 V, ?* g* T* Q! D% E
  12.                 GPIO_InitTypeDef GPIO_InitStructure; * u# u. v5 ?2 ~
  13.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能IOA
    2 S) x3 h" L+ h" K; O* g
  14.                 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE); //使能TIM2,TIM3
    ; v6 C$ L; I% s& d, z# B
  15.                 ; a; i$ p7 g% O6 ?
  16.             /* Timer2 Channel 1, PA0 */ 9 q' o4 @! c$ u. ~
  17.             GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0; . K% T  u( X  \# Z! M3 x+ V- _
  18.             GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用输出
    ; q# E) r7 I$ P" |
  19.             GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 9 E, ]8 q  ~9 N) E
  20.             GPIO_Init(GPIOA, &GPIO_InitStructure);
    - b9 N% }5 z! T
  21.                  
    8 A; Y) ^8 x' l3 v
  22.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_11|GPIO_Pin_12;
    4 M8 H9 ?) l/ S3 L+ k1 m; Y
  23.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式- v0 G& u; T% c' e; s5 G
  24.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ9 K+ W( M% J4 g# a( j( |
  25.                 GPIO_Init(GPIOA, &GPIO_InitStructure);                   //
    2 o1 W% x' Z, C4 |1 y; J3 R4 ^
  26.                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向. C  ?# {1 L( g5 b7 q5 \
  27.                 GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能3 ^- A* |. S: P* I4 G' V
  28.                 GPIO_SetBits(GPIOA, GPIO_Pin_11);//指定引脚输出低电平,此时灯全灭,方向# u; C8 I( m4 ]$ ^4 d3 @
  29.                 GPIO_SetBits(GPIOA, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能# C* A* F+ L' p" R
  30.        
    8 O! S; V# c% g% |# }4 Z
  31.          
      Q# U) ^. u! F) Y' x% e0 {
  32.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;6 m/ x' V$ |* j% I1 f7 p% f
  33.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;         //通用推挽输出模式
    # ~! m6 G) {  j" n+ w$ X- x; X; `
  34.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ( k# J. U4 k; t
  35.                 GPIO_Init(GPIOA, &GPIO_InitStructure);                   //
    ! t8 B- R/ R8 q
  36.                
    / R; m- K9 E3 o7 N& @$ w' c
  37.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    ( n" H6 C& y1 r' L
  38.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    ! L. ?% V' e$ m# Q) r: p8 Y3 ]
  39.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式+ u" k/ j7 U! S/ n2 N$ V
  40.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ4 W& N4 h4 x( c7 c. k6 ~& R& V
  41.                 GPIO_Init(GPIOB, &GPIO_InitStructure);                   //
    ! h. c. C/ `# B; U
  42.                 GPIO_ResetBits(GPIOB, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能
    ; ^/ U( L+ _( i, S4 @' w# h
  43.                
    7 g, Y( V2 q, ?- t* Z* L9 m
  44.                 //GPIO_ResetBits  GPIO_SetBits* W$ s" D7 A( `+ D% u
  45. }
    " o$ @* ~* L; \) E" }
  46. # ^* N, x( b2 G  j$ t% z+ h
  47. //================================================================================. T8 V% w' {! Q- E. K
  48. /**************************4 U1 h  M0 T6 `8 x0 Q2 d: d
  49. * 函数名:TIM2_Master__TIM3_Slave_Configuration" T7 R; K: D; s9 O. r
  50. * 描述  :主从定时器配置
    4 N) P+ q, _: j- h' e/ t/ ]
  51. * 输入  :电机转速speed,转角angle
    * l) n. R  A* K8 |8 D
  52. * 输出  :无
    3 k& [2 i% U: b
  53. * 调用  :主函数& K5 ]( b: i' }. T
  54. * 返回值:无$ f: s3 A! }7 q3 L! v- i+ A
  55. ****************************/* x! e* b2 A* K. Z& _3 p, p1 g
  56. void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency, u32 pulse) 8 R" S; I' e; P8 Z
  57. {+ D" r- Z6 m5 J' A
  58.         TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; " z  p- K( j+ P+ i
  59.         TIM_OCInitTypeDef TIM_OCInitStructure; " i0 }, O+ \0 n; }1 v" _
  60.        
    8 v$ {0 a" @( z7 a
  61.         u16 nPDTemp ;
    8 z5 {/ q9 Z' u: E) q) R
  62.         u16 pulse_number;) d5 _# U5 M2 p5 A$ Z7 m: i
  63.         float p=PulseFrequency;% @5 h+ S  S3 {0 A6 L+ l* N4 X
  64.         TIM_Cmd(TIM2, DISABLE); 2 M9 ]3 [9 U' {  f( N  G
  65.         nPDTemp = (11.25/p);                            //TIM2重装值是11.25时1s转一圈(电机32细分下)
    * o2 M+ F' k! Y% S! e2 E" [  `! }
  66.         pulse_number = (16.7778*pulse);//TIM3重装值是16.7778时转1°(电机32细分下)) [0 }5 h; m3 H
  67.        
    ( p! [2 ^! {' h+ F/ g7 H
  68.         // 时基配置:配置PWM输出定时器——TIM2   O: c) L! J/ L$ X& }7 I
  69.         /* Time base configuration */
    / }, @' ~: O* w; o% ?* B# M
  70.         TIM_TimeBaseStructure.TIM_Period = nPDTemp; //定时周期为nPDTemp& S# O6 v3 X+ o' J, k
  71.         TIM_TimeBaseStructure.TIM_Prescaler = 999; //预分频值1000,即f=72khz
    - G7 I+ p7 \+ G" \# w7 e
  72.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分频因子,会影响滤波器采样频率,与本实验无影响9 |5 E8 d: a% h
  73.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式. ^; y8 h( @2 {6 `6 V
  74.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //指定重复计数器值
    ! V: n8 Q0 O3 Q. g  u
  75.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    ' j; E: G* S' n$ B1 [. ?" p
  76.         . `7 R# T; a  V' _% N
  77.         // 输出配置:配置PWM输出定时器——TIM2 7 H. L" V7 b1 ?) e- J
  78.         /* PWM1 Mode configuration: Channel1 */   
    1 j3 n$ l7 H& D* ?1 l
  79.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM 脉冲宽度调制模式 1
    % Z% `* \1 Z+ |2 ?; v' J( U3 D) w8 E
  80.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平有效4 i1 ^' a- M0 _, w, s# o& X0 U
  81.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出
    % \' e; }5 ^" ?# E8 l! X
  82.         TIM_OCInitStructure.TIM_Pulse = nPDTemp>>1;//50% //比较tim_ccr的值,输出脉冲发生跳变
    # A4 t9 ?# c# i3 G) [0 o
  83.         TIM_OC1Init(TIM2, &TIM_OCInitStructure); //初始化' B! B2 x2 b. J8 j% ^
  84.         TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能 TIMx 在 CCR1 上的预装载寄存器! ~1 ^4 u& G& w) E& ?% n
  85.         TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能 TIMx 在 ARR 上的预装载寄存器, j5 b) E- h7 t$ x' `, \0 j) ?. x
  86.        
    # m( r4 A/ W! x. U) Q
  87.         // 时基配置:配置脉冲计数寄存器——TIM3
    / A; d1 i! Y' N- K- D3 t
  88.         TIM_TimeBaseStructure.TIM_Period = pulse_number;      //0x1900是360°;//改变给电机的脉冲个数                     
    : }! q8 {# J' y  ^: X) ^
  89.         TIM_TimeBaseStructure.TIM_Prescaler = 0; 9 k, ?5 Z3 h- x. x  ^
  90.         TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    * k5 M6 ]2 W2 R* ]9 j% p
  91.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    0 B$ p$ U6 a; m4 {# d  n! V
  92.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    : i" Z; |0 b0 |0 O
  93.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    ' b' C! {  D9 K8 v% X4 \( x7 g& f2 n- Z
  94.         // 输出配置:配置输出比较非主动模式定时器——TIM3% R) t& E: H" w: v' }
  95.         // Output Compare Active Mode configuration: Channel1 : l, z9 U4 _& V, w+ X) j, J
  96.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; //输出比较非主动模式,(匹配时设置输出引脚为无效        电平,当计数值为比较/捕获寄存器值相同时,强制输出为低电平)      
    ; o' g# [7 E0 Q. }" P/ ~2 y) H
  97.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; , l! S4 l, o6 y8 V) k
  98.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    9 T$ J' K% S6 [
  99.         TIM_OCInitStructure.TIM_Pulse = 0xFFFF; // 这里的配置值意义不大   
      u  J" c! f+ H! i' ^) e
  100.         TIM_OC1Init(TIM3, &TIM_OCInitStructure); $ A1 s9 M+ k3 b  ?+ h' e3 G, v

  101. + L& d7 `5 y2 ~9 L4 n! U* t
  102.         // 配置TIM2为主定时器 , v# y& A' ~1 E0 o
  103.         // Select the Master Slave Mode ) t5 X6 Q! g: y: e4 \8 F  h
  104.         TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //设置 TIM2 主/从模式并使能
    0 X: b2 x/ c/ _  o4 K$ p
  105.         // Master Mode selection  8 T2 [+ r2 M8 r2 D. @
  106.         TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); //使用更新事件作为触发输出
    ) B. E: U& q; c# h/ k0 Q
  107.         , W* V* ~0 b9 Y) R( M; \
  108.         // 配置TIM3为从定时器 # }- P& s/ q0 A7 B/ Y
  109.         // Slave Mode selection: TIM3
    $ E, t: X& {3 K  R6 `$ `  c  |
  110.         TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated); //选择 TIM3为从模式   TIM_SlaveMode_Gated-当触发信号(TRGI)为高电平时计数器时钟使能, _# }1 p  h+ O1 `9 s8 H
  111.         TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); //选择 TIM3 输入触发源    TIM_TS_ITR1-TIM 内部触发 1
    % W5 n- Y; J1 F$ j2 X  M
  112.         TIM_ITRxExternalClockConfig(TIM3, TIM_TS_ITR1);//设置 TIM3 内部触发为外部时钟模式   TIM_TS_ITR1-TIM 内部触发 1
    : i1 z, Z" @6 M- U4 X8 z
  113.         TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); //使能TIM3     TIM 捕获/比较 1 中断源          
    7 r6 l# X1 L$ V" a% I
  114.         7 S, e8 V  {/ P' e% c, x
  115.         TIM_Cmd(TIM2, ENABLE);
    2 J( y. g" \: B8 f: ^
  116.         TIM_Cmd(TIM3, ENABLE); ! Z- J8 o; l8 d4 q/ ^
  117. }
    / U7 q0 Z# H7 B3 T

  118. ( G9 x4 n4 a* ^
  119. /****************************************************
    * t2 d& p" E- r3 O2 h2 R
  120. * 函数名:Output_Pulse% ]1 J1 k  B4 y7 v# t; J' z$ W1 }
  121. * 描述  :无) i: ?# a( ^/ J0 K
  122. * 输入  :无
    , L3 V& e. M) {  r
  123. * 输出  :无/ g: d7 E# I0 X# i( b4 b
  124. * 返回值:无
    , c- @( [7 c8 C0 A' |# }
  125. ******************************************************/2 j+ r3 d& [" R+ s% X
  126. void Output_Pulse(u16 Num)5 R% Q& }* @6 u" {& u
  127. {7 p% h  O! z8 v' V
  128.                 GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能' `, `$ G7 N5 H) \; U3 h
  129.                 TIM3->CCR1 = Num;
    , E$ _: d/ h4 \4 z5 }; ]
  130.                 TIM3->CNT = 0;
    " B( @8 \4 l3 u' s8 y& X: d
  131.                 TIM_Cmd(TIM3, ENABLE);
    ' z; d& p/ {+ z2 R( `
  132.                 TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
    3 k/ N" j0 [8 ~& B1 |; V
  133.                 TIM_Cmd(TIM2, ENABLE);
    $ e4 D1 }* c9 u5 `9 s3 ?0 ]
  134. }
    ' z; _' |- I" ]6 k. W
  135. $ a; m" {+ o8 [, l6 n
  136. /****************************************************, E* q5 N* C" T. i7 y
  137. * 函数名:angle_set
    , @3 F; B" P4 I$ j5 m4 v; j. F8 D1 F
  138. * 描述  :无$ M+ v9 V1 S4 G/ H! ~
  139. * 输入  :无 # w  M1 L2 m, |5 T) b3 o- [
  140. * 输出  :无0 n0 \( c6 I6 ]( X+ g! `! i
  141. * 返回值:无
    & I2 p3 @1 e1 Z- s4 G  E1 O1 a: S
  142. ******************************************************/
    , K4 a0 C- R  ?' o3 q3 j+ S
  143. void angle_set(u8 dir,u8 angle)
    9 p9 a+ D7 e2 A: v% c9 h
  144. {
    8 V! J& O7 [! D( H. J  {
  145.         if(dir==0)
    # Z& L6 K% S8 x- H2 [4 V
  146.                                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
    * J/ [, @) \; M/ C# }: |
  147.         else
    - T( h* r" c. V% E- ]4 s1 p
  148.                                 GPIO_SetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向. W: Z) V/ y7 n' W8 ^. v+ X$ j# i
  149.        
    ' \) T& J6 u$ H. c' o- p4 g
  150.         Output_Pulse(angle*6400);% Y0 S' q- K: ]5 ?* e$ T& X# S& E
  151. }
    # T8 ~! u/ H  B4 Y/ [( u; c
复制代码
4.time.h程序4 P- A- l  X* v
  1. #ifndef __TIMER_H* N, C1 {% ?5 W
  2. #define        __TIMER_H: [5 H8 {) H& [* c- u6 H% l
  3. #include "main.h"* h5 W8 B5 t' z0 Y0 a
  4. extern unsigned char Flag;# Y7 e+ b; g5 R' p$ _: Z! y' i6 v
  5. extern unsigned char TIM2_Pulse_TIM3_Counter_OK;
    1 P! r, b' T, o2 c6 D: b5 M$ @
  6. void GPIO_Config(void);; X3 C. ^# f3 l1 }- p
  7. void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency,u32 pulse);
    9 J4 D/ W) h5 O
  8. void Frequence_Setting(u32 PulseFrequency);0 j7 d2 e7 e6 [7 L# ]1 F
  9. void Output_Pulse(u16 Num);
    9 _4 D5 \8 @, s( d) Q' U
  10. void angle_set(u8 dir,u8 angle);
    9 \: T/ C8 @9 ?  ~+ i
  11. #endif
    ) c/ G) ~6 P3 j( g! ^
复制代码
5.usart1.c程序! Z" S& y* D* w- ]
  1. #include <main.h>
    / m) U3 |# e3 E
  2. #include <usart1.h>
    ( s( t9 G" [  U. H" D
  3. #include <string.h>/ \6 C- Q/ f% Q# P
  4. #include <math.h>7 R& \# T7 D7 f2 Q8 F) e

  5. 7 p4 ]2 W" h8 p8 a
  6. /******************************************************
    3 {1 L& C; J3 Q( X4 E, ^. E
  7. * 函数名:USART1_Config* j, c( K: D; d$ ]0 V/ `2 \3 p& u
  8. * 描述  :USART1 GPIO 配置,工作模式配置
    . E2 `: b- R, W( `
  9. * 输入  :无
    - u7 Z) d1 @/ M: @# U
  10. * 输出  : 无. U6 G) Y3 g7 w/ j$ q% g
  11. * 调用  :外部调用+ I% H8 D( ?0 ]9 k! s
  12. ***************************************************** */% ~) M/ i" \5 f' c
  13. void USART1_Config(void)0 X/ w9 w+ ]  C  f
  14. {( {* ^7 y& B" t
  15.         GPIO_InitTypeDef GPIO_InitStructure;
    ' z: r# z% j: [; v1 j0 Q
  16.         USART_InitTypeDef USART_InitStructure;8 P) y4 f7 w8 d8 k
  17.         - I' p# Q4 {0 J5 @; s+ d0 x: e0 N
  18.         /* config USART1 clock */
    , A) X8 G2 {  S! m+ F5 u
  19.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    * ~7 S/ h& w8 [5 o1 R5 _
  20.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    ! T" U, t3 M. J! h: p3 j$ X
  21. % E0 I6 T( j4 `# T( C3 {
  22.         /* USART1 GPIO config */
    1 d" \* F  s9 O+ m6 [' W) D
  23.         /* Configure USART1 Tx (PA.09) as alternate function push-pull */' m/ V1 k" O" A! p6 O
  24.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;7 A5 `& M, @$ y) j5 B
  25.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;5 L1 f7 i( f9 H$ ~+ I& H
  26.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    . Y' h/ K0 D( K/ w
  27.         GPIO_Init(GPIOA, &GPIO_InitStructure);    7 j" C' E( c4 O) g0 ~" Q9 Y
  28.         /* Configure USART1 Rx (PA.10) as input floating */
    7 h& ?8 a: W1 ]
  29.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;3 e& K; `% N8 E. i* D& V* c
  30.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    3 F4 S4 T0 `; m2 c1 Z# j
  31.         GPIO_Init(GPIOA, &GPIO_InitStructure);; h! q$ Y$ D$ U: O
  32.        
    0 o% ], o- \. {
  33.         /* USART1 mode config */
    ! L, Q: s/ y. G, Q( P# F
  34.         USART_InitStructure.USART_BaudRate = 115200;
    ( X; h2 F2 k2 }1 U1 }. s
  35.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    " J# x6 _% Y2 _: a8 d% I3 l
  36.         USART_InitStructure.USART_StopBits = USART_StopBits_1;0 m9 ~6 D2 A; D' @) @
  37.         USART_InitStructure.USART_Parity = USART_Parity_No ;
    % p9 C( }7 A3 `( U! i1 l
  38.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    $ y4 |* L9 b& A
  39.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    9 N1 \) Z! M8 q: f1 F, _
  40.         USART_Init(USART1, &USART_InitStructure);
    4 S; b8 `7 B6 ~4 J+ F4 H9 {
  41.         USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    , p/ s  h. `  M: \# c
  42.        
    : i% F5 k4 g1 I, y: A" L
  43.         USART_Cmd(USART1, ENABLE);) p/ X* V2 o* `" T) [: `' Z3 f
  44. }  n4 D. M7 G8 x
  45. 1 U9 Z& b4 ]( `$ M
  46. /******************************************************
    + M: w( u6 V, K5 X3 C; G! L
  47. * 函数名:fputc
    6 P# F' y6 T% U& K% c
  48. * 描述  :重定向c库函数printf到USART1
    & h& r2 y% V" \9 l
  49. * 输入  :无
    5 R# A& s4 t. P% H7 |5 m
  50. * 输出  :无
    9 a4 ~9 j/ c. B# \% u. h
  51. * 调用  :由printf调用4 E7 E" b1 Z1 m, V0 B7 w
  52. ***************************************************** */& E2 V; [- a7 G: C9 u9 n
  53. int fputc(int ch, FILE *f); H8 N0 J6 e/ y
  54. {2 d3 [5 y; [# h$ ]: N6 A
  55.         /* 将Printf内容发往串口 */5 Y+ B5 D( _& D1 \. c
  56.         USART_SendData(USART1, (unsigned char) ch);& C3 f% A. ^* w; w, l& o2 @
  57.         while (!(USART1->SR & USART_FLAG_TXE));
    . X  c3 r6 [$ R5 m1 R% q6 x
  58.         ; s4 |% S& ^* q& p2 h' T( g! c& d5 p
  59.         return (ch);
    ) v6 t, N/ Y; P
  60. }1 K8 e% ]' |' j+ a9 I' H3 A

  61. 3 i8 H9 F( C( U8 v. _" G1 N# P2 Q
  62. /*-------------------------------------------------------------------------------*/
    ' C$ T! T, ^$ q1 g5 q! I% h
  63. /******************************************************4 _% S( ?0 n( o% L3 g2 Y2 f
  64. * 函数名:USART1_IRQHandler
    + s8 P- q! f' f0 _8 O7 _
  65. * 描述  :USART1中断服务函数
    / J/ h& z, l% z+ e! H
  66. * 输入  :无
    ) ]/ x# D# y$ n( O3 f
  67. * 输出  :无
    * B: u6 H( k5 p; ^; H; V. b; B* B
  68. * 调用  :中断调用# d$ A' f2 z  V; \
  69. ***************************************************** */" ?( V; {6 \. U6 |' `, X
  70. u8 Res;
    / x$ M+ G4 z& n; Y5 e
  71. extern int a;8 K5 Z3 O4 B# z! ~' t, E
  72. u16 USART_RX_STA=0;       //接收状态标记         
    1 n/ r' F7 r4 [# r
  73. u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
    $ f& ?$ H6 X2 Q9 ?% Q4 [- t' i
  74. void USART1_IRQHandler(void)                        //串口1中断服务程序
    , h7 @* p& o) n' o' H% F
  75.         {% p! B9 j* D8 y7 h
  76.                 " H& f  P8 z9 w+ ^$ ^! S
  77.                 Res =USART_ReceiveData(USART1);        //读取接收到的数据+ `" @' K1 R9 P2 ^4 H
  78.                 & |$ ^$ C$ `' N, [3 P5 r, S
  79.                 if((USART_RX_STA&0x8000)==0)//接收未完成8 Y, q* [- x2 q+ I2 [) P5 i
  80.                         {
    ' s5 N/ v" A) u) L8 X& u
  81.                         if(USART_RX_STA&0x4000)//接收到了0x0d; o2 M4 Z, \( F8 p
  82.                                 {
    ( v( E  F; k+ P7 a4 J3 X6 A( f
  83.                                 if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始4 o1 j7 f2 }9 R8 Q
  84.                                 else USART_RX_STA|=0x8000;        //接收完成了
    - [* P& u$ e, N0 l$ C. [" q! e
  85.                                 }* I6 ~+ a: A! n$ Q2 {6 b
  86.                         else //还没收到0X0D
    & f6 L$ c3 S8 F
  87.                                 {       
    . R' m! X' b7 I" u" y1 w
  88.                                 if(Res==0x0d)USART_RX_STA|=0x4000;5 u, ], N6 Q3 V; f+ `5 v4 G
  89.                                 else
    " z: Q) @( |: V' U4 v  u' x
  90.                                         {7 n0 ?: c6 t0 V$ J* J
  91.                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;. A. O3 H: k% d1 z* O
  92.                                         USART_RX_STA++;
    2 V3 S( c$ p' ]' q  u- D
  93.                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收          # Y3 l. Y$ ?6 E& {! M; {
  94.                                         }                 
    8 B6 V/ {, u  R/ ~
  95.                                 }
      D! g6 D# \- @
  96.                         }               
    8 F+ p% O; G. h: W0 g# h* d
  97.                                 a=1;         
    / I, z. \$ ?& w
  98.         } / Z7 z6 A! n2 J# \
  99. #if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.5 g$ |5 Y' O0 D  o
  100.         OSIntExit();                                                                                           
    ; j# N" N7 R- d, c
  101. #endif
    - n: g" I* H$ C2 B- n& _+ d' }

  102.   k* m; v5 h: ]. f' r1 c" m0 V
  103. /******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/
    ' g$ W" |9 z% U. [
复制代码
6.usart1.h程序
7 x+ v& q5 b  C, D+ Y
  1. #ifndef __USART1_H
    6 S9 p5 s& N( d  ^3 ?8 B* d
  2. #define        __USART1_H
    ' D+ A/ f# [2 U/ n* D$ ]1 X2 p  ?
  3. #include <main.h>; J# x! o- ^- z! @( Z& R
  4. #include <stdio.h>0 g+ r" E) ?) w5 r# B$ A) l! S  G

  5. ) J- u, a4 d( _3 C' \
  6. #define USART_REC_LEN                          200          //定义最大接收字节数 200
    % V- L) b* Z4 _4 f/ a. J2 T
  7. #define EN_USART1_RX                         1                //使能(1)/禁止(0)串口1接收0 G" D) G. T' ]; l% U% S0 j/ H
  8. extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 : X) Z- H) F2 v( Y6 z6 S
  9. extern u16 USART_RX_STA;                         //接收状态标记
    : [9 N' _% Y0 ?/ C4 K
  10. int simple_atoi(char *source);0 K/ \' T9 g: X( ?. |$ V
  11. void USART1_Config(void);
    7 ^8 }+ t* k5 d% l
  12. #endif /* __USART1_H */0 T+ k4 I8 U  Q4 u; s, c8 L+ }; Q, A
复制代码
源码:
. u6 r. M3 L1 i0 c6 F8 U 步进电机程序—串口控制速度角度.zip (4.75 MB, 下载次数: 115)
收藏 1 评论0 发布时间:2021-6-25 13:30

举报

0个回答

所属标签

相似分享

官网相关资源

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