基于STM32F103的通用定时器和 PWM 的原理及应用(实现SG90舵机的转动)

发布于:2025-02-11 ⋅ 阅读:(54) ⋅ 点赞:(0)

一,通用定时器的原理

1,首先查阅通用定时器章节,了解通用定时器的基本功能

2,看懂通用定时器框图

输入捕获的要点总结

  • 基本定时器没有通道,通用定时器有通道
  • GPIO口和定时器通道是合作关系,需要通过GPIO口才能输入/输出脉冲信号(所以后面可以直接用IO口加延时来模拟脉冲信号)
  • 查阅数据手册可以知道哪个GPIO口跟定时器通道相连

3,重点理解输出比较功能(实现PWM的关键),首先就是要知道定时器之所以能够生成规律的脉冲信号,离不开通用定时器的定时功能

 

4,由上图可知,首先就是要知道所选的通用定时器是挂载在哪个总线下,就需要查阅2.3存储器映像查阅(本次使用TIM2),这样就知道该定时器的时钟频率

5,搞定了定时器的时钟频率,后面的操作就是对PWM所需寄存器进行配置,查阅PWM模式

寄存器配置总结:

  • ARR寄存器(自动重装寄存器)负责确定频率,CCR寄存器(捕获/比较寄存器)负责调节占空比
  • 在CCMR寄存器(捕获/比较模式寄存器)中通过配置OCxM位来选择PWM模式
  • 在CCER寄存器(捕获/比较使能寄存器)中通过配置CCxP位中设置极性,即选择高电平有效还是低电平有效

6,添加tim外设源文件,可参考stm32f4配置注释

二,代码实现

1,硬件接线

2,转动原理

只要产生一个周期的信号即(20ms)舵机就能转动 ,如果一直保持这个信号,舵机也不会再转动。

3,具体代码

在SG90.c中

#include "SG90.h"


/**
  * @brief  舵机的初始化
  * @param  None
  * @retval None
	* @note   舵机的信号线接PB8,PB8对应的是TIM4_CH3
  */
void SG90_PWMConfig(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	
	//打开GPIO时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	//打开定时器的时钟  TIM4_CH3
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, 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(GPIOB, &GPIO_InitStructure); 
	
	/* Time base configuration */
	TIM_TimeBaseStructure.TIM_Period = (200-1);			//配置自动重载值  20ms = 20 * 10 = 200
	TIM_TimeBaseStructure.TIM_Prescaler = (7200-1);		//配置分频系数    72MHz / 7200 = 10000  就1s 数 10000次, 1ms 数 10 次
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

	/* PWM1 Mode configuration: Channel3 */
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;						 //配置为PWM模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0;
	TIM_OC3Init(TIM4, &TIM_OCInitStructure);
	TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);
	
	TIM_ARRPreloadConfig(TIM4, ENABLE);

	/* TIM4 enable counter */
	TIM_Cmd(TIM4, ENABLE);

	
}


/**
  * @brief  打开门锁
  * @param  None
  * @retval None
	* @note   舵机的信号线接PB8,PB8对应的是TIM4_CH3
  */
void SG90_Open(void)
{
	TIM_SetCompare3(TIM4,15);//转到90度位置
}



/**
  * @brief  关闭门锁
  * @param  None
  * @retval None
	* @note   舵机的信号线接PB8,PB8对应的是TIM4_CH3
  */
void SG90_Close(void)
{
	TIM_SetCompare3(TIM4,5);//转到0度位置
}


在SG90.h中

#ifndef _SG90_H_
#define _SG90_H_

#include "stm32f10x.h"


void SG90_PWMConfig(void);		/*该函数初始化SG90舵机,用于模拟门锁闭合*/
void SG90_Open(void);			/*该函数用于模拟门锁打开*/
void SG90_Close(void);			/*该函数用于模拟门锁关闭*/


#endif

要点总结:

  • 在使用TIM_SetCompare3这个接口时,需要知道自己用的是哪个定时器的通道(例如我使用的定时器TIM4的通道CH3,选错通道就不行)
  • PWM只是用到了定时器的输出比较和定时的功能,并没有使用到中断功能

代码步骤总结:

  1. 打开定时器和GPIO时钟
  2. 配置GPIO引脚参数(设置复用模式)
  3. 配置定时器时基(配置自动重载值、配置预分频系数、选择计数模式)
  4. 配置PWM模式(设置PWM1模式、选择引脚输出模式、设置占空比的值、选择定时器通道、使能预装载功能)