目录
一.前言
材料:STM32F103VET6开发板,TS90A舵机。
写此文章是为作为学习笔记,如有不足还请多指教。
二.主要知识点
大部分内容,包括端口复用,重映射在之前的呼吸灯文章中有记录。且此次代码注释详细,这里就不赘述了,直接上代码。
1.舵机
(1)ts90a.h
#ifndef __TS90A_H
#define __TS90A_H
#include "stm32f10x.h"
#define arr 200 //计数周期
#define psc 7200 //分频
#define angle 180 //角度
// 72000000/psc = f 分频后的频率(单位:Hz )
// 1/f 计一个数的时间(单位:s)
// arr*(1/f) = T 时间周期(单位:s) (这需要看舵机的参数)
// 1 - pwmval/arr = high_time/T TIM_SetCompare函数的参数(pwmval)与我们所需要高电平时间(high_time)的关系
// 高电平输出时间0.5ms~2.5ms对应的舵机转动是0°~180° (这需要看舵机的参数)
// (high_time - 0.0005)/(0.0025 - 0.0005) = (angle - 0°)/(180°-0°)
// 所以最后得出 angle 和 pwmval 之间的关系:pwmval = arr - 800*angle/psc - 5*7200/psc
// 再将 arr 和 psc 带入,得:pwmval = 195 - angle/9
void PWM_TIM3CH2RE_Config(void);
#endif /* __TS90A_H */
(2)ts90a.c
#include "ts90a.h"
void PWM_TIM3CH2RE_Config(void)
{
//使能GPIO时钟、定时器3时钟和AFIO时钟,并部分重映射
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能 GPIO时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能 外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能 AFIO时钟
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //部分重映射Timer3 TIM3_CH2->PB5
//配置GPIO引脚为复用功能
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //选择引脚为复用推挽功能
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //选择引脚速度
GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化GPIO
//配置定时器3
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period=(arr-1); //定时器周期
TIM_TimeBaseStructure.TIM_Prescaler=(psc-1); //预分频器
TIM_TimeBaseStructure.TIM_RepetitionCounter=TIM_CKD_DIV1; //时钟分频因子,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //计数模式
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); //初始化定时器
//配置定时器3通道2
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; //打开或者关闭脉冲输出
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; //有效电平设置为高状态
TIM_OC2Init(TIM3,&TIM_OCInitStructure); //初始化定时器通道2
//使能预装载
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
//开启定时器3
TIM_Cmd(TIM3,ENABLE);
}
2.主函数
(1)一次转动 main.c
#include "stm32f10x.h"
#include "ts90a.h"
int main(void)
{
PWM_TIM3CH2RE_Config();
while(1)
{
TIM_SetCompare2(TIM3,195 - angle/9); // pwmval = 195 - angle/9
while(1);
}
}
现在只要改变ts90a.h文件中的宏定义angle,就可以改变舵机旋转到哪一度了,0°、45°、90°……轻松实现。
(2)连续转动 main.c
#include "stm32f10x.h"
#include "ts90a.h"
#include "delay.h"
int main(void)
{
PWM_TIM3CH2RE_Config();
while(1)
{
u16 i;
for(i=175;i<195;i++)
{
TIM_SetCompare2(TIM3,i);
delay_ms(100);
}
for(i=195;i>175;i--)
{
TIM_SetCompare2(TIM3,i);
delay_ms(100);
}
}
}
该代码实现0°到180°连续摆动。
合理的延时是必须的。
3.部分函数补充
(1)TIM_SetCompare
此函数第二个参数pwmval是计时周期arr中低电平的计数次数。我的arr为200,如果这个参数pwmval设为190,那么占空比就是190/200*100%=95%。
三.感想
1.一定要明确舵机的参数;
2.舵机可以单独供电,但一定要与开发板供地(我因为没供地查了两天的资料,硬是没发现是这问题);
3.附加连线图片;
我的舵机是褐色接地,橘色5V,黄色PWM。
分别是GND和5V
PWM信号线接B5脚