备战蓝桥杯之嵌入式——PWM

今天对AFIO有了正确的认识。

在使用引脚的重映射功能和外部中断时需要使用AIFO时钟。

贴一段官方手册对AFIO的解释:

为了优化64脚或100脚封装的外设数目,可以把一些复用功能重新映射到其他引脚上。设置复用
重映射和调试I/O配置寄存器(AFIO_MAPR)实现引脚的重新映射。这时,复用功能不再映射到它们的原始分配上。

 

这次PWM实验要实验的功能就是呼吸灯。

配置步骤如下:

1:使能GPIO和TIM1时钟;

2:配置GPIO,MODE查中文参考手册确定为为AF_PP;

3:配置定时器;

4:配置TIM1_CH1输出比较函数;

5:因为TIM1为高级定时器,普通定时器在完成以上设置了之后, 就可以输出 PWM 了,但是高级定时器,我们还需要使能刹车和死区寄存器( TIM1_BDTR)的 MOE 位,以使能整个 OCx(即PWM)输出。 库函数的设置函数为:
TIM_CtrlPWMOutputs(TIM1,ENABLE);// MOE 主输出使能

6:使能预装载;

7:使能自动重装载;(区别仅在于是否是本次还是下一个周期进行改变,可写,可不写)

8:使能定时器。

贴出timer.c

voidPWM_Init(u16 arr,u16 psc)

{

         GPIO_InitTypeDef GPIO_InitStructure;

         TIM_TimeBaseInitTypeDefTIM_TimeBaseInitStructure;

         TIM_OCInitTypeDef TIM_OCInitStructure;

        

         RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1|RCC_APB2Periph_GPIOA,ENABLE);

        

         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;

         GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;

         GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;                            

         GPIO_Init(GPIOA,&GPIO_InitStructure);

        

         TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;

         TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;

         TIM_TimeBaseInitStructure.TIM_Period=arr;

         TIM_TimeBaseInitStructure.TIM_Prescaler=psc;

         TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);

        

         TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM2;

         TIM_OCInitStructure.TIM_Pulse=0;(初值)

         TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;

         TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;

         TIM_OC1Init(TIM1,&TIM_OCInitStructure);

        

         TIM_CtrlPWMOutputs(TIM1,ENABLE);

        

         TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);

        

         TIM_ARRPreloadConfig(TIM1,ENABLE);

        

         TIM_Cmd(TIM1,ENABLE);

}

然后在主函数中只需调用TIM_SetCompare1(TIM1,led0val);就可以完成占空比的变化。

贴出主函数:

#include"timer.h"

#include"delay.h"

int main(void)

{

         u16 led0val=0;

         u8 dir;

         PWM_Init(899,0);           频率为1/(900/72000000)=80KHz

         delay_init();

         while(1)

         {

                   delay_ms(10);                  (延时函数万万不能漏!)

                   if(led0val>300)       dir=0;

                   else if(led0val==0)         dir=1;

                   if(dir)       led0val++;

                   else led0val--;

                   TIM_SetCompare1(TIM1,led0val);

         }

}

这里,我们从死循环函数可以看出,我们控制 LED0_PWM_VAL 的值从 0 变到 300,然后
又从300 变到 0,如此循环,因此 DS0 的亮度也会跟着从暗变到亮,然后又从亮变到暗。至于
这里的值,我们为什么取 300,是因为 PWM 的输出占空比达到这个值的时候,我们的 LED 亮
度变化就不大了(虽然最大值可以设置到 899),因此设计过大的值在这里是没必要的。至此,
我们的软件设计就完成了。

 

最后我还做了另外一个小实验,同时使用两个定时器控制两个呼吸灯,一开始新配置的那盏怎么都不行,后来发现原来是RCC时钟没给它配置好,真是兜了个机灵!洗澡,休息!

 

 

************************************************************

更新:

做了输入捕获实验后,发现主函数中还可以这样写:

                   TIM_SetCompare1(TIM1,TIM_GetCapture1(TIM1)+1);

                   if(TIM_GetCapture1(TIM1)>300)       TIM_SetCompare1(TIM1,0);

严重声明的是这里的TIM_GetCapture1();得到的是寄存器CCR1的值;

这里来说一下CCR1寄存器,它有点特别。

它在输入捕获模式和输出比较模式下的用法是不一样的。

在输入捕获时,它是CNT计数值;

在输出比较时,它是预装载值;

详见手册P293。

 

你可能感兴趣的:(嵌入式)