STM32控制舵机原理分享,理解不到位欢迎指正
- 时间:
- 浏览:211
- 来源:中国微特电机网
你知道不!舵机这东西可太神奇!它主要靠伺服电机,就服服帖帖按信号命令来动作,给不同信号就能转到不同角度,这多牛!不过怎么用stm32控制它?下面咱就聊一下。
舵机原理大揭秘
舵机的核心是伺服电机! servo,这词多洋气,意思就是服从信号要求行动。咱能给舵机输入不同信号,它就乖乖对应旋转。它接收 PWM 信号,信号进去内部电路产生偏置电压,刺激电机通过减速齿轮带动电位器移动。等电压差为零,电机就停下,就这么达到了伺服效果。比如说,给个特定 PWM 信号,它就精准到指定位置,厉害得很!
PWM 信号小课堂
一般而言,舵机接收的 PWM 信号频率是 50HZstm32 控制17个电机,也就是周期为 20ms。当高电平脉宽在 0.5ms - 2.5ms 之间,舵机能转到不同角度。就像不同密码对应不同宝藏一样。要是脉宽在这范围之外,那就没啥用这种对应关系超级关键,懂了它,咱对舵机的控制就多了几分把握。
STM32 上阵搭配
想让 stm32 给舵机输信号,得用 TIM 定时器。基本定时器可没 PWM 输出功能,咱只能选通用定时器和高级定时器。选了合适的定时器,好比练武选对了好兵器,后面控制起来就顺畅多了。就像你去选工具,选错了那事可就办不成。
外设初始化秘诀
初始化这些外设就那几步路来着,我的妈咱得记牢!第一步,开启外设施时钟,不然它都启动不了。第二步,要配置初始化结构体,如果有对应的 GPIO,还得初始化。之后,要调用结构体初始化函数。最后,该使能的就得使能。每一步都像给机器组装零件,少一个都不行
static void TIM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 输出比较通道 GPIO 初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 输出比较通道互补通道 GPIO 初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// BKIN引脚默认先输出低电平
GPIO_ResetBits(ADVANCE_TIM_BKIN_PORT,ADVANCE_TIM_BKIN_PIN);
}
static void Advance_TIM_Config(void)
{
// 开启定时器时钟,即内部时钟CK_INT=72M
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
/*--------------------时基结构体初始化-------------------------*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
TIM_TimeBaseStructure.TIM_Period= (200-1);
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler= (7200-1);
// 时钟分频因子 ,用于配置死区时间,没用到,随意
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,没用到,可以随意设置
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/*--------------------输出比较结构体初始化-------------------*/
TIM_OCInitTypeDef TIM_OCInitStructure;
// 配置为PWM模式2
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
// 输出使能
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
// 互补输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
// 设置占空比大小
TIM_OCInitStructure.TIM_Pulse = 0;
// 输出通道电平极性配置
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 互补输出通道电平极性配置
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
// 输出通道空闲电平极性配置
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
// 互补输出通道空闲电平极性配置
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
// 使能计数器
TIM_Cmd(TIM1, ENABLE);
// 主输出使能,当使用的是通用定时器时,这句不需要
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
void TIM_Init(void)
{
TIM_GPIO_Config();
Advance_TIM_Config();
}
配置关键要素
TIM 初始化有两个结构体,时基结构体和输出比较结构体。咱先得选好具体开哪条输出通道,我选的是 TIM1(高级定时器)的 CH1(通道一),对应的 GPIO 是 PA8。特别得注意时基结构体里的 TIM_Period(自动重装载寄存器值,叫 arr)和 TIM_Prescaler(预分频寄存器值,简称 psc)这俩,它俩决定了输出 PWM 信号的周期。咱这么配置,就是要让输出信号符合舵机要求的 20ms 周期。要是这俩没弄对,信号就不达标
代码实战环节
初始化完,就能在 main 里输出信号了。在 20ms 周期的 PWM 信号里,不同脉宽对应舵机不同转动角度,在 0.5ms - 2.5ms 范围里才有效。咱们就可以在 main 里配置不同脉宽,不过 stm32 不是直接配置脉宽stm32 控制17个电机,而是通过占空比来弄。有个重要函数 TIM_SetCompare1(),不懂用法去看手册。在定时器初始化时选了 PWM1 模式,main 中的占空比依次为 25、20、15、10、5。你们自己试验,占空比多试试不同值,看看会有啥结果!
朋友们,你们在试验 stm32 控制舵机时,遇到过啥让人摸不着头脑的事情不?觉得我说得有点道理,就给我点个赞,分享给更多朋友!
#include "stm32f10x.h"
#include "bsp_Advance_tim.h"
#include "delay.h"
int main(void)
{
int delay_time;
delay_init(); //延时函数初始化
TIM_Init(); //定时器初始化
delay_time = 500;
while(1)
{
delay_ms(delay_time);
TIM_SetCompare1(ADVANCE_TIM, 175); //对应180度
delay_ms(delay_time);
TIM_SetCompare1(ADVANCE_TIM, 180); //对应135度
delay_ms(delay_time);
TIM_SetCompare1(ADVANCE_TIM, 185); //对应90度
delay_ms(delay_time);
TIM_SetCompare1(ADVANCE_TIM, 190); //对应45度
delay_ms(delay_time);
TIM_SetCompare1(ADVANCE_TIM, 195); //对应0度
}
}
猜你喜欢