抽空写了些模块的驱动,顺便加深对程序的理解。今天写了舵机的驱动,这里记录学习的过程,以及收获。
- 舵机简介
- 程序编写
舵机简介
我这次用到的舵机其中之一是SG90,另外一个黑色的舵机应该是MG90,看图:
要实现舵机的控制,我觉得最重要的是理解STM32的时钟。查阅资料很容易就可以知道,要使舵机正常工作,首先要输入20ms的周期信号。STM32F4是通过对自动重装载值和分频系数的设置完成这个周期信号的输出的。舵机部分详细介绍可以参考 _pray 的博客,写得非常棒。
程序编写
舵机配置部分,我把说明写在了函数里面的注释,应该比较容易理解,毕竟就是用到PWM输出的原理。
/*****************************************************************************
函数功能:利用通用定时器输出PWM波控制舵机转动角度,舵机转动角度范围:0`-180`
舵机分析:舵机接收PWM频率为50Hz,由f=1/T,当f=50时,T=0.02s,即20ms,
因此可通过配置通用定时器输出周期为20ms的PWM波来使舵机工作
相关配置:定时器选取通用定时器3,通道选取通道2,GPIO口输出为PB5
参数设置:自动装载值:2000,定时器分频系数:900,根据公式:
计数频率:90M/900=0.1M,PWM频率:0.1M/2000=50Hz
个人总结:输出的方波周期就是自动重装载值的值(us为单位),占空比 = compare / arr
*****************************************************************************/
#include "duoji.h"
TIM_HandleTypeDef TIM3_Handler;
TIM_OC_InitTypeDef TIM3_CH2_Handler;
//舵机初始化函数,这里使用到的是定时器3通道2输出PWM
void duoji_init(u16 arr,u16 psc)
{
TIM3_Handler.Instance=TIM3;//选取通用定时器3
TIM3_Handler.Init.Prescaler=psc;//定时器分频
TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;//向上计数模式
TIM3_Handler.Init.Period=arr;//自动重装载值
TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;//
HAL_TIM_PWM_Init(&TIM3_Handler);//初始化PWM配置
TIM3_CH2_Handler.OCMode=TIM_OCMODE_PWM1;//选取模式1
TIM3_CH2_Handler.Pulse=arr/2;//设置比较值,确定占空比
TIM3_CH2_Handler.OCNPolarity=TIM_OCPOLARITY_LOW;//输出比较极性为低
HAL_TIM_PWM_ConfigChannel(&TIM3_Handler,&TIM3_CH2_Handler,TIM_CHANNEL_2);//配置TIM3通道2
HAL_TIM_PWM_Start(&TIM3_Handler,TIM_CHANNEL_2);//开启PWM通道2
}
//回调函数
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_TIM3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_Initure.Pin=GPIO_PIN_5;//PB5
GPIO_Initure.Mode=GPIO_MODE_AF_PP;//复用推挽输出
GPIO_Initure.Pull=GPIO_PULLUP;//上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH;//高速
GPIO_Initure.Alternate=GPIO_AF2_TIM3;//复用为TIM3_CH2
HAL_GPIO_Init(GPIOB,&GPIO_Initure);//初始化GPIOB
}
//设置 TIM 通道 4 的占空比
//compare:比较值
void TIM_SetTIM3Compare2(u32 compare)
{
TIM3->CCR2=compare;
}
在主函数部分,为了方便自己调试角度,就把控制逻辑也就是占空比的配置注释掉了,用原子提供的usmart调试。这里就得夸一下原子哥了,usmart真心好用,省时省力。代码写得很简单,凑合着看吧。。。(要是需要修改后的usmart程序可以找我要)
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "usmart.h"
#include "duoji.h"
//自定义函数,供usmart_config.c调试调用
void led_set(u8 sta)
{
LED0=sta;
}
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180);
uart_init(115200);
LED_Init();
duoji_init(2000-1,900-1);//50Hz频率
usmart_dev.init(90);//初始化usmart
while(1)
{
//TIM_SetTIM3Compare2(162);//居中
//TIM_SetTIM3Compare2(110);//左满
//TIM_SetTIM3Compare2(200);//右满
}
}
要注意的是,算出来的角度和实际测出来的角度是存在一定的误差的,所以最好还是自己调角度。
这是调的几个占空比的具体波形,就是在串口里面输入TIM_SetTIM3Compare1()加具体数值就行了: