基于stm32单片机的可调节pwm输出

目标:

1.通过按键1切换pwm频率的切换。

2.通过按键2实现pwm占空比的切换。

3.备注:不附加硬件原理图,但是通过描述简单介绍引脚的连接。

硬件原理描述:

1.通过3个IO口实现16个按键的检测。
2.按键1,按键2不多做描述,通过键盘扫描程序循环检测按键
3.通过TIM2 CHI通道PA0输出波形。

pwm输出配置功能函数:

#include "pwm.h"
static  u16 Tim_Prescaler=35;       //配置TIM默认时钟分频
static  u16 TIMCompare1=200;        //配置TIM默认脉冲比较值
void GPIO_cfg() //配置pwm输出相关引脚  
{  
    GPIO_InitTypeDef GPIO_InitStructure;  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //使能GPIOA的时钟 
    //RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);    //复用时钟不需要失能
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  //选择引脚0                                                           
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //输出频率最大50MHz                                                 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       //复用推挽输出   
    GPIO_Init(GPIOA,&GPIO_InitStructure);   
} 
void TIMER_cfg(void)//配置TIM2   
{  
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);   //开启TIM2的时钟   
    //设置预分频系数  
    TIM_TimeBaseStructure.TIM_Prescaler =Tim_Prescaler;  
    //设置计数自动重装值大小  
    TIM_TimeBaseStructure.TIM_Period = 1000;    
    //设置计数器模式为向上 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;    
    //设置时钟分割---不分割  
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  
    //将配置应用到TIM2中  
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
} 
void PWM_cfg(void)//配置pwm输出   
{  
    TIM_OCInitTypeDef TimOCInitStructure;  
    //TIM_OCStructInit(&TimOCInitStructure);  
    //PWM模式1输出 
    TimOCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;  
    //设置占空比0.2 
    TimOCInitStructure.TIM_Pulse = 200;  
    //TIM输出比较极性高  
    TimOCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  
    //使能输出状态  
    TimOCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  
    //TIM2的CH1输出  
    TIM_OC1Init(TIM2, & TimOCInitStructure);  
    //设置TIM2的PWM输出为使能  
    //TIM_CtrlPWMOutputs(TIM2,ENABLE); //高级定时器专用,TIM2不需要此函数功能


    //使能或者失能TIM2在CCR1上的预装载寄存器 使能:在更新事件发生时才会传送预装载值(从CCR1到影子寄存器);失能:直接传送预装载值
    //TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
    //使能或者失能 TIMx 自动重装载寄存器· 
    //TIM_ARRPreloadConfig(TIM2, ENABLE);
}
//pwm输出初始化,默认输出方波频率=2Khz,占空比=0.2 
void PWM_Init(void) 
{
    GPIO_cfg();
    TIMER_cfg();
    PWM_cfg();
    TIM_Cmd(TIM2,ENABLE);
}
void PWM_changefre(void)  //频率转换:2Khz  200hz
{
    if(Tim_Prescaler==359)
    {
        Tim_Prescaler=35;
    }
    else
    {
        Tim_Prescaler=359;
    }
    TIM_PrescalerConfig(TIM2, Tim_Prescaler,TIM_PSCReloadMode_Update);//设置 TIM2 预分频,即时或者下次更新作用
}
//更改占空比,默认0.2,0.4,0.6,0.8,0.2依次循环
void PWM_changeduty(void) 
{
    if(TIMCompare1<800)
    {
        TIMCompare1+=200;
    }
    else
        TIMCompare1=200;
    TIM_SetCompare1(TIM2, TIMCompare1);//设置 TIMx 捕获比较 1 寄存器值
}


主函数:

#include "public.h"
static u8 key=0x10;
int main(void)
{
    SystemInit();               //init system rcc  HSE 72Mhz
    power_init();               //open power sourse
    delay_init(72);             //system clock frequency 72Mhz
    KEY_Init();
    PWM_Init();
    while(1)
    {
        key=KEY_Scan();
        if(key==0)              //修改定时器预分频值,完成pwm频率切换。200HZ--------2KHZ
        {
            key=0xff;
            delay_ms(100);      
            PWM_changefre();
        }
        if(key==2)              //修改占空比
        {
            key=0xff;
            delay_ms(100);
            PWM_changeduty();
        }
    }
}

总结:

1.配置pwm输出的一般性步骤:

1.配置pwm输出相应的GPIO口。
2.配置pwm输出相应的定时器。
3.配置pwm输出相应的输出通道。

2.几个要点的理解:

1.涉及到IO口重映射问题
2.AFIO时钟问题
对寄存器 AFIO_EVCR、AFIO_MAPR 和 AFIO_EXTICRX 进行读写操作前,应当首先打开 AFIO 的时钟。
上句话是从stm32中文参考手册找到的。
也就是说配置AFIO的事件控制寄存器(AFIO_EVCR)、复用重映射和调试I/O 配置寄存器(AFIO_MAPR)、外部中断配置寄存器 1(AFIO_EXTICR1)等才需要启用AFIO时钟。
并不是说引脚复用时就必须开启AFIO时钟。所以,在上述程序中,不需要开启AFIO 时钟(已经验证OK)。
3.计数器(TIMx_CNT)
这个寄存器是用来计数的,数数用的
4.自动重装载寄存器  和(影子寄存器)--->实际的自动重装载寄存器
a.自动重装载寄存器存储的是TIM计数值的大小,计数器到了这个值就会发生溢出停止计数,但并是用该寄存器直接和计数器比较。
b.真正用来和计数器比较的是影子寄存器(物理存在的),自动重装载寄存器的值送到了这里。
c. 这两个寄存器是联通的。
d.什么时候把自动重装载寄存器值送到影子寄存器?
先来看一下下面这个函数:它的作用是 使能或者失能 TIMx 在 ARR 上的预装载寄存器(自动重装载寄存器)
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState Newstate)
失能=0:TIMx_ARR寄存器没有缓冲;
使能=1:TIMx_ARR寄存器被装入缓冲器。
答案:通过配置TIMx_CR1的ARPE位,决定什么时候把自动重装载寄存器值送到影子寄存器。
5.捕获/ 比较寄存器(输出模式下)
该寄存器的值决定pwm输出时的占空比。计数器会根据这个值的大小来判断何时翻转电平。比如:计数值100,,比较值50,则占空比就为50%
同样的,该寄存器也有相应的影子寄存器。功能同上。
6.转换频率:
首先要理解定时器是怎么完成频率输出:
a.系统频率设置为72Mhz          设为X频率
b.初始化定时器时,配置时钟分割X/(时钟分割+1)
c.初始化定时器时,预分频。X/(时钟分割+1)/(预分频系数+1)
d.得到定时器的时钟输入频率。
e.设置自动重装载寄存器(计数值),得到定时器的频率输出 X/(时钟分割+1)/(预分频系数+1)/计数值
其次,判断可更改的变量来改变频率输出。
本次试验选取更改预分频系数,作为控制变量。
7.转换占空比
duty=TIM2_CCR1/TIM2_ARR
本次试验选择改变TIM2_CCR1。

3.心得:

1.参考了网上一些pwm案例,觉得有些案例实现起来,调用了一些不需要的函数,效率下降。

2.本次学习仅仅总结了PWM输出的用法,对定时器的其他功能认知仍存在大量不足。

3.第一次,写这么长的总结,很有成就感。

你可能感兴趣的:(stm32学习)