基于AT89C51单片机的无级调光系统的实现

基于AT89C51单片机的无级调光系统的实现

在生活中有很多可以自主调节挡位的设备,比如台灯的亮度、玩具车的速度、风扇的转速等等。它们调节档位的方式各有不同,有些是改变功率,有些是改变动力,但都离不开对激励或输入信号的改变,我们这里简单介绍一下对LED灯的无级调光的实现,可以自己动手做一个可变亮度的小灯。

一、所需器材:

AT89C51×1、100Ω定值电阻×1、LED×1、示波器×1、滑动变阻器×1、直流电压表×1、ADC0808×1、500kHz时钟信号×1、+5V直流电源×2。

主要器材介绍:(我们这里只做简单介绍,各接口定义可自行查阅资料——反正这里也用不着)

(1)AT89C51:AT89C51是一种带4K字节FLASH存储器(FPEROM—Flash Programmable and Erasable Read Only Memory)的低电压、高性能CMOS 8位微处理器,俗称51单片机。

图1 51单片机局部图

(2)ADC0808:ADC0808 是含8 位A/D 转换器、8 路多路开关,以及与微型计算机兼容的控制逻辑的CMOS组件,其转换方法为逐次逼近型。ADC0808的精度为 1/2LSB。在AD 转换器内部有一个高阻抗斩波稳定比较器,一个带模拟开关树组的256 电阻分压器,以及一个逐次逼近型寄存器。8 路的模拟开关的通断由地址锁存器和译码器控制,可以在8 个通道中任意访问一个单边的模拟信号。

说白了,就是可以将模拟信号转为数字信号。例如0—5V的电压信号可转为数字量为十六进制的00—FF。

图2 ADC0808局部图

二、基本思路

(1)要实现调亮,先要产生亮度等级信号,利用滑动变阻器调整阻值,将滑动变阻器两端点样进行采样,用ADC0808进行模数转换,得到数字量。将采集到的数字量除以256(8位二进制数最大值)进行归一化,再乘以10(将亮度划分为10个等级,当然计算的结果可能是实数,但肉眼观察的各等级变化也不明显,相当于是无极调光),作为调光等级。

调光等级n=(数字量/256)*10

(2)产生PWM波来控制灯的亮度,因为PWM波可以通过调整占空比来控制灯的亮度。当占空比大时,也就是一个周期内灯亮的时间占比大,暗的时间占比少,当频率足够快时,灯就看起来亮;相反的,占空比小时,灯看起来就暗。结合1的分析,通过采集到的数字量进行处理之后来调整占空比,计算的结果表示占空比的大小,例如n=5时,表示占空比为50%。

名词解释:PWM波:PWM就是脉冲宽度调制,也就是占空比可变的脉冲波形。

图3 PWM波

占空比:如图所示,在一个周期T内,高电平持续时间T1占整个周期的比值。调整占空比就可以调整灯的亮度,不光可以应用在这,比如还可以控制舵机来控制小车的转速,在拐弯时占空比可以调小一点,速度减慢,防止发生侧滑。

占空比=T1/T

小知识:我们平常所看到的大多数灯持续发光,实际上并不是一直发光的,而是“一闪一闪的”,只不过当闪的速度大于我们肉眼感受光的速度时,看起来就会觉得灯在“一直亮”。通常肉眼可感受到的频率大概在60Hz(因人而异,有的飞行员可感受到220Hz的变化)以下,也就是灯如果1s内闪的次数小于60,那肉眼是可以感受到的。所以这里的PWM频率至少为60Hz,以至于不起来灯在闪。这里我们为效果更好,取1kHz。

(3)利用51单片机作为硬件控制器,用ADC0808作为模数转换器。使用定时器0实现中断,产生PWM波并调整占空比。输出的PWM波从P2^0口输出,并用示波器检测输出信号的占空比。

三、电路实现

(1) 电压采样与模数转换电路

电位器可通过上下滑动改变自身阻值,两端电压也相对改变,通过电压表测量电位器两端电压,得到输入模拟量。

