利用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
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
(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 }
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- @
三、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
0 a$ J. S7 J/ I5 h! x p& Z
电流大小设定4 L0 X+ Z( L6 R3 ^+ R
* 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; @
# 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
. 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
, 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- #include "main.h"
* y/ M9 O- E$ O) E9 R, b - #include "sys.h"" U3 `2 f0 X. N: u v9 { c
- #include "usart1.h"
' }. a) r. r9 a: q; g: {/ b5 B - #include "delay.h"0 ]' I0 ?. k; I
- #include "math.h"9 H8 P! Y) i; g6 W0 V" @9 X9 F
& J" p2 ?! t H" l8 Y' \7 [+ c# Q- u16 t;
$ x# j+ n8 V! _* z6 m - u16 len; //接收到的数据长度8 L6 v2 r( t& D% B9 t/ \' y3 F) Z
- u16 times=0;' |6 f" ]! q8 G+ d
- char receive_data[60]; //接收到的字符 3 d9 O. m3 n; m# d: m7 w# V; [3 R
- char state; //电机正反转标志位0正转,1反转% f/ M9 J. D% R- }" o- `# `
- int speed,angle; //旋转速度,角度
* ~: e2 k$ x8 ?. F; F E8 g - int a=0; //判断是否接收到数据) `3 e$ e! `. f% g
- int r,data=0; //用于数据转换
2 T' g+ B, M6 @( V - int type; //转换后的数据
4 H, }; r8 a( R - extern u16 USART_RX_STA;6 p5 C' D; E8 C/ r( t
- 4 T) x# o; w4 ?; ?! ]0 R* R
- /**************************
0 T) {3 y* Y l- a# d! n6 V - * 函数名:delay
( x ^' M) C) E+ L2 ~4 F - * 描述 :延时函数0 f) X1 z3 o* [: [" D; g6 |7 K
- * 输入 :无
K2 d3 i7 o4 y1 f0 Q' F V. K$ u' E! r - * 输出 :无
- s9 n/ A5 w; g8 X- d" V' R - * 返回值:无
) R9 R1 K2 e8 b/ T - ****************************/- K* @2 [% n( A) C- @) J
- void delay()//延时1 v: t: j; [) K" K, t
- {
. }( I- F, ]) v$ g - int i,j;1 ~6 B R6 y6 A5 U1 r5 T4 x
- for(i=0;i<2000;i++)
3 @9 m1 G) j& a5 K0 J - for(j=0;j<1000;j++);( B: s, Z; k& [$ h! V. a3 y- c8 T
- }
5 V- o- I. Q: h- }" Z
, I/ t _# D1 R" V' G) h N' d7 N& V- /**************************
6 |% Q6 H" g( E' z - * 函数名:Waiting_receptio! W) n, y8 ]/ [9 O6 K* J# H
- * 描述 :等待串口接收数据
& `+ A* Z: E) Q" F! Q$ Z - * 输入 :无 , k! ~9 D, e+ E4 S& u& w
- * 输出 :无
% L$ U" a+ w0 l* X: }( F5 j - * 返回值:无
& e; }3 I5 O1 T5 Z( t - ****************************/) C7 M }6 S/ T `3 {: h
- void Waiting_reception(void)
7 X7 M) f7 c" m - {
0 @* }; S ?- F( I2 M - while(a==0)//等待数据发送完成( r1 g: F' c, R! k3 V; y
- {
P, I8 m- G: A& r" r+ k - delay_ms(100);4 ?, k, f1 k6 G( c; U
- if(a==1)//接收到数据
1 t1 a" `7 H8 d: B$ I; H0 o - {, c$ d6 t; D' e5 D* w8 U
- if(USART_RX_STA&0x8000)//(串口接收用到了正点原子的例程)& {" M6 j* A) F8 ]+ G; x
- {6 J8 G) ~7 B, u# y+ I& u0 w9 \' j
- len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度+ V/ v# M% m* k( W
- r=len; : _# p% B$ X) b8 |9 i
- type=0;
. h6 v* W/ |3 a% X - for(t=0;t<len;t++)//拷贝数据,将字符转换为十进制数8 f# T( F6 e* P) W2 R' i+ o( ^
- {7 Q! ^( [9 o8 I6 W
- receive_data[t]=USART_RX_BUF[t];
$ r. S% W* v9 O t - data=(int)receive_data[t]-48;
( G# L; v- Y' h, V2 L' n - r=r-1;1 z3 z/ Y: c. U, e
- type=type+data*(pow(10,r));. D' S& _; [& w* O5 v
- }6 \: g& s# K- Q" c# x. t. W6 N" C% g
- USART_RX_STA=0;
& l5 Z7 d5 L+ i7 k7 Q) d - a=0;
# q0 w( m5 J" i) l: E( D7 ? - delay_ms(500);
4 D" m c" s6 ]$ F! c% q Y6 F% ` - break;. \' K3 _" m0 k+ N
- }$ `4 N! _! h. Q) ]* z* a
- }' n3 l& i9 P$ z2 ^' t
- }
- y' ^" p5 H) X( B - }: W5 ]+ H5 ]- }: \
- /**************************) h# r$ k* [/ r+ A
- * 函数名:KeyStates8 J# k0 y( d$ r8 |6 R3 [
- * 描述 :监测按键状态3 U/ c' A0 Q# s8 ?# c! W
- * 输入 :无 8 a, D% I2 y# \7 s" O
- * 输出 :无* S. @ n2 [- h& z4 \; W) b
- * 返回值:0/1
5 c( N" a' M- J5 P4 j' B - ****************************/ ~% C3 \! [. C5 g+ w
- u8 KeyStates()//按键状态
4 d% y. e. `' R - {
7 q# V' t1 X; P - static u8 i = 0;
8 m( T) A9 n8 W P+ p - if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)
& i1 L' e3 `7 x7 _4 ] - {
% G6 l! I7 z n6 ^9 }% k4 A - delay();
* O! ]5 r$ ?0 l2 j* u" b! {& { - if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)0 [; Y9 ^* ]7 u& B2 k9 q1 [
- while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0);
5 G0 j7 C' c& @2 ]& Y6 k: H - i = ~i;$ c- {" b/ u% _/ r" ^
- }8 a4 K( F9 J! ^
- return i;! d* m5 B# [1 |! m( m
- }
8 c9 T7 F, R: u& w) S& g - /****************
% b: f/ x m, M* l( f0 C - * 函数名:main
; O; @" F* ]2 p! ` - * 描述 :主函数# w& ~- r: q d; P
- * 输入 :无 3 o; m& G2 S0 t5 q t6 R
- * 输出 :无
4 @" w! ~( z% X4 r - ******************/4 l9 c% c0 E1 |' t7 b
- int main(void)% n/ r3 D, D& M+ c, g# p; X( l, n: y4 M
- {& g R* W: ~" s5 A2 \
- NVIC_Configuration(); //中断初始化% o7 }$ r0 K& u% U2 A
- GPIO_Config(); //IO口初始化3 G5 `( u9 i' {3 n/ i, Q# J4 X
- USART1_Config(); //串口初始化7 y9 O$ p( l/ w( x9 {, ?1 p9 @
- delay_init(); //延时函数初始化 ; p1 m& ?! U% R" W& ]" ]8 @6 `8 u
- GPIO_ResetBits(GPIOA, GPIO_Pin_11);//A11置零 A11——EAN+, |5 V7 P( c, T& o3 O
- GPIO_ResetBits(GPIOA, GPIO_Pin_12);//A12置零 A12——DIR+
1 I' i! v6 J4 e6 N# B% k - while(1)# m( r4 O5 i; I0 }. k
- { F) k# h/ |3 m6 @9 m2 A; I
- delay_ms(100);6 y) d4 y8 f* L, \/ g/ T
- Initial_state: printf("\r\n 请选择正反转,正转输入0,反转输入1 (以新行作为结束标志)\r\n");
2 Q- F) n5 a1 Y l0 N* W% I - Waiting_reception();
" n* Y& t! Z; c1 t+ R - state=type;//将接收到的数据给type
' F% [% b, I5 A, r - if(type==0)//电机正转5 D" I) t" c9 { D0 t' n# j
- {
. Z f/ C" e3 F* |7 ? a - GPIO_SetBits(GPIOA, GPIO_Pin_12);//电机正转
. `$ {; p1 O, g5 G - printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");
, J) c3 {/ v$ `3 D: B: N z -
/ m) c" X/ a: ^3 u# _3 P5 Q - /*********************************************此模块用于配置速度参数********************************************************/0 ?8 L+ u* q7 E. u5 l
& `) J7 u) p2 F- r) j& D- part1:Waiting_reception();
- Q' L% W9 E4 ^5 U7 s1 R. P - speed =type;//将接收到的数据给speed; u* J/ j0 q+ p- s9 K6 D
- if(speed==0)goto Initial_state;//如果是0则返回初始模式
7 y `# t3 q: H# e! j5 p9 q$ G6 `7 |! u - else{4 {- ?5 O( G/ d6 p }
- if(speed>=15)# J+ t. W. D. A. @
- {
; V5 ^ C2 n0 n# p+ u( t - printf("\r\n 旋转速度>15rad/s,请重新选择旋转速度。\r\n");
5 q- c" m1 C, o8 W* G1 } - goto part1;
1 b0 D, R, D$ c8 A) h: q2 B - }6 c4 g& d! W$ a' x
- else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式 \r\n",speed);% K. y4 v9 M' `" k8 J- H% j
- }
5 l6 F, I$ {) S+ c" V& u - 5 B9 s0 x- Z2 D: z& i( [
- /*********************************************此模块用于配置角度参数********************************************************/
. n/ o5 L% x( K! ]) A9 P - & l9 G1 f( J4 T
- Waiting_reception();
r2 L( s( x) B2 O0 e8 \ - angle =type;//将接收到的数据给type
B( R; [3 z6 r% g$ S - for(;;)
/ }# W! b8 g4 n$ V- G( ~9 f, O. r - {
* y0 b- X8 ] `0 X2 _ - if(angle>0)//接收到的数据不是0
; d; K! v$ W& M: i7 z3 i2 Q& W - {! Q+ G. F* y6 Y7 \" w9 V
- TIM2_Master__TIM3_Slave_Configuration(speed,angle); // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度$ E: K& e$ E* l' p
- delay_ms(20000);//电机保护/ [$ v4 \/ c5 Y. [" E4 h
- printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式; \r\n",angle);
3 {. S' M& F! f" ^8 q+ W: O - angle=0;
% T2 ]. C# H. f# n8 c - Waiting_reception();
8 S: O- r% V' |6 J. M - angle =type;
6 j6 W1 K/ n8 @1 L- e E* n2 _5 [ - }else{+ A W( X. H) I
- if(angle==0)goto Initial_state;//返回初始状态
$ J2 t7 y) i2 p6 a" m - else {
- u, e' U8 M$ U- [5 q& Y - printf("\r\n 角度错误,已返回初始模式 \r\n"); : w. p0 z7 K* {
- goto Initial_state;
: B# C* F9 h! r: e - }
}3 t; H1 B, Q% a' T" J - }
& L0 ^ p) l L# i - }
1 I2 t3 y* `. ]! M+ Q' z - } ! u/ j% }; J- K
- /*********************************************反转模式********************************************************/ 9 z- \/ j( Z0 g* h1 k9 q
- else{
0 [- F- I; ]2 R - if(type==1)
9 O, m' C. c/ P - {
. U6 q' ~7 q: f0 k; D6 A* v - GPIO_ResetBits(GPIOA, GPIO_Pin_12);//电机反转
) b8 v* I9 q8 {- v$ ~ - printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");! |# o$ K; p# f# x, H* o
-
0 A/ I. P ~% l! U h; Q2 L% O* `9 S/ S - /*********************************************此模块用于配置速度参数********************************************************/+ k/ o* u$ R2 Z; ^
- part2: Waiting_reception();
5 c' u X# q+ v, k8 I - speed =type;//将接收到的数据给speed
4 A9 K1 ^: o$ i- F" u1 W - if(speed==0)goto Initial_state;//如果是0则返回初始模式2 p. z0 b! x; @2 P
- else{$ [0 _8 g9 I3 ]4 O5 y! w- m
- if(speed>=15)8 [: B! ]2 V, u
- {9 l8 @# W" w- h
- printf("\r\n旋转速度>15rad/s,请重新选择旋转速度。\r\n");
0 {. a& I* A- ^8 j/ r - goto part2;- p5 _2 s* I: ?" T
- }else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式 \r\n",speed);
6 k1 k1 \3 j& K6 I6 i3 b8 ^$ S - } 3 R; W- r7 _! W7 e. G
- /*********************************************此模块用于配置角度参数********************************************************/ " ?5 F! ~( V0 c; y: c
- Waiting_reception();
* x9 g# v; U5 s( ]7 W8 @! m$ o - angle =type;//将接收到的数据给type
. E2 \& o8 k2 Y1 p - for(;;): z e+ y2 M0 S8 V& }' g; j
- {
7 K+ f: P: l6 P - if(angle>0)//接收到的数据不是0: P6 f# K l& e7 _
- {7 o9 \* Q( a8 X% m3 G+ k
- TIM2_Master__TIM3_Slave_Configuration(speed,angle); // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度( T8 ~) D2 d M! T V* N
- delay_ms(20000);//电机保护8 V4 O7 s- e# L7 S- P l
- printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式;\r\n",angle);
/ D- ?3 _5 z3 Z/ ~ - angle=0;
/ a- e( \( A3 B, E$ g/ X - Waiting_reception(); F) k. T3 z0 B( O& B
- angle =type; - v( E% K% M& V
- }else{9 o. K- t3 E8 H. q: E
- if(angle==0)goto Initial_state;//返回初始状态 7 `/ C, z! ]& \) H
- else {" A+ R+ v- p' U9 m$ [8 s
- printf("\r\n 角度错误,已返回初始模式 \r\n"); ' n7 W0 G5 N5 Y c9 z
- goto Initial_state;- N5 B5 _5 h) S& Q5 D$ k
- } / N6 ?6 G7 S6 z0 V, W, v$ i# i
- }( w/ m" ~% F' M; q
- }
+ F7 q, X X9 k - /****************************************************************************************************************************/ 6 i y1 X. p- d- [8 z6 J
- }else{//if(a!=0)&(a!=1)2 C" t. R3 Y. d9 [, W& e, G) y
- type=NULL;
4 Q+ x& j' D* u% J; z4 E$ D* U7 v; t - printf("\r\n 输入无效 \r\n");
4 n& E1 E( K2 x* U$ C3 z, v! a( g - goto Initial_state;//返回初始状态- |+ q% S7 \1 I7 G1 {
- }
2 Z _9 [. Y, b/ n- v - }
# R& y* d1 |- @ - }- S% p- z6 D, y* w
- }3 c: B* N; V5 e8 J1 Z
复制代码 2.main.h程序
- l" q0 ]( F V$ w1 n$ F- #ifndef _MAIN_H; j: A% n5 I% N" P( x, U- J1 I
- #define _MAIN_H- J% n; x- k% r3 h3 Q7 F& o1 s- C7 J3 B
- #include <stm32f10x.h>2 K4 a% @0 r( a2 J
- #include <usart1.h>
/ c n( H, e1 v* B- M. H - #include <misc.h>
* i, J8 `7 R7 X# {1 b - #include <nvic.h>
6 S) R ~6 o7 N- T - #include <stdio.h>$ M! y K* ~4 s: o C
- #include "stm32f10x_tim.h"
5 ^) @& L+ i6 g5 P% h - #include "timer.h"8 r, y( x; T6 \2 \
- #endif
+ ]* v+ k/ W: i+ D8 n
复制代码 3.time.c程序; T; Y1 F5 R% O$ x# j) k [' g
- #include "timer.h"3 x4 x j) V+ ]: W! E, q
- /**************************( Q# T- ?% O& I1 O# l7 b
- * 函数名:GPIO_Config* O+ G! v) h1 S/ d. w/ A0 k. G8 \
- * 描述 :无% L6 o. L) j9 D1 I4 ~) O2 N* J6 i
- * 输入 :无 6 f& a" P) D# y
- * 输出 :无9 |. D; f* W/ G" H7 f3 U- _- W
- * 调用 :主函数
& \, Z8 s$ w/ `8 G; r V* h - * 返回值:无( s" ?. R% f! Z- [# ~
- ****************************/
3 S3 q# Z2 I# V - void GPIO_Config(void)
( X; C) z& v( P - {
Q( i5 T! `3 y7 I0 }$ b - GPIO_InitTypeDef GPIO_InitStructure;
" N% g9 `9 x* Q0 x" @, y* N - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能IOA& Z3 Y1 k1 l7 e% R
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE); //使能TIM2,TIM3
5 j. N+ j* E* {% [ - 9 {) d/ n: O4 d
- /* Timer2 Channel 1, PA0 */ + K" L" n" p7 x- ^
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; $ f1 B1 W: S) w2 V
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用输出
) U6 F! w' w3 h) d* Y - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ' x$ c. ~: z% P$ C- B! S( D0 U
- GPIO_Init(GPIOA, &GPIO_InitStructure);
" E. G& Y, Y6 d5 F( b0 ~& E0 {& h - , i W- I: ~& v: ]
- 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
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //通用推挽输出模式
9 \, b' m" ?6 ]3 a5 D6 M - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //指定GPIO引脚可输出的最高频率为50MHZ. H- P$ H9 n' d$ A& [1 h0 |
- GPIO_Init(GPIOA, &GPIO_InitStructure); //+ Q9 B/ s! o1 W
- GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向# Q& G1 R. n0 E* m; R, T
- GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭 使能
8 g: n1 O4 a$ M0 W5 v) P - GPIO_SetBits(GPIOA, GPIO_Pin_11);//指定引脚输出低电平,此时灯全灭,方向
# m8 k9 Q1 A, m1 E1 v/ R/ z' n - GPIO_SetBits(GPIOA, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭 使能
4 z# I* Q# B) y4 _, D( y -
; ]2 Q; G0 U2 Y( R# r5 E3 P. ^* Z - - W" ?) `! E9 m$ J
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;2 z }6 S3 l7 n% ]# c" G2 M+ [# x
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //通用推挽输出模式' z" ^, y& f O9 ~1 f
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //指定GPIO引脚可输出的最高频率为50MHZ1 Q {; q: e) ]$ D4 `3 u* k" q
- GPIO_Init(GPIOA, &GPIO_InitStructure); //0 D" w- d: O& M* A% P3 e/ a
-
5 p; H0 |! T* @. m+ n# @7 W - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); , M9 p' z! F, Z. z; F
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;9 p3 q! z( i1 i! R, N2 O, P% W# w
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //通用推挽输出模式
' j' Z& a g, C0 E* H, P - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //指定GPIO引脚可输出的最高频率为50MHZ2 g; y- k' F7 v# W
- GPIO_Init(GPIOB, &GPIO_InitStructure); //
6 G3 H9 u8 N' `4 R - GPIO_ResetBits(GPIOB, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭 使能 o/ s. f# g. }& }) o( x9 J
-
. B4 ~7 {) l, f& e* H/ m0 r# M1 |0 U - //GPIO_ResetBits GPIO_SetBits% }* s' t: M2 I S) |
- }
7 G$ a [2 _- N" Z6 o2 M
; U7 \$ V0 A$ ?, b9 m- //================================================================================) D: k" t/ h9 v+ h/ P/ T& x- u: I
- /**************************
7 X9 a1 F4 X; g2 J$ }/ e - * 函数名:TIM2_Master__TIM3_Slave_Configuration$ N- l: i+ s d( G# Z6 M
- * 描述 :主从定时器配置( n2 |- s5 {5 R; s8 M0 D
- * 输入 :电机转速speed,转角angle
F1 F4 q! l' U! G; a0 x5 \; D$ U - * 输出 :无/ P5 v2 w4 C( ^8 m& y
- * 调用 :主函数
, o/ f: q8 j0 J* h5 c6 s5 M - * 返回值:无/ J* x: \% c8 {/ V3 h {
- ****************************/
' K! d1 |& o$ I - void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency, u32 pulse) # H D5 j! p7 j( q) U
- {$ ]) E% R7 o9 }+ r
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
# U- Q0 v$ f+ u - TIM_OCInitTypeDef TIM_OCInitStructure; 7 t# O- p- @7 {- v0 G
-
' r; p1 c, _% m - u16 nPDTemp ; ! q! D3 ?7 C) x5 a! D1 A
- u16 pulse_number;
4 j0 c8 X( R1 K5 D - float p=PulseFrequency;; e& q2 i$ q3 N7 a0 q6 ~: p
- TIM_Cmd(TIM2, DISABLE); 1 Z/ i" e* P6 \5 r
- nPDTemp = (11.25/p); //TIM2重装值是11.25时1s转一圈(电机32细分下)' C! S( U; _5 a; R
- pulse_number = (16.7778*pulse);//TIM3重装值是16.7778时转1°(电机32细分下)% a4 h2 S/ i9 _
- : K+ V* F" D* {; x
- // 时基配置:配置PWM输出定时器——TIM2
K; f U5 R; M; v9 z - /* Time base configuration */
7 M- `' G4 }) s5 T+ G1 _ - TIM_TimeBaseStructure.TIM_Period = nPDTemp; //定时周期为nPDTemp- ~2 x* e3 Y, ? l
- TIM_TimeBaseStructure.TIM_Prescaler = 999; //预分频值1000,即f=72khz
8 [; I3 G6 |0 H% | - TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分频因子,会影响滤波器采样频率,与本实验无影响7 p$ Z3 n9 W( [# {9 B& F' c3 N7 ?
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
" { Y- [8 ?- A! V - TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //指定重复计数器值/ T: V# U) Z* D$ a
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
8 d* T0 O4 O B- \( {/ z9 ~" U -
+ l1 w( l: \2 K1 f/ B - // 输出配置:配置PWM输出定时器——TIM2 7 w/ Q& [% u# b) ]& T" D N% X
- /* PWM1 Mode configuration: Channel1 */ ; M: k# R# V) ?+ _3 Q
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM 脉冲宽度调制模式 16 v& A! c; e" a) U* o) @
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平有效
7 E: |1 n8 A0 ^# Q2 } - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出3 N- k \) ^+ u& m0 b/ F, a
- TIM_OCInitStructure.TIM_Pulse = nPDTemp>>1;//50% //比较tim_ccr的值,输出脉冲发生跳变/ s. d j2 r: W
- TIM_OC1Init(TIM2, &TIM_OCInitStructure); //初始化
3 R, e0 f, U6 `) l0 l& w- F9 u* L - TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能 TIMx 在 CCR1 上的预装载寄存器
5 U* \# Y% T0 K/ C& f7 Y - TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能 TIMx 在 ARR 上的预装载寄存器7 o g6 Z0 b G2 }+ `( Y
- ) p2 ~+ g- {1 W: O$ A' d; E
- // 时基配置:配置脉冲计数寄存器——TIM3
* m1 e% i& H( o1 K - TIM_TimeBaseStructure.TIM_Period = pulse_number; //0x1900是360°;//改变给电机的脉冲个数
' _ A1 c, H( W" F& U' P - TIM_TimeBaseStructure.TIM_Prescaler = 0; ( ~8 v# ?# B8 u* k5 s: j& r
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; ' M4 g% B. f3 a/ H8 D( w% f
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; % m. \5 S: O2 B9 N2 \5 }
- TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
% f1 d7 P8 T, ]3 j - TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); ! M% w( e% d5 Z% w
- // 输出配置:配置输出比较非主动模式定时器——TIM39 P# O7 L% f+ T; o
- // Output Compare Active Mode configuration: Channel1
& D- Y- Z( r$ j0 @8 W - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; //输出比较非主动模式,(匹配时设置输出引脚为无效 电平,当计数值为比较/捕获寄存器值相同时,强制输出为低电平)
# H3 E0 F& }1 k" g- N. ~. N - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
* H4 X5 }- y3 k* _( A$ i. F( d+ B - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; ; V8 C2 Q+ d1 }, e& J! P; j9 S9 g
- TIM_OCInitStructure.TIM_Pulse = 0xFFFF; // 这里的配置值意义不大 + I5 J; v# ~; `- ]. E
- TIM_OC1Init(TIM3, &TIM_OCInitStructure); * \' C5 Z& Y5 A% s1 v M) Y
3 J6 @/ K5 l2 D% M. M, z- // 配置TIM2为主定时器
7 R' s8 V; D4 w6 [6 l4 y - // Select the Master Slave Mode 7 {6 q, Y* T. V) j0 x
- TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //设置 TIM2 主/从模式并使能' Y0 X( V, \. A. k; @' A9 A
- // Master Mode selection
6 G0 \+ ~: s0 | C# p% J, f( l" ? - TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); //使用更新事件作为触发输出
. O! }5 M- M6 P0 Z4 O4 I3 r' I - 3 J& u( z6 y4 J$ ?; `
- // 配置TIM3为从定时器
% u; E/ {2 [. b - // Slave Mode selection: TIM3 & p6 M3 N. n% j5 ]: d: |
- TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated); //选择 TIM3为从模式 TIM_SlaveMode_Gated-当触发信号(TRGI)为高电平时计数器时钟使能" m; P7 x3 J9 V3 R, L* U- C
- TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); //选择 TIM3 输入触发源 TIM_TS_ITR1-TIM 内部触发 1- g. S3 N; x/ \3 l+ n) z
- TIM_ITRxExternalClockConfig(TIM3, TIM_TS_ITR1);//设置 TIM3 内部触发为外部时钟模式 TIM_TS_ITR1-TIM 内部触发 17 J1 |( G* W0 Q. J: c" e
- TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); //使能TIM3 TIM 捕获/比较 1 中断源 # M, P8 v5 s; e" F7 u6 I: G- s+ ?
- / k2 } U$ f+ v! @ H& x, m: n! U
- TIM_Cmd(TIM2, ENABLE); 6 r8 |2 J6 G3 t% T* U {, c
- TIM_Cmd(TIM3, ENABLE);
8 A$ s% m0 T) O- W H7 y1 P7 r, a" ] - }
- R1 m y' C& r+ Y' |# R& a0 l% L8 e - 5 G2 H* f3 U& o6 ]8 g+ z9 B
- /****************************************************! i2 L* B) m1 @+ y V/ |
- * 函数名:Output_Pulse
' Z. [' C) Y$ K6 r9 ~4 i7 P, }7 { - * 描述 :无+ r" a3 A8 @- B0 g- f! O; G
- * 输入 :无 & `7 p% ^ |+ x! C
- * 输出 :无
- C% U7 v6 y/ f6 ]: i ^: l; [ - * 返回值:无
& i3 \: {7 Z# I2 ]; Q( y$ [ - ******************************************************/2 q. {: f5 R7 ?4 M3 o0 @( r. h- c
- void Output_Pulse(u16 Num)
/ s6 T; g, l# X+ [! O0 @* c - {) ~, Y- [, o _1 U
- GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭 使能% ], N2 X# B. {1 s& v
- TIM3->CCR1 = Num;
2 j/ r. U# z ^1 V0 x - TIM3->CNT = 0;
. c$ ?8 H% V4 `4 m H' I - TIM_Cmd(TIM3, ENABLE);
& F! Q* e% k2 y - TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); % t( {2 P0 G2 }2 Y
- TIM_Cmd(TIM2, ENABLE);
& i, k3 K( s. Y+ [* |$ u - }
6 r; |: I0 d1 E4 L ?! {
0 R- z7 c( D' _# O8 H: ?& W8 H- /**************************************************** g8 }( j& A# O2 t! }
- * 函数名:angle_set# V. A: h! d9 z/ s+ p
- * 描述 :无. U: f- U3 \1 e! X" ~
- * 输入 :无 / J; e& W v6 l7 S9 K
- * 输出 :无8 L8 `, E1 D' W" n: G: w# w
- * 返回值:无
$ Q% |( O! a+ M - ******************************************************/6 `' v, k p0 ~8 J# G
- void angle_set(u8 dir,u8 angle)
) {, K X- t# W - {
! f5 u) ]7 }, H; O* K$ d3 V - if(dir==0)& k& t+ q3 X6 K4 W* E
- GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
$ i& A9 W9 l* x4 { - else
) g, b0 [3 p: X- m" Q/ [6 P - GPIO_SetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向( X+ ]$ @4 d4 n9 Y4 s6 m$ W
-
& v F2 a: V/ o5 _; O6 a+ k - Output_Pulse(angle*6400);5 g8 a/ ?! v3 |' C2 i }
- }' h- h/ t! Z/ E6 Y! k& o5 N
复制代码 4.time.h程序
4 d2 L9 f% K6 M @9 `6 z- #ifndef __TIMER_H7 l9 P8 b$ ^, O% ?" E
- #define __TIMER_H1 h6 f6 t @6 A) Q/ R
- #include "main.h"8 e- E. x) n9 U" @) R
- extern unsigned char Flag;% W7 F8 D' F! v
- extern unsigned char TIM2_Pulse_TIM3_Counter_OK;
) A, j! {) F: `3 P/ A - void GPIO_Config(void);
; b5 f* j& Y9 | - void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency,u32 pulse);5 r& f0 U* h) j$ T: \+ X9 W. M
- void Frequence_Setting(u32 PulseFrequency);
% ?8 ?9 E& v/ P! T2 n7 l# J - void Output_Pulse(u16 Num);8 ~* x5 ]2 ]+ o1 M6 V8 s
- void angle_set(u8 dir,u8 angle);) m% S% w* t) |4 [! Q
- #endif
& R# S# C, Y* Q& O
复制代码 5.usart1.c程序5 i/ V$ r' p: D3 t9 j8 F* _9 w
- #include <main.h>* G2 g# K$ c, g8 T1 \ e: g% d
- #include <usart1.h>
/ O: b7 a8 r; i - #include <string.h>+ D+ C& C2 C, f) Q n
- #include <math.h>
9 L# |& V% z$ x2 F% s* f
( |* h! x7 Q# G9 _8 M; h/ s6 q- /******************************************************
$ Y- h: f/ M) ^ _! W- b# X! K5 q - * 函数名:USART1_Config
. B: C' G) y' {# h3 g8 a- | - * 描述 :USART1 GPIO 配置,工作模式配置
0 n- @! i3 j; B' J" n - * 输入 :无
: G* m/ n- Y3 z - * 输出 : 无
( o2 ~+ [- b6 e& p - * 调用 :外部调用
6 u! t0 B8 g* Y/ l f0 p - ***************************************************** */& D! W0 d, h. b7 e- ^) D
- void USART1_Config(void)/ V4 f" j; z9 r+ ~0 I L
- {' F( _5 ^) i7 N y
- GPIO_InitTypeDef GPIO_InitStructure;
8 ]5 l5 T8 d* e7 r2 R& @ - USART_InitTypeDef USART_InitStructure;
, S n) i. f6 j1 m, R! _: a2 B/ Y -
& ^* L5 }' J$ Y+ \3 \3 B/ M - /* config USART1 clock */
5 T' j) ?, H9 ^* O) W - RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);7 P5 i2 x9 \5 m8 y, F" \
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
# l' O: d7 O! [4 [: p
- _( {# A# D3 ?- /* USART1 GPIO config */
& H2 J; u3 u; c - /* Configure USART1 Tx (PA.09) as alternate function push-pull */
$ B! t: i# I9 M% F2 r - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
' E8 Q" c" D7 s9 C, e - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;. `# T+ w* v/ n- S3 O" W# O& o
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;9 _& ^$ u, Z+ f0 n. f/ X0 }* f5 k/ Q
- GPIO_Init(GPIOA, &GPIO_InitStructure);
. K7 _0 D1 k" e( ^0 ?7 H/ z - /* Configure USART1 Rx (PA.10) as input floating */, v6 C8 S f2 \
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
6 y# K5 x5 u8 {; D% x, ~ - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
) Z; C) D% R/ d* P) w' u - GPIO_Init(GPIOA, &GPIO_InitStructure);6 ?, w* K" ^4 @: m
- , c. `) F& I7 f% b' L* m
- /* USART1 mode config */7 K, @% o, `# G4 _0 b2 y
- USART_InitStructure.USART_BaudRate = 115200;4 ^! y/ G: e" h0 ?
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
2 n. M6 @) g$ b/ q - USART_InitStructure.USART_StopBits = USART_StopBits_1;
" j$ p+ H" N- H8 }$ K - USART_InitStructure.USART_Parity = USART_Parity_No ;
9 m6 d2 D) {' C; `2 @/ L - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
4 v4 O. K1 X" @1 Z* L- u6 u - USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
3 L9 T. }& r' D9 G! j/ V - USART_Init(USART1, &USART_InitStructure);
* ]) I4 v' E2 Z& o. m5 r5 A, Z - USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);7 J% s$ k" h) Q ^6 }7 F, a8 b
- * M* P. r. E6 I2 _/ P9 u
- USART_Cmd(USART1, ENABLE);
o- v8 E: b% l* ]6 z' S) d - }% P! G0 V& j, @( {
: z" u2 u* x; V$ l8 \- /******************************************************
0 O1 F: G" D5 l- l ?' L6 | - * 函数名:fputc
1 a$ o9 u/ q6 d) g' D# M# o# n7 k - * 描述 :重定向c库函数printf到USART1# ^4 U; |: k8 ]5 f' z7 O. _1 d
- * 输入 :无
9 t" g0 R+ `! f2 S - * 输出 :无# s9 }' t+ \8 T3 |5 w. A6 i
- * 调用 :由printf调用7 M- P0 U3 t: [" C- Y
- ***************************************************** */
* K: M" [# D" Z7 A0 B - int fputc(int ch, FILE *f)
; C/ n. P# @/ q: e - {' U0 G( H# j: d5 p
- /* 将Printf内容发往串口 */% ~% `: v% P) r9 G' s
- USART_SendData(USART1, (unsigned char) ch);6 ]3 i( N! V8 J1 {1 |- {
- while (!(USART1->SR & USART_FLAG_TXE));
& A( r3 F+ O) ^& F+ N -
/ W$ Q* z) U1 ~+ C( H: C2 [6 w - return (ch);' E- \. |0 E' D- l
- }
' ?# M8 |& \! j - . e, g0 P9 g4 l
- /*-------------------------------------------------------------------------------*/
; `$ {; V9 u. r1 W6 f6 W8 z& P9 | - /******************************************************2 U; i+ ^+ i* y. B2 a2 t# V m
- * 函数名:USART1_IRQHandler, m( b) Q. s8 q, Q
- * 描述 :USART1中断服务函数
% S' J8 }+ W8 ^& p - * 输入 :无
+ E: ?0 Q, b4 c' z) Y) n+ | - * 输出 :无- l/ ^% }( w5 f+ n. q' L0 w
- * 调用 :中断调用% p3 r; J; s6 V. j) p
- ***************************************************** */5 s# `0 F6 O# E1 A
- u8 Res;
/ K& V3 f$ v& _! u. P. r* D& D/ K - extern int a;
0 _# C$ F" ^$ U+ {7 I - u16 USART_RX_STA=0; //接收状态标记
$ T* n4 V1 x; x% @7 ]- k - u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.0 H i4 Z$ l4 I" K
- void USART1_IRQHandler(void) //串口1中断服务程序1 \: b! b8 H% d- t$ s# S4 G
- {/ C& O# u% P9 M/ j6 ]3 M
-
, h4 c8 V. f7 M0 o+ m/ i - Res =USART_ReceiveData(USART1); //读取接收到的数据
5 @- R; A+ ?8 O -
' P1 X3 f7 y% E# z: G& C! r - if((USART_RX_STA&0x8000)==0)//接收未完成% _9 c9 Y) j2 _2 v. g! Q
- {% i* V4 b( {, `. _ X
- if(USART_RX_STA&0x4000)//接收到了0x0d
. d& U5 A; z- G2 O9 M. W - {
% ~9 F" \' |) M - if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
8 }! T9 _! F0 Q1 E* I) c, J: {, W - else USART_RX_STA|=0x8000; //接收完成了
' R: L6 z" [$ Q9 b: ]- z" N7 c" J - }
9 f9 @6 u6 g" h" g6 S( k3 h - else //还没收到0X0D+ K% m9 g; M* P" k+ W2 n) A6 F5 _
- {
1 P2 |: q6 T5 N' W - if(Res==0x0d)USART_RX_STA|=0x4000;) k9 t n/ S t0 C/ q" G- X2 x0 q1 W
- else
# U7 O; O3 g& \( }7 U - {- v" F. A3 C' U8 ] l" P& k( f
- USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
2 J, F6 k" `/ Q p4 j, B - USART_RX_STA++; j+ z8 o+ O3 ^) }2 b1 B6 `' o
- if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
Q. d5 I# ?' ~1 T0 A& Y - }
) X( Y9 A2 t/ |$ c/ R# A - }
8 `4 d' E2 b- K& K9 y: M - } 5 a g. P3 E$ Y! `
- a=1; + ~" M2 n6 C& e: e0 j" |2 b' p
- } 2 ^! U3 w) I& W- K* g
- #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
! c/ M4 L$ |! G* W6 ? - OSIntExit(); % @4 b8 {7 |/ C" B7 i& `
- #endif- `/ q8 y& n I3 X
- # g/ V9 l! I, E+ h
- /******************* (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
- #ifndef __USART1_H
6 q6 w% h8 f. s% M - #define __USART1_H
( ]4 _6 k+ F r4 i! _( J' @9 e - #include <main.h>. R* G) y$ V/ w& e$ x- ^
- #include <stdio.h>
+ P5 v2 r T0 a! d' U
7 U) j( ~* T) N" b6 a+ @! F- #define USART_REC_LEN 200 //定义最大接收字节数 200
) O2 P; W* V* C% I! |; `! d4 V - #define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收
9 ?! S8 p. B# H, `2 p2 a6 j7 i - extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符
{- R2 ]* P+ [3 `! e" c - extern u16 USART_RX_STA; //接收状态标记
7 o2 k- z$ }" J/ L3 S1 u - int simple_atoi(char *source);
$ {, Q5 { ^6 Z: k, ` A$ | - void USART1_Config(void);
5 w" D& w% |7 F; F8 B1 V - #endif /* __USART1_H */: O* S: [: E& M! F
复制代码 源码:
& }: l' x+ h/ M, O# f
步进电机程序—串口控制速度角度.zip
(4.75 MB, 下载次数: 115)
|