假设有一个5V的电源和一个灯,要控制灯的亮度,如何实现呢?
- 一种办法是串联一个可 调电阻,改变电阻的阻值,灯的亮度就会改变。
- 另种办法是串联一个开关,假设在Is内,有0.5s 开关是闭合的,0.5s 开关是断开的,那么灯就亮0.5s、 灭0.s,这样灯看上去是闪烁的。如果把开关闭合和断开的时间缩短,比如0.5ms闭合、0.5ms 断开,那么灯的闪烁频率就会变得更高。由于人眼的视觉暂留效应,闪烁频率超过一定值后 人就感觉不到闪烁,这时看不到灯的闪烁,只看到灯的亮度降低到原来的一半。
同理,如果开关在1ms内,0.1ms闭合、0.9ms断开,那么灯的亮度就只有原来的1/10。这就是脉冲宽度调制( Pulse Width Modulation, PWM )的基本原理。
PWM是指对脉冲的宽度进行调制,是一种对模拟信号电平开关进行数字编码的方法,即通过对一系列脉冲的宽度进行调制,来等效获得所需要的波形(包括形状和幅值)。PWM是一种模拟控制方式,根据相应载荷的变化调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。这种方式能使电源的输出电压在工作条件变化时保持恒定,是利用微处理器的数字信号对模拟电路进行控制的一种非常有效的技术。
在PWM中,高电平保持的时间与该PWM的时钟周期之比称为占空比。例如,如果PWM的频率是1000Hz,那么它的时钟周期就是1000如果高电平保持的时间是200us,那么低电平保持的时间是800pus,占空比就是200: 1000,也就是20%。
实现呼吸灯时则通过改变占空比实现,此处只展示main.c中代码,其余配置读者需自行探索。
/*
* Loongson 1B Bare Program, Sample main file
*/
#include <stdio.h>
#include "ls1b.h"
#include "mips.h"
//-------------------------------------------------------------------------------------------------
// BSP
//-------------------------------------------------------------------------------------------------
#include "bsp.h"
#include "ls1b_gpio.h"
#include "ls1x_pwm.h"
#ifdef BSP_USE_FB
#include "ls1x_fb.h"
#ifdef XPT2046_DRV
char LCD_display_mode[] = LCD_800x480;
#elif defined(GT1151_DRV)
char LCD_display_mode[] = LCD_480x800;
#else
#error "在bsp.h中选择配置 XPT2046_DRV 或者 GT1151_DRV"
"XPT2046_DRV: 用于800*480 横屏的触摸屏."
"GT1151_DRV: 用于480*800 竖屏的触摸屏."
"如果都不选择, 注释掉本 error 信息, 然后自定义: LCD_display_mode[]"
#endif
#endif
//-------------------------------------------------------------------------------------------------
// 主程序
//-------------------------------------------------------------------------------------------------
int main(void)
{
printk("\r\nmain() function.\r\n");
//此处使用gpio_disable函数是为了gpio与pwm的功能冲突
gpio_disable(2);//在ls1b芯片原理图中可知LED3、LED4的控制引脚具有PWM的功能 但是此处LED4显示有问题 故未使用
unsigned int period=5000;
unsigned int hrc=1,dir=1;
pwm_cfg_t cfg;
cfg.isr=NULL;
cfg.mode=PWM_CONTINUE_PULSE;
cfg.cb=NULL;
/*
* 裸机主循环
*/
while(1)
{
if(dir)
hrc++;
else
hrc--;
printk("hrc=%d\n",hrc);
cfg.hi_ns=period-hrc*100;
cfg.lo_ns=hrc*100;
ls1x_pwm_pulse_start(devPWM2,&cfg);
delay_ms(20);
ls1x_pwm_pulse_stop(devPWM2);
if(hrc==49)
dir=0;
if(hrc==1)
dir=1;
}
/*
* Never goto here!
*/
return 0;
}
/*
* @@ End
*/