STM32 PWM控制舵机

目录

    • 舵机简介
    • 舵机工作原理
    • 什么是PWM
    • 硬件连线
    • 代码
    • 实现结果
    • 总结

舵机简介

舵机是指在自动驾驶仪中操纵飞机舵面(操纵面)转动的一种执行部件。分有:①电动舵机,由电动机、传动部件和离合器组成。接受自动驾驶仪的指令信号而工作,当人工驾驶飞机时,由于离合器保持脱开而传动部件不发生作用。②液压舵机,由液压作动器和旁通活门组成。当人工驾驶飞机时,旁通活门打开,由于作动器活塞两边的液压互相连通而不妨碍人工操纵。此外,还有电动液压舵机,简称“电液舵机”。
STM32 PWM控制舵机_第1张图片

舵机工作原理

舵机的主要组成部分为伺服电机,所谓伺服就是服从信号的要求而动作。在信号来之前,转子停止不动;信号来到之后,转子立即运动。因此我们就可以给舵机输入不同的信号,来控制其旋转到不同的角度。
舵机接收的是PWM信号,当信号进入内部电路产生一个偏置电压,触发电机通过减速齿轮带动电位器移动,使电压差为零时,电机停转,从而达到伺服的效果。简单来说就是给舵机一个特定的PWM信号,舵机就可以旋转到指定的位置。

STM32 PWM控制舵机_第2张图片
舵机上有三根线,分别是GND、VCC和SIG,也就是地线、电源线和信号线,其中的PWM波就是从信号线输入给舵机的。
一般来说,舵机接收的PWM信号频率为50HZ,即周期为20ms。当高电平的脉宽在0.5ms-2.5ms之间时舵机就可以对应旋转到不同的角度。
STM32 PWM控制舵机_第3张图片
舵机是通过高电平的占空比来调节输出轴的角度,舵机的驱动信号是50Hz的方波信号,每个周期为20ms,其中高电平的占比在0.5ms-2.5ms之间。
占空比 = t/T

t = 0.5ms——————-舵机会转到 0 °
t = 1.0ms——————-舵机会转到 45°
t = 1.5ms——————-舵机会转到 90°
t = 2.0ms——————-舵机会转到 135°
t = 2.5ms——————-舵机会转到 180°

因为舵机的驱动信号时50HZ,就能得到周期

T=  1/f=1/50=0.02s=20ms

因此可以计算出TIM_Period和TIM_Prescaler的值。
PWM周期为20ms = (7200*200)/72000000=0.02

什么是PWM

简介
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽
度的控制。STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出!
PWM的频率
是指1秒钟内信号从高电平到低电平再回到高电平的次数(一个周期);也就是说一秒钟PWM有多少个周期。
PWM的周期

T=1/f
周期=1/频率

根据舵机50Hz = 20ms 一个周期,如果频率为50Hz ,也就是说一个周期是20ms 那么一秒钟就有 50次PWM周期。
PWM占空比
是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,由于PWM周期为20ms,所以(以舵机会转动 45°为例),占空比就应该为1ms/20ms = 5%,所以TIM_SetCompare1的 TIMx 捕获比较 1 寄存器值就为200-200*5% = 190
单位: % (0%-100%)

硬件连线

舵机红线-----------5V
舵机棕线-----------GND
舵机黄线-----------PA6

代码

servo.c

#include "servo.h"

