STM32外设系列—sg90(舵机)


🎀 文章作者:二土电子

🌸 关注文末公众号获取其他资料和工程文件!

🐸 期待大家一起学习交流!


一、sg90简介

首先介绍说一下什么是舵机。舵机是一种位置(角度)伺服的驱动器。适用于一些需要角度不断变化的,可以保持的控制系统。sg90就是舵机的一种。

sg90

舵机的工作原理比较简单。舵机内部有一个基准电压,单片机产生的PWM信号通过信号线进入舵机,与舵机内部的基准电压作比较,获得电压差输出。电压差的正负输出到电机驱动芯片上,从而决定正反转。开始旋转的时候,舵机内部通过级联减速齿轮带动电位器旋转,使得电压差为零,电机停止转动。

二、引脚连接

sg90有三个引脚,分别是红线(VCC),棕线(GND)和橙线(信号线)。通常使用5V供电,信号线接单片机引脚,用老来接收单片机发送的PWM。

三、控制方法

控制sg90舵机旋转也比较简单,只需要给它输出PWM波,修改占空比就可以调整角度。sg90的控制一般需要一个20ms 左右的时基脉冲,脉冲的高电平部分一般在0.5ms~2.5ms。高电平持续时间与旋转角度的对应关系如下

高电平持续时间/ms舵机角度/°
0.50
1.045
1.590
2.0135
2.5180

四、程序设计

这里以180°的sg90,来展示一下程序设计

4.1 配置定时器

要使用sg90,首先要配置定时器,产生PWM。关于定时器和PWM相关知识,可以看博主STM32速成笔记定时器篇,这里就不再做详细介绍了。上面说,控制sg90需要一个20ms左右的脉冲,也就是说PWM的周期为20ms左右。计算一下可以知道,配置定时器时,预分频系数设置为7199,自动重装载值设置为200。我们初始化TIM3的通道1来控制sg90。PWM引输出脚映射到PC6。初始化程序如下

/*
 *==============================================================================
 *函数名称:TIM3_CH1_PWM_Init
 *函数功能:初始化定时器3的PWM通道1
 *输入参数:per:自动重装载值;psc:预分频系数
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void TIM3_CH1_PWM_Init (u16 per,u16 psc)
{
	// 结构体定义
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// 开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	// 初始化GPIO
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   // 复用推挽输出
	GPIO_Init(GPIOC,&GPIO_InitStructure);
	
	GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);   // 改变指定管脚的映射	
	
	// 初始化定时器参数
	TIM_TimeBaseInitStructure.TIM_Period = per;   // 自动装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler = psc;   // 分频系数
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;   // 设置向上计数模式
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);	
	
	// 初始化PWM参数
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   // 比较输出模式
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;   // 输出极性
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   // 输出使能
	TIM_OC1Init(TIM3,&TIM_OCInitStructure);   // 输出比较通道1初始化
	
	TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);   // 使能TIMx在 CCR1 上的预装载寄存器
	TIM_ARRPreloadConfig(TIM3,ENABLE);   // 使能预装载寄存器
	
	TIM_Cmd(TIM3,ENABLE);   // 使能定时器
}

初始化时,程序如下

TIM3_CH1_PWM_Init(200,7199);   // 初始化TIM3 PWM1

4.2 编写控制程序

根据高电平持续时间与角度关系对应表格来编写sg90的控制程序

  while(1)
  {
		TIM_SetCompare1(TIM3,195);   // 旋转到0°
		delay_ms(500);
		TIM_SetCompare1(TIM3,190);   // 旋转到45°
		delay_ms(500);
		TIM_SetCompare1(TIM3,185);   // 旋转到90°
		delay_ms(500);
		TIM_SetCompare1(TIM3,180);   // 旋转到135°
		delay_ms(500);
		TIM_SetCompare1(TIM3,175);   // 旋转到180°
		delay_ms(500);
	}

五、360°舵机

除了上面介绍的180°舵机之外,还有一种360°舵机。与180°舵机不同的是,360°舵机是无法控制角度的,它只能控制旋转方向和旋转速度。360°的舵机也是由脉冲宽度为20ms的PWM控制。高电平持续时间与舵机转向和转速的对应关系如下

高电平持续时间/ms舵机转向和转速
0.5~1.5正转,速度越来越慢
1.5停止
1.5~2.5反转,速度越来越快
### STM32 控制 SG90 舵机教程 #### 使用 PWM 功能控制舵机角度 STM32F103C8T 微控制器可以通过其内置的定时器模块产生的脉宽调制 (PWM) 信号来精确控制SG90舵机的角度[^1]。具体来说,通过调整PWM占空比,可以实现对舵机位置的不同设定。 对于SG90舵机而言,通常情况下: - 当输入宽度为0.5ms的高电平时,对应的是0度的位置; - 输入宽度为2.5ms时,则表示转向180度;而中间值即1.5ms代表90度方向。 因此,在编程过程中需要配置好相应的寄存器参数以生成合适的周期性和持续时间变化规律的方波形电压序列给到连接端口上从而达到预期效果。 下面是一份基于上述原理编写的简单示例程序,该代码实现了让两个不同通道上的舵机分别转动至指定角度的功能[^3]。 ```c #include <stdint.h> #include "stm32f1xx_hal.h" // 定义使用的TIM外设及其对应的GPIO引脚 #define SERVO_TIM TIM2 #define SERVO_CHANNEL_1 TIM_CHANNEL_1 #define SERVO_PIN GPIO_PIN_0 #define SERVO_GPIO_PORT GPIOA void Servo_Init(void); void SetServoAngle(uint8_t angle); int main(void) { HAL_Init(); // 初始化系统时钟, 配置并使能所需资源... __HAL_RCC_TIM2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /* 配置PA0作为TIM2 CH1 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = SERVO_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF1_TIM2; HAL_GPIO_Init(SERVO_GPIO_PORT, &GPIO_InitStruct); Servo_Init(); while (1){ // 设置舵机角度为例程中的特定数值 SetServoAngle(45); // 将舵机转到45度角 HAL_Delay(1000); // 延迟一秒后再改变角度 SetServoAngle(90); // 接着将舵机转到90度角 HAL_Delay(1000); SetServoAngle(135); // 最后把舵机转到135度角 HAL_Delay(1000); } } /* 初始化伺服电机所用的定时器 */ void Servo_Init(){ TIM_OC_InitTypeDef sConfigOC; htim2.Instance = SERVO_TIM; htim2.Init.Prescaler = 79; // 设定预分频系数使得计数频率等于1KHz htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 19999; // 自动重装载值设置成最大可能范围内的任意整数N(这里取接近20kHz) htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_PWM_Init(&htim2) != HAL_OK){Error_Handler();} sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim2,&sConfigOC,SERVO_CHANNEL_1)!= HAL_OK){Error_Handler();} HAL_TIM_PWM_Start(&htim2, SERVO_CHANNEL_1); } /* 根据传入的角度参数计算出相应占空比,并应用到PWM输出上去 */ void SetServoAngle(uint8_t angle){ uint32_t pulse_width = ((angle * 2000 / 180) + 500)*100/20000*20000/(htim2.Init.Period+1); __HAL_TIM_SET_COMPARE(&htim2, SERVO_CHANNEL_1,pulse_width ); } ``` 此段代码展示了如何初始化硬件资源以及编写函数`SetServoAngle()` 来接收一个介于0~180之间的整型变量 `angle`, 并据此调整PWM信号的具体形态进而指挥舵机完成动作转换过程。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二土电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值