论文部分内容阅读
在单片机上实现流水灯很简单,只需要几条指令就可以完成,大部分学生都可以完成任务。于是在第二课堂中就此提出了一个新的问题:能不能实现一个亮度渐变的、按规律移动的超酷流水灯?学生都觉得并不是很容易实现,反映的主要问题是IO口只能写开关量(只能写1或者写0),也就是说只能控制LED灯的亮和灭,却不能控制LED灯的亮度,IO口的两值性不能表示出亮度变化的渐变过程。可是在单片机中还有一种PWM技术可用01方式虚拟表示出一个模拟量,通过这个模拟量可控制LED灯实现渐变的过程。本文介绍如何让单片机通过使用PWM技术来实现超酷流水灯的设计方法。
一、什么叫PWM技术
PWM是脉冲宽度调制的简称。PWM波是一个连续的方波,在一个周期中,其高电平和低电平的占空比是不同的。一个典型PWM的波形如图1所示。
在图1中,T是PWM波的周期,T1是高电平的宽度,Vcc是高电平值。可以得到其输出的平均电压为:
式中,T1/T称为PWM波的占空比。控制调节和改变T1的宽度,即改变PWM的占空比,就可以得到不同的平均电压。我们在实际应用中,常可以利用PWM波的输出,实现调节输出电压的功能。
二、如何在单片机上实现PWM
如何周期性地控制输出脉冲?有两种方案:第一种方案是在主程序通过延时控制再输出;第二种方案是通过单片机的计时器中断延时驱动输出。第一种方案占用CPU运行时间;第二种方案计时器可以在后台独立运行,在等待过程中计时器不占用CPU运行时间。
单片机时钟中断生成PWM时系统有两个状态,状态A输出高电平,状态B输出低电平,状态A和状态B的时间宽度总和不变,为一常数TW,状态A的时间T1和状态B的时间T2分别与需要输出的平均电压相关。
在单片机实际软件设计上具体的做法是:在定时器中设定下次中断的延时时间,中断发生后,来到状态A,IO脚输出高电平,根据要输出的电压,设定下次中断来的延时时间为T1,T1时间到,新中断发生后,来到状态B,设定IO脚输出低电平,再设定下次中断来的延时时间为T2 (T2=TW-T1),下次中断发生后,来到状态A。周而复始,形成PWM达到调整输出电压的目的。由于输出电压可以变化,外部所接的LED就可以达到渐变的发光效果,流程如图2所示。
图3是一个输出平均电压逐渐变大的例子,TW为常数,T1增大,T2变小,从而达到占空比的变化。
三、PWM时间常数的选择
在硬件上51单片机的CPU主频时钟为22.1184MHZ,由于要求在1秒钟内LED的亮度发生250种变化呈现渐亮效果,所以每次变化时间TW定义为1s/250=4ms,使用51定时器1方式,延时4MS的初始值为0xe333。变化的时间长度为4ms/255,在定时器中的4ms/255的调整时间常数为0x001d。
四、如何实现状态保存
局部变量在函数执行完毕退出时消失,定时器中断过程中定时状态不断地在状态A和状态B中转换,保存状态的方式是使用静态变量的方式,通过静态变量达到变量保存的状态值不随函数退出而丢失的效果。
五、如何实现流水效果
把流水灯的花样通过一个数组来保存(数组名game),这样的好处是修改流水的花样可以通过修改数组元素来达到。因为在1秒钟内,完成其中一个元素渐亮过程,状态发生了2*250即500种变化,通过对状态变化次数进行计数,状态变化次数到500次时把控制对象转化成为下一个数组元素。
六、程序代码(提供时钟中断程序代码片段)
#define TIMER_BEGIN0xe333;//4ms
const int inc_timer_count=0x001d;
unsigned char code game[16]= {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x18,0x24,0x42,0x81,0x03,0x0c,0x30,0xc0};
volatile unsigned int pre_time_set=0;
void modi_timer0()interrupt 1 using 1//定时器T0中断
{ static bit c_state=0;//当前状态
static unsigned int proc_count=0;//处理次数
static unsigned int timer0_high=0;
static unsigned int timer0_low=0;
static unsigned char cur_proc_led=0;
TR0=0;
if (!proc_count)
{
timer0_high=TIMER_BEGIN;
timer0_low=0x0ffff;
}
if (c_state)//输出低电平,状态为B
{
timer0_high=timer0_high inc_timer_count;//调整延时时间
TH0=(timer0_high )>>8;
TL0=(timer0_high)
一、什么叫PWM技术
PWM是脉冲宽度调制的简称。PWM波是一个连续的方波,在一个周期中,其高电平和低电平的占空比是不同的。一个典型PWM的波形如图1所示。

在图1中,T是PWM波的周期,T1是高电平的宽度,Vcc是高电平值。可以得到其输出的平均电压为:

式中,T1/T称为PWM波的占空比。控制调节和改变T1的宽度,即改变PWM的占空比,就可以得到不同的平均电压。我们在实际应用中,常可以利用PWM波的输出,实现调节输出电压的功能。
二、如何在单片机上实现PWM
如何周期性地控制输出脉冲?有两种方案:第一种方案是在主程序通过延时控制再输出;第二种方案是通过单片机的计时器中断延时驱动输出。第一种方案占用CPU运行时间;第二种方案计时器可以在后台独立运行,在等待过程中计时器不占用CPU运行时间。
单片机时钟中断生成PWM时系统有两个状态,状态A输出高电平,状态B输出低电平,状态A和状态B的时间宽度总和不变,为一常数TW,状态A的时间T1和状态B的时间T2分别与需要输出的平均电压相关。
在单片机实际软件设计上具体的做法是:在定时器中设定下次中断的延时时间,中断发生后,来到状态A,IO脚输出高电平,根据要输出的电压,设定下次中断来的延时时间为T1,T1时间到,新中断发生后,来到状态B,设定IO脚输出低电平,再设定下次中断来的延时时间为T2 (T2=TW-T1),下次中断发生后,来到状态A。周而复始,形成PWM达到调整输出电压的目的。由于输出电压可以变化,外部所接的LED就可以达到渐变的发光效果,流程如图2所示。

图3是一个输出平均电压逐渐变大的例子,TW为常数,T1增大,T2变小,从而达到占空比的变化。
三、PWM时间常数的选择
在硬件上51单片机的CPU主频时钟为22.1184MHZ,由于要求在1秒钟内LED的亮度发生250种变化呈现渐亮效果,所以每次变化时间TW定义为1s/250=4ms,使用51定时器1方式,延时4MS的初始值为0xe333。变化的时间长度为4ms/255,在定时器中的4ms/255的调整时间常数为0x001d。
四、如何实现状态保存
局部变量在函数执行完毕退出时消失,定时器中断过程中定时状态不断地在状态A和状态B中转换,保存状态的方式是使用静态变量的方式,通过静态变量达到变量保存的状态值不随函数退出而丢失的效果。
五、如何实现流水效果
把流水灯的花样通过一个数组来保存(数组名game),这样的好处是修改流水的花样可以通过修改数组元素来达到。因为在1秒钟内,完成其中一个元素渐亮过程,状态发生了2*250即500种变化,通过对状态变化次数进行计数,状态变化次数到500次时把控制对象转化成为下一个数组元素。
六、程序代码(提供时钟中断程序代码片段)
#define TIMER_BEGIN0xe333;//4ms
const int inc_timer_count=0x001d;
unsigned char code game[16]= {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x18,0x24,0x42,0x81,0x03,0x0c,0x30,0xc0};
volatile unsigned int pre_time_set=0;
void modi_timer0()interrupt 1 using 1//定时器T0中断
{ static bit c_state=0;//当前状态
static unsigned int proc_count=0;//处理次数
static unsigned int timer0_high=0;
static unsigned int timer0_low=0;
static unsigned char cur_proc_led=0;
TR0=0;
if (!proc_count)
{
timer0_high=TIMER_BEGIN;
timer0_low=0x0ffff;
}
if (c_state)//输出低电平,状态为B
{
timer0_high=timer0_high inc_timer_count;//调整延时时间
TH0=(timer0_high )>>8;
TL0=(timer0_high)