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

利用STM32F103精确控制步进电机

[复制链接]
STMCU-管管 发布时间:2021-6-25 13:30
利用STM32F103精确控制步进电机
一、用到的元器件
' J( R  h1 r2 N7 Y3 Y$ Y+ U% KSTM32F103C8T6
* }9 g% B" z& k/ }$ l6 ?" Z42步进电机(42SHDC4040-17B)5 U) x8 m# Z( ~3 A0 v( R
TB6600电机驱动器升级版" |) m* R! O) R7 m" J+ L
6 J* I+ g3 }' o' o( u4 ^

: p% t4 ?$ V/ Q& J% R- U. b" F0 i二、42步进电机1 j" `1 t! C# m* x. M
1.步进电机的基本知识, I) C) j2 A, A' K1 J$ F
(1)拍数——每一次循环所包含的通电状态数(电机转过一个齿距角所需脉冲数)
' Q1 }; |2 ^) J) H* J, l(2)单拍制分配方式——状态数=相数
+ ?, p8 H) j. B  U(3)双拍制分配方式——状态数=相数的两倍# i/ w) l+ j7 b6 B
(4)步距角 ——步进机通过一个电脉冲转子转过的角度2 M7 h# y5 x1 g; V4 K1 r
11.png
N:一个周期的运行拍数5 t! J: k9 x# ~! t4 d
Zr:转子齿数% o5 }& N7 o, I" x$ e( T! x) R( s
拍数:N=km
* Z" F' A+ q( j6 N% am:相数
( }2 k0 ?& t5 \& A2 ]k=1单拍制9 Q0 y  ?2 s+ ^9 R6 F- t: _7 P
k=2双拍制% T( S4 V$ N1 ~" v
(5)转速& a- i/ ~1 T: ]4 M& B* x
12.png
(6)角度细分的原理
% t: \$ n2 P! W# ^' D% ^7 y- B' ~/ V  j3 S
0 |* X$ m* w0 c' B! K5 R3 v
电磁力的大小与绕组通电电流的大小有关。- p' V4 `' }  i3 J- I4 _
当通电相的电流并不马上升到位,而断电相的电流也非立即降为0时,它们所产生的磁场合力,会使转子有一个新的平衡位置,这个新的平衡位置是在原来的步距角范围内。4 h' X: K1 S+ b7 D  K! U
2. 42步进电机参数  W" H1 W5 S' A
无法查找到42SHDC4040-17B型号的详细资料,以通用42步进电机为例:
9 [; d/ ^  f& c4 b1 y  L7 g% Z5 r步距角 1.8°, i$ B& B0 g2 u) y% U' m. M
步距角精度 ±5%  ?! a. z0 w" E7 c
相数 2相/ s( |( l4 h# e8 C% [
励磁方式 混合式, k7 j( P. r) {" X: ?1 ^- W
转子齿数 504 S* d. t, b0 ^5 Y( F$ T3 i
拍制 双拍制, D& _& b5 G: |4 b
其他参数:无4 P9 b) C% ~) C8 y
由步距角=1.8°推算出转子齿数为50,拍制为双拍制
7 i9 s+ Q1 b& J# I$ U. F( c+ K3 B+ w, U+ k6 f# J* l# \

' X- }6 x$ e# c* U7 z( I. l3. 42步进电机速度与角度控制- d. d0 Z9 y4 t, R
电机的转速与脉冲频率成正比,电机转过的角度与脉冲数成正比。所以控制脉冲数和脉冲频率就可以精确调速。1 P9 @7 C3 q" Q, M% |# [& j  ^
理论上步进电机转速 = 频率 * 60 /((360/T)*x)( _2 a# t1 X! _; G' H1 }
21.png
5 }5 @' ~. Y$ W3 L​       
7 Z5 G% o" e, ?, h' x4 D转速单位: 转/ 分) u4 L( f2 j6 v: O
频率单位:赫兹
) T  s( H& e( l" x9 |# z) Jx 细分倍数
' v7 R3 @) h5 \9 G. eT 步距角3 Q* U% ~( a& i; @, X5 u9 ^7 f3 e0 L
例如,在本实验中,32细分;频率72000 赫兹;步距角1.8°;套用公式72000 ∗ 60 ( ( 360 / 1.8 ) ∗ 32 ) = 112.5 \frac{72000*60}{((360/1.8)*32)}=112.5 7 e6 T. E; E. |$ j+ u1 X; y3 j
((360/1.8)∗32)6 l& d/ P8 t9 [( r. f
72000∗60
2 ~& J) d& Y% e* \; D! ?. f​       
8 T6 [- q+ t) ~# g2 m =112.5rad/ min,即1.875 rad/s.( [0 o. O- X3 b4 T" ?" H- @
13.png
三、TB6600电机驱动器升级版参数4 j! Y6 p/ y* p# Q4 ~* I8 g
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 型两相、四相混合式步进电机。
* t& m9 j0 Y1 X4 _# p/ \
, \6 j$ S6 B0 N- P. \, t

% L0 [  U% V: e' P$ k7 I* u1.信号输入端
# q+ M# g0 S  d- s0 yPUL+:脉冲信号输入正。( CP+ )
) _) Y. `- |6 ~7 d9 ^PUL-:脉冲信号输入负。( CP- )8 q8 T4 J# E8 ?# U* r) d3 l
DIR+:电机正、反转控制正。
* G1 D2 }4 w5 a4 W& m6 NDIR-:电机正、反转控制负。* }6 C7 r4 A) X* Q8 r
EN+:电机脱机控制正。
) i7 }0 C, F3 U* v( tEN-:电机脱机控制负。
5 ]% x& N) W; X3 H* ~( u- R+ K9 n3 m% b
# ~8 L0 e# i) x" ~5 o1 y/ t
共阳极接法:分别将PUL+,DIR+,EN+连接到控制系统的电源上, 如果此电源是+5V则可直接接入,如果此电源大于+5V,则须外部另加限流电阻R,保证给驱动器内部光藕提供8—15mA 的驱动电流。
7 ~, u- R* O6 m! i. u+ [9 S" J3 V共阴极接法:分别将 PUL-,DIR-,EN-连接到控制系统的地端;脉冲输入信号通过PUL+接入,方向信号通过DIR+接入,使能信号通过EN+接入。若需限流电阻,限流电阻R的接法取值与共阳极接法相同。
1 ?6 B8 N/ z; c- K+ j注:EN端可不接,EN有效时电机转子处于自由状态(脱机状态),这时可以手动转动电机转轴。
; _. W$ Z7 M% ]( f2.电机绕组连接, ^0 }, \: q- b8 ~" d/ y* R
A+:连接电机绕组A+相。. C1 ]" I# z" _5 T
A-:连接电机绕组A-相。
5 o/ Q. `( [4 w8 v' ?+ lB+:连接电机绕组B+相。: s* K$ n. i. k' X
B-:连接电机绕组B-相。
- s. n% n& p7 M3 _* t6 l: i5 ]
* a6 \4 k% ~( x, A

: U; F  e1 A! P- e+ K" f1 h9 \3.电源电压连接* q' [" u" _6 n- }( b
VCC:电源正端“+”( D5 `, F) Z* ]# E1 y9 r
GND:电源负端“-”
5 ~; L3 b/ I8 {# D注意:DC直流范围:9-32V。不可以超过此范围,否则会无法正常工作甚至损坏驱动器.
: p9 t, M: {3 ^" [9 F6 i- [1 s3 K' a4 K. r" G% ?& v1 K

* C3 S5 }! r! s1 U) U1 n' t4.拨码开关
8 x2 d0 j; f. V; v! b 14.png 0 a$ J. S7 J/ I5 h! x  p& Z
电流大小设定4 L0 X+ Z( L6 R3 ^+ R
15.png * Q, ?! O) k- E; f9 X# o
三、STM32F103
6 D" l) _( y+ P, }- |' W2 Y& B------说明:引脚部分在文章末尾有解释--------5 Y8 y  R% C( I) n, L! W1 V5 w; J
/ G' [/ a& Z3 D
. i( e) F0 X+ `& j" K) J
1.引脚连接5 p, R+ z9 T% U! w- K
A 0——PUL+
: ]5 q' W# q' w2 g3 ]8 [# G/ N3 nA 3——KEY1——V3. e4 Y, p7 u; m3 n
A12——DIR+" w2 ?. d; w9 E" c% B9 n9 A
A11——EAN+
2 K) h$ |) L, B$ q  K, A* N; ZGND——EAN- ——KEY0
+ K. E. a/ h- T4 y8 S
8 v$ m' x( U4 y. R, B  U7 l

6 v9 s0 H& x7 {; Q5 k' R; N. S9 {2.引脚功能
3 D( K  x* l9 u* P# aA0控制电机转速
( T* L4 b  J) `) W6 \- QA3控制按键
8 Q2 J6 D  j8 w2 `A9
9 i8 d8 L4 k% g1 w$ v; V' V' `A11
% O6 [1 |& H& @9 h/ b* t0 K: t7 DA11控制电机是否为锁死状态* {+ O  n% q8 s% g4 C, z
A12控制电机正反转
4 z/ a0 c# g1 p/ `
% i- Z. Z# L7 i5 A4 w  f

( T6 w6 \' ?/ I3.定时器/ J* a1 d+ l  x: `+ N. [, l# c- ?) h
1.本实验利用定时器TIM2和定时器TIM3构造一个主从定时器,TIM2作为主定时器控制电机的转速,TIM3作为从定时器控制电机的转动角度。% B( p  ^4 _, Z" D8 B! O
2.电机的转速和转角还与驱动器自身的细分数有关,但是驱动器细分数是通过影响电机的步距角来影响转速和转角,而TIM2和TIM3是控制步进电机的频率和脉冲数来控制转速转角
. X: \9 r& K) o8 [- p% j3.电机的转速和角度与定时器的关系(在不考虑电机自身的细分数下)
5 l* n6 T7 ~1 y0 x: x4 o9 }! |7 E* f- F5 r, `- j+ O3 |; z% p

) d: U% e0 k6 c' @设TIM2的定时周期(即重装值)为nPDTemp2,预分频值为OCPolarity2
2 {* t3 D, L8 D7 t  s TIM3的定时周期(即重装值)为nPDTemp3,预分频值为OCPolarity3,
+ T1 I. W4 H9 _3 s: f则单片机产生一个脉冲所需要的时间为:
4 ?; R( x% J  P( b; @ 23.png
# b! Y& [* n( f; o% @# E" ^4 \  {+ n​       
5 Y$ u" \  B( `6 _  本实验中设TIM2的定时周期nPDTemp2=72000/5000-1,预分频值OCPolarity2=999,TIM3的定时周期nPDTemp3=6399,预分频值OCPolarity3为0。即
3 e$ F" ^" s" F. z3 a$ U, Y 22.png . c4 U/ b- g0 m- p2 q9 ?
  定时器共产生nPDTemp3+1=6400个脉冲,电机转过的角度为6400*1.8°=11520°,即电机转了32圈。  \: l+ z! S( |6 u
  转动速度. h% ?/ I8 o8 y* K% x8 p
24.png , T0 y% I; q- ~  N+ S& [6 G
( }$ W+ z& M) P
+ [) Z) r2 i  _7 M- x
4.在32细分的情况下电机1rad/s和转1°需要的重装值为nPDTemp2=11.25,nPDTemp3=17.7778。! I5 C; V+ q3 b1 q. p

  F3 w+ `4 m, i" e9 R2 b4 z; c; [
6 l: y- ]7 o5 q; i* b' Z" X% W# o
四、程序实现% V$ c2 h3 Y6 s$ Q
1.main.c程序
3 N& m3 F( P5 z& r: m
  1. #include "main.h"
    * y/ M9 O- E$ O) E9 R, b
  2. #include "sys.h"" U3 `2 f0 X. N: u  v9 {  c
  3. #include "usart1.h"
    ' }. a) r. r9 a: q; g: {/ b5 B
  4. #include "delay.h"0 ]' I0 ?. k; I
  5. #include "math.h"9 H8 P! Y) i; g6 W0 V" @9 X9 F

  6. & J" p2 ?! t  H" l8 Y' \7 [+ c# Q
  7. u16 t;  
    $ x# j+ n8 V! _* z6 m
  8. u16 len;                    //接收到的数据长度8 L6 v2 r( t& D% B9 t/ \' y3 F) Z
  9. u16 times=0;' |6 f" ]! q8 G+ d
  10. char receive_data[60];        //接收到的字符 3 d9 O. m3 n; m# d: m7 w# V; [3 R
  11. char state;                                //电机正反转标志位0正转,1反转% f/ M9 J. D% R- }" o- `# `
  12. int speed,angle;                //旋转速度,角度
    * ~: e2 k$ x8 ?. F; F  E8 g
  13. int a=0;                        //判断是否接收到数据) `3 e$ e! `. f% g
  14. int r,data=0;                          //用于数据转换
    2 T' g+ B, M6 @( V
  15. int type;                                //转换后的数据   
    4 H, }; r8 a( R
  16. extern u16 USART_RX_STA;6 p5 C' D; E8 C/ r( t
  17. 4 T) x# o; w4 ?; ?! ]0 R* R
  18. /**************************
    0 T) {3 y* Y  l- a# d! n6 V
  19. * 函数名:delay
    ( x  ^' M) C) E+ L2 ~4 F
  20. * 描述  :延时函数0 f) X1 z3 o* [: [" D; g6 |7 K
  21. * 输入  :无
      K2 d3 i7 o4 y1 f0 Q' F  V. K$ u' E! r
  22. * 输出  :无
    - s9 n/ A5 w; g8 X- d" V' R
  23. * 返回值:无
    ) R9 R1 K2 e8 b/ T
  24. ****************************/- K* @2 [% n( A) C- @) J
  25. void delay()//延时1 v: t: j; [) K" K, t
  26. {
    . }( I- F, ]) v$ g
  27.          int i,j;1 ~6 B  R6 y6 A5 U1 r5 T4 x
  28.          for(i=0;i<2000;i++)
    3 @9 m1 G) j& a5 K0 J
  29.          for(j=0;j<1000;j++);( B: s, Z; k& [$ h! V. a3 y- c8 T
  30. }
    5 V- o- I. Q: h- }" Z

  31. , I/ t  _# D1 R" V' G) h  N' d7 N& V
  32. /**************************
    6 |% Q6 H" g( E' z
  33. * 函数名:Waiting_receptio! W) n, y8 ]/ [9 O6 K* J# H
  34. * 描述  :等待串口接收数据
    & `+ A* Z: E) Q" F! Q$ Z
  35. * 输入  :无 , k! ~9 D, e+ E4 S& u& w
  36. * 输出  :无
    % L$ U" a+ w0 l* X: }( F5 j
  37. * 返回值:无
    & e; }3 I5 O1 T5 Z( t
  38. ****************************/) C7 M  }6 S/ T  `3 {: h
  39. void Waiting_reception(void)
    7 X7 M) f7 c" m
  40. {
    0 @* }; S  ?- F( I2 M
  41.         while(a==0)//等待数据发送完成( r1 g: F' c, R! k3 V; y
  42.         {
      P, I8 m- G: A& r" r+ k
  43.                 delay_ms(100);4 ?, k, f1 k6 G( c; U
  44.                 if(a==1)//接收到数据
    1 t1 a" `7 H8 d: B$ I; H0 o
  45.                 {, c$ d6 t; D' e5 D* w8 U
  46.                         if(USART_RX_STA&0x8000)//(串口接收用到了正点原子的例程)& {" M6 j* A) F8 ]+ G; x
  47.                         {6 J8 G) ~7 B, u# y+ I& u0 w9 \' j
  48.                                 len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度+ V/ v# M% m* k( W
  49.                                 r=len;                                : _# p% B$ X) b8 |9 i
  50.                                 type=0;
    . h6 v* W/ |3 a% X
  51.                                 for(t=0;t<len;t++)//拷贝数据,将字符转换为十进制数8 f# T( F6 e* P) W2 R' i+ o( ^
  52.                                 {7 Q! ^( [9 o8 I6 W
  53.                                         receive_data[t]=USART_RX_BUF[t];
    $ r. S% W* v9 O  t
  54.                                         data=(int)receive_data[t]-48;
    ( G# L; v- Y' h, V2 L' n
  55.                                         r=r-1;1 z3 z/ Y: c. U, e
  56.                                         type=type+data*(pow(10,r));. D' S& _; [& w* O5 v
  57.                                 }6 \: g& s# K- Q" c# x. t. W6 N" C% g
  58.                                 USART_RX_STA=0;
    & l5 Z7 d5 L+ i7 k7 Q) d
  59.                                 a=0;
    # q0 w( m5 J" i) l: E( D7 ?
  60.                                 delay_ms(500);
    4 D" m  c" s6 ]$ F! c% q  Y6 F% `
  61.                                 break;. \' K3 _" m0 k+ N
  62.                         }$ `4 N! _! h. Q) ]* z* a
  63.                 }' n3 l& i9 P$ z2 ^' t
  64.         }
    - y' ^" p5 H) X( B
  65. }: W5 ]+ H5 ]- }: \
  66. /**************************) h# r$ k* [/ r+ A
  67. * 函数名:KeyStates8 J# k0 y( d$ r8 |6 R3 [
  68. * 描述  :监测按键状态3 U/ c' A0 Q# s8 ?# c! W
  69. * 输入  :无 8 a, D% I2 y# \7 s" O
  70. * 输出  :无* S. @  n2 [- h& z4 \; W) b
  71. * 返回值:0/1
    5 c( N" a' M- J5 P4 j' B
  72. ****************************/  ~% C3 \! [. C5 g+ w
  73. u8 KeyStates()//按键状态
    4 d% y. e. `' R
  74. {
    7 q# V' t1 X; P
  75.         static u8 i = 0;
    8 m( T) A9 n8 W  P+ p
  76.         if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)
    & i1 L' e3 `7 x7 _4 ]
  77.         {
    % G6 l! I7 z  n6 ^9 }% k4 A
  78.                 delay();
    * O! ]5 r$ ?0 l2 j* u" b! {& {
  79.                 if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)0 [; Y9 ^* ]7 u& B2 k9 q1 [
  80.                         while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0);
    5 G0 j7 C' c& @2 ]& Y6 k: H
  81.                         i = ~i;$ c- {" b/ u% _/ r" ^
  82.         }8 a4 K( F9 J! ^
  83.         return i;! d* m5 B# [1 |! m( m
  84. }
    8 c9 T7 F, R: u& w) S& g
  85. /****************
    % b: f/ x  m, M* l( f0 C
  86. * 函数名:main
    ; O; @" F* ]2 p! `
  87. * 描述  :主函数# w& ~- r: q  d; P
  88. * 输入  :无 3 o; m& G2 S0 t5 q  t6 R
  89. * 输出  :无
    4 @" w! ~( z% X4 r
  90. ******************/4 l9 c% c0 E1 |' t7 b
  91. int main(void)% n/ r3 D, D& M+ c, g# p; X( l, n: y4 M
  92. {& g  R* W: ~" s5 A2 \
  93.         NVIC_Configuration();                        //中断初始化% o7 }$ r0 K& u% U2 A
  94.         GPIO_Config();                                        //IO口初始化3 G5 `( u9 i' {3 n/ i, Q# J4 X
  95.         USART1_Config();                                //串口初始化7 y9 O$ p( l/ w( x9 {, ?1 p9 @
  96.     delay_init();                                   //延时函数初始化        ; p1 m& ?! U% R" W& ]" ]8 @6 `8 u
  97.         GPIO_ResetBits(GPIOA, GPIO_Pin_11);//A11置零  A11——EAN+, |5 V7 P( c, T& o3 O
  98.         GPIO_ResetBits(GPIOA, GPIO_Pin_12);//A12置零  A12——DIR+
    1 I' i! v6 J4 e6 N# B% k
  99.         while(1)# m( r4 O5 i; I0 }. k
  100.         {  F) k# h/ |3 m6 @9 m2 A; I
  101.                 delay_ms(100);6 y) d4 y8 f* L, \/ g/ T
  102.                 Initial_state:                printf("\r\n 请选择正反转,正转输入0,反转输入1 (以新行作为结束标志)\r\n");       
    2 Q- F) n5 a1 Y  l0 N* W% I
  103.                 Waiting_reception();
    " n* Y& t! Z; c1 t+ R
  104.                 state=type;//将接收到的数据给type
    ' F% [% b, I5 A, r
  105.                 if(type==0)//电机正转5 D" I) t" c9 {  D0 t' n# j
  106.                 {
    . Z  f/ C" e3 F* |7 ?  a
  107.                         GPIO_SetBits(GPIOA, GPIO_Pin_12);//电机正转
    . `$ {; p1 O, g5 G
  108.                         printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");
    , J) c3 {/ v$ `3 D: B: N  z
  109.                        
    / m) c" X/ a: ^3 u# _3 P5 Q
  110. /*********************************************此模块用于配置速度参数********************************************************/0 ?8 L+ u* q7 E. u5 l

  111. & `) J7 u) p2 F- r) j& D
  112.                         part1:Waiting_reception();
    - Q' L% W9 E4 ^5 U7 s1 R. P
  113.                         speed =type;//将接收到的数据给speed; u* J/ j0 q+ p- s9 K6 D
  114.                         if(speed==0)goto Initial_state;//如果是0则返回初始模式
    7 y  `# t3 q: H# e! j5 p9 q$ G6 `7 |! u
  115.                                 else{4 {- ?5 O( G/ d6 p  }
  116.                                         if(speed>=15)# J+ t. W. D. A. @
  117.                                         {
    ; V5 ^  C2 n0 n# p+ u( t
  118.                                                 printf("\r\n 旋转速度>15rad/s,请重新选择旋转速度。\r\n");
    5 q- c" m1 C, o8 W* G1 }
  119.                                                 goto part1;
    1 b0 D, R, D$ c8 A) h: q2 B
  120.                                         }6 c4 g& d! W$ a' x
  121.                                                 else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式 \r\n",speed);% K. y4 v9 M' `" k8 J- H% j
  122.                                 }
    5 l6 F, I$ {) S+ c" V& u
  123.         5 B9 s0 x- Z2 D: z& i( [
  124. /*********************************************此模块用于配置角度参数********************************************************/               
    . n/ o5 L% x( K! ]) A9 P
  125. & l9 G1 f( J4 T
  126.                         Waiting_reception();
      r2 L( s( x) B2 O0 e8 \
  127.                         angle =type;//将接收到的数据给type
      B( R; [3 z6 r% g$ S
  128.                         for(;;)
    / }# W! b8 g4 n$ V- G( ~9 f, O. r
  129.                         {
    * y0 b- X8 ]  `0 X2 _
  130.                                 if(angle>0)//接收到的数据不是0
    ; d; K! v$ W& M: i7 z3 i2 Q& W
  131.                                 {! Q+ G. F* y6 Y7 \" w9 V
  132.                                         TIM2_Master__TIM3_Slave_Configuration(speed,angle);        // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度$ E: K& e$ E* l' p
  133.                                         delay_ms(20000);//电机保护/ [$ v4 \/ c5 Y. [" E4 h
  134.                                         printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式; \r\n",angle);
    3 {. S' M& F! f" ^8 q+ W: O
  135.                                         angle=0;
    % T2 ]. C# H. f# n8 c
  136.                                         Waiting_reception();               
    8 S: O- r% V' |6 J. M
  137.                                         angle =type;                                       
    6 j6 W1 K/ n8 @1 L- e  E* n2 _5 [
  138.                                 }else{+ A  W( X. H) I
  139.                                         if(angle==0)goto Initial_state;//返回初始状态       
    $ J2 t7 y) i2 p6 a" m
  140.                                         else {
    - u, e' U8 M$ U- [5 q& Y
  141.                                                 printf("\r\n 角度错误,已返回初始模式 \r\n");                : w. p0 z7 K* {
  142.                                                 goto Initial_state;
    : B# C* F9 h! r: e
  143.                                         }                                               
      }3 t; H1 B, Q% a' T" J
  144.                                 }
    & L0 ^  p) l  L# i
  145.                         }
    1 I2 t3 y* `. ]! M+ Q' z
  146.                 }                ! u/ j% }; J- K
  147. /*********************************************反转模式********************************************************/                9 z- \/ j( Z0 g* h1 k9 q
  148.                 else{
    0 [- F- I; ]2 R
  149.                         if(type==1)
    9 O, m' C. c/ P
  150.                         {
    . U6 q' ~7 q: f0 k; D6 A* v
  151.                                 GPIO_ResetBits(GPIOA, GPIO_Pin_12);//电机反转
    ) b8 v* I9 q8 {- v$ ~
  152.                                 printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");! |# o$ K; p# f# x, H* o
  153.                                
    0 A/ I. P  ~% l! U  h; Q2 L% O* `9 S/ S
  154. /*********************************************此模块用于配置速度参数********************************************************/+ k/ o* u$ R2 Z; ^
  155.                                 part2:                                Waiting_reception();
    5 c' u  X# q+ v, k8 I
  156.                                 speed =type;//将接收到的数据给speed
    4 A9 K1 ^: o$ i- F" u1 W
  157.                                 if(speed==0)goto Initial_state;//如果是0则返回初始模式2 p. z0 b! x; @2 P
  158.                                         else{$ [0 _8 g9 I3 ]4 O5 y! w- m
  159.                                                 if(speed>=15)8 [: B! ]2 V, u
  160.                                                 {9 l8 @# W" w- h
  161.                                                         printf("\r\n旋转速度>15rad/s,请重新选择旋转速度。\r\n");
    0 {. a& I* A- ^8 j/ r
  162.                                                         goto part2;- p5 _2 s* I: ?" T
  163.                                                 }else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式  \r\n",speed);
    6 k1 k1 \3 j& K6 I6 i3 b8 ^$ S
  164.                                         }        3 R; W- r7 _! W7 e. G
  165. /*********************************************此模块用于配置角度参数********************************************************/                " ?5 F! ~( V0 c; y: c
  166.                                 Waiting_reception();
    * x9 g# v; U5 s( ]7 W8 @! m$ o
  167.                                 angle =type;//将接收到的数据给type
    . E2 \& o8 k2 Y1 p
  168.                                 for(;;): z  e+ y2 M0 S8 V& }' g; j
  169.                                 {
    7 K+ f: P: l6 P
  170.                                         if(angle>0)//接收到的数据不是0: P6 f# K  l& e7 _
  171.                                         {7 o9 \* Q( a8 X% m3 G+ k
  172.                                                 TIM2_Master__TIM3_Slave_Configuration(speed,angle);        // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度( T8 ~) D2 d  M! T  V* N
  173.                                                 delay_ms(20000);//电机保护8 V4 O7 s- e# L7 S- P  l
  174.                                                 printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式;\r\n",angle);
    / D- ?3 _5 z3 Z/ ~
  175.                                                 angle=0;
    / a- e( \( A3 B, E$ g/ X
  176.                                                 Waiting_reception();                  F) k. T3 z0 B( O& B
  177.                                                 angle =type;                                        - v( E% K% M& V
  178.                                         }else{9 o. K- t3 E8 H. q: E
  179.                                                 if(angle==0)goto Initial_state;//返回初始状态        7 `/ C, z! ]& \) H
  180.                                                 else {" A+ R+ v- p' U9 m$ [8 s
  181.                                                         printf("\r\n 角度错误,已返回初始模式 \r\n");                ' n7 W0 G5 N5 Y  c9 z
  182.                                                         goto Initial_state;- N5 B5 _5 h) S& Q5 D$ k
  183.                                                 }                                                                / N6 ?6 G7 S6 z0 V, W, v$ i# i
  184.                                         }( w/ m" ~% F' M; q
  185.                                 }
    + F7 q, X  X9 k
  186. /****************************************************************************************************************************/                                        6 i  y1 X. p- d- [8 z6 J
  187.                 }else{//if(a!=0)&(a!=1)2 C" t. R3 Y. d9 [, W& e, G) y
  188.                         type=NULL;
    4 Q+ x& j' D* u% J; z4 E$ D* U7 v; t
  189.                         printf("\r\n 输入无效 \r\n");
    4 n& E1 E( K2 x* U$ C3 z, v! a( g
  190.                         goto Initial_state;//返回初始状态- |+ q% S7 \1 I7 G1 {
  191.                         }
    2 Z  _9 [. Y, b/ n- v
  192.                 }
    # R& y* d1 |- @
  193.         }- S% p- z6 D, y* w
  194. }3 c: B* N; V5 e8 J1 Z
