stm32学习记录-5.2PWM输出控制sg90舵机角度

本文详细介绍了STM32中的定时器中断、PWM输出机制、输出比较和OC功能,以及如何配置高级定时器驱动三相无刷电机和SG90舵机,包括GPIO设置、PWM模式选择、频率和占空比计算。还提供了代码示例和常见问题解决方法。

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

源码连接:https://gitee.com/HL12334/stm32-learning-code

前提知识:

1.定时器中断

1.关键概念

1.1pwm输出

1.常用术语

  • OC(output compare)输出比较
  • CNT(counter),定时器中用于计数的寄存器:当前定时器计数值
  • CCR(Capture/Compare),捕获比较寄存器:与CNT寄存器的值进行比较,用于确定PWM占空比
  • PSC(Prescaler),预分频器:降低定时器输入频率,可以进行更长时间的定时
  • ARR(Auto-Reload Register),自动重装寄存器: 用于确定PWM周期, 当CNT==ARR时,计数器重新开始计数

2.每个高级定时器和通用定时器都拥有4个输出比较通道。

3.高级定时器的前三个通道额外拥有死区生成和互补输出的功能,用于驱动三相无刷电机。

4.有效电平: 自行设置有效电平为高电平还是低电平,反正则为无效电平

5.输出比较模式,常用模式

  1.  PWM模式1
    向上计数时(一般使用向上计数):CNT<CCR时输出有效电平,CNT>=CCR时输出无效电平
    向下计数时:CNT>CCR时输出无效电平,CNT<=CCR时输出无效电平
  2.  PWM模式2
     与PWM模式1相反

6.参数计算(有效电平为高电平,向上计数模式,计数模式为PWM模式1,其他一样的道理)

  • PWM频率:Freq=CK_PSC/(PSC+1)/(ARR+1)
  • PWM占空比Duty=CCR/(ARR+1)

示例:ARR=99,CCR=30,使用向上计数,有效电平设置为高电平,使用PWM模式1。输出占空比为30%的PWM波。

向上计数在小于30时(CNT<CCR),由于计数模式是PWM模式1,所以输出有效电平(高电平),大于等于30时(CNT>=CCR)输出无效电平(低电平),当计数为99(CNT==ARR)时,计数器又重新开始计数(开始下一个脉冲)

1.2sg90舵机

驱动是直流电机,内部通过电位器确定当前角度,再通过内部电板控制使其运动到pwm波计算所得位置。

输入PWM要求,周期为20ms,高电平宽度为0.5ms~2.5ms。中间其他角度自行按比例计算。控制的是绝对角度。

接线,一般橙色是PWM控制线,黑色是地线,红色为vcc。

2.配置流程

1.GPIO配置:PWM输出引脚配置,根据所选定时器硬件确定的引脚,查询《STM32中文参考手册_V10》8.3.7章节,配置为复用推挽输出。

2.定时器配置:设置pwm周期
3.输出比较配置:

  1. 创建输出比较配置结构体TIM_OCInitTypeDef
  2. 给结构体赋初始值(增加代码通用性,高级定时器参数很多,未初始化的值使用时可能会导致其他问题)-TIM_OCStructInit
  3. 配置关键参数:输出比较模式(一般选择为PWM模式1)、有效电平、输出使能、CCR值
  4. 初始化结构体:TIM_OCYInit(TIMX, &TIM_OCInitStructure),配置定时器X的第Y个通道输出PWM

3.使用流程

1.初始化

2.修改占空比(修改CCR值):TIM_SetCompareX(TIMY),修改定时器Y的第X通道的CCR值。

4.代码

使用通用定时器2的通道1(PA0)驱动舵机转动,

pwm.c

#include "pwm.h"

//通过通用定时器2通道1输出PWM控制舵机
void PWMInit(int psc,int arr){
	//1.GPIO初始化配置,定时器2通道1对应IO口为PA0
	GPIO_InitTypeDef GPIO_InitStructure;//创建gpio初始化结构体
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PA端口对应时钟

	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//配置为复用推挽输出
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;//PA0
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出速度为50mhz
	GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化端口PA0
	
	//2.定时器配置
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//创建定时器配置结构体
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能通用定时器2时钟
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure);//初始化结构体参数,提高代码通用性
	
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc-1;//设置预分频值
	TIM_TimeBaseInitStructure.TIM_Period=arr-1;//设置自动重装值
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//初始化定时器
	
	//3.输出比较配置
	TIM_OCInitTypeDef TIM_OCInitStructure;//创建输出比较配置结构体
	TIM_OCStructInit(&TIM_OCInitStructure);//初始化比较配置结构体,方便配置其他定时器
	
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//设置输出比较模式为PWM1模式
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//有效电平为高电平
	TIM_OCInitStructure.TIM_Pulse=0;//设置比较寄存器值为0,后续在程序中动态修改
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//启用比较输出通道
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);//初始化比较输出配置
	
	TIM_Cmd(TIM2, ENABLE);  //使能TIM2
}

pwm.h

#ifndef __PWM_H
#define __PWM_H
#include "sys.h"

void PWMInit(int psc,int arr);//初始化函数

#endif

main.c

#include "stm32f10x.h"
#include "pwm.h"
#include "delay.h"

 int main(void)
 {	
	 delay_init();//延时函数初始化
	 PWMInit(7200,200);//初始化定时器,频率为72mhz/7200/200=50hz
  while(1)
	{
		delay_ms(1000);//延迟1s
		TIM_SetCompare1(TIM2,5);//占空比为5/200,舵机角度为0°
		delay_ms(1000);//延时1s
		TIM_SetCompare1(TIM2,15);//占空比为15/200,舵机角度为90°
		delay_ms(1000);//延时1s
		TIM_SetCompare1(TIM2,25);//占空比为25/200,舵机角度为180°
		
	}
 }

5.问题总结

1.同一定时器输出多路PWM波形都是一样的吗
  同一个定时器所以频率、相位一样,占空比由各自输出比较配置确定

2.输出PWM错误
1.端口输出模式要配置为复用推挽输出。 2.检查定时器是否选择错误,通道端口号是否正确

3.使用定时器高级定时器无法输出PWM
高级定时器还要进行主输出使能, TIM_CtrlPWMOutputs

实验效果

stm32输出PWM驱动舵机

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值