stm32 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

void PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_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。