复制代码
2.main.h程序
- l" q0 ]( F  V$ w1 n$ F
  1. #ifndef _MAIN_H; j: A% n5 I% N" P( x, U- J1 I
  2. #define        _MAIN_H- J% n; x- k% r3 h3 Q7 F& o1 s- C7 J3 B
  3. #include <stm32f10x.h>2 K4 a% @0 r( a2 J
  4. #include <usart1.h>
    / c  n( H, e1 v* B- M. H
  5. #include <misc.h>
    * i, J8 `7 R7 X# {1 b
  6. #include <nvic.h>
    6 S) R  ~6 o7 N- T
  7. #include <stdio.h>$ M! y  K* ~4 s: o  C
  8. #include "stm32f10x_tim.h"
    5 ^) @& L+ i6 g5 P% h
  9. #include "timer.h"8 r, y( x; T6 \2 \
  10. #endif
    + ]* v+ k/ W: i+ D8 n
复制代码
3.time.c程序; T; Y1 F5 R% O$ x# j) k  [' g
  1. #include "timer.h"3 x4 x  j) V+ ]: W! E, q
  2. /**************************( Q# T- ?% O& I1 O# l7 b
  3. * 函数名:GPIO_Config* O+ G! v) h1 S/ d. w/ A0 k. G8 \
  4. * 描述  :无% L6 o. L) j9 D1 I4 ~) O2 N* J6 i
  5. * 输入  :无 6 f& a" P) D# y
  6. * 输出  :无9 |. D; f* W/ G" H7 f3 U- _- W
  7. * 调用  :主函数
    & \, Z8 s$ w/ `8 G; r  V* h
  8. * 返回值:无( s" ?. R% f! Z- [# ~
  9. ****************************/
    3 S3 q# Z2 I# V
  10. void GPIO_Config(void)
    ( X; C) z& v( P
  11. {
      Q( i5 T! `3 y7 I0 }$ b
  12.                 GPIO_InitTypeDef GPIO_InitStructure;
    " N% g9 `9 x* Q0 x" @, y* N
  13.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能IOA& Z3 Y1 k1 l7 e% R
  14.                 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE); //使能TIM2,TIM3
    5 j. N+ j* E* {% [
  15.                 9 {) d/ n: O4 d
  16.             /* Timer2 Channel 1, PA0 */ + K" L" n" p7 x- ^
  17.             GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0; $ f1 B1 W: S) w2 V
  18.             GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用输出
    ) U6 F! w' w3 h) d* Y
  19.             GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ' x$ c. ~: z% P$ C- B! S( D0 U
  20.             GPIO_Init(GPIOA, &GPIO_InitStructure);
    " E. G& Y, Y6 d5 F( b0 ~& E0 {& h
  21.                  , i  W- I: ~& v: ]
  22.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_11|GPIO_Pin_12;! Q, I5 c0 x( J, l% N/ t/ E
  23.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式
    9 \, b' m" ?6 ]3 a5 D6 M
  24.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ. H- P$ H9 n' d$ A& [1 h0 |
  25.                 GPIO_Init(GPIOA, &GPIO_InitStructure);                   //+ Q9 B/ s! o1 W
  26.                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向# Q& G1 R. n0 E* m; R, T
  27.                 GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能
    8 g: n1 O4 a$ M0 W5 v) P
  28.                 GPIO_SetBits(GPIOA, GPIO_Pin_11);//指定引脚输出低电平,此时灯全灭,方向
    # m8 k9 Q1 A, m1 E1 v/ R/ z' n
  29.                 GPIO_SetBits(GPIOA, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能
    4 z# I* Q# B) y4 _, D( y
  30.        
    ; ]2 Q; G0 U2 Y( R# r5 E3 P. ^* Z
  31.          - W" ?) `! E9 m$ J
  32.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;2 z  }6 S3 l7 n% ]# c" G2 M+ [# x
  33.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;         //通用推挽输出模式' z" ^, y& f  O9 ~1 f
  34.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ1 Q  {; q: e) ]$ D4 `3 u* k" q
  35.                 GPIO_Init(GPIOA, &GPIO_InitStructure);                   //0 D" w- d: O& M* A% P3 e/ a
  36.                
    5 p; H0 |! T* @. m+ n# @7 W
  37.                 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); , M9 p' z! F, Z. z; F
  38.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;9 p3 q! z( i1 i! R, N2 O, P% W# w
  39.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         //通用推挽输出模式
    ' j' Z& a  g, C0 E* H, P
  40.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //指定GPIO引脚可输出的最高频率为50MHZ2 g; y- k' F7 v# W
  41.                 GPIO_Init(GPIOB, &GPIO_InitStructure);                   //
    6 G3 H9 u8 N' `4 R
  42.                 GPIO_ResetBits(GPIOB, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭        使能  o/ s. f# g. }& }) o( x9 J
  43.                
    . B4 ~7 {) l, f& e* H/ m0 r# M1 |0 U
  44.                 //GPIO_ResetBits  GPIO_SetBits% }* s' t: M2 I  S) |
  45. }
    7 G$ a  [2 _- N" Z6 o2 M

  46. ; U7 \$ V0 A$ ?, b9 m
  47. //================================================================================) D: k" t/ h9 v+ h/ P/ T& x- u: I
  48. /**************************
    7 X9 a1 F4 X; g2 J$ }/ e
  49. * 函数名:TIM2_Master__TIM3_Slave_Configuration$ N- l: i+ s  d( G# Z6 M
  50. * 描述  :主从定时器配置( n2 |- s5 {5 R; s8 M0 D
  51. * 输入  :电机转速speed,转角angle
      F1 F4 q! l' U! G; a0 x5 \; D$ U
  52. * 输出  :无/ P5 v2 w4 C( ^8 m& y
  53. * 调用  :主函数
    , o/ f: q8 j0 J* h5 c6 s5 M
  54. * 返回值:无/ J* x: \% c8 {/ V3 h  {
  55. ****************************/
    ' K! d1 |& o$ I
  56. void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency, u32 pulse) # H  D5 j! p7 j( q) U
  57. {$ ]) E% R7 o9 }+ r
  58.         TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    # U- Q0 v$ f+ u
  59.         TIM_OCInitTypeDef TIM_OCInitStructure; 7 t# O- p- @7 {- v0 G
  60.        
    ' r; p1 c, _% m
  61.         u16 nPDTemp ; ! q! D3 ?7 C) x5 a! D1 A
  62.         u16 pulse_number;
    4 j0 c8 X( R1 K5 D
  63.         float p=PulseFrequency;; e& q2 i$ q3 N7 a0 q6 ~: p
  64.         TIM_Cmd(TIM2, DISABLE); 1 Z/ i" e* P6 \5 r
  65.         nPDTemp = (11.25/p);                            //TIM2重装值是11.25时1s转一圈(电机32细分下)' C! S( U; _5 a; R
  66.         pulse_number = (16.7778*pulse);//TIM3重装值是16.7778时转1°(电机32细分下)% a4 h2 S/ i9 _
  67.         : K+ V* F" D* {; x
  68.         // 时基配置:配置PWM输出定时器——TIM2
      K; f  U5 R; M; v9 z
  69.         /* Time base configuration */
    7 M- `' G4 }) s5 T+ G1 _
  70.         TIM_TimeBaseStructure.TIM_Period = nPDTemp; //定时周期为nPDTemp- ~2 x* e3 Y, ?  l
  71.         TIM_TimeBaseStructure.TIM_Prescaler = 999; //预分频值1000,即f=72khz
    8 [; I3 G6 |0 H% |
  72.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分频因子,会影响滤波器采样频率,与本实验无影响7 p$ Z3 n9 W( [# {9 B& F' c3 N7 ?
  73.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
    " {  Y- [8 ?- A! V
  74.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //指定重复计数器值/ T: V# U) Z* D$ a
  75.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    8 d* T0 O4 O  B- \( {/ z9 ~" U
  76.        
    + l1 w( l: \2 K1 f/ B
  77.         // 输出配置:配置PWM输出定时器——TIM2 7 w/ Q& [% u# b) ]& T" D  N% X
  78.         /* PWM1 Mode configuration: Channel1 */    ; M: k# R# V) ?+ _3 Q
  79.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM 脉冲宽度调制模式 16 v& A! c; e" a) U* o) @
  80.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平有效
    7 E: |1 n8 A0 ^# Q2 }
  81.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出3 N- k  \) ^+ u& m0 b/ F, a
  82.         TIM_OCInitStructure.TIM_Pulse = nPDTemp>>1;//50% //比较tim_ccr的值,输出脉冲发生跳变/ s. d  j2 r: W
  83.         TIM_OC1Init(TIM2, &TIM_OCInitStructure); //初始化
    3 R, e0 f, U6 `) l0 l& w- F9 u* L
  84.         TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能 TIMx 在 CCR1 上的预装载寄存器
    5 U* \# Y% T0 K/ C& f7 Y
  85.         TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能 TIMx 在 ARR 上的预装载寄存器7 o  g6 Z0 b  G2 }+ `( Y
  86.         ) p2 ~+ g- {1 W: O$ A' d; E
  87.         // 时基配置:配置脉冲计数寄存器——TIM3
    * m1 e% i& H( o1 K
  88.         TIM_TimeBaseStructure.TIM_Period = pulse_number;      //0x1900是360°;//改变给电机的脉冲个数                     
    ' _  A1 c, H( W" F& U' P
  89.         TIM_TimeBaseStructure.TIM_Prescaler = 0; ( ~8 v# ?# B8 u* k5 s: j& r
  90.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; ' M4 g% B. f3 a/ H8 D( w% f
  91.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; % m. \5 S: O2 B9 N2 \5 }
  92.         TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    % f1 d7 P8 T, ]3 j
  93.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); ! M% w( e% d5 Z% w
  94.         // 输出配置:配置输出比较非主动模式定时器——TIM39 P# O7 L% f+ T; o
  95.         // Output Compare Active Mode configuration: Channel1
    & D- Y- Z( r$ j0 @8 W
  96.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; //输出比较非主动模式,(匹配时设置输出引脚为无效        电平,当计数值为比较/捕获寄存器值相同时,强制输出为低电平)      
    # H3 E0 F& }1 k" g- N. ~. N
  97.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    * H4 X5 }- y3 k* _( A$ i. F( d+ B
  98.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; ; V8 C2 Q+ d1 }, e& J! P; j9 S9 g
  99.         TIM_OCInitStructure.TIM_Pulse = 0xFFFF; // 这里的配置值意义不大   + I5 J; v# ~; `- ]. E
  100.         TIM_OC1Init(TIM3, &TIM_OCInitStructure); * \' C5 Z& Y5 A% s1 v  M) Y

  101. 3 J6 @/ K5 l2 D% M. M, z
  102.         // 配置TIM2为主定时器
    7 R' s8 V; D4 w6 [6 l4 y
  103.         // Select the Master Slave Mode 7 {6 q, Y* T. V) j0 x
  104.         TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //设置 TIM2 主/从模式并使能' Y0 X( V, \. A. k; @' A9 A
  105.         // Master Mode selection  
    6 G0 \+ ~: s0 |  C# p% J, f( l" ?
  106.         TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); //使用更新事件作为触发输出
    . O! }5 M- M6 P0 Z4 O4 I3 r' I
  107.         3 J& u( z6 y4 J$ ?; `
  108.         // 配置TIM3为从定时器
    % u; E/ {2 [. b
  109.         // Slave Mode selection: TIM3 & p6 M3 N. n% j5 ]: d: |
  110.         TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated); //选择 TIM3为从模式   TIM_SlaveMode_Gated-当触发信号(TRGI)为高电平时计数器时钟使能" m; P7 x3 J9 V3 R, L* U- C
  111.         TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); //选择 TIM3 输入触发源    TIM_TS_ITR1-TIM 内部触发 1- g. S3 N; x/ \3 l+ n) z
  112.         TIM_ITRxExternalClockConfig(TIM3, TIM_TS_ITR1);//设置 TIM3 内部触发为外部时钟模式   TIM_TS_ITR1-TIM 内部触发 17 J1 |( G* W0 Q. J: c" e
  113.         TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); //使能TIM3     TIM 捕获/比较 1 中断源          # M, P8 v5 s; e" F7 u6 I: G- s+ ?
  114.         / k2 }  U$ f+ v! @  H& x, m: n! U
  115.         TIM_Cmd(TIM2, ENABLE); 6 r8 |2 J6 G3 t% T* U  {, c
  116.         TIM_Cmd(TIM3, ENABLE);
    8 A$ s% m0 T) O- W  H7 y1 P7 r, a" ]
  117. }
    - R1 m  y' C& r+ Y' |# R& a0 l% L8 e
  118. 5 G2 H* f3 U& o6 ]8 g+ z9 B
  119. /****************************************************! i2 L* B) m1 @+ y  V/ |
  120. * 函数名:Output_Pulse
    ' Z. [' C) Y$ K6 r9 ~4 i7 P, }7 {
  121. * 描述  :无+ r" a3 A8 @- B0 g- f! O; G
  122. * 输入  :无 & `7 p% ^  |+ x! C
  123. * 输出  :无
    - C% U7 v6 y/ f6 ]: i  ^: l; [
  124. * 返回值:无
    & i3 \: {7 Z# I2 ]; Q( y$ [
  125. ******************************************************/2 q. {: f5 R7 ?4 M3 o0 @( r. h- c
  126. void Output_Pulse(u16 Num)
    / s6 T; g, l# X+ [! O0 @* c
  127. {) ~, Y- [, o  _1 U
  128.                 GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭        使能% ], N2 X# B. {1 s& v
  129.                 TIM3->CCR1 = Num;
    2 j/ r. U# z  ^1 V0 x
  130.                 TIM3->CNT = 0;
    . c$ ?8 H% V4 `4 m  H' I
  131.                 TIM_Cmd(TIM3, ENABLE);
    & F! Q* e% k2 y
  132.                 TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); % t( {2 P0 G2 }2 Y
  133.                 TIM_Cmd(TIM2, ENABLE);
    & i, k3 K( s. Y+ [* |$ u
  134. }
    6 r; |: I0 d1 E4 L  ?! {

  135. 0 R- z7 c( D' _# O8 H: ?& W8 H
  136. /****************************************************  g8 }( j& A# O2 t! }
  137. * 函数名:angle_set# V. A: h! d9 z/ s+ p
  138. * 描述  :无. U: f- U3 \1 e! X" ~
  139. * 输入  :无 / J; e& W  v6 l7 S9 K
  140. * 输出  :无8 L8 `, E1 D' W" n: G: w# w
  141. * 返回值:无
    $ Q% |( O! a+ M
  142. ******************************************************/6 `' v, k  p0 ~8 J# G
  143. void angle_set(u8 dir,u8 angle)
    ) {, K  X- t# W
  144. {
    ! f5 u) ]7 }, H; O* K$ d3 V
  145.         if(dir==0)& k& t+ q3 X6 K4 W* E
  146.                                 GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
    $ i& A9 W9 l* x4 {
  147.         else
    ) g, b0 [3 p: X- m" Q/ [6 P
  148.                                 GPIO_SetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向( X+ ]$ @4 d4 n9 Y4 s6 m$ W
  149.        
    & v  F2 a: V/ o5 _; O6 a+ k
  150.         Output_Pulse(angle*6400);5 g8 a/ ?! v3 |' C2 i  }
  151. }' h- h/ t! Z/ E6 Y! k& o5 N
复制代码
4.time.h程序
4 d2 L9 f% K6 M  @9 `6 z
  1. #ifndef __TIMER_H7 l9 P8 b$ ^, O% ?" E
  2. #define        __TIMER_H1 h6 f6 t  @6 A) Q/ R
  3. #include "main.h"8 e- E. x) n9 U" @) R
  4. extern unsigned char Flag;% W7 F8 D' F! v
  5. extern unsigned char TIM2_Pulse_TIM3_Counter_OK;
    ) A, j! {) F: `3 P/ A
  6. void GPIO_Config(void);
    ; b5 f* j& Y9 |
  7. void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency,u32 pulse);5 r& f0 U* h) j$ T: \+ X9 W. M
  8. void Frequence_Setting(u32 PulseFrequency);
    % ?8 ?9 E& v/ P! T2 n7 l# J
  9. void Output_Pulse(u16 Num);8 ~* x5 ]2 ]+ o1 M6 V8 s
  10. void angle_set(u8 dir,u8 angle);) m% S% w* t) |4 [! Q
  11. #endif
    & R# S# C, Y* Q& O
复制代码
5.usart1.c程序5 i/ V$ r' p: D3 t9 j8 F* _9 w
  1. #include <main.h>* G2 g# K$ c, g8 T1 \  e: g% d
  2. #include <usart1.h>
    / O: b7 a8 r; i
  3. #include <string.h>+ D+ C& C2 C, f) Q  n
  4. #include <math.h>
    9 L# |& V% z$ x2 F% s* f

  5. ( |* h! x7 Q# G9 _8 M; h/ s6 q
  6. /******************************************************
    $ Y- h: f/ M) ^  _! W- b# X! K5 q
  7. * 函数名:USART1_Config
    . B: C' G) y' {# h3 g8 a- |
  8. * 描述  :USART1 GPIO 配置,工作模式配置
    0 n- @! i3 j; B' J" n
  9. * 输入  :无
    : G* m/ n- Y3 z
  10. * 输出  : 无
    ( o2 ~+ [- b6 e& p
  11. * 调用  :外部调用
    6 u! t0 B8 g* Y/ l  f0 p
  12. ***************************************************** */& D! W0 d, h. b7 e- ^) D
  13. void USART1_Config(void)/ V4 f" j; z9 r+ ~0 I  L
  14. {' F( _5 ^) i7 N  y
  15.         GPIO_InitTypeDef GPIO_InitStructure;
    8 ]5 l5 T8 d* e7 r2 R& @
  16.         USART_InitTypeDef USART_InitStructure;
    , S  n) i. f6 j1 m, R! _: a2 B/ Y
  17.        
    & ^* L5 }' J$ Y+ \3 \3 B/ M
  18.         /* config USART1 clock */
    5 T' j) ?, H9 ^* O) W
  19.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);7 P5 i2 x9 \5 m8 y, F" \
  20.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    # l' O: d7 O! [4 [: p

  21. - _( {# A# D3 ?
  22.         /* USART1 GPIO config */
    & H2 J; u3 u; c
  23.         /* Configure USART1 Tx (PA.09) as alternate function push-pull */
    $ B! t: i# I9 M% F2 r
  24.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    ' E8 Q" c" D7 s9 C, e
  25.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;. `# T+ w* v/ n- S3 O" W# O& o
  26.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;9 _& ^$ u, Z+ f0 n. f/ X0 }* f5 k/ Q
  27.         GPIO_Init(GPIOA, &GPIO_InitStructure);   
    . K7 _0 D1 k" e( ^0 ?7 H/ z
  28.         /* Configure USART1 Rx (PA.10) as input floating */, v6 C8 S  f2 \
  29.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    6 y# K5 x5 u8 {; D% x, ~
  30.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    ) Z; C) D% R/ d* P) w' u
  31.         GPIO_Init(GPIOA, &GPIO_InitStructure);6 ?, w* K" ^4 @: m
  32.         , c. `) F& I7 f% b' L* m
  33.         /* USART1 mode config */7 K, @% o, `# G4 _0 b2 y
  34.         USART_InitStructure.USART_BaudRate = 115200;4 ^! y/ G: e" h0 ?
  35.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    2 n. M6 @) g$ b/ q
  36.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
    " j$ p+ H" N- H8 }$ K
  37.         USART_InitStructure.USART_Parity = USART_Parity_No ;
    9 m6 d2 D) {' C; `2 @/ L
  38.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    4 v4 O. K1 X" @1 Z* L- u6 u
  39.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    3 L9 T. }& r' D9 G! j/ V
  40.         USART_Init(USART1, &USART_InitStructure);
    * ]) I4 v' E2 Z& o. m5 r5 A, Z
  41.         USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);7 J% s$ k" h) Q  ^6 }7 F, a8 b
  42.         * M* P. r. E6 I2 _/ P9 u
  43.         USART_Cmd(USART1, ENABLE);
      o- v8 E: b% l* ]6 z' S) d
  44. }% P! G0 V& j, @( {

  45. : z" u2 u* x; V$ l8 \
  46. /******************************************************
    0 O1 F: G" D5 l- l  ?' L6 |
  47. * 函数名:fputc
    1 a$ o9 u/ q6 d) g' D# M# o# n7 k
  48. * 描述  :重定向c库函数printf到USART1# ^4 U; |: k8 ]5 f' z7 O. _1 d
  49. * 输入  :无
    9 t" g0 R+ `! f2 S
  50. * 输出  :无# s9 }' t+ \8 T3 |5 w. A6 i
  51. * 调用  :由printf调用7 M- P0 U3 t: [" C- Y
  52. ***************************************************** */
    * K: M" [# D" Z7 A0 B
  53. int fputc(int ch, FILE *f)
    ; C/ n. P# @/ q: e
  54. {' U0 G( H# j: d5 p
  55.         /* 将Printf内容发往串口 */% ~% `: v% P) r9 G' s
  56.         USART_SendData(USART1, (unsigned char) ch);6 ]3 i( N! V8 J1 {1 |- {
  57.         while (!(USART1->SR & USART_FLAG_TXE));
    & A( r3 F+ O) ^& F+ N
  58.        
    / W$ Q* z) U1 ~+ C( H: C2 [6 w
  59.         return (ch);' E- \. |0 E' D- l
  60. }
    ' ?# M8 |& \! j
  61. . e, g0 P9 g4 l
  62. /*-------------------------------------------------------------------------------*/
    ; `$ {; V9 u. r1 W6 f6 W8 z& P9 |
  63. /******************************************************2 U; i+ ^+ i* y. B2 a2 t# V  m
  64. * 函数名:USART1_IRQHandler, m( b) Q. s8 q, Q
  65. * 描述  :USART1中断服务函数
    % S' J8 }+ W8 ^& p
  66. * 输入  :无
    + E: ?0 Q, b4 c' z) Y) n+ |
  67. * 输出  :无- l/ ^% }( w5 f+ n. q' L0 w
  68. * 调用  :中断调用% p3 r; J; s6 V. j) p
  69. ***************************************************** */5 s# `0 F6 O# E1 A
  70. u8 Res;
    / K& V3 f$ v& _! u. P. r* D& D/ K
  71. extern int a;
    0 _# C$ F" ^$ U+ {7 I
  72. u16 USART_RX_STA=0;       //接收状态标记         
    $ T* n4 V1 x; x% @7 ]- k
  73. u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.0 H  i4 Z$ l4 I" K
  74. void USART1_IRQHandler(void)                        //串口1中断服务程序1 \: b! b8 H% d- t$ s# S4 G
  75.         {/ C& O# u% P9 M/ j6 ]3 M
  76.                
    , h4 c8 V. f7 M0 o+ m/ i
  77.                 Res =USART_ReceiveData(USART1);        //读取接收到的数据
    5 @- R; A+ ?8 O
  78.                
    ' P1 X3 f7 y% E# z: G& C! r
  79.                 if((USART_RX_STA&0x8000)==0)//接收未完成% _9 c9 Y) j2 _2 v. g! Q
  80.                         {% i* V4 b( {, `. _  X
  81.                         if(USART_RX_STA&0x4000)//接收到了0x0d
    . d& U5 A; z- G2 O9 M. W
  82.                                 {
    % ~9 F" \' |) M
  83.                                 if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
    8 }! T9 _! F0 Q1 E* I) c, J: {, W
  84.                                 else USART_RX_STA|=0x8000;        //接收完成了
    ' R: L6 z" [$ Q9 b: ]- z" N7 c" J
  85.                                 }
    9 f9 @6 u6 g" h" g6 S( k3 h
  86.                         else //还没收到0X0D+ K% m9 g; M* P" k+ W2 n) A6 F5 _
  87.                                 {       
    1 P2 |: q6 T5 N' W
  88.                                 if(Res==0x0d)USART_RX_STA|=0x4000;) k9 t  n/ S  t0 C/ q" G- X2 x0 q1 W
  89.                                 else
    # U7 O; O3 g& \( }7 U
  90.                                         {- v" F. A3 C' U8 ]  l" P& k( f
  91.                                         USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
    2 J, F6 k" `/ Q  p4 j, B
  92.                                         USART_RX_STA++;  j+ z8 o+ O3 ^) }2 b1 B6 `' o
  93.                                         if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收          
      Q. d5 I# ?' ~1 T0 A& Y
  94.                                         }                 
    ) X( Y9 A2 t/ |$ c/ R# A
  95.                                 }
    8 `4 d' E2 b- K& K9 y: M
  96.                         }                5 a  g. P3 E$ Y! `
  97.                                 a=1;         + ~" M2 n6 C& e: e0 j" |2 b' p
  98.         } 2 ^! U3 w) I& W- K* g
  99. #if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
    ! c/ M4 L$ |! G* W6 ?
  100.         OSIntExit();                                                                                           % @4 b8 {7 |/ C" B7 i& `
  101. #endif- `/ q8 y& n  I3 X
  102. # g/ V9 l! I, E+ h
  103. /******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/
    4 f4 G1 I2 K/ T  A, X3 O: M
复制代码
6.usart1.h程序! W! L  O( f  l  V: \9 K1 F( b
  1. #ifndef __USART1_H
    6 q6 w% h8 f. s% M
  2. #define        __USART1_H
    ( ]4 _6 k+ F  r4 i! _( J' @9 e
  3. #include <main.h>. R* G) y$ V/ w& e$ x- ^
  4. #include <stdio.h>
    + P5 v2 r  T0 a! d' U

  5. 7 U) j( ~* T) N" b6 a+ @! F
  6. #define USART_REC_LEN                          200          //定义最大接收字节数 200
    ) O2 P; W* V* C% I! |; `! d4 V
  7. #define EN_USART1_RX                         1                //使能(1)/禁止(0)串口1接收
    9 ?! S8 p. B# H, `2 p2 a6 j7 i
  8. extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
      {- R2 ]* P+ [3 `! e" c
  9. extern u16 USART_RX_STA;                         //接收状态标记
    7 o2 k- z$ }" J/ L3 S1 u
  10. int simple_atoi(char *source);
    $ {, Q5 {  ^6 Z: k, `  A$ |
  11. void USART1_Config(void);
    5 w" D& w% |7 F; F8 B1 V
  12. #endif /* __USART1_H */: O* S: [: E& M! F
复制代码
源码:
& }: l' x+ h/ M, O# f 步进电机程序—串口控制速度角度.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 手机版