利用STM32F103精确控制步进电机 一、用到的元器件8 z* M* g# ~# @# T9 u
STM32F103C8T6
6 T/ C1 D/ M3 f" t42步进电机(42SHDC4040-17B)$ @) v) i7 q# h
TB6600电机驱动器升级版# L' Z" z, R) P: S6 B
' l4 X$ ]: C# P( Y- B y" G" m
" K0 ~0 {3 i+ O8 R0 \
二、42步进电机
( _# w5 A/ E5 e6 z- X/ s3 q1.步进电机的基本知识5 d! u g0 ?+ x6 {7 q% S
(1)拍数——每一次循环所包含的通电状态数(电机转过一个齿距角所需脉冲数)2 N3 i3 L; u; ?* i: ~
(2)单拍制分配方式——状态数=相数
, l* G0 L+ w5 Q6 b(3)双拍制分配方式——状态数=相数的两倍' b- }6 N, m1 P! w/ J
(4)步距角 ——步进机通过一个电脉冲转子转过的角度! \# z7 E/ y: t
N:一个周期的运行拍数. z- o$ [! d- ^! E
Zr:转子齿数
* y$ a5 N4 w4 z0 L1 P6 O拍数:N=km
9 I$ a: |7 o/ }/ m) X" V ^m:相数
8 Y+ S7 V* g0 i9 B7 v, i8 xk=1单拍制
! f+ w7 {- I: X9 {/ h" O+ x$ E; hk=2双拍制
+ A A& I1 T( M(5)转速
# Q, l4 y( m3 ?8 e(6)角度细分的原理- w( x% t: t% q! D& }& D
4 d: a: Z: B, g5 c. D( P
( U# s$ U' p1 w9 G/ S& o* x电磁力的大小与绕组通电电流的大小有关。3 y* T' e6 o+ u% A6 t o
当通电相的电流并不马上升到位,而断电相的电流也非立即降为0时,它们所产生的磁场合力,会使转子有一个新的平衡位置,这个新的平衡位置是在原来的步距角范围内。
6 J* x6 U! [' m; O7 ?, F2. 42步进电机参数
3 I; B. A: d' w. X9 B [/ O无法查找到42SHDC4040-17B型号的详细资料,以通用42步进电机为例:
$ l5 [, Y+ l' ?" @步距角 1.8°
( l$ R, i* U* h" U步距角精度 ±5%
* o( y @! j, i4 o相数 2相
& r2 G1 G- ~, k" i励磁方式 混合式2 t$ i( F7 W, L4 }& d2 P/ W" e
转子齿数 50. p6 G A8 x: {
拍制 双拍制% z6 D4 J/ f3 F5 O
其他参数:无
% e, W" s6 k |( n/ }2 \由步距角=1.8°推算出转子齿数为50,拍制为双拍制
6 e9 ^8 o) I9 _' j9 b" ?2 S* w( y2 C
3 w" t( h) s5 L
3. 42步进电机速度与角度控制9 G: q, w! v: O! F! F+ M# z
电机的转速与脉冲频率成正比,电机转过的角度与脉冲数成正比。所以控制脉冲数和脉冲频率就可以精确调速。
* o6 @ L7 @/ o6 S2 p! ~1 v3 N" D理论上步进电机转速 = 频率 * 60 /((360/T)*x)
% C, ~3 _5 e! K2 k: l5 g
6 q4 W& ]9 N6 M3 C3 ^
; b, G1 [9 u: F5 d7 g6 |$ Y
转速单位: 转/ 分
4 p% @6 V6 h) y% |6 J1 B) X" M频率单位:赫兹0 U1 r0 E% C( \# N
x 细分倍数
5 X" Q3 ]5 {0 T2 `+ {$ mT 步距角9 K1 }$ u: I# a$ Q
例如,在本实验中,32细分;频率72000 赫兹;步距角1.8°;套用公式72000 ∗ 60 ( ( 360 / 1.8 ) ∗ 32 ) = 112.5 \frac{72000*60}{((360/1.8)*32)}=112.5 # h( D0 \2 @3 e6 C1 f1 o
((360/1.8)∗32)+ L4 F0 ]! C8 I6 M* L4 V* O2 F
72000∗60
& D1 W5 \7 j/ V; h! H2 S 2 Q# }& W! }( [$ v
=112.5rad/ min,即1.875 rad/s.( b: ` L8 Q0 {/ f5 V' b
三、TB6600电机驱动器升级版参数) Y! P; S' G: R8 P( e* V: D
TB6600步进电机驱动器升级版是一款专业的两相步进电机驱动,可实现正反转控制。通过S1,S2,S3 3位拨码开关选择7档细分控制(1,2/A,2/B,4,8,16,32,),通过S4,S5,S6 3位拨码开关选择8 档电流控制(0.5A,1A,1.5A,2A,2.5A,2.8A,3.0A,3.5A)。适合驱动57,42 型两相、四相混合式步进电机。" t9 L0 V9 x7 F/ {* ?
* h! w- N: v2 R3 L! P
1 h p+ B4 f) c2 V1.信号输入端0 E6 d' r0 C- l9 e% l0 c9 t
PUL+:脉冲信号输入正。( CP+ )
/ o$ P7 g/ p% [PUL-:脉冲信号输入负。( CP- )0 y( N' V% |/ V' \& | A6 Q7 z% J' W8 I% u- N
DIR+:电机正、反转控制正。
% k! l: p n n1 k7 bDIR-:电机正、反转控制负。( M- p9 f; r4 ^9 r
EN+:电机脱机控制正。7 S, t' T# A' R7 d" k6 S& V4 R" i
EN-:电机脱机控制负。9 }4 V, { I7 L0 t
7 @7 |( P( m( G8 H2 U
' Q, y L5 ~, N" a" E共阳极接法:分别将PUL+,DIR+,EN+连接到控制系统的电源上, 如果此电源是+5V则可直接接入,如果此电源大于+5V,则须外部另加限流电阻R,保证给驱动器内部光藕提供8—15mA 的驱动电流。, l. \) `( Z* {+ O* I8 c! v$ b9 ]8 D7 y8 G
共阴极接法:分别将 PUL-,DIR-,EN-连接到控制系统的地端;脉冲输入信号通过PUL+接入,方向信号通过DIR+接入,使能信号通过EN+接入。若需限流电阻,限流电阻R的接法取值与共阳极接法相同。, o; _$ Z4 g! v2 k2 x5 S. t& d7 G
注:EN端可不接,EN有效时电机转子处于自由状态(脱机状态),这时可以手动转动电机转轴。
# b0 }+ i8 ^; I6 B2 q/ f2.电机绕组连接
, ~+ I) U4 q) D0 D/ m; VA+:连接电机绕组A+相。5 a) Q8 l% Y, ~: v! I5 p$ r
A-:连接电机绕组A-相。' {$ q V; ]# o
B+:连接电机绕组B+相。
5 B# J! O! u0 @- |' ]B-:连接电机绕组B-相。
: S- r0 D: O& Q8 Z
L1 u( s! l2 w- s8 Y: b0 j0 A4 J- [
3.电源电压连接
# c, v* J; M0 L1 s; jVCC:电源正端“+”
) @# b% s( e0 a% JGND:电源负端“-”+ X% H+ ?" [: Q
注意:DC直流范围:9-32V。不可以超过此范围,否则会无法正常工作甚至损坏驱动器., @3 d1 k+ R/ Y, p" A0 N
& ^1 B; Q" R) l9 P
$ u! ^; Z7 c/ q4.拨码开关
/ h# _+ D" H8 x G0 v- {! A R
( B0 o) w. P2 P% u8 m! h
电流大小设定' q, ~; Q- w3 A9 h: ^
! Q# H7 J1 `8 q% z" } q
三、STM32F103
0 C% V6 G5 e" J% G" H------说明:引脚部分在文章末尾有解释--------
% x" l9 p5 @+ ]9 x$ P
7 y* o& D5 z4 L6 X8 b6 u% ]
$ B! }7 V, \0 }- O5 X1.引脚连接
2 T H2 L# q" P" U2 p9 V1 yA 0——PUL+: I- m: z% b3 A1 R% v- O$ e* `
A 3——KEY1——V3: Y8 u2 `" e9 E5 d
A12——DIR+ E1 G' H" O0 q
A11——EAN+0 B, Q, b2 e% W% p
GND——EAN- ——KEY0
: G* r7 L) {8 a4 j9 I7 m7 v) {9 { d1 V& Y8 {
7 j1 q9 c3 [; T- T m
2.引脚功能
+ v3 h: w: T) }7 Z# g: [1 H. |; cA0控制电机转速( l7 ~0 [' F; L" z' a/ H
A3控制按键
' g# t' P' t# D- r6 E$ yA9
$ t# @! z% M. O% HA11% } Y9 k" Z$ I" Y
A11控制电机是否为锁死状态
( {3 b7 ~4 _" j5 O6 E% ]& uA12控制电机正反转
* t: P6 A0 h6 A$ k B* B
: _) U6 N1 E9 S! y& H! I! y. B4 i! |8 X$ q( D
3.定时器+ U! Q+ [% a; |0 E7 h. A& P
1.本实验利用定时器TIM2和定时器TIM3构造一个主从定时器,TIM2作为主定时器控制电机的转速,TIM3作为从定时器控制电机的转动角度。
( ^, j! |$ b- |' V% `; Y2.电机的转速和转角还与驱动器自身的细分数有关,但是驱动器细分数是通过影响电机的步距角来影响转速和转角,而TIM2和TIM3是控制步进电机的频率和脉冲数来控制转速转角! L( |3 f B6 B8 k; B: _/ j
3.电机的转速和角度与定时器的关系(在不考虑电机自身的细分数下)& _# A) \9 X, ?* |) x- \5 m2 _. b, L3 W8 N
1 Y. X4 u+ I/ F) i: r) g% f
0 U0 \6 D& p6 R( l. [1 F9 A& o设TIM2的定时周期(即重装值)为nPDTemp2,预分频值为OCPolarity2; x+ j* F. X8 Z" A" _5 Y. z% Z. g* O% y
TIM3的定时周期(即重装值)为nPDTemp3,预分频值为OCPolarity3,( Y3 t) ]# ]4 |& X6 ]
则单片机产生一个脉冲所需要的时间为:
; x( o. x1 h5 q$ r8 ~
; [$ i1 l! {- q! a& m I+ I! Y/ t
3 l/ S- H8 o' W7 q2 L |
本实验中设TIM2的定时周期nPDTemp2=72000/5000-1,预分频值OCPolarity2=999,TIM3的定时周期nPDTemp3=6399,预分频值OCPolarity3为0。即
& y* {6 x O7 m% Q1 E6 D
* m& {, p& h! I8 s! P3 S9 q/ N 定时器共产生nPDTemp3+1=6400个脉冲,电机转过的角度为6400*1.8°=11520°,即电机转了32圈。4 p% ~' Q q T" j
转动速度
8 X2 j9 T8 R+ U, v, d
' F. N& _2 p+ W$ |. H! S7 c! Q
, T" b4 b: w$ U4 t. P0 N& h, y
7 L. o8 d. ~) F- b4.在32细分的情况下电机1rad/s和转1°需要的重装值为nPDTemp2=11.25,nPDTemp3=17.7778。
8 D- P* s. s" W u5 N V* S; E+ @; G# a6 K
* B# i/ m! O- N: P2 P: l
四、程序实现* |* N1 L4 W, {
1.main.c程序3 \) M+ v' M3 }' C8 L3 R
- #include "main.h"
\ N/ n; N- F6 y$ b$ t1 `9 x. z - #include "sys.h"; M8 n( m& x8 B1 c5 d
- #include "usart1.h"
5 M$ [: l D7 c' Y - #include "delay.h") l+ e3 Q0 a0 h8 k: c
- #include "math.h"/ P5 v, q0 u$ n% h
- D. }' l- a5 T9 [! Z1 |; j- u16 t; 1 `+ y9 H- d* y! ?7 Y. n4 m6 ^
- u16 len; //接收到的数据长度
1 w6 E9 n& @' q, f, D, n, T% a - u16 times=0;: V; U0 I- l4 e8 @5 Z! G$ \# U
- char receive_data[60]; //接收到的字符 - M( S; N7 E, T6 f
- char state; //电机正反转标志位0正转,1反转
5 a' C+ F& P2 N9 z8 R+ M8 V - int speed,angle; //旋转速度,角度
4 @+ m3 l% g5 i - int a=0; //判断是否接收到数据 L. h6 n# w) ?( }* k0 c
- int r,data=0; //用于数据转换% P9 J2 ?# |) [, G' f8 h+ O8 G w
- int type; //转换后的数据 % K1 V2 C8 _, {: Z% b& Y( s2 X+ X
- extern u16 USART_RX_STA;
p ?6 D) a8 f, \4 \; @ - 0 W/ Y0 q2 }: P3 x P7 N: T
- /**************************$ g8 h* \. M. A7 n
- * 函数名:delay
2 t! n$ g2 R. ? - * 描述 :延时函数
$ o8 f7 x' r) A) ?" Y - * 输入 :无
/ {, _* T7 _! k& ?; ?/ c- h - * 输出 :无
( b% l7 _* C* a% Z2 b3 Z0 T - * 返回值:无7 A( t; Y& c3 v# n3 ?
- ****************************/* B0 J, v; u) ^' A; x9 k
- void delay()//延时3 q& _ o' b+ U
- {
& P& I* W8 j$ u% b2 Z0 H - int i,j;
! b% C4 T& a6 A) \% d7 y - for(i=0;i<2000;i++)
. u$ B' Y' ^# d0 p7 J$ z7 q - for(j=0;j<1000;j++);) b7 K7 v! T+ N/ R9 i, g' h9 [
- }- J5 f' N/ u' ^6 Z
* ?. t9 n8 c' x0 X, \- /**************************3 A+ f( Q6 @1 U% ?) E
- * 函数名:Waiting_receptio
0 B1 I$ s2 @$ ]) `% j - * 描述 :等待串口接收数据
; t V% M4 {5 ^+ {8 u - * 输入 :无 7 R# e+ @3 J# |+ o) S( k
- * 输出 :无
) M0 T, d% ?. R7 [) W - * 返回值:无
% K7 x* R2 X: | - ****************************/
|7 Y r2 V& I5 V" k+ _% A - void Waiting_reception(void)& `0 b+ G) _8 \+ d# I* g5 I1 ^, T
- {# c6 C9 y: R( z
- while(a==0)//等待数据发送完成) C1 K( X4 n* ?) ]9 A
- {
: t6 ^8 r+ l% G - delay_ms(100);
$ x! Z6 v2 ?- I4 A' ?+ [ - if(a==1)//接收到数据( m& k$ Z1 R+ h5 {, ?; A# A
- {* e( z" L0 K& h- t0 R( `
- if(USART_RX_STA&0x8000)//(串口接收用到了正点原子的例程)) b7 d; ^0 }2 _1 p7 y
- {2 y9 [7 S5 s$ T5 k* x. V
- len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
2 j* l3 [6 {5 R" `2 v5 W7 I" ^ - r=len;
3 k. z# \2 w: b' O% f - type=0;2 G8 M. [3 m F% _2 z
- for(t=0;t<len;t++)//拷贝数据,将字符转换为十进制数
+ I2 `0 L7 z- d/ h6 r! v; k - {
( r1 z1 ?+ E! G+ E - receive_data[t]=USART_RX_BUF[t];' U; u0 q7 y" V
- data=(int)receive_data[t]-48;- e; q* ?2 W" @
- r=r-1;
- _* C4 b/ y) [+ `+ }/ m - type=type+data*(pow(10,r));
, U8 e3 b3 {% r# n& Z( U- K - }
# F5 o9 \1 R: X9 W+ F, h& r - USART_RX_STA=0;
; R# @7 h' @2 \/ A- b - a=0;- q' i$ t* a/ L( |. @0 O4 p' Q
- delay_ms(500);
$ |; q' Z% l3 @9 h* @5 m - break;
' R% p8 H: H; V) q v& F - }: h" m6 X$ l2 N
- }
( B9 O. R1 f7 T( Y' F% K* w - }
" k4 F S& k; b - }
6 @9 W7 h0 }4 }' v2 L - /**************************
. W/ r; k0 W% @9 V. r. o2 ~ - * 函数名:KeyStates! M8 Y- U* M% Z5 g
- * 描述 :监测按键状态5 ^/ e0 R8 j+ _8 @5 v
- * 输入 :无
3 G6 W0 I+ o0 A+ A - * 输出 :无3 Q7 V; F) h4 r6 a) ?5 Y R
- * 返回值:0/14 |! \4 p, x h9 t. S: y/ S1 h
- ****************************/$ S/ V- d5 g0 x4 |8 U+ _
- u8 KeyStates()//按键状态
% q" Z* S5 f8 |6 n5 ?; m- f3 n. ~ - {
% M4 h# i- T" r# t; R# ?+ p. r - static u8 i = 0;7 g- }6 {, ]+ }+ B$ X
- if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)
. g j: y# K2 M/ o - {
3 a% q8 V$ x6 O# r - delay();
" t& \, ~7 A1 E8 k h$ n - if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0)
$ p, _3 }4 _$ f5 s: r; j4 K - while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)==0);
+ v( n! L+ I& D6 l& U/ l) \ - i = ~i;) r! Q+ X& z3 d5 D( \1 B; Y# [7 ]( `
- }1 a7 r% k# f$ i1 \' ?$ l
- return i;) i) A& g' l- M
- }, e' E, |0 c' ]* Q! s' e: A( Z2 L
- /****************: b; e# W, l, ]7 K* o* |
- * 函数名:main
3 N/ J4 V% O1 T9 H- o* b& b7 g; ~6 { - * 描述 :主函数& x* p. v! T* }1 k
- * 输入 :无
% z9 c) Z7 p) l, V8 k, U% Z - * 输出 :无; `9 F$ M' o" b; Z% @3 i
- ******************/2 J$ _9 I. L5 ^
- int main(void)+ v$ J3 C& [+ w- d% @
- {
8 n" s- l+ n/ W: c1 E - NVIC_Configuration(); //中断初始化
% Z0 P8 P0 d, P" q6 g. X& m O+ ]- c - GPIO_Config(); //IO口初始化, J6 L1 Z7 w9 C2 \' [- ^
- USART1_Config(); //串口初始化; @9 L6 X* x4 T3 ^) K, p( x
- delay_init(); //延时函数初始化
' q l' b8 h. S5 d2 q - GPIO_ResetBits(GPIOA, GPIO_Pin_11);//A11置零 A11——EAN+& r1 a4 Z# M! G, ~ y
- GPIO_ResetBits(GPIOA, GPIO_Pin_12);//A12置零 A12——DIR+
7 n1 H) f2 L& k M& P, Y- j - while(1)
) k1 L! q N' i& E - {
W, K) L1 u- }" w: L1 g - delay_ms(100);
# U |. K! d0 R - Initial_state: printf("\r\n 请选择正反转,正转输入0,反转输入1 (以新行作为结束标志)\r\n"); 6 } W+ ^# k% q
- Waiting_reception();/ B; ?2 K7 `* o
- state=type;//将接收到的数据给type/ ]# x; p' R* D7 [5 M
- if(type==0)//电机正转+ w$ @3 I0 |- K: a
- {1 z4 M5 `1 Z$ W- z
- GPIO_SetBits(GPIOA, GPIO_Pin_12);//电机正转+ J4 ]! ?4 A. T1 i( B
- printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");
. L `7 b7 H4 N& B+ Y - , ^ s R& [3 t3 g5 R
- /*********************************************此模块用于配置速度参数********************************************************/; e8 y! @2 Q9 c
1 f l, {2 O- P3 a" L6 u- part1:Waiting_reception();
; M% n% Z6 k- Y - speed =type;//将接收到的数据给speed5 I6 w# K$ n2 W# b$ x) ~# l
- if(speed==0)goto Initial_state;//如果是0则返回初始模式+ d4 y( n8 r$ i) }+ C, _; }9 }* V
- else{
8 A& q; K3 t% S; U! A& J, x - if(speed>=15)
r' S0 [3 X; C1 c" z+ C4 X - {
N3 |/ K2 _3 b- d4 G( D - printf("\r\n 旋转速度>15rad/s,请重新选择旋转速度。\r\n");
: a6 q4 v7 ` k2 F* a+ h3 @ - goto part1;
4 k" ?" I3 ^' B - }
- Y" Y7 w* A- M# D6 L- S0 I6 k' @ - else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式 \r\n",speed);
/ F9 e+ _5 n/ _* N! z' H+ d - }: E2 q5 y" p! u' b. W' }
- 1 c8 S, c T! `
- /*********************************************此模块用于配置角度参数********************************************************/ 7 j0 e3 |$ x1 f3 |$ y2 X' X; |1 y
7 k& T; {; X: O) F6 t# W- Waiting_reception();
4 ?1 p w* P2 e A& D2 i d - angle =type;//将接收到的数据给type7 a" h, G# j: r0 y' X
- for(;;)
% { M! n: H5 {# [+ Z; v: K - {
' W2 M7 O% p8 i R- e3 f9 X - if(angle>0)//接收到的数据不是07 B6 x3 ^) u9 e3 {" M* K$ x
- {
, i6 O$ p8 @+ ^' s8 d- t. [ - TIM2_Master__TIM3_Slave_Configuration(speed,angle); // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度
. W3 m3 W( m2 V6 K% R, t* l+ r - delay_ms(20000);//电机保护- I- D8 v& O; X
- printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式; \r\n",angle);
# Q$ ^6 ?+ D! s - angle=0;
* D, Z/ a0 q/ ~ - Waiting_reception();
+ O; c4 Q; V. ~( l2 O- B6 H% W - angle =type;
1 ^% k r; d# d/ Z - }else{
. {. ^% K' h+ V- S) M! } - if(angle==0)goto Initial_state;//返回初始状态 , j8 W% D& X9 _! t
- else {# I0 ?! G* f! A+ V3 T: P6 D# g1 z
- printf("\r\n 角度错误,已返回初始模式 \r\n");
) Y2 j+ l0 w" N) m6 v' { - goto Initial_state;
$ U4 G/ f0 T. z; N4 f - }
( j/ k& R- r- {( P8 T! |. g - }
+ H; j8 ~# k9 z' ?! p M' ~ - }
9 y% c* n1 ]6 X' |$ D% m7 K( {, y - }
8 j: J2 N1 m* d3 u _! f - /*********************************************反转模式********************************************************/ 5 c/ H0 n. x* j
- else{
3 ~7 h: e# h& ] - if(type==1)
$ w( _+ y2 Q3 p1 {. f - {
: z% o ?' D! Q0 d - GPIO_ResetBits(GPIOA, GPIO_Pin_12);//电机反转. {. d* K* @* L& F$ T, `+ A
- printf("\r\n 电机为正转模式,请输入旋转速度(rad/s),输入0返回初始模式 \r\n");- U% r$ @& w+ `& P- |% q- z
-
- Q5 d0 K& b2 X. M! t0 o - /*********************************************此模块用于配置速度参数********************************************************/( C4 j" i, K# N# w6 h; v4 {
- part2: Waiting_reception();
' w- ~* y, P& i$ T' G( p - speed =type;//将接收到的数据给speed# F3 K$ [% E4 w# O9 u8 l; U' }
- if(speed==0)goto Initial_state;//如果是0则返回初始模式
6 W7 b g: \- n1 O$ z% b1 x - else{
5 t7 y# R/ V) [' O& _. D9 H7 J - if(speed>=15)
' V$ c( I: K+ v1 u- q p2 z& U3 E - {
* G k: _( p, B" j$ z$ L - printf("\r\n旋转速度>15rad/s,请重新选择旋转速度。\r\n");$ P" \- I6 d$ {8 R) G! _" A) O6 f
- goto part2;% Z5 H$ a3 n2 T: U! p0 s7 \
- }else printf("\r\n 电机旋转速度为%d rad/s,请输入旋转角度,输入0返回初始模式 \r\n",speed);
3 V8 ~2 G# |0 H: @# |2 w9 @6 w - }
7 s$ y& R% l% }) [ - /*********************************************此模块用于配置角度参数********************************************************/
5 z" o1 c. ^* f3 T3 X; M - Waiting_reception();
4 K7 g2 f, o6 G& w, `! S* [0 m7 E - angle =type;//将接收到的数据给type
$ ^4 M$ r+ ]: y: R+ G$ D- E. d0 e - for(;;)% e5 d \2 e' r0 r1 R
- {8 G5 J+ ^+ k( x
- if(angle>0)//接收到的数据不是06 G7 V) T+ ^2 @" c& V1 ^
- {* C# G; P. n/ ?+ N- V5 g' P
- TIM2_Master__TIM3_Slave_Configuration(speed,angle); // 配置TIM2和TIM3的重装值 ,改变电机转动速度和角度
6 j! r7 O1 @ G! I1 q - delay_ms(20000);//电机保护" c n% j& {! n
- printf("\r\n 电机已旋转%d °,请输入下一次旋转角度,输入0返回初始模式;\r\n",angle);
! ]2 K! j$ f$ O _3 ~0 e - angle=0;2 x: M# o2 J& N, k
- Waiting_reception(); ) c: |. S9 J7 s9 z
- angle =type; / J6 i7 R& s/ a7 n7 n
- }else{" H; a6 P! x6 K$ D% S: U0 N
- if(angle==0)goto Initial_state;//返回初始状态 - V6 S' O. e& X3 \: |$ w
- else {- D, K; u# ?+ A/ t; G9 T
- printf("\r\n 角度错误,已返回初始模式 \r\n");
7 p9 k$ e" n/ O# d! n: [ - goto Initial_state;
2 d& [1 E0 }6 J% {$ E E% `9 | - }
8 u2 K9 d: L( b- R - }! K' o$ ^+ Q* K; w+ c7 x
- }
$ [4 ^( ^4 @1 ]' c# j. U- z - /****************************************************************************************************************************/
! S7 U( }, I3 r! L$ X - }else{//if(a!=0)&(a!=1)
5 i' v0 |+ @6 K! i3 E - type=NULL;; k: t/ Z) a) d i$ ~# w G. E
- printf("\r\n 输入无效 \r\n");; `$ }, i. C! u1 L
- goto Initial_state;//返回初始状态2 p" N) i! W( C! |
- }
7 \* l9 a' T" L - }
4 T: Z9 Q8 R- a- B! D6 q - }1 R; }( Q7 p9 [" d/ F2 F
- }
% x& O+ q5 G" e9 `/ M; q
复制代码 2.main.h程序: z J! |6 d* J
- #ifndef _MAIN_H' t/ }8 g( f8 S, o) H" x$ U+ q
- #define _MAIN_H
7 D3 S' k" \+ M( h& B - #include <stm32f10x.h>
8 Q- n% Z5 w* d - #include <usart1.h>
2 u1 _. o) e9 c: b, }9 t# n5 ?+ h - #include <misc.h>
5 Q% q! g8 Z* `' g. K- a. n! ]3 B# M - #include <nvic.h>
! V1 A& L& b7 s. K- I& f - #include <stdio.h>0 `: m( e4 }% p6 E- {" X
- #include "stm32f10x_tim.h"
! W" I3 Q: T' c( D8 B1 ?6 W- Z' I - #include "timer.h"
2 u' V$ i% K) }6 q - #endif( w. U: s/ t7 i& T( A
复制代码 3.time.c程序
5 Z; Y4 d* t/ Q/ w$ ~- #include "timer.h"
- p7 r' ]: S8 P2 u - /**************************% f9 n: B( [8 C% w4 s
- * 函数名:GPIO_Config) O4 R" \! b! \( [
- * 描述 :无
6 P) f: }! p6 { Y9 e a - * 输入 :无
* A0 ]4 }/ Y* P! H! b9 c) | - * 输出 :无+ ?' ]6 Q+ c; k( {. [5 |/ A
- * 调用 :主函数! }& q( x- D7 L7 I
- * 返回值:无
) B) l% n) i; x - ****************************/: ^/ B1 b0 V8 T
- void GPIO_Config(void)
" C" u0 T& k' N/ F9 Z2 P - {
# b" C, ^; J5 Z8 G - GPIO_InitTypeDef GPIO_InitStructure; 8 h. t2 n/ z5 W$ L" x* p
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能IOA! g4 i) ?9 n7 w' |) m$ C/ r! k/ ~
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3, ENABLE); //使能TIM2,TIM3
' S! Y; j( M/ M# o6 A9 ~ - 3 x/ x0 |- ^* o2 [9 w; @' v
- /* Timer2 Channel 1, PA0 */ 9 O j& i6 v& x! O
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
" x; {7 f( y8 C' Z! X - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用输出+ U; C7 b( U* j
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
, G: k) Y# P: e' r3 r7 S3 z - GPIO_Init(GPIOA, &GPIO_InitStructure);
2 z# y2 `- I; i6 y' X5 u1 ` -
; l. {3 H; T2 o - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_11|GPIO_Pin_12; I8 l4 R# ~/ i$ F
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //通用推挽输出模式
6 q5 f- h9 L5 t* w1 ~# }' E3 m - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //指定GPIO引脚可输出的最高频率为50MHZ
2 [ k4 G2 l- [: P9 ] - GPIO_Init(GPIOA, &GPIO_InitStructure); //( {4 k4 O8 b/ y' n0 x
- GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向
" L! J+ `4 c! W" T; D - GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭 使能( }7 J( p/ k( \4 w; F4 V2 L1 J
- GPIO_SetBits(GPIOA, GPIO_Pin_11);//指定引脚输出低电平,此时灯全灭,方向
% x* _) A6 Z! }0 F% d - GPIO_SetBits(GPIOA, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭 使能
. |+ S. `5 x4 D9 h% S, k1 A -
9 P0 j! \) d Q* k - 0 B4 @5 Z5 @2 a3 W2 c
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
1 j( t0 c$ q( I0 c* v ~ - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //通用推挽输出模式- u; {) t1 k% d( o" S9 v8 i, `5 J
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //指定GPIO引脚可输出的最高频率为50MHZ3 _( @: U( }8 j0 ~: Y& X
- GPIO_Init(GPIOA, &GPIO_InitStructure); //* `% B* P1 D' o9 z% B
-
) v# Y' P, J) A! c) `6 b& a0 r5 L6 G9 V - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 3 V h( A0 b8 o( @6 E' f9 B8 m3 w
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
3 {5 P; x/ @" }/ h+ x" U- c7 [, N( B - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //通用推挽输出模式
; \1 z# D% ^$ g7 J2 D) I - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //指定GPIO引脚可输出的最高频率为50MHZ- a; c, ?( R, H
- GPIO_Init(GPIOB, &GPIO_InitStructure); //
0 p( Y1 y1 } D0 Q* n+ D - GPIO_ResetBits(GPIOB, GPIO_Pin_12);//指定引脚输出低电平,此时灯全灭 使能
6 y$ v3 i& }' [( E/ w- b - 7 {: O0 ~ O8 k
- //GPIO_ResetBits GPIO_SetBits) }1 R( U! I4 J$ W1 _
- }& t8 b8 {% U) u
, k1 @8 c6 L; x$ f7 {; N3 u1 V# o! n4 `- //================================================================================8 ?* W: Z7 _1 P
- /**************************
) z3 V* @4 w% Y5 J8 K/ h* a. w d - * 函数名:TIM2_Master__TIM3_Slave_Configuration
7 l/ U0 J u: E/ U - * 描述 :主从定时器配置& a3 i; R" u" i: ~
- * 输入 :电机转速speed,转角angle
5 R' U; H; d4 U - * 输出 :无
8 ]( d8 e+ s+ n% g8 T+ n - * 调用 :主函数
3 y/ }9 O4 ^. D6 j6 C% @5 c - * 返回值:无
3 A& R* i; v/ ^! a1 r - ****************************/ k, E; C2 g G: f
- void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency, u32 pulse) ' ~0 Z4 G* Y" J) F
- {! e8 G- t# Z+ o4 R
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
) ]1 P! e$ w, U1 ~9 ^1 U' d7 { - TIM_OCInitTypeDef TIM_OCInitStructure; 6 S5 e" N( w$ \, p5 t7 f* e
- * n2 d+ t% T i& r
- u16 nPDTemp ; : w# Z$ U- K% ?1 B% g5 @
- u16 pulse_number;
( o) ?9 C# \4 y3 E: S) v& m+ W - float p=PulseFrequency;
. b; D2 I/ }$ d( v6 k* g% B X - TIM_Cmd(TIM2, DISABLE); " h9 q0 c" @/ P5 \& c5 M1 ]% q
- nPDTemp = (11.25/p); //TIM2重装值是11.25时1s转一圈(电机32细分下)
5 W0 l" }; |& s# Y6 V3 P0 r5 Y; h - pulse_number = (16.7778*pulse);//TIM3重装值是16.7778时转1°(电机32细分下)
' n8 \ P/ C( j ?/ O. k8 Y - ' n8 E' M* d- b1 G$ d* z
- // 时基配置:配置PWM输出定时器——TIM2 , n" ?! }- L3 d7 \3 b H
- /* Time base configuration */
0 L1 c3 i; A ]4 M d* U - TIM_TimeBaseStructure.TIM_Period = nPDTemp; //定时周期为nPDTemp
8 h3 j8 w* j) |, V( y - TIM_TimeBaseStructure.TIM_Prescaler = 999; //预分频值1000,即f=72khz/ }' i8 z0 k/ C' P; r
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分频因子,会影响滤波器采样频率,与本实验无影响
& K* E5 K" i) l1 C6 y - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式
+ c( F% Q0 n6 ~5 d" z* `+ o, n - TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //指定重复计数器值
8 _8 n( v2 [+ X) i: O" r1 q - TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
: _5 S( b9 O9 Q! e+ Z+ _8 n -
/ p- W8 | D6 G4 t C9 m8 Y! V - // 输出配置:配置PWM输出定时器——TIM2 4 }1 f1 ~; ^8 g! C
- /* PWM1 Mode configuration: Channel1 */ 7 q7 ~ c- h1 L
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM 脉冲宽度调制模式 1
8 d$ F0 k, t' w& D0 B' e8 m+ n - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高电平有效
* ` G5 w& d4 N( J) F R - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能输出$ Y3 A/ J( r' P9 U: B. E; e
- TIM_OCInitStructure.TIM_Pulse = nPDTemp>>1;//50% //比较tim_ccr的值,输出脉冲发生跳变
, _* a) G" ?7 d5 G8 t6 a1 s6 [ - TIM_OC1Init(TIM2, &TIM_OCInitStructure); //初始化/ n H, R! _ @
- TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能 TIMx 在 CCR1 上的预装载寄存器3 k3 e7 H1 [- R( ^) R
- TIM_ARRPreloadConfig(TIM2, ENABLE); //使能或者失能 TIMx 在 ARR 上的预装载寄存器' P' h2 Y8 N5 L1 Q8 O
- ; o1 N- o( h# ^7 n) X
- // 时基配置:配置脉冲计数寄存器——TIM3 ( t5 S' w. q4 q8 f! {. Q
- TIM_TimeBaseStructure.TIM_Period = pulse_number; //0x1900是360°;//改变给电机的脉冲个数 4 b$ _% n; a7 n( t! X3 h
- TIM_TimeBaseStructure.TIM_Prescaler = 0; # M5 J6 h5 O2 Y& i2 p9 A9 b
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- F/ w, a; V: Z/ B: G - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
$ K% F3 H: H1 ^9 E9 S4 D9 I - TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
* p( T3 A6 X+ G6 m3 x9 H - TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
: N, x% }9 w5 I) k4 V2 p* | - // 输出配置:配置输出比较非主动模式定时器——TIM31 {' k1 {3 u! h1 P$ W( n( s6 X) J
- // Output Compare Active Mode configuration: Channel1 " G9 s* b, M: l+ \$ F
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; //输出比较非主动模式,(匹配时设置输出引脚为无效 电平,当计数值为比较/捕获寄存器值相同时,强制输出为低电平) ' k6 G6 M4 k$ \0 U
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; + ]9 {: G \, N: Y5 Z2 |
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
8 r5 @; ?1 e" B% k6 b# R8 } - TIM_OCInitStructure.TIM_Pulse = 0xFFFF; // 这里的配置值意义不大
+ `3 i2 s G; b" F% \ - TIM_OC1Init(TIM3, &TIM_OCInitStructure); * I' F7 ^: Y" L/ l
+ y2 l( Q( y5 Z3 y3 P# C- // 配置TIM2为主定时器 , ^5 C8 {# o p% f: D
- // Select the Master Slave Mode 7 ^2 U1 |! d) q1 f7 ?1 R$ i
- TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable); //设置 TIM2 主/从模式并使能1 r, H% Z3 H5 O, A7 S0 l, ]/ W
- // Master Mode selection
# L2 f* N* }- v# G5 d/ G. A+ l3 B - TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); //使用更新事件作为触发输出/ q1 r! b( @* Q V6 _- c) P ^1 j, Z2 n
-
7 ]4 ?/ o* h# i( k - // 配置TIM3为从定时器 $ p) Y4 l+ Y5 \0 U. f
- // Slave Mode selection: TIM3
, T& ~/ }& ^* x9 H# b. L6 G. }( {! V - TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated); //选择 TIM3为从模式 TIM_SlaveMode_Gated-当触发信号(TRGI)为高电平时计数器时钟使能
% w4 D2 v& a* z2 c8 y* \0 G2 \" H - TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); //选择 TIM3 输入触发源 TIM_TS_ITR1-TIM 内部触发 1
- j! t5 s( G5 A - TIM_ITRxExternalClockConfig(TIM3, TIM_TS_ITR1);//设置 TIM3 内部触发为外部时钟模式 TIM_TS_ITR1-TIM 内部触发 13 z0 l9 ~5 L' t9 Z& Y2 k6 m
- TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); //使能TIM3 TIM 捕获/比较 1 中断源
6 V2 F8 k" E; l$ F2 o -
S2 j: w& y0 O0 C" e( D4 B0 i - TIM_Cmd(TIM2, ENABLE); ) Z; D7 h( h8 T# n- S6 R
- TIM_Cmd(TIM3, ENABLE); / n7 Y9 N6 @4 x/ {- t6 S
- }
* e, B" o- l& ~6 Z, D, ^) J+ b4 C - ; ?! M3 \* W+ h
- /****************************************************- n# V& n* v* g T% j# l; b3 T
- * 函数名:Output_Pulse
6 J, v( p$ Y9 l+ v8 z/ W - * 描述 :无- {: l7 V$ v7 k6 ?$ M' \
- * 输入 :无
/ N+ S9 A i% u/ e0 { - * 输出 :无8 T8 Q o, d8 E" B3 {9 h
- * 返回值:无- ~6 h9 R, X; G1 J$ R
- ******************************************************/ k6 i/ p* j& `0 K/ Q& Z
- void Output_Pulse(u16 Num): D8 q- i& U$ u/ y# j
- {
3 F/ W& Q- G% c# I9 B - GPIO_ResetBits(GPIOA, GPIO_Pin_2);//指定引脚输出低电平,此时灯全灭 使能# ^2 b' i) c y' I [, I
- TIM3->CCR1 = Num; 8 W: c! W# g$ @: Q2 {' {% W
- TIM3->CNT = 0;
" E, X8 @8 v' ^. ^/ }/ q/ L' D% { - TIM_Cmd(TIM3, ENABLE); $ {0 u& ]; \6 q8 p) E
- TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
( b* G4 }( F& Z# w - TIM_Cmd(TIM2, ENABLE); - F) [% v, I W: \
- }8 o' e$ u. g, g; W1 ^& I# A P
- " g* j# G3 ~6 E/ L6 e4 F6 r/ ]
- /****************************************************+ \7 E9 O* b) Z X
- * 函数名:angle_set& J5 M5 }6 e, Z. i/ L j
- * 描述 :无2 P/ V t; [- F% a# r
- * 输入 :无 & }- l9 W( `/ T8 e) D& @: R6 r5 C
- * 输出 :无
! Y4 I7 @$ Q8 @; J* J, j% O' ~ - * 返回值:无; }$ A9 i' R: P3 E# H. O
- ******************************************************/ I, H r/ Z; @3 k
- void angle_set(u8 dir,u8 angle)/ a+ X" I+ p; Q0 g z4 f6 ?
- {. T: {9 N5 u6 `& Z
- if(dir==0)* V! v2 n/ ]9 q, n* h1 a+ S. J
- GPIO_ResetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向; n' |8 g0 |( C; X* o1 u0 n/ [
- else4 t; y/ T& e3 E( p% }% a
- GPIO_SetBits(GPIOA, GPIO_Pin_1);//指定引脚输出低电平,此时灯全灭,方向6 n# D# `- P; ~" \0 b# [+ A2 K
-
) x% U: d7 P+ I. C1 m j - Output_Pulse(angle*6400);; i7 y( l" ~/ _7 W
- }( t- e" s. b! O0 z* B* L
复制代码 4.time.h程序
' ] q, ~& D8 \$ X- #ifndef __TIMER_H
, u ?. E/ F% m. v% s3 r! h9 o" Q - #define __TIMER_H1 ~ R4 X$ q" v) {' i8 A r4 M* ?4 z5 g
- #include "main.h"0 w7 w( A6 e8 G0 x2 q/ u
- extern unsigned char Flag;9 }1 ~3 s* e5 L6 j- H5 |/ J, t
- extern unsigned char TIM2_Pulse_TIM3_Counter_OK;! O4 C' e7 o0 b, {3 j0 D$ Z
- void GPIO_Config(void);
3 x% I, D+ Q% ` o - void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency,u32 pulse);$ c7 Q! p) g4 D& P
- void Frequence_Setting(u32 PulseFrequency);( V/ p- y5 V2 l& e5 }6 k7 G
- void Output_Pulse(u16 Num);5 \8 f0 d7 H, z4 ]* o4 M) Y
- void angle_set(u8 dir,u8 angle);
% I8 ^8 E/ a& V( [7 ? - #endif" h' }* M. x4 C; @
复制代码 5.usart1.c程序. V! R8 z/ B$ `1 V" h; I
- #include <main.h>
) B9 {( N3 \% U2 c, i4 o! } - #include <usart1.h>
2 f; p+ }: y; A - #include <string.h>1 f: T" N5 g# c9 H0 M7 f ?" U% P
- #include <math.h>! @! s6 F. A7 A j/ Y( G7 c# a! I
- [0 q" j# N$ \) ?9 O3 x% a% P. ~9 {- /******************************************************5 ~; d: d' p+ Q1 R! b
- * 函数名:USART1_Config
4 N) P9 s1 O9 c9 s% X- A T9 [% k - * 描述 :USART1 GPIO 配置,工作模式配置* P- }/ k# h* R: S q2 N
- * 输入 :无
3 P8 u! h2 E. V( |* Y - * 输出 : 无
2 K4 C% F {) p - * 调用 :外部调用1 [ v: k7 {; s: C* E' ]$ u) L& y( f
- ***************************************************** */
7 @6 _1 n4 l5 @# ]% E, Y - void USART1_Config(void)
6 T8 o4 W: R% ^1 j - {
3 v9 F! |3 k+ T - GPIO_InitTypeDef GPIO_InitStructure;
: J, n, e- F: ^+ l& E - USART_InitTypeDef USART_InitStructure;
: g/ l0 D- e4 E2 z5 t6 w - - R7 D& s6 G. E
- /* config USART1 clock */) C, b0 a3 F2 W5 w# r/ t
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);0 R |* t; B" O- X$ A/ x+ M
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
+ f0 r' U; ?( p* v Z3 V1 o+ R - : k2 D5 c3 n* B! P! G
- /* USART1 GPIO config */. k) f1 [* G9 S* X; S
- /* Configure USART1 Tx (PA.09) as alternate function push-pull */' ?; _1 {' q" w j
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;# G& b' P6 ^# H9 _
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
$ ^: w% C; H8 \) ~7 h - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
1 j$ m% K. q+ k( b% R - GPIO_Init(GPIOA, &GPIO_InitStructure);
# P+ {, I* e, e+ e+ N: F" z1 E - /* Configure USART1 Rx (PA.10) as input floating */; ^9 n4 o) k" ?8 y. N: a( h1 O
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;5 Q9 d6 w) T `" [9 a( Z
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
( U( y; p/ L# }/ f- w - GPIO_Init(GPIOA, &GPIO_InitStructure);0 N# s! f4 o6 N5 @* |9 v% y
-
6 C% _- Y. ]2 P4 s1 J+ k* @ - /* USART1 mode config */
* Z( T$ Y. c8 A, ~1 d3 f - USART_InitStructure.USART_BaudRate = 115200;
8 ^( w4 D' x% v; q* ?9 Y! Q - USART_InitStructure.USART_WordLength = USART_WordLength_8b;
Z$ }. F/ a* U s/ R - USART_InitStructure.USART_StopBits = USART_StopBits_1;
5 P5 U1 t8 u, ?/ x - USART_InitStructure.USART_Parity = USART_Parity_No ;
' F* A) x5 Q! t" }# I+ s5 }+ q6 r - USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;5 b, b# a& ?3 W
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
. ]8 f9 f7 n0 l+ g' m* _ - USART_Init(USART1, &USART_InitStructure);
0 J: q! M( n5 g - USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);1 _' a& K* @' R; V) Z6 b
-
' d# T S H$ C - USART_Cmd(USART1, ENABLE);
, _5 _$ K6 O" b& h q' y( { - }" @+ C) G$ T8 W% s
; c1 g5 b5 i4 u: g- /******************************************************$ m: ^, a; t) U) S: v
- * 函数名:fputc. \0 q8 I: r+ e/ e9 B9 u* h
- * 描述 :重定向c库函数printf到USART1
) p$ [* K* H. J7 x+ n e- ] - * 输入 :无4 e4 U% D: H' p* x
- * 输出 :无
/ |+ o/ ]* O- a+ @ - * 调用 :由printf调用
' F" Q0 _6 i, a1 l9 a, J3 J8 G - ***************************************************** */
# y$ R& k. O( {. C - int fputc(int ch, FILE *f), x5 A) ^6 m. r
- {& v) x3 w, p$ j) n
- /* 将Printf内容发往串口 */
( j; ^7 f" `$ `( Z - USART_SendData(USART1, (unsigned char) ch);
, ?& o4 v$ _( x - while (!(USART1->SR & USART_FLAG_TXE));
. r2 ~7 r: T" w! B -
; O0 G/ n3 Q! A2 m9 z2 `# K - return (ch);% _ k$ T0 Y, `/ ?8 H0 `
- }
3 ]& U4 t* q4 |. }* y" o - + U, \; i( k: u5 @( v
- /*-------------------------------------------------------------------------------*/( Q& N- V e; u+ [
- /******************************************************; X8 c7 U- z; S, O% b- V
- * 函数名:USART1_IRQHandler
) O5 d. I& h1 b' Y7 w5 G. l4 z - * 描述 :USART1中断服务函数
/ c7 x' `5 f6 k% S- q3 \2 {8 B( y - * 输入 :无
0 Z$ U6 m/ `$ d) B - * 输出 :无1 ~4 V% H! g; V6 t
- * 调用 :中断调用
' A! K- V9 t5 r7 s% l. l$ c4 I - ***************************************************** */
' u% H, `6 K& t4 p - u8 Res;
" s. O4 V# r$ i1 v* v4 J - extern int a;
7 T- Q5 k$ `1 Z! K' D - u16 USART_RX_STA=0; //接收状态标记 1 S$ u& W. d/ g% ~1 G
- u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.1 X% V1 v) N, Y
- void USART1_IRQHandler(void) //串口1中断服务程序
& X$ `# \4 n2 _5 U' W& \$ h2 [ - {
! @% U! h/ F! c4 T) J% `/ O -
$ \2 m' z& V* e - Res =USART_ReceiveData(USART1); //读取接收到的数据
- m) v- J+ j! I -
( w0 u& K% [, O' S - if((USART_RX_STA&0x8000)==0)//接收未完成
' k5 N/ }' d& N6 y - {
|7 ~& W% Z q; { - if(USART_RX_STA&0x4000)//接收到了0x0d
* y/ t5 p+ o: x; X1 v6 M - {
3 e5 \ P, t1 L3 P" ~$ _' r5 I - if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始1 k- ?3 _: D' f3 T$ v
- else USART_RX_STA|=0x8000; //接收完成了
. p0 k& C4 a1 e" w) r - }
6 ^( F, D H; g8 S0 P$ i- n% }( \ - else //还没收到0X0D1 u1 ?& a) j1 |2 ^ Q! d6 N% a
- {
* f( q) v1 Z( c( A( N - if(Res==0x0d)USART_RX_STA|=0x4000;' B% `' l! j3 |+ u
- else$ L9 b8 [: Y& P
- {3 F( T" g/ |3 y
- USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;* T9 z$ t9 p' X3 K. g
- USART_RX_STA++;1 j+ x. _4 w0 K. o( J2 p) x7 {% ^
- if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收 % F: s3 e* `1 e) v3 |6 t9 D
- }
$ G& }5 I; E+ | - }
& ^& _/ L$ b( i& Y9 ?& H- T - } # S# Z. t7 r5 W3 W3 q
- a=1;
]3 v$ v( Y S0 X - }
" }0 j( ?0 |( l, \, q1 J2 k - #if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
N4 s2 x7 r' V5 v - OSIntExit();
2 C, F4 W- u0 V. j3 S - #endif- W' o* O# u$ K- x8 z$ S: _4 Y
- . K% x+ X/ ^ s% ?* m* O. b- ?
- /******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/
% A+ i7 `! C {! }
复制代码 6.usart1.h程序* T. g1 C0 U8 H) s
- #ifndef __USART1_H
: C* k. K7 V5 N2 u1 M - #define __USART1_H
4 |8 r& Y& f5 v2 A! \0 J' s0 [ - #include <main.h>4 B- u- C6 M Z! v2 Z7 M4 m- H. M4 r
- #include <stdio.h>2 n5 J+ J& b7 q! F, `
- 9 R" z8 v* z s1 H5 J/ U, L
- #define USART_REC_LEN 200 //定义最大接收字节数 200
0 K: o: o7 o% A) Z" a) ` - #define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收
; X4 d1 S' ~! `& i3 { - extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 ! k* }3 n1 p$ I
- extern u16 USART_RX_STA; //接收状态标记
# R0 X9 a) _' C) I3 U1 F: ]& n/ r% K - int simple_atoi(char *source);. ^* C, T" P" t5 b9 c! I
- void USART1_Config(void);# b: U: N9 g3 a2 W" L9 G
- #endif /* __USART1_H */
% D3 _+ |: u1 T9 S( P" J) D0 e
复制代码 源码:/ Q5 t) Q4 |. q/ y& x
步进电机程序—串口控制速度角度.zip
(4.75 MB, 下载次数: 113)
|