目录
1、硬件介绍
单片机:STM32F1
舵机:MG995


2、PWM口配置
20毫秒的PWM脉冲占空比,对舵机控制效果较好
计算的公式:

PSC、ARR值的选取:SG90要求的频率是20ms,则72MHz / (PSC+1) / (ARR+1) = 1/0.02;这里PSC和ARR的参数是不固定的。经过多次尝试最终确定PSC=72-1,ARR=20k-1时,舵机旋转效果最好。
PWM配置程序
void pwm_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure_For_Servo;
TIM_TimeBaseInitTypeDef TIM_TimeBaseImitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/*µÚÒ>>²½¿ªÆôRCCʱÖÓ*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
/*µÚ¶þ²½ÅäÖÃGPIO¶Ë¿---PA1Ú*/
GPIO_InitStructure_For_Servo.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure_For_Servo.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure_For_Servo.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure_For_Servo);
TIM_InternalClockConfig(TIM2);/*??????*/
/*µÚÈý²½ÅäÖÃʱ>>ùµ¥Ôª*/ //20msƵÂÊ(¶æ>>úÒªÇóµÄÕâ¸öƵÂÊЧ¹û×îºÃ)
TIM_TimeBaseImitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseImitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseImitStructure.TIM_Period = 20000 - 1;
TIM_TimeBaseImitStructure.TIM_Prescaler = 72 - 1;
TIM_TimeBaseImitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseImitStructure);
/*µÚËIJ½ÅäÖÃÊä³ö±È½Ïµ¥Ôª*/
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);
}
设置脉冲
void pwm_setcompare2(uint16_t compare)
{
TIM_SetCompare2(TIM2,compare);
}
完整代码
#include "pwm.h"
void pwm_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure_For_Servo;
TIM_TimeBaseInitTypeDef TIM_TimeBaseImitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/*µÚÒ>>²½¿ªÆôRCCʱÖÓ*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
/*µÚ¶þ²½ÅäÖÃGPIO¶Ë¿---PA1Ú*/
GPIO_InitStructure_For_Servo.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure_For_Servo.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure_For_Servo.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure_For_Servo);
TIM_InternalClockConfig(TIM2);/*??????*/
/*µÚÈý²½ÅäÖÃʱ>>ùµ¥Ôª*/ //20msƵÂÊ(¶æ>>úÒªÇóµÄÕâ¸öƵÂÊЧ¹û×îºÃ)
TIM_TimeBaseImitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseImitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseImitStructure.TIM_Period = 20000 - 1;
TIM_TimeBaseImitStructure.TIM_Prescaler = 72 - 1;
TIM_TimeBaseImitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseImitStructure);
/*µÚËIJ½ÅäÖÃÊä³ö±È½Ïµ¥Ôª*/
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);
}
void pwm_setcompare2(uint16_t compare)
{
TIM_SetCompare2(TIM2,compare);
}
3、角度转换
void servo_set_angle(double angle)
{
pwm_setcompare2(angle / 180 * 2000 + 500);
}
完整代码
#include "stepmotor.h"
#include "pwm.h"
void servo_init(void)
{
pwm_init();
}
void servo_set_angle(double angle)
{
pwm_setcompare2(angle / 180 * 2000 + 500);
}
4、main函数中应用
2秒运动执行一次,分别从0度->180度->270度。(若180度舵机,运动到180度就不再往后转270度了,等到0度的时候转到0度)
//2秒运行一次
if(i%2000==0)
{
count++;
//printf("count:%d \r\n",count);
//printf("Pitch: %.2f ,Roll: %.2f,Yaw: %.2f \r\n",Pitch,Roll,Yaw); //Pitch,Roll,YawÊý¾Ý´<<µ½´®¿Ú
count2++;
if(count2==1)
{
angle=0;
servo_set_angle(angle);
printf("angle:%.2f \r\n",angle);
}
if(count2==2)
{
angle=180;
servo_set_angle(angle);
printf("angle:%.2f \r\n",angle);
}
if(count2==3)
{
angle=270;
servo_set_angle(angle);
count2=0;
printf("angle:%.2f \r\n",angle);
}
}
完整代码
#include "system.h"
#include "SysTick.h"
#include "SysDelay.h"
#include "led.h"
#include "usart.h"
#include "mpu6050.h"
#include "stepmotor.h"
double angle;
int main()
{
u8 count=0;
u16 i=0;
u16 count2=0;
SystemInit(); //ϵͳ³õʼ>>¯
SysDelay_Init(72); //×Ô¶¨ÒåÑÓʱº¯Êý³õʼ>>¯
LED_Init();
USART1_Config(); //´®¿Ú1³õʼ>>¯ ÉÏÎ>>>>ú
USART3_Config(); //´®¿Ú3³õʼ>>¯ À¶ÑÀÓëUSART3¹<<ÓÃÏàͬIO¿Ú
SysDelay_ms(10); //10ºÁÃëÑÓʱ
MPU6050_Init(); //MPU6050 DMPÍÓÂÝÒdzõʼ>>¯
delay_ms(1000);
servo_init();
while(1)
{
/* 1¡¢LEDµÆÉÁ˸ */
if(i%500==0)
{
led1=!led1;
}
//2ÃëÖ´ÐÐÒ>>´Î
if(i%2000==0)
{
count++;
//printf("count:%d \r\n",count);
//printf("Pitch: %.2f ,Roll: %.2f,Yaw: %.2f \r\n",Pitch,Roll,Yaw); //Pitch,Roll,YawÊý¾Ý´<<µ½´®¿Ú
count2++;
if(count2==1)
{
angle=0;
servo_set_angle(angle);
printf("angle:%.2f \r\n",angle);
}
if(count2==2)
{
angle=180;
servo_set_angle(angle);
printf("angle:%.2f \r\n",angle);
}
if(count2==3)
{
angle=270;
servo_set_angle(angle);
count2=0;
printf("angle:%.2f \r\n",angle);
}
}
//20ºÁÃëÖ´ÐÐÒ>>´Î
if(i%20==0)
{
}
/*>>ñÈ¡MPU6050½Ç¶È״̬*/
//ÔÚ´®¿ÚÊý¾Ý·¢ËÍÖ®ºó
MPU6050_Pose(); //Pitch·¹ö£¬Roll¸©Ñö£¬YawÆ<<º½
SysDelay_ms(1); //1ºÁÃëÑÓʱ
i++;
}
}
5、工程下载连接
https://download.csdn.net/download/panjinliang066333/90437321