weixin_44940434
野棠雪枝
2021-01-23 20:17

求大佬看看Proteus仿真单片机电路为啥对输入没反应

  • c语言

编译软件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;				  //热释电计时秒清零
		}		
	}	
}

 

  • 点赞
  • 回答
  • 收藏
  • 复制链接分享

0条回答

为你推荐

换一换