STM32F401舵机实验

本文介绍了使用STM32F401开发板和SG90舵机的实验,通过PWM控制舵机的频率和占空比,实现不同角度的旋转。代码展示了如何初始化PWM、设置PWM周期和占空比,以及通过按键控制舵机旋转30度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实验介绍

硬件资源:

STM32F401开发板,SG90舵机

舵机的要求输入电压为5V,周期是20ms,即频率为50Hz,高电平时间0.5~2.5ms

黄红棕三条线分别接在STM32板的PA1,5V和GND三个接口上

实验原理

PWM频率:Freq = CK_PSC (72M)/ (PSC+1)/(ARR+1)      

PWM占空比: Duty = CCR/(ARR +1)

由于舵机频率要求为50Hz,那么在满足Freq = 50的情况下,可以任意设置PSC和ARR的值。

这里PSC设置为72-1,ARR为20k-1,那么20k对应20ms,也就是周期为20ms,

当CCR设置为500时,Duty=1/40,高电平时间就是20ms*(1/40)=0.5ms,

同理CCR为2500,高电平时间为2.5ms

高电平的持续时间就对应着舵机的旋转角度

代码部分

PWM.c

#include "stm32f4xx.h"                  // Device header

void PWM_Init(){
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	//对于普通输出,引脚控制权来自输出数据寄存器,
	//要用定时器控制,就要复用推挽输出,输出控制权转移给片上外设,即TIM2_CH
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource1,GPIO_AF_TIM2);
	
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //推挽输出
	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	
	TIM_InternalClockConfig(TIM2);//选择内部时钟
	//初始化时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = 20000-1;	//ARR周期,自动重装值
	TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1; //PSC预分频值
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复计数器
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);//初始化时基单元
	
	TIM_OCInitTypeDef TIM_OCInitStruct;
	//给结构体各成员赋初始值,使其可以通用高级定时器	
	//TIM_OCStructInit(&TIM_OCInitStruct);
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; //设置输出比较模式为PWM1模式
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//设置输出比较极性
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//设置输出比较使能
	TIM_OCInitStruct.TIM_Pulse = 0;//设置CCR的值由函数封装
	TIM_OC2Init(TIM2,&TIM_OCInitStruct); //通道2初始化
	TIM_Cmd(TIM2,ENABLE);//开启定时器
		
}

void PWM_SetCompare2(uint32_t ccr){
	TIM_SetCompare2(TIM2,ccr);//设置通道2的CCR值,来改变占空比
}

PWM.h文件

#ifndef PWM_H
#define PWM_H

void PWM_Init(void);
void PWM_SetCompare2(uint32_t ccr);//设置通道2的CCR值
	
#endif

为了更简单的表示,设置一个Servo.c来直接设置角度而不是CCR的值

由线性关系计算对应角度下的CCR值

#include "stm32f4xx.h"                  // Device header
#include "PWM.h"

void Servo_Init(){
	PWM_Init();
	
}
void Servo_SetAngle(float Angle){
	//CCR=500->0度,CR=2500->180度
    //则由线性关系得到下面的角度和CCR关系公式
	PWM_SetCompare2(2000*Angle/180+500);

}

Servo.h

#ifndef SERVO_H
#define SERVO_H

void Servo_Init(void);//将PWM初始化放在这一部分
void Servo_SetAngle(float Angle);

#endif

这样可以直接在main函数Servo_SetAngle(Angle);里设置舵机角度

本次用按键改变舵机角度,每次按下舵机旋转30度

Key.c

#include "stm32f4xx.h"                  // Device header
#include "Delay.h"   

void Key_Init(){
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13;
	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
	GPIO_InitStruct.GPIO_Speed=GPIO_Fast_Speed;
	
	GPIO_Init(GPIOC,&GPIO_InitStruct);

}
uint8_t Key_GetNum(void){
	uint8_t KeyNum=0;
	if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==1){
		Delay_ms(10);
		while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==1);
		Delay_ms(10);
		KeyNum=1;
	}
	return KeyNum;
}

Key.h

#ifndef KEY_H
#define KEY_H

void Key_Init(void );
uint8_t Key_GetNum(void);//接收按键按下情况

#endif

main.c

#include "stm32f4xx.h"                  // Device header
#include "Key.h"
#include "Servo.h"


uint8_t i;
int main(void){
	Servo_Init();
	Key_Init();
    float Angle=0;
	while(1){
		Servo_SetAngle(Angle);
		if(Key_GetNum()==1){
			if(Angle<180)//未旋转至180时每次按下旋转30度
				Angle+=30;
			else Angle=0;//旋转至180时角度归0
		}
		
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值