编译软件keil4,仿真软件Proteus7.8。keil4编译好的hex写入Proteus中的单片机ADC0808,程序编译无问题。
程序是一个智能光照控制的实现,初始化为自动模式,单片机获取外界光照数值进行计算,控制LED灯的亮度和光照强度保持一致,周围无人时自动关闭。手动模式时,通过加减按键调整LED亮度,无人时也自动关灯。
但在Proteus的仿真中,无论怎样调整加、减、模式切换三个按键单片机都无反应,因为Proteus模拟人体感应很麻烦所以我直接在P3.6接了一个开关控制高低电平,也就是模拟有人/无人状况,但无人时单片机也并不反应,LED灯仍然不关闭。现在觉得可能是输入哪里写错了?但是检查了很多遍也不知道错在哪里……
程序和仿真电路图如下。
/**********智能调光系统
1.自动模式:根据环境光变化LED灯亮度
2.手动模式:通过加减按键调整LED亮度
3.两种模式下均需要通过热释电控制灯的亮灭
*********************/
#include <reg51.h>
#include <ADC0808.H>
#define uchar unsigned char
#define uint unsigned int
#define DUAN P0
code uchar seg7code[10]= { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //????
uchar pdata tt[51]; //定义空数组用于AD0808取平均值
uchar scale=20,rsd_sec; //定义占空比比例,热释电计时秒变量
char min,sec; //定义计时分秒
uchar lum; //ad0808读出值
bit bdata flag_auto, //自动切换标志位
ss, //闪烁标志位
flag_bs, //报警位标志位
flag_rsd; //热释电动作标志位
sbit ST=P3^0;
sbit OE=P3^1;
sbit EOC=P3^2;
sbit ALE=P3^3;
sbit LED = P3^4; //PWM输出
sbit change= P2^3; //自动模式切换按键
sbit add = P2^1; //加按键
sbit sub = P2^0; //减按键
sbit rsd = P3^6; //热释电
sbit buzz=P3^7;
void delay(uchar i);
uint read_ADC0808(void)
{
uint ADC_Value;
OE=0;
ST=0;
ALE=0;
ALE=1;
ST=1;
ALE=0;
ST=0;
delay(10);
while(!EOC);
OE=1;
ADC_Value=P1;
OE=0;
return ADC_Value;
}
void KEY()
{
uint lum_mean,lum_all;
uchar b,c;
if(change==0) //自动切换按键按下
{
delay(10); //去抖
if(change==0) //再次判断按键按下
{
buzz=0; //蜂鸣器鸣响
flag_auto=!flag_auto; //自动模式标志位取反
if(flag_auto==1) //当切换到手动模式时 首先将LED发光比例PWM设置在50%
scale=20;
}
while(!change)
{
buzz=1; //等待按键释放 松开按键后关闭蜂鸣器、刷新显示
}
}
if(flag_auto==0) //自动模式
{
if(flag_rsd==1) //且有人在范围内时 环境发光强度控制灯光变化
{
for(b=0;b<49;b++) //将空数组tt[]内数值整体左移一位
{
tt[b]=tt[b+1]; //将后一数值放到前一位置
}
tt[49]=read_ADC0808(); //将读出的ad0808数值放入tt[49]
for(c=0;c<50;c++) //将tt[]内数值相加
{
lum_all=lum_all+tt[c];
}
lum_mean=lum_all/50; //将总数/50取出平均值
lum_all=0; //将总数清零
if(lum_mean<=30)
scale=1; //判断取出平均值大小 小于30 发光强度0%
else if(lum_mean>=150)
scale=41; //大于150 发光强度100%
else
scale=((lum_mean-30)/3)+1; //其他值时将其计算得到发光强度 (计算目的是为了得到一个1-41之间的数值 控制灯光变化)
}
else
scale=1; //没有人在范围内时 将灯光亮度调至0%
}
else //手动模式下
{
if(flag_rsd==1) //且有人在范围内时
{
if(add==0) //加键按下
{
delay(10);
if(add==0)
{
scale++; //灯光比例++
if(scale >= 41)
scale = 41;
}
}
if(sub==0) //减键按下时
{
delay(10);
if(sub==0)
{
// buzz=0; //蜂鸣器响
scale--; //灯光比例--
if(scale < 1)
scale = 1;
}
}
}
else
scale=1; //没有人在范围内时 将灯光亮度调至0%
}
}
/**********************************************************************
* 名称 : init();
* 功能 : 初始化定时器
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init()
{
TMOD=0x11; //工作方式1
TH1=0x3c;
TL1=0xb0; //T1赋初值50ms
TH0=0xff;
TL0=0xe7; //T0赋初值25us
ET0=1;
ET1=1; //打开中断允许开关
EA=1; //中断总开关
TR0=1; //开定时器0 开关
TR1=0; //关定时器0 开关
}
/**********************************************************************
* 名称 : main();
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void main()
{
init(); //调用初始化函数
flag_auto=0; //初始化自动模式
rsd=0; //热释电引脚置低(有信号时时高电平)
delay(500); //延时500ms后开机
while(1) //大循环
{
KEY(); //调用包函数
}
}
/**********************************************************************
* 名称 : void time0() interrupt 1
* 功能 : 定时器T0 中断服务函数:PWM脉冲发生函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void time0() interrupt 1
{
uchar n;
TH0=0xff;
TL0=0xe7; //重新赋初值
n++; //每25us n++
if(n>1) //n<设置比例时,打开灯
{
LED=1;
}
else if(n<=scale)//n大于等于设置比例时 关闭灯
{
LED=0;
}
if(n==scale) //n==40 :25us*40=1ms 1kHZ
{
n=0; //n=0
}
else ;
}
/**********************************************************************
* 名称 : void time1() interrupt 3
* 功能 : 定时器T1 中断服务函数:计时和闪烁控制 红外热释
* 输入 : 无
* 输出 : 无
***********************************************************************/
void time1() interrupt 3
{
uchar m;
TH1=0x3c;
TL1=0xb0; //重新赋初值
m++; //50ms m++
if((m==10||m==20)&&0) //每过500ms 并且 在设置状态时
{
ss=!ss; //闪烁变量取反
}
if(m==20) //到达1s时
{
m=0; //m=0
if(rsd==0) //热释电无信号时
rsd_sec++; //热释电计时秒++
if(rsd_sec<=30&&rsd==1) //热释电计时秒小于等于30 并且 热释电有信号时
{
rsd_sec=0; //将热释电秒清零
flag_rsd=1; //标志位置1 控制AD0808采集数值 调节灯光亮度
}
else if(rsd_sec>30&&rsd==0) //热释电计时秒大于30 并且 热释电无信号时
{
flag_rsd=0; //标志位置0 停止ad0808转换 关闭灯光
rsd_sec=0; //热释电计时秒清零
}
}
}