拍的GIF太朦胧了,就不备份了。。。
呼吸灯的实现实则是通过PWM控制的LED的亮灭时间间隔,由于人眼视觉的暂缓效应,达到预期的效果。
那么呼吸灯的设计思路是怎么的呢?
①需要点灯--LED的配置和实现(GPIO_InitTypeDef结构体)
②时间的调用--定时器的配置(TIM_TimeBaseInitTypeDef结构体)
③时间间隔的控制--PWM的配置和实现(TIM_OCInitTypeDef结构体)
通俗的讲,就是理论上想让LED达到图a的亮灭的效果(LED灯由亮逐渐熄灭后在逐渐点亮),然而在MCU的识别到的高电平为2.2~2.9V以上,也就是说MCU电平变化只有两种情况,高电平(或1)低电平(或0),它没办法达到在电压上 的逐渐升高。因此,利用人眼的暂缓效应,代码设计思想为图b,通过LED的亮灭时间间隔来达到预期的效果。
通过LED8(PC7)实现呼吸灯功能,通过查找数据手册的GPIO复用功能可知,应该使用定时器3的通道2。
void pwm_init() { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure;//初始化外设TIMx RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_Init(GPIOC,&GPIO_InitStructure); TIM_TimeBaseInitStructure.TIM_Period = 900; //PWM频率 = 720000/900=8KHz TIM_TimeBaseInitStructure.TIM_Prescaler = 0;//100Khz计数频率 TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;//时钟分割 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseInit(TIM3, & TIM_TimeBaseInitStructure); GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//改变指定管脚的映射 //PWM参数配置 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //定时器模式 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; //指定输出引脚的极性 TIM_OC2Init(TIM3,&TIM_OCInitStructure);//开启定时器3的通道2 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能TIMx在CCR2上的预装载寄存器 TIM_Cmd(TIM3,ENABLE);//使能TIMx外设 }
主函数相对简单,使用的普中的例子。
int main() { u8 fx=1;//呼吸方向位 u32 ti=0; pwm_init(); while(1) { delay_ms(10); if(fx==1) { ti++; if(ti>300) { fx=0; } } else { ti--; if(ti==0) { fx=1; } } TIM_SetCompare2(TIM3, ti);//设置TIMx捕获比较2寄存器值 } }