stm32f103c8t6利用蓝牙控制180度舵机9 k8 c. Q2 A- W) j- ^* a
& k6 d8 s' S. J5 @. g8 e
关于蓝牙模块部分,如果不了解蓝牙模块的可以看我之前发的东西。* |+ `7 j8 o. w+ V B
一般来说,舵机接收的PWM信号频率为50HZ,即周期为20ms。当高电平的脉宽在0.5ms-2.5ms之间时舵机就可以对应旋转到不同的角度。以180度角度舵机为例,那么对应的控制关系是这样的:
8 b. a) W! s9 c8 d0.5ms--------------0度;/ ^3 G% E6 Y7 W- w
1.0ms------------45度;
9 Q. B/ N, d6 g$ J% [6 M0 M# A1.5ms------------90度;
: E7 a* D r0 U# v: J2.0ms-----------135度;
+ o2 z2 k1 s- ~! R4 ~" u' C: B2.5ms-----------180度;
0 y. a' ?" ^, O, G g' d
; @5 s! o0 t9 }+ W- B. N. k+ g- e: S. T$ S. _+ ~( X. ?
% d( d+ i: @. ^4 V% H+ t$ }9 K
/ m/ Z1 ~ F: u1 ]; j2 `2 `. n关于舵机的话,本人用的是6~8.4V的的60KG大舵机,这里需要注意的是, 控制板上面只提供5V电压,满足不了这种舵机的电压,所以我利用12V的锂电池,让锂电池的正负极接在降压模块输入端的正负极,接着让降压模块输出端的正负极接舵机的正负极,也就是说舵机是独立供电的,最重要的一点就是舵机外接电源的GND需要和控制板的GND接在一起,也就是共地,这样舵机才能转动,否则是转动不了的,如果你用的是5V的舵机,虽然大多数情况直接接控制板的正负极可以让舵机转动,但是这样电压不稳定,会导致舵机转动一个角度后就卡死了,所以本人建议舵机最好都给他个独立的电源,这样舵机就能连续转动,不会产生卡死状态。以下是本人所用的降压模块和60K大舵机的图片及视频效果,这种大舵机速度比较慢,但是扭矩大。8 V3 D; h1 n0 q& x0 c7 _2 p
以下的舵机VCC->降压模块的VCC' D# k( U+ {3 Q1 w5 q V# ?
舵机的GND->降压模块的GND0 X( o2 O" ~0 k
舵机的信号线->stm32控制板的PB5(TIM3_CH2)
+ `; w, s1 r# R; N0 X2 A0 f* r% ^: e6 W# J- `" r3 K
' q# ?8 Y) G* o
b2 _+ J( G- T8 p
. _8 k( e" P4 B4 n. s下面附上主程序:
1 I4 R3 h; i. P. P9 s9 z9 Y) b
+ ?' f: c$ P2 s* ~; W1 v9 {- <font face="Tahoma"><font size="3"><font color="#000000">#include "led.h"</font></font></font>
9 X! P& Z( I/ o) O' w- O: b - <font face="Tahoma"><font size="3"><font color="#000000">#include "delay.h"</font></font></font>
; }& A8 t8 B9 O% T! F' C - <font face="Tahoma"><font size="3"><font color="#000000">#include "key.h"</font></font></font>, C& U4 i+ T/ L3 Q, Y3 e3 O
- <font face="Tahoma"><font size="3"><font color="#000000">#include "sys.h"</font></font></font>
3 T& r4 g( l" m - <font face="Tahoma"><font size="3"><font color="#000000">#include "usart.h"</font></font></font>
3 L( V$ q) Y. I# W- y$ | - <font face="Tahoma"><font size="3"><font color="#000000">#include "timer.h"</font></font></font>4 P9 i1 V; R/ I' p9 ~7 D- f
- <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>- p R% ^/ y% E3 e) a
- <font face="Tahoma"><font size="3"><font color="#000000">0 ^: J7 {! u% R2 ]5 ^1 U
- </font></font></font>
3 a2 }& [/ R6 z! Q$ A2 N - <font face="Tahoma"><font size="3"><font color="#000000">extern u8 res; </font></font></font>
' M% F( O0 Z5 W( r* S: L - <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>
. I' ~" C6 A1 Q9 f: x, d! T - <font face="Tahoma"><font size="3"><font color="#000000"> int main(void)</font></font></font>
1 d+ j7 d6 t7 p% n3 h; R - <font face="Tahoma"><font size="3"><font color="#000000"> { </font></font></font>+ P+ y4 v' H; S0 A! [
- <font face="Tahoma"><font size="3"><font color="#000000"> int len;</font></font></font>% G+ Z; `' }! b
- <font face="Tahoma"><font size="3"><font color="#000000"> int t;</font></font></font>
$ {- e- w1 F4 ~$ p# W - <font face="Tahoma"><font size="3"><font color="#000000">int i; </font></font></font>
" \% W0 [& {# E* p9 S% @/ S* V - <font face="Tahoma"><font size="3"><font color="#000000"> delay_init(); //延时函数初始化 </font></font></font> g3 {2 r3 r1 r" i6 X0 i4 ~
- <font face="Tahoma"><font size="3"><font color="#000000"> NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级</font></font></font>
8 X7 T8 \* k4 }( n( S/ F! i y - <font face="Tahoma"><font size="3"><font color="#000000"> uart_init(115200); //串口初始化为115200</font></font></font>
U9 P0 \! G+ { - <font face="Tahoma"><font size="3"><font color="#000000"> My_USART2_Init();</font></font></font>
% c! a3 R) i, Z$ _, k9 v. }0 p5 ^ - <font face="Tahoma"><font size="3"><font color="#000000"> TIM1_PWM_Init(199,7199); //不分频。T为20ms,这样的配置就是为了让输出的PWM信号达到舵机要求的20ms周期。</font></font></font>2 w! y) P- W2 Q, S2 J: K
- <font face="Tahoma"><font size="3"><font color="#000000"> while(1)</font></font></font>9 a! y: s+ j+ d! n0 z
- <font face="Tahoma"><font size="3"><font color="#000000"> {</font></font></font>& X7 e7 B2 Y7 a7 N0 i o; ^
- <font face="Tahoma"><font size="3"><font color="#000000"> if(res=='1'){TIM_SetCompare2(TIM3,175);delay_ms(1000);}对应180度</font></font></font>8 w: h' C! ^1 R& i: F2 E I- R4 X
- <font face="Tahoma"><font size="3"><font color="#000000"> if(res=='2'){TIM_SetCompare2(TIM3,180);delay_ms(1000);}对应135度</font></font></font>
0 g9 t! u% |8 K, F) f - <font face="Tahoma"><font size="3"><font color="#000000"> if(res=='3'){TIM_SetCompare2(TIM3,185);delay_ms(1000);}对应90度</font></font></font>
) C0 k, J/ D9 x5 I - <font face="Tahoma"><font size="3"><font color="#000000"> if(res=='4'){TIM_SetCompare2(TIM3,190);delay_ms(1000);}对应45度</font></font></font>
d& ]5 ~# q5 o+ O+ O5 s( p - <font face="Tahoma"><font size="3"><font color="#000000"> if(res=='5'){TIM_SetCompare2(TIM3,195);delay_ms(1000);}对应0度</font></font></font>
, f) m- {$ L2 F) u - <font face="Tahoma"><font size="3"><font color="#000000"> //在周期20ms的PWM信号中,不同的脉宽对应舵机不同的转动角度,在0.5ms-2.5ms间有效 </font></font></font>, v) d- I& D: j2 _1 u
- <font face="Tahoma"><font size="3"><font color="#000000"> // TIM_SetCompare2(TIM4,175);//总共计数200,前面设置的模式是计数在比较值之后才是高电平</font></font></font>
0 d- \& s) n$ o" b% ~ - <font face="Tahoma"><font size="3"><font color="#000000"> //也就是高电平的时间是[(200-175)/200]*20ms=2.5ms,即转过360度,180度舵机依次类推 </font></font></font>
5 t0 v# ?+ A& ]8 j* L - <font face="Tahoma"><font size="3"><font color="#000000"> } </font></font></font>
6 E% E+ b0 e) T' s7 f' }# C) G - <font face="Tahoma"><font size="3"><font color="#000000"> }</font></font></font>
复制代码
& m/ x* Z0 H3 Z# `$ B+ |9 ^子程序:! c) A; k* _0 n' r& y3 W& _* L
- <font face="Tahoma"><font size="3"><font color="#000000">#include "timer.h"</font></font></font>, f% p# a: H; U, g3 |
- <font face="Tahoma"><font size="3"><font color="#000000">#include "led.h"</font></font></font>7 ]+ u- Y" z' v% h. @; |( v: M
- <font face="Tahoma"><font size="3"><font color="#000000">#include "usart.h"</font></font></font>& U1 A5 L/ }, I+ J
- <font face="Tahoma"><font size="3"><font color="#000000">void TIM1_PWM_Init(u16 arr,u16 psc)</font></font></font>& r9 M% i$ u8 [6 C @6 o) n
- <font face="Tahoma"><font size="3"><font color="#000000">{ </font></font></font>, m6 X7 ?) j: `3 B7 e1 v( h% e
- <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_InitTypeDef GPIO_InitStructure;</font></font></font>
1 _4 P4 S2 a) W5 b1 z5 Z( m6 @& m - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;</font></font></font>
9 j" U( {7 [7 ?( }6 U - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OCInitTypeDef TIM_OCInitStructure;</font></font></font>
7 @0 f) ?4 u) i- i2 m5 E - <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>6 o/ ^4 K( i: m
- <font face="Tahoma"><font size="3"><font color="#000000"> RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB| RCC_APB2Periph_AFIO , ENABLE); </font></font></font>, A0 b7 E! i8 M
- <font face="Tahoma"><font size="3"><font color="#000000"> RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);</font></font></font>, Q# C3 h x/ t1 k7 b
- <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>& h$ J- w% ]0 x; Z
- <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); </font></font></font>& L7 h, _6 F& O4 e
- <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>
8 T9 v5 w; |3 F/ f - <font face="Tahoma"><font size="3"><font color="#000000"> //设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形 GPIOA.8</font></font></font>
, c+ e% h" R8 U* W - <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH1</font></font></font>" E* F: @ Q: U; Q* @% Q
- <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出</font></font></font>9 S% C: s- n$ L. ~7 y8 E
- <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;</font></font></font>
# X! W6 N# n7 Q! ]! {8 d - <font face="Tahoma"><font size="3"><font color="#000000"> GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO</font></font></font>! c$ w4 U5 B8 [/ y% }
- <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>4 v5 K7 q$ h3 }
- <font face="Tahoma"><font size="3"><font color="#000000"> //初始化TIM1</font></font></font>
6 k3 l5 e, u& E3 f8 U3 Y - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值</font></font></font>
# L( n. s0 ]8 }8 t! S* e7 ]) o - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 </font></font></font>
7 n3 x" q7 y; U1 Q. z; F# v1 O- b( g' ^ - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim</font></font></font>; C3 y1 d; [# E/ h/ ?
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式</font></font></font>
; C, o* r" I3 B - <font face="Tahoma"><font size="3"><font color="#000000">// TIM_TimeBaseStructure.TIM_RepetitionCounter=0;//重复计数器的值</font></font></font>
% H: ?* S& P& N7 ?& K - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位</font></font></font>
9 e( M, [$ T$ _% ] - <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>
. x4 E4 l5 K7 C# J, u' T: } - <font face="Tahoma"><font size="3"><font color="#000000"> //初始化TIM1 Channel1 PWM模式 </font></font></font>
& x" X9 ^' T1 L' F1 B+ p& B - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2</font></font></font>
6 O5 c& E% |! T5 c2 T - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能</font></font></font>
' w4 H) u. ?0 [$ g - <font face="Tahoma"><font size="3"><font color="#000000"> //TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;</font></font></font>
) W4 E9 _% U& \! Z# `# H: D - <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高</font></font></font>
% T( m/ D0 V$ c5 O" }/ b - <font face="Tahoma"><font size="3"><font color="#000000"> //TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;//输出通道空闲电平极性设置</font></font></font>, x5 e) t$ _) R
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2</font></font></font>
4 r K9 @3 p$ l4 y1 ]6 `- y7 c/ k - <font face="Tahoma"><font size="3"><font color="#000000">//TIM_OC4Init(TIM1, &TIM_OCInitStructure);</font></font></font># e0 c% o% z, x& y
- <font face="Tahoma"><font size="3"><font color="#000000">, H& e! F- i+ Q0 D0 R- Q/ y* n8 t
- </font></font></font>( x3 j( A, D% `! t
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM1在CCR1上的预装载寄存器</font></font></font>: J; Y: B8 `0 r% J
- <font face="Tahoma"><font size="3"><font color="#000000">// TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable); </font></font></font>
" t! g7 W& L, k% B) _% A' K) x. ` - <font face="Tahoma"><font size="3"><font color="#000000"> </font></font></font>% X& O) B9 Q7 O1 O- r
- <font face="Tahoma"><font size="3"><font color="#000000"> TIM_Cmd(TIM3, ENABLE); //使能TIM1</font></font></font>
' e2 J U n1 j: Q - <font face="Tahoma"><font size="3"><font color="#000000"> //TIM_CtrlPWMOutputs(TIM1, ENABLE);//主输出使能,当使用的通用定时器时,这句不需要</font></font></font># B$ ^" C+ m# }; Z1 N
- <font face="Tahoma"><font size="3"><font color="#000000">
7 E& Z& e* ?2 [( O; F7 A9 F7 [5 w - </font></font></font>- H/ X) _9 U( Y& U1 H9 L' D
- <font face="Tahoma"><font size="3"><font color="#000000">}</font></font></font>
复制代码
4 l3 |" s1 J) L3 _3 z2 q7 \( {* s) P如果在定时器初始化时TIM_OCInitStructure.TIM_OCMode配置的是PWM1模式那么main中的占空比就依次为25、20、15、10、5。下面解释一下模式PWM1和模式PWM2的区别:
, x. l; z( n% M( F假定TIM_OCInitTypeDef.TIM_OCPolarity = TIM_OCPolarity_High
- i: D: M& V* o+ q若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM1时:+ Q* \. h: I. ]6 \
当计时器值小于比较器设定值时则TIMX输出脚此时输出有效高电位。
) H$ W! R$ I. E2 r/ N' N当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出低电位。
4 u. H# b' h4 n! i" |5 p若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM2时:6 v4 K' S4 T' k! E( E
当计时器值小于比较器设定值时则TIMX输出脚此时输出有效低电位。
/ P( w1 j" n" q2 F当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出高电位。
, X1 p, { x2 Z$ E* x+ f8 T3 d本人用的是PWM2模式,在你们自己试验时,可以将占空比设置成各种不同的值,看看有什么不同的效果。
) X) o3 E1 u6 b5 V1 a# h————————————————
$ H0 }9 Z7 A% w" w( E M. P版权声明:i土豆
& R* u: m1 M+ [) C7 }6 y0 a" P% A! |- `4 ?) C( l0 F
|