各位大侠进来帮忙看看这个有多少问题啊【十万火急】

2019-07-18 10:42发布

功能包括:显示时间,修改时间,设置定时,查询法扩展了4个中断,分别是进入自动模式、手动模式、一键关灯、一键开灯,关灯状态进入不了其他模式,只能进入一键开灯,在任意模式下,都可以通过按键进入到其他模式。
能帮的请不要吝啬您的知识啊,先谢谢啦
程序:
//*********编译预处理**********//
#pragma SMALL
#include<reg51.h>
#include<absacc.h>
//*********************************************************************************************************************************//
#define uchar unsigned char
#define COM8155 XBYTE[0x7ff0] //命令/状态口地址
#define PA8155 XBYTE[0x7ff1] //PA口地址
#define PB8155 XBYTE[0x7ff2] //PB口地址
#define PC8155 XBYTE[0x7ff3] //PC口地址
#define IN0 XBYTE[0xfef8] //设置ADC0809的通道0的地址
sbit ad_busy=P3^2; //定义EOC状态
sbit P2_2=P2^2;//可寻址位定义
//**********************************************************全局变量**********************************************************************//
void display(unsigned char *p);//6位LED显示函数,指针p为显示数据区首地址
unsigned char keytest();//测试按键有无按下
unsigned char h,t,l,x,y,r;//h=1,定时开灯,h=0,延时关灯,t是adc0809转换结果,l手动模式下设置LED亮的个数,x模式切换前灯亮的个数,y值代表关灯前模式,r代表关灯状态下允许启动的模式
unsigned char search();//按键识别
void alARM();//定时判断启动
void ftion0();//时钟修改
void ftion1();//定时修改
void cum();//加1修改
void moren();//默认模式
void zidong();//自动模式子函数
void dengset();//手动模式灯设置子函数
void shoudong();//手动模式子函数
void kaideng();//一键开灯子函数
void guandeng();//一键关灯子函数
void keypanduan();//键盘判断子函数
void keyset();//键盘设置子函数
void adc0809();//ADC0809转换子函数
unsigned char clockbuf[3]={0,0,0};//存放时钟时、分、秒的十进制数
unsigned char bellbuf[3]={0,0,0};//存放定时时、分、秒的十进制数
unsigned char msec1;//10ms中断次数
unsigned char msec2;//1s循环次数
unsigned char timdata,rtimdata;//时钟和定时修改位置标志
unsigned char count;//定时启动后10s计时单元
unsigned char *dis_p;//显示缓冲区指针
bit armbit;//定时标志,armbit=0,定时没有设定,armbit=1,定时已设定
bit rtimbit;//定时是否启动标志,rtimbit=1,定时已启动
bit rhourbit;//定时小时修改标志,rhourbit=1,正在修改定时小时
bit rminbit;//定时分修改标志,rminbit=1,正在修改定时分钟
bit hourbit;//时钟小时修改标志位,hourbit=1,正在修改时钟小时
bit minbit;//时钟分修改标志位,minbit=1,正在修改时钟分钟
bit secbit;//时钟秒修改标志位,secbit=1,正在修改时钟秒
//*************************************************************主函数*****************************************************************//
void main()
{COM8155=0x03;//PA口、PB口输出
armbit=0;//清零定时标志位
msec1=0;//设置10ms中断次数初值
msec2=0;//设置1s中断次数初值
timdata=0;//时钟内容修改位置记忆单元清零
rtimdata=0;//定时内容修改位置记忆单元清零
count=0;//定时启动后保持10s计时单元清零
TMOD=0x02;//初始化定时器,定时器T0为工作方式2
TL0=0x06;//定时250us初始值
TH0=0x06;
EA=1;//开总中断允许位
EX0=1;//开外部中断0中断允许位
IT0=1;//设置外部中断0为下降沿触发
EX1=1;//开外部中断0中断允许位
IT1=1;//设置外部中断1为下降沿触发
ET0=1;//定时器0开中断
TR0=1;//启动定时器0
dis_p=clockbuf;//将时钟值所在地址送入显示指针
moren();//调用默认子函数
}
//************************adc转换子程序********************************************//
void adc0809()
{uchar b;
while(1){
P2_2=1;
for(b=0;b<50;b++);//延时
P2_2=0;//在P2_2引脚产生下降沿,START和ALE引脚产生上升沿,锁存通道地址,所有内部寄存器清零
for(b=0;b<50;b++);//延时
P2_2=1;//在P2_2上产生上升沿,START上产生下降沿,AD转换开始
while(ad_busy==0);//等待转换完成,EOC=1表示转换完成
P2_2=0;//P2_2=0,则OE=1,允许读数
t=P0;//读AD转换数据
}
}
//************************************************6位LED显示函数************************************************//
void display(unsigned char *p)
{unsigned char buffer[]={0,0,0,0,0,0};
unsigned char k,i,j,m,temp;
unsigned char led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9的显示码
buffer[0]=p[0]/10;//将缓冲区中数据的十位和个位分开
buffer[1]=p[0]%10;
buffer[2]=p[1]/10;
buffer[3]=p[1]%10;
buffer[4]=p[2]/10;
buffer[5]=p[2]%10;
for(k=0;k<3;k++){
temp=0x01;
for(i=0;i<6;i++){
PB8155=0xff;//关显示
j=buffer;
PB8155=led[j];//PB8155送段码
PA8155&=~temp;//PA8155对应端口低电平选位
temp<<=1;
for(m=0;m<100;m++);//每一位显示延时
}
}
}
//***********************************************键盘检测函数*****************************************************//
unsigned char keytest()
{unsigned char c;
PA8155=0xf0;
c=PC8155;
c=c&0x0f;//按键行输入为PC8155.0~PC8155.3,屏蔽无关位
return(c);
}
//************************************************查询键值函数********************************************************//
unsigned char search()
{unsigned char a,b,c,d;
c=0xfe;//首列扫描字送变量c
a=0;//首列号送a
while(1){
PA8155=c;//列扫描字送PA8155口
d=PC8155;//读入PC8155口的行状态
if(d&0x01==0) { b=0;break;}//第0行有键按下,第0行行首号送b
else if(d&0x02==0) { b=4;break;}//第1行有键按下,第1行行首号送b
else if(d&0x04==0) { b=8;break;}//第2行有键按下,第2行行首号送b
else if(d&0x08==0) { b=12;break;}//第3行有键按下,第3行行首号送b
a++;//扫描列号加1
c<<=1;//修改列扫描字,扫描下一列
}
c=a+b;//将行首号与列号相加,求键号
do{display(dis_p);}
while((d=keytest())!=0x0f);//等待释放按键,若有问题将0x0f换成0x07
return(c);
}
//******************************************************定时判断启动函数*****************************************************//
void alarm()
{if((clockbuf[0]==bellbuf[0])&&(clockbuf[1]==bellbuf[1]))
{ while(1){
display(dis_p);//调用显示程序
if(h==1)
{kaideng();
}//调用开灯子函数
else
{guandeng();
}//调用关灯子函数
}
}
}
//*******************************************************时钟设置函数**************************************************************//
void ftion0()
{TR0=0;//关定时器
rhourbit=0;//禁止定时时间参数修改,清定时修改标志位
rminbit=0;
dis_p=clockbuf;//将时钟缓冲区首地址送显示指针
rtimdata=0;//清定时修改位置标志记录
timdata++;//将时钟修改记录值加1
switch(timdata){
case 0x01:secbit=1;break;//记录值为1,则将时钟秒修改标志置1
case 0x02:secbit=0;minbit=1;break;//记录值为2,则将时钟分修改标志置1
case 0x03:minbit=0;hourbit=1;break;//记录值为3,则将时钟时修改标志置1
case 0x04:timdata=0;hourbit=0;TR0=1;break;//按4次则清时钟单元修改位置,记录,定时器重新启动
default:break;
}
}
//****************************************************************定时设置函数******************************************************//
void ftion1()
{secbit=0;//禁止时钟时间修改
minbit=0;
hourbit=0;
dis_p=bellbuf;//设置定时显示标志
timdata=0;//清时钟修改位置标志记录
rtimdata++;//将定时修改记录值加1
switch(rtimdata){
case 0x01:rminbit=1;break;//若记录值为1,则将定时分修改标志置1
case 0x02:rminbit=0;rhourbit=1;break;//若记录值为2,则将时钟分修改标志置1
case 0x03:rtimdata=0;rhourbit=0;//若按3次则清定时单元修改位置记录
armbit=1;//设置定时已设定标志位
dis_p=clockbuf;//恢复时钟显示标志
break;
default:break;
}
}
//*************************************************************加1修改功能函数*******************************************************//
void cum()
{if(secbit==1)//若时钟秒修改标志为1,则秒单元内容加1
{
if(clockbuf[2]==59) clockbuf[2]=0;
else clockbuf[2]++;
}
else if(minbit==1)//若时钟分修改标志为1,则分单元内容加1
{if(clockbuf[1]==59) clockbuf[1]=0;
else clockbuf[1]++;
}
else if(hourbit==1)//若时钟时修改标志为1,则时单元内容加1
{if(clockbuf[0]==23) clockbuf[0]=0;
else clockbuf[0]++;
}
else if(rminbit==1)//若定时分修改标志为1,则分单元内容加1
{if(bellbuf[1]==59) bellbuf[1]=0;
else bellbuf[1]++;
}
else if(rhourbit==1)//若定时小时修改标志为1,则小时单元内容加1
{if(bellbuf[0]==23) bellbuf[0]=0;
else bellbuf[0]++;
}
}
//****************************************************************定时器中断函数****************************************************//
void clock() interrupt 1
{EA=0;//关中断
if(msec1!=0x28)
msec1++;//到10ms否,不到则msec1加1
else
{msec1=0;
if(msec2!=100)
msec2++;//到1s否,不到则msec2加1
else
{if(rtimbit==1)
count++;
msec2=0;
if(clockbuf[2]!=59)
clockbuf[2]++;//到1min否,不到则clockbuf[2]加1
else
{clockbuf[2]=0;
if(clockbuf[1]!=59)
clockbuf[1]++;//到1h否,不到则clockbuf[1]加1
else
{clockbuf[1]=0;
if(clockbuf[0]!=23)
clockbuf[0]++;//到24h否,不到则clockbuf[0]加1
else clockbuf[0]=0;
}
}
}
}
EA=1;//开中断
}
//******************************************************************键盘判断子函数*************************************************//
void keypanduan()
{unsigned char a;
a=keytest();//调用键盘检测子程序
if(a==0x0f)
{display(dis_p);//无键输入调用显示程序
if(armbit==1) alarm();
}//判断定时设定否,若已设定则调用闹钟启动子程序
else
{display(dis_p);//调用显示子程序作为延时去抖动
a=keytest();
if(a!=0x0f)//没有抖动,表示有按键按下
{a=search();//调用查键子程序
switch (a){
case 0x00:ftion0();break;//是时钟参数修改功能键,调用时钟设置子程序
case 0x02:cum();break;//是加1功能键,则调用加1修改功能子程序
case 0x03:h=1;keyset();break;//定时开,h=1,调用键盘设置子函数
case 0x04:h=0;keyset();break;//延时关,h=0,调用键盘设置子函数
default:break;
}
}
}
}
//******************************************************************键盘设置子函数*************************************************//
void keyset()
{unsigned char b;
while(1){
b=keytest();//调用键盘检测子程序
if(b==0x0f)
{display(dis_p);//无键输入调用显示程序
}
else
{display(dis_p);//调用显示子程序作为延时去抖动
b=keytest();
if(b!=0x0f)//没有抖动,表示有按键按下
{b=search();//调用查键子程序
switch (b){
case 0x01:ftion1();break;//是定时参数修改功能键,调用定时设置子程序
case 0x02:cum();break;//是加1功能键,则调用加1修改功能子程序
default:break;
}
}
}
}
}
//******************************************************************手动模式灯设置子函数*************************************************//
void dengset()
{unsigned char a;
a=keytest();//调用键盘检测子程序
if(a==0x0f)
{display(dis_p);//无键输入调用显示程序
if(armbit==1) alarm();
}//判断定时设定否,若已设定则调用闹钟启动子程序
else
{display(dis_p);//调用显示子程序作为延时去抖动
a=keytest();
if(a!=0x0f)//没有抖动,表示有按键按下
{a=search();//调用查键子程序
switch (a){
case 0x00:ftion0();break;//是时钟参数修改功能键,调用时钟设置子程序
case 0x02:cum();break;//是加1功能键,则调用加1修改功能子程序
case 0x03:h=1;keyset();break;//定时,h=1,调用键盘设置子函数
case 0x04:h=0;keyset();break;//延时,h=0,调用键盘设置子函数
case 0x05:l=0x01;break;//5#键盘代表亮1个LED
case 0x06:l=0x03;break;//6#键盘代表亮2个LED
case 0x07:l=0x07;break;//7#键盘代表亮3个LED
case 0x08:l=0x0f;break;//8#键盘代表亮4个LED
case 0x09:l=0x1f;break;//9#键盘代表亮5个LED
case 0x0a:l=0x3f;break;//10#键盘代表亮6个LED
case 0x0b:l=0x7f;break;//11#键盘代表亮7个LED
case 0x0c:l=0xff;break;//12#键盘代表亮8个LED
default:break;
                  }
}
}
}
//******************************************************************外部中断1中断函数*************************************************//
void int_1() interrupt 2//外部中断1中断类型号为2
{ unsigned char i;
P2=0xff;//读P2口引脚前先全部置1
i=P2;//在P2口引脚状态读入变量i
i&=0x78;//采用与操作屏蔽掉i的低4位
switch(i)
{case 0x08:zidong();break;//调用zidong()子函数,进入自动模式
case 0x10:shoudong();break;//调用shoudong()子函数,进入手动模式
case 0x20:guandeng();break;//调用guandeng()子函数,进入一键关灯
case 0x40:kaideng();break;//调用kaideng()子函数,进入一键开灯
default:break;
}
}
//*****************************************************************自动模式子函数*******************************************************//
void zidong()
{if(r==1){
while(1){P1=x;
display(dis_p);//调用显示程序
adc0809();//调用ADC转换子函数
x=t;//将转换结果送给变量x,并且保存LED灯亮的个数
keypanduan();//调用键盘判断子函数
y=0x01;//保存模式
r=1;
}
}
}
//*****************************************************************手动模式子函数*******************************************************//
void shoudong()
{if(r==1) {
while(1){
P1=x;
display(dis_p);//调用显示程序
dengset();//调用手动模式灯设置子函数
x=l;//将设置LED灯亮的个数保存起来
y=0x02;//保存模式
r=1;
}
}
}
//*****************************************************************一键关灯子函数*******************************************************//
void guandeng()
{P1=x;r=0;
while(1){
P1=0x00;
keypanduan();
}
}
//*****************************************************************一键开灯子函数*******************************************************//
void kaideng()
{P1=x;r=1;
while(1){
switch(y)
{case 0x00:moren();break;//恢复默认模式
case 0x01:zidong();break;//恢复自动模式
case 0x02:shoudong();break;//恢复手动模式
default:break;
}
}
}
//*****************************************************************默认模式*******************************************************//
void moren()
{ r=1;
while(1){
P1=0x3f;
keypanduan();
x=0x3f;
y=0x00;//保存模式
}


}

原理图 原理图
运行结果 运行结果
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。