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