今天对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:使能定时器。
贴出
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""
#include""
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。