STM32F103C8T6控制SG90舵机的使用指南

1.接线

SG90带有一个3P的接头
根据颜色分为

  • 黄线(信号线)
  • 红线(电源线)
  • 棕色 (地线)
  • 舵机的工作电压4.8V-6V,接在STM32系统板上驱动不了,所以需要接电源模块单独的5V供电,我使用的是如图所示的电源模块

    注:
    如果STM32系统板供电和舵机供电不为同一模块,则需要共地,否则控制不成功!!!

    2.舵机的控制

    舵机的控制需要一个20ms左右的时基脉冲,该脉冲的高电平部分0.5ms到2.5ms控制舵机转动角度0°-180°呈线性变化。

    控制原理:舵机内部有一个基准电路,产生周期20ms,宽度1.5ms的基准信号,通过比较器,将外加信号与基准信号相比较,判断出方向和大小,从而产生电机的转动信号。

    知道原理之后,让我们来编写驱动代码,首先需要一个总周期为20ms的时基脉冲,这里采用TIM3CH2(定时器3通道2)对应的GPIOB5作为输出控制信号

    首先是PWM的基础配置

    void TIM3_PWM_Init(u16 arr,u16 psc)//GPIOB5	
    {
    	GPIO_InitTypeDef GPIO_InitStruct;
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
    	TIM_OCInitTypeDef TIM_OCInitStruct;
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);//RCC配置GPIO,复用时钟 ->APB2	
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//TIM3->APB1
    	//GPIO初始化
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//GPIOB5 
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;	
    	GPIO_Init(GPIOB,&GPIO_InitStruct);
    	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);//设置部分重映射
    
    	//初始化TIM3
    	TIM_TimeBaseStruct.TIM_Period=arr;//定时器周期
    	TIM_TimeBaseStruct.TIM_Prescaler=psc;//预分频系数定时器周期                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
    	TIM_TimeBaseStruct.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
    	TIM_TimeBaseStruct.TIM_ClockDivision=TIM_CKD_DIV1;
    	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStruct);
    	//设置比较通道CH2
    	/*
    	PWM模式2- 在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为
    	有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。
    	PWM模式1- 在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为
    	无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平,否则为有效电平。
    	*/
    	//PWM1极性高 向上记数 CNT小于CCR为高电平	
    	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;			//PWM输出模式选择
    	TIM_OCInitStruct.TIM_Pulse=0;							//通道比较值设定,可以自己设定
    	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;	//极性选择 (有效电平为高/低)
    	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//输出状态使能
    	TIM_OC2Init(TIM3,&TIM_OCInitStruct);					//通道CH2 GPIOB5		
    	//使能预装载寄存器
    	 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //通道CH2 GPIOB5
    	//定时器使能
    	TIM_Cmd(TIM3,ENABLE);
    }
    

    然后根据需要的周期设置总记数值以及分频系数

    void Sg90_Init(void){
    	//舵机控制总周期要求为20ms
    	//通过改变脉宽0.5ms-2.5ms代表0-180°
    	TIM3_PWM_Init(2000-1,720-1);
    	//2000*720/72M = 20000us = 20ms
    }
    

    然后通过改变比较值来改变舵机转动的角度

    void SetAngle(int angle){
    	//angle 范围为0-180
    	if(angle >= 0 || angle <= 180){
    		//总记数值为2000 比较值50-250代表0°-180°
    		TIM_SetCompare2(TIM3,50+(200*angle/180));//修改定时器3通道2的比较值
    	}
    }
    

    附带一个测试函数

    void Sg90_Test(void){//运行一次角度+10° 大于180°时重新从0开始
    	static int n = 0;
    	n += 10;
    	SetAngle(n%180);	
    }
    

    main.c

    sys.h为官方库函数文件

    #include "sys.h"
    #include "delay.h"
    #include "led.h"
    #include "sg90.h"
    int main()
    {
    	delay_init();
    	LedInit();
    	Sg90_Init();	
    	while(1)
    	{	
    		delay_ms(500);
    		LED1 = ~LED1;
    		Sg90_Test();		
    	}
    }
    

    这里使用了板载的LED灯,监测运行是否正常。

    sg90.c

    #include "sg90.h"
    /*********
    SG90控制
    GPIOB5 
    *********/
    void Sg90_Init(void){
    	//舵机控制总周期要求为20ms
    	//通过改变脉宽0.5ms-2.5ms代表0-180°
    	TIM3_PWM_Init(1999,719);
    	//2000*720/72M = 20000us = 20ms
    
    }
    void TIM3_PWM_Init(u16 arr,u16 psc)//GPIOB5	
    {
    	GPIO_InitTypeDef GPIO_InitStruct;
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
    	TIM_OCInitTypeDef TIM_OCInitStruct;
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);//RCC配置GPIO,复用时钟 ->APB2	
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//TIM3->APB1
    	//GPIO初始化
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//GPIOB5 
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;	
    	GPIO_Init(GPIOB,&GPIO_InitStruct);
    	GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);//设置部分重映射
    
    	//初始化TIM3
    	TIM_TimeBaseStruct.TIM_Period=arr;//定时器周期
    	TIM_TimeBaseStruct.TIM_Prescaler=psc;//预分频系数定时器周期                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
    	TIM_TimeBaseStruct.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
    	TIM_TimeBaseStruct.TIM_ClockDivision=TIM_CKD_DIV1;
    	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStruct);
    	//设置比较通道CH2
    	/*
    	PWM模式2- 在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为
    	有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。
    	PWM模式1- 在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为
    	无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平,否则为有效电平。
    	*/
    	//PWM1极性高 向上记数 CNT小于CCR为高电平	
    	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;			//PWM输出模式选择
    	TIM_OCInitStruct.TIM_Pulse=0;							//通道比较值设定,可以自己设定
    	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;	//极性选择 (有效电平为高/低)
    	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//输出状态使能
    	TIM_OC2Init(TIM3,&TIM_OCInitStruct);					//通道CH2 GPIOB5		
    	//使能预装载寄存器
    	 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //通道CH2 GPIOB5
    	//定时器使能
    	TIM_Cmd(TIM3,ENABLE);
    }
    void SetAngle(int angle){
    	//angle 范围为0-180
    	if(angle >= 0 || angle <= 180){
    		//总记数值为2000 比较值50-250代表0°-180°
    		TIM_SetCompare2(TIM3,50+(200*angle/180));//修改定时器3通道2的比较值
    	}
    }
    void Sg90_Test(void){//运行一次角度+10° 大于180°时重新从0开始
    	static int n = 0;
    	n += 10;
    	SetAngle(n%180);	
    }
    
    

    sg90.h

    #ifndef  __SG90_H_
    #define  __SG90_H_
    #include "sys.h"
    
    void Sg90_Init(void);
    void SetAngle(int angle);
    void Sg90_Test(void);
    void TIM3_PWM_Init(u16 arr,u16 psc);
    #endif //__SG90_H_
    
    

    led.c

    #include "led.h"
    void LedInit(void)
    {
    	//库函数版本
    	GPIO_InitTypeDef GPIO_InitStructor;
    	//开启硬件时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
    	//配置IO 推挽输出,输出速度
    	GPIO_InitStructor.GPIO_Pin=GPIO_Pin_13;
    	GPIO_InitStructor.GPIO_Mode=GPIO_Mode_Out_PP;
    	GPIO_InitStructor.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOC,&GPIO_InitStructor);
    }
    

    led.h

    #ifndef  __LED_H_
    #define  __LED_H_
    #include "sys.h"
    #define LED1 PCout(13)
    
    void LedInit(void);
    #endif //__LED_H_
    
    

    附带项目总体文件
    点击下载项目文件
    链接:https://pan.baidu.com/s/1SlVU4H5foOcHIOLDQ_t5NQ?pwd=6666
    提取码:6666

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32F103C8T6控制SG90舵机的使用指南

    发表评论