/*我这里采用通用计时器3*/
static void Servo_GPIO_Config()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	/*开启GPIO时钟*/
	RCC_APB2PeriphClockCmd(BASIC_GPIOA_CLK,ENABLE);
	/*配置GPIO*/
	GPIO_InitStructure.GPIO_Pin			= GPIOA_CH1_PIN;//TIM_CH1 
	GPIO_InitStructure.GPIO_Mode		= GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStructure.GPIO_Speed		= GPIO_Speed_50MHz;
	/*初始化*/
	GPIO_Init(GPIOA_CH1_PORT,&GPIO_InitStructure);
	

}
static void Servo_TIM2_Config()
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	/*开启定时器时钟*/
	RCC_APB1PeriphClockCmd(BASIC_TIM_CLK,ENABLE);
	
	/*
	TIM2时基单元配置
	重要配置:TIM_Prescaler(预分频值)TIM_Period(定时周期)
	将TIM_Period设置成999,则计数器会数1000个(TIM_Period+1)
	节拍为一个定时器的周期。这个和后面需要配置的TIM_Pulse共同
	控制着定时器输出波形的占空比。
	TIM_Prescaler用来指定TIM时钟的分频值。也就是说它是进一步来
	分频TIM clock的。	简单来说也就是定时器每一次数数的时间间隔是多少。
	*/
	
	/*配置TIM3,一般的驱动PWM信号都是周期20毫秒,频率为50HZ。所以我们设定周期为20ms*/
	
	
											/*时基结构体成员配置*/
	//自动重装载值寄存器的值
	TIM_TimeBaseInitStructure.TIM_Period					= BASIC_TIM_Period;
	//时钟预分频数
	TIM_TimeBaseInitStructure.TIM_Prescaler				=	BASIC_TIM_Prescaler;
	//时钟分频因子
	TIM_TimeBaseInitStructure.TIM_ClockDivision		= TIM_CKD_DIV1;
	//计数器计数模式,设置向上计数,
	TIM_TimeBaseInitStructure.TIM_CounterMode			= TIM_CounterMode_Up;
	/*初始化结构体*/
	TIM_TimeBaseInit(BASIC_TIM,&TIM_TimeBaseInitStructure);
	
	
									/*定时器输出比较结构体成员初始化*/
	TIM_OCInitStructure.TIM_OCMode				= TIM_OCMode_PWM2;
	// 输出使能
	TIM_OCInitStructure.TIM_OutputState		= TIM_OutputState_Enable;
	//TIM_OCInitStructure.TIM_OutputNState	= TIM_OutputNState_Enable;
	// 设置占空比大小,主要取主函数里设置占空比这边先设置成0
	TIM_OCInitStructure.TIM_Pulse					= 0;
	// 输出通道电平极性配置
	TIM_OCInitStructure.TIM_OCPolarity		= TIM_OCPolarity_High;
	//TIM_OCInitStructure.TIM_OCNPolarity		=	TIM_OCNPolarity_High;
	// 输出通道空闲电平极性配置
	TIM_OCInitStructure.TIM_OCIdleState		= TIM_OCIdleState_Set;
	//TIM_OCInitStructure.TIM_OCNIdleState  = TIM_OCNIdleState_Reset;
	/*初始化结构体*/
	TIM_OC1Init(BASIC_TIM,&TIM_OCInitStructure);
	
	//使能TIMx在CCR2上的预装载寄存器
	TIM_OC1PreloadConfig(BASIC_TIM,TIM_OCPreload_Enable);
	
	// 使能计数器
	TIM_Cmd(BASIC_TIM, ENABLE);	
	// 主输出使能,当使用的是通用定时器时,这句不需要
	TIM_CtrlPWMOutputs(BASIC_TIM, ENABLE);

}


void initServo(void)
{
	Servo_GPIO_Config();
	Servo_TIM2_Config();
	
}



main.c


#include "led.h"
#include "delay.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "beep.h"
#include "servo.h"

 int main(void)
 {	
	u16 i;
	delay_init();
	LED_Init();	 
	LED0 = 0;
	LED1 = 0;
	initServo();
	LED1 = 1;
	

	while(1){
		delay_ms(300);
		TIM_SetCompare1(BASIC_TIM, 175); //对应180度
		delay_ms(300);
		TIM_SetCompare1(BASIC_TIM, 180); //对应135度
		delay_ms(300);
		TIM_SetCompare1(BASIC_TIM, 185); //对应90度
		delay_ms(300);
		TIM_SetCompare1(BASIC_TIM, 190); //对应45度
		delay_ms(300);
		TIM_SetCompare1(BASIC_TIM, 195); //对应0度
		for(i = 195; i > 174; i--){
			TIM_SetCompare1(BASIC_TIM, i);
		}
		delay_ms(100);
		for(i = 175; i < 195; i++){
			TIM_SetCompare1(BASIC_TIM, i);
		}
	} 
}

实现结果

总结

通过这次舵机学习,让我初步了解到了STM32 PWM调制相关的知识,期间还是遇到问题。我本次采用的是TIM3通道1,但是我修改代码改成TIM3通道2就不能实现了,希望好心人能帮我解答一下。
接下来打算配合昨天写的超声波测距代码,两者整合形成一个基于STM32的感应垃圾桶。

参考:https://blog.csdn.net/qq_42866708/article/details/113355329

你可能感兴趣的:(STM32f103,stm32,嵌入式,单片机)