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