STM32 PWM驱动舵机
接线图:
这里将信号线连接到了开发板的PA1上
代码配置:
这里的PWM配置与呼吸灯一样,呼吸灯连接的是PA0引脚,输出比较单元用的是OC1通道,这里只需改为OC2通道即可。
完整代码:
#include "servo.h"
void servo_Init(void)
{
//-----------------定义结构体变量----------------------
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO结构体变量
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义TimeBase结构体变量
TIM_OCInitTypeDef TIM_OCInitStructure; //定义OC结构体变量
//-----------------定义结构体变量----------------------
//配置时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//打开GPIO时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//打开TIM2时钟
//-----------------配置GPIO----------------------------
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//选择复用推挽模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //配置引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速率
GPIO_Init(GPIOA, &GPIO_InitStructure); //GPIO初始化
//-----------------配置GPIO----------------------------
//-------------------配置时基单元----------------------
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,这里选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;//周期 就是自动重装器ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;//预分频器 PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //TimeBase初始化
//-------------------配置时基单元----------------------
//------------------配置输出比较单元-------------------
TIM_OCStructInit(&TIM_OCInitStructure); //给结构体赋初值
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//配置输出比较模式
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设置输出比较极性
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //设置输出使能
TIM_OCInitStructure.TIM_Pulse = 0;//CCR的值
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
//------------------配置输出比较单元-------------------
TIM_Cmd(TIM2,ENABLE);//开启定时器
}
//0°占空比为500 180°占空比为2000
void Servo_SetAngle(float Angle)
{
TIM_SetCompare2(TIM2,Angle/180 * 2000 + 500);
}
主函数:
实现了通过按键控制舵机
#include "Servo.h"
int main(void)
{
LED_Init();
OLED_Init();
KEY_Init();
servo_Init();
uint16_t Angle = 0;
OLED_ShowString(1, 1, "Angle:");
while(1)
{
if(KEY_Scanf(GPIOB,GPIO_Pin_1) == 1)
{
Angle += 30;
if(Angle >= 180)
{
Angle = 0;
}
}
Servo_SetAngle(Angle);
OLED_ShowNum(1, 7, Angle, 3);
}
}