stm32f103c8t6利用蓝牙控制180度舵机
/ h+ J3 z( G( K3 o4 }! c' A; c$ k5 I; B' R, [
关于蓝牙模块部分,如果不了解蓝牙模块的可以看我之前发的东西。
- V5 k9 {( L# e t一般来说,舵机接收的PWM信号频率为50HZ,即周期为20ms。当高电平的脉宽在0.5ms-2.5ms之间时舵机就可以对应旋转到不同的角度。以180度角度舵机为例,那么对应的控制关系是这样的:
- i, C% h6 Z3 D: N: {, D0.5ms--------------0度;4 m5 ^& p/ m5 a
1.0ms------------45度;
2 p1 I1 o# f- s" i! B e1.5ms------------90度;; l. [: Y" P) V; w5 W( p
2.0ms-----------135度;5 x% t4 @& Q1 T* o# N z
2.5ms-----------180度;
& Q \/ T8 x% b& S# V9 ]5 s
$ A* v8 {- L7 V3 a! b; K. o4 K
8 A7 b7 u% P1 @% F. _; s! {$ f [3 a
# w+ _! S$ a; y$ x; [5 C7 \) U
关于舵机的话,本人用的是6~8.4V的的60KG大舵机,这里需要注意的是, 控制板上面只提供5V电压,满足不了这种舵机的电压,所以我利用12V的锂电池,让锂电池的正负极接在降压模块输入端的正负极,接着让降压模块输出端的正负极接舵机的正负极,也就是说舵机是独立供电的,最重要的一点就是舵机外接电源的GND需要和控制板的GND接在一起,也就是共地,这样舵机才能转动,否则是转动不了的,如果你用的是5V的舵机,虽然大多数情况直接接控制板的正负极可以让舵机转动,但是这样电压不稳定,会导致舵机转动一个角度后就卡死了,所以本人建议舵机最好都给他个独立的电源,这样舵机就能连续转动,不会产生卡死状态。以下是本人所用的降压模块和60K大舵机的图片及视频效果,这种大舵机速度比较慢,但是扭矩大。
* |( Y+ i/ j" W* |5 R以下的舵机VCC->降压模块的VCC, ^# ?- e V9 [4 ]. [; f
舵机的GND->降压模块的GND+ d1 J2 ^+ t3 u* p
舵机的信号线->stm32控制板的PB5(TIM3_CH2)
8 a7 q3 z! p! V' C$ R: }& n* Y% d- n$ i
) u5 Q' Z; ~9 Y, g) j4 n+ R$ L" O7 O
0 ^6 e4 Q, f: n" A' X& p, z, S% |, f
下面附上主程序:- e! n. p* E% J6 k p* A E$ Q
8 A" \2 _/ b+ W/ M) E, F# T- <font face="Tahoma"><font size="3"><font color="#000000">#include "led.h"</font></font></font>6 Q7 W( L# V9 L, S
- <font face="Tahoma"><font size="3"><font color="#000000">#include "delay.h"</font></font></font>% i) }" t7 @) T# r; M) \. R3 w2 j
- <font face="Tahoma"><font size="3"><font color="#000000">#include "key.h"</font></font></font>1 _, D e4 w0 N- I
- <font face="Tahoma"><font size="3"><font color="#000000">#include "sys.h"</font></font></font>
U# \3 L# y: a1 I+ I - <font face="Tahoma"><font size="3"><font color="#000000">#include "usart.h"</font></font></font>7 ^6 \: w4 L' J d) M4 t+ C; c
- <font face="Tahoma"><font size="3"><font color="#000000">#include "timer.h"</font></font></font>+ B3 r5 E* N) m( ~3 C
- <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>6 X. J# c3 g$ I3 X( c% _( A; I
- <font face="Tahoma"><font size="3"><font color="#000000">
3 \# m0 b% S8 T- g6 ` - </font></font></font>
7 u# R5 F9 r6 w0 \9 V - <font face="Tahoma"><font size="3"><font color="#000000">extern u8 res; </font></font></font> F3 A$ k. p+ J1 M$ \. g
- <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>
. s. C7 z$ Y- h. Z. c7 F: _$ U9 f - <font face="Tahoma"><font size="3"><font color="#000000"> int main(void)</font></font></font>
2 W* J: R6 L( J$ O3 f - <font face="Tahoma"><font size="3"><font color="#000000"> { </font></font></font>
3 R* p1 h" U4 p @( u& g; Y - <font face="Tahoma"><font size="3"><font color="#000000"> int len;</font></font></font>
+ {5 l) c$ K7 [2 b; r3 G; ?8 u4 P d$ k - <font face="Tahoma"><font size="3"><font color="#000000"> int t;</font></font></font>
r/ f' b2 v4 N( \7 h, n - <font face="Tahoma"><font size="3"><font color="#000000">int i; </font></font></font>
2 N/ v9 i3 s$ Z, ^6 ~! H1 K" n - <font face="Tahoma"><font size="3"><font color="#000000"> delay_init(); //延时函数初始化 </font></font></font>
1 v* E! n; ~8 g* ^- N - <font face="Tahoma"><font size="3"><font color="#000000"> NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级</font></font></font>. N9 Q' p7 Z1 K' f; u$ p+ X8 o5 t
- <font face="Tahoma"><font size="3"><font color="#000000"> uart_init(115200); //串口初始化为115200</font></font></font>% y6 l' e9 g) Z
- <font face="Tahoma"><font size="3"><font color="#000000"> My_USART2_Init();</font></font></font>8 x0 }3 f' s. ` a" `
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM1_PWM_Init(199,7199); //不分频。T为20ms,这样的配置就是为了让输出的PWM信号达到舵机要求的20ms周期。</font></font></font>
' Z. y7 J+ \- |# S5 B9 P+ m - <font face="Tahoma"><font size="3"><font color="#000000"> while(1)</font></font></font>" b: A# W2 p- a* m/ B4 Z
- <font face="Tahoma"><font size="3"><font color="#000000"> {</font></font></font>5 l, {( U" ]& o. {" w+ E
- <font face="Tahoma"><font size="3"><font color="#000000"> if(res=='1'){TIM_SetCompare2(TIM3,175);delay_ms(1000);}对应180度</font></font></font>, ]7 k8 _6 J- Y# |6 l6 \
- <font face="Tahoma"><font size="3"><font color="#000000"> if(res=='2'){TIM_SetCompare2(TIM3,180);delay_ms(1000);}对应135度</font></font></font>3 m* ?+ H. a% H) s
- <font face="Tahoma"><font size="3"><font color="#000000"> if(res=='3'){TIM_SetCompare2(TIM3,185);delay_ms(1000);}对应90度</font></font></font>( C8 C* j$ I0 Y1 p/ y! i q
- <font face="Tahoma"><font size="3"><font color="#000000"> if(res=='4'){TIM_SetCompare2(TIM3,190);delay_ms(1000);}对应45度</font></font></font>
) E& S1 E# u, | w% k' _) @ - <font face="Tahoma"><font size="3"><font color="#000000"> if(res=='5'){TIM_SetCompare2(TIM3,195);delay_ms(1000);}对应0度</font></font></font>
7 ^' t( q; K# J: @3 O: Q+ T - <font face="Tahoma"><font size="3"><font color="#000000"> //在周期20ms的PWM信号中,不同的脉宽对应舵机不同的转动角度,在0.5ms-2.5ms间有效 </font></font></font>
. }! H0 n% {8 a. i6 q. M& M9 q6 Q - <font face="Tahoma"><font size="3"><font color="#000000"> // TIM_SetCompare2(TIM4,175);//总共计数200,前面设置的模式是计数在比较值之后才是高电平</font></font></font>
" X0 i' D$ J1 W, x( ?" i - <font face="Tahoma"><font size="3"><font color="#000000"> //也就是高电平的时间是[(200-175)/200]*20ms=2.5ms,即转过360度,180度舵机依次类推 </font></font></font>
! r5 ]/ H* G3 a; A6 ]4 c - <font face="Tahoma"><font size="3"><font color="#000000"> } </font></font></font>; \: g. n) z% U2 ]
- <font face="Tahoma"><font size="3"><font color="#000000"> }</font></font></font>
复制代码
: r4 C [: V4 V& i2 s0 G! N子程序:
2 |5 W- W' Y3 f: r2 d3 q; v- <font face="Tahoma"><font size="3"><font color="#000000">#include "timer.h"</font></font></font>; j$ p4 M' @; h- s/ j/ Z# h
- <font face="Tahoma"><font size="3"><font color="#000000">#include "led.h"</font></font></font>$ {" X4 g" J' v5 t
- <font face="Tahoma"><font size="3"><font color="#000000">#include "usart.h"</font></font></font>+ D. C) B- k4 d5 J4 [# l q2 _- S6 t
- <font face="Tahoma"><font size="3"><font color="#000000">void TIM1_PWM_Init(u16 arr,u16 psc)</font></font></font>
5 I/ N% `3 b' w4 G& o( ?" B1 f - <font face="Tahoma"><font size="3"><font color="#000000">{ </font></font></font>- E0 |+ J1 c4 p
- <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_InitTypeDef GPIO_InitStructure;</font></font></font>8 U/ h, H, u0 D: M- J i% T1 W
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;</font></font></font>. [. g k/ A+ L) r) ]; S5 P
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OCInitTypeDef TIM_OCInitStructure;</font></font></font>* [. X- S6 ?7 C6 ^4 Q* ]
- <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>2 g4 e1 n4 r7 C/ B6 ~
- <font face="Tahoma"><font size="3"><font color="#000000"> RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB| RCC_APB2Periph_AFIO , ENABLE); </font></font></font>
& O$ v8 G% D# Z( ^/ O - <font face="Tahoma"><font size="3"><font color="#000000"> RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);</font></font></font>; E( m+ t0 N3 U7 p; W
- <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>
9 K! D, s8 z/ Z* i. @7 ~ - <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); </font></font></font>
: }; z- p/ f' W: d* _9 C* B - <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>
8 w6 ]5 Y6 ]& J" ~4 T/ f - <font face="Tahoma"><font size="3"><font color="#000000"> //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIOA.8</font></font></font>
5 ]( Q2 b- Y% t+ X. x& }2 G" c, u - <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH1</font></font></font>( Z- C% z, \4 u1 P+ [% _0 |
- <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出</font></font></font>$ s! i9 W0 V# ]+ n9 L$ a" W( t
- <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;</font></font></font>
, y. p6 B" E. [/ y! E5 z/ `. y - <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO</font></font></font>
: Q. ]3 a5 C. q4 z. T+ [, J1 O' x" ?% h - <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>
; w" }2 e9 h+ X6 r+ |* U( l+ d - <font face="Tahoma"><font size="3"><font color="#000000"> //初始化TIM1</font></font></font>
, x2 S5 j4 P* @ - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值</font></font></font>& ]: Z& p Q9 O
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 </font></font></font>) b1 v% n& \; `. I0 T% H9 {
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim</font></font></font>. E: V5 A6 e- R
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式</font></font></font>
& `' x1 J) V' F+ k2 p1 [6 i - <font face="Tahoma"><font size="3"><font color="#000000">// TIM_TimeBaseStructure.TIM_RepetitionCounter=0;//重复计数器的值</font></font></font>0 k5 a* L; r$ f( z# c
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位</font></font></font>, s$ O& N L# j( K+ y6 S" b
- <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>$ j" k% l' O! H9 p. t1 f& [
- <font face="Tahoma"><font size="3"><font color="#000000"> //初始化TIM1 Channel1 PWM模式 </font></font></font>. P/ f$ Z# R: C3 {* {1 I
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2</font></font></font>3 c, ^$ t* \/ ?7 h5 e: p
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能</font></font></font>0 x" D- ?' @3 o* Q2 j! ~
- <font face="Tahoma"><font size="3"><font color="#000000"> //TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;</font></font></font>2 e! e3 [$ F) A6 F D# a
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高</font></font></font>
( Q' g- r9 [! z1 F2 _ - <font face="Tahoma"><font size="3"><font color="#000000"> //TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;//输出通道空闲电平极性设置</font></font></font>1 Y7 @9 x0 G+ a( S
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2</font></font></font>
9 p+ K& L1 y1 w2 ?* Z - <font face="Tahoma"><font size="3"><font color="#000000">//TIM_OC4Init(TIM1, &TIM_OCInitStructure);</font></font></font>
4 v+ ?0 a; q1 l7 ]# s' T6 ~ - <font face="Tahoma"><font size="3"><font color="#000000">
# X- a2 d' W' c' ]3 H - </font></font></font>
) {+ ^ n, |9 L3 L - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM1在CCR1上的预装载寄存器</font></font></font>7 [ E7 A* L, |
- <font face="Tahoma"><font size="3"><font color="#000000">// TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable); </font></font></font>
9 H" H+ d7 t/ a- T - <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>
% t) J* t/ | \# n: O8 ]- G! b - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_Cmd(TIM3, ENABLE); //使能TIM1</font></font></font>+ f+ _6 _7 u- B: V- L7 [; e
- <font face="Tahoma"><font size="3"><font color="#000000"> //TIM_CtrlPWMOutputs(TIM1, ENABLE);//主输出使能,当使用的通用定时器时,这句不需要</font></font></font>% m; W. R" D$ p2 S: Y$ m
- <font face="Tahoma"><font size="3"><font color="#000000">
7 ?6 o# t% d+ v4 `# C! A - </font></font></font>
1 v, Y8 ^! d0 f+ }* ] - <font face="Tahoma"><font size="3"><font color="#000000">}</font></font></font>
复制代码 4 T- P: Q! Z5 x' n8 e
如果在定时器初始化时TIM_OCInitStructure.TIM_OCMode配置的是PWM1模式那么main中的占空比就依次为25、20、15、10、5。下面解释一下模式PWM1和模式PWM2的区别:
( F6 }4 J' [0 q i$ Z& `3 m假定TIM_OCInitTypeDef.TIM_OCPolarity = TIM_OCPolarity_High \$ J- y, j0 g$ n/ E) D
若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM1时:. L7 S, Y; r7 V1 i d( J! N
当计时器值小于比较器设定值时则TIMX输出脚此时输出有效高电位。
; M; i {6 J. o5 ?+ J( e) A当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出低电位。) ^! \0 T% d' C+ c
若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM2时:
$ @: o8 {5 m2 S6 H% p: Q当计时器值小于比较器设定值时则TIMX输出脚此时输出有效低电位。9 A! e$ L& h6 i3 g6 t
当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出高电位。3 C3 J# H& s) {+ J+ W* D( `% q
本人用的是PWM2模式,在你们自己试验时,可以将占空比设置成各种不同的值,看看有什么不同的效果。
& {1 {! j7 s7 q% ? w1 `————————————————
( m8 p, T& O- h4 {, }版权声明:i土豆9 h8 h+ U) f' c! T
" Q" n( O( ?+ j5 D' h |