一,通用定时器的原理
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只是用到了定时器的输出比较和定时的功能,并没有使用到中断功能
代码步骤总结:
- 打开定时器和GPIO时钟
- 配置GPIO引脚参数(设置复用模式)
- 配置定时器时基(配置自动重载值、配置预分频系数、选择计数模式)
- 配置PWM模式(设置PWM1模式、选择引脚输出模式、设置占空比的值、选择定时器通道、使能预装载功能)