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