ADC0808的时钟端给500kHz时钟信号,其实也可以用51单片机产生,直接用激励源更方便。ADDA~C是模拟信号输入选择通道,这里从IN0输入,对应ABC值为000,直接将三个端口接地。将START与P3^4相连,由P3^4口给采样开始信号,同时给ALE地址锁存允许信号一个高电平,对地址进行锁存。P3^3口接收AD转换完成信号,接收到高电平时说明转换完成。P1端接收采样输出信号,OUT8为最低位OUT1为最高位,OUT8-OUT1分别接单片机的P1.0到P0.7端,各个端口反过来接收,最后得到的才是采样后的数字量。

图4 电压采样与模数转换电路

2)PWM波输出电路

51单片机与LED的连接,PWM波从P2^0口输出,中间串联一个100欧的限流电阻,更接近实际情况。示波器接与LED灯并联,检测输入信号情况,观察占空比变化。

图5 PWM波输出电路

(3) 输出结果

当滑动变阻器阻值为0时,电压为0,由图6可以看到LED灯熄灭,输出的PWM波占空比很小,几乎为0。不为零的原因是程序编写问题,在一个周期中,当时间time<=n时,输出高电平,所以导致当n=0时,也会有一瞬间的高电平产生,但是不影响观察结果。

图6 电位器为0时的PWM波形与LED亮度

当滑动变阻器指针在中间时,两端电压为2.5V,由图7可以看到LED灯比之前亮,输出的PWM波占空为50%。

图7 电位器位于中间时的PWM波形与LED亮度

当滑动变阻器指针在顶端时,两端电压为5V,由图8可以看到LED灯达到最亮,输出的PWM波占空为100%,一直输出高电平。

图8 电位器位处于最大值时的PWM波形与LED亮度

可以看到,LED灯的亮度随滑动变阻器的变化而变化,观察示波器也可以看到,PWM波的占空比大的时候灯越亮,占空比小的时候灯越暗。

四、完整项目

(1)仿真程序

#include "reg51.h"

sbit pwm=P2^0; //从P2^0口输出PWM波信号

sbit START=P3^4; //AD启动信号,高电平有效

sbit EOC=P3^3; //转换启动时为低电平,转换结束为高电平

sbit OE=P3^5; //输出允许信号,输入高电平有效。当A/D转换结束时,此端输入一个高电平,才能打开输出三态门,输出数字量。

unsigned char time=0;

unsigned int d; //保存采样的数字量

//ADC0808读取电位器值,转化为数字量并储存在d中

void adc0808_read()

{

START=0;

START=1; //一高一低产生一个上升沿,使0808复位

START=0; //产生下降沿,启动AD转换

while(EOC==0); //等待转换完成,EOC为高电平时,转换完成

OE=1;

d=P1; //从P1端接收转换后的数字量

OE=0;

}

//主函数

void main()

{

TMOD = 0x01; //设置TMOD寄存器,定时方式,工作方式1

TH0 =(65536-1000)/256; //定时时长为0.1ms

TL0= (65536-1000)%256;

TR0 = 1; //启动计数

ET0 = 1; //T0中断

EA = 1; //开启总中断

while(1);

}

//定时器T0中断函数//

void Timer0() interrupt 1

{

int n;

adc0808_read();

n=d*10/256;

TH0 =(65536-1000)/256; //重新赋初始值

TL0= (65536-1000)%256;

time++;

if(time>=10) //确保频率时1KHZ,每次0.1ms,计数10次就是1ms

time = 0;

if(time<=n) //n相当于亮度等级和占空比,一个周期内<=n的为高电平

pwm=1;

else

pwm=0;

}

(2)Proteus仿真图

图9 完整仿真图

相关推荐

口碑营销的主要方式有哪些
beat365在线体育访问不了

口碑营销的主要方式有哪些

⌛ 2025-10-26 👁️ 9786
山东菏泽市有几个区几个县
365服务平台

山东菏泽市有几个区几个县

⌛ 2025-07-24 👁️ 6733
彻底删除小米云端数据:安全指南及完整步骤
beta365体育

彻底删除小米云端数据:安全指南及完整步骤

⌛ 2025-07-31 👁️ 8929