这是本文档旧的修订版!


PWM控制SG90舵机

// main.c

#include "stm32f10x.h"                  // Device header
#include "PWM.h"

int main(void)
{
    PWM_Init();
    while(1);
}
#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
    // 时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    TIM_InternalClockConfig(TIM2); // 可不写这一句,上电默认内部时钟源
    
    // 时基单元
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrucure;
    TIM_TimeBaseInitStrucure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStrucure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStrucure.TIM_Period = 359; // 【ARR】
    TIM_TimeBaseInitStrucure.TIM_Prescaler = 3999; // 【PSC】
    TIM_TimeBaseInitStrucure.TIM_RepetitionCounter = 0; //通用定时器没有重复计数器
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStrucure);
    
    // 初始化输出比较OC
    TIM_OCInitTypeDef TIM_OCInitStruture;
    TIM_OCStructInit(&TIM_OCInitStruture); // 给结构体赋初始值,因为下面用不到结构体的全部成员
    TIM_OCInitStruture.TIM_OCMode = TIM_OCMode_PWM1; // 模式PWM1
    TIM_OCInitStruture.TIM_OCPolarity = TIM_OCPolarity_High; // REF有效时输出高电平(有效电平为高电平)
    TIM_OCInitStruture.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
    TIM_OCInitStruture.TIM_Pulse = 27; // 【CCR】的值,在0-FFFF之间(16位)
    TIM_OC2Init(TIM2, &TIM_OCInitStruture);
    // 现在OC1就初始化好了,下面还需要初始化TIM2的OC2对应的GPIO口
    // 不同定时器不同OC对应的GPIO是不同的,是固定的,需要查表,得是PA1口
    
    // 配置GPIOA PIN1
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 要设置为复用推挽输出,原因看GPIO结构
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 启动定时器
    TIM_Cmd(TIM2, ENABLE);
    
    /*
    【计算公式】:
    Freq = CK_PSC / (PSC+1)*(ARR+1)  其中CK_PSC是72Mhz
    Duty = CCR / (ARR+1)
    Reso = 1 / (ARR+1)
    
    要输出频率50Hz,占空比5%,分辨率360的PWM波形:
    PSC = 3999,ARR = 359,CCR = 18
    保持上述频率和分辨率不变,输出占空比10%的PWM波形,只需修改CCR = 36。
    */
}