本帖最后由 gf521258 于 2013-7-25 18:50 编辑
用中断设计红外遥控,当显示到1602液晶屏上时,delay函数延时无效。。之后上网百度,各种脑补知识。。但是本人刚学单片机。。有些还是没法理解,求大虾们帮忙!由于刚自学。。编程问题,还仅显示实现功能,没有涉及到一下问题,请大家见谅。。现在的问题是,我在中断中调用了Disp子函数,但是子函数中的delay延时函数没有祈祷任何作用。。ZZ和ZF是直流电机
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit IR=P3^2; //红外接收
sbit en=P2^2;
sbit rw=P2^1;
sbit rs=P2^0;
sbit BEEP=P3^6;
sbit ZZ=P3^0;
sbit FZ=P3^1;
uchar a[4],b,n=0,m,num; //储存用户码、用户反码与键数据码、键数据反码 b液晶显示位数 n输入密码位数
uchar tab_key[50]; //输入密码
uchar mima[8]={0,1,2,3,4,5,6,7}; //初始密码
uint LowTime,HighTime,xiugaiflag,c; //xiugaiflag修改密码标志位
uchar code table[]={"0123456789"};
uchar code table1[]={"I's error"};
uchar code table2[]={"input the passco"};
uchar code table3[]={"de: --------"};
uchar code table4[]={"define the passc"};
uchar code table5[]={"ode: --------"};
uchar code table6[]={"code is new"};
uchar code table7[]={"the frist error"};
uchar code table8[]={"the second error"};
uchar code table9[]={"the third error"};
uchar code table10[]={"u tomorrow (^_^)"};
uchar code table11[]={"welcome to home"};
uchar code wnmima[8]={1,9,9,3,0,1,2,5};
void delay(uchar z)
{ uchar i,j;
for(j=0;j<z;j++)
{for(i=0;i<125;i++);}
}
void write_com(uchar com) //写地址
{ rs=0;
rw=0;
en=0;
P0=com;
delay(5);
en=1;
delay(5);
en=0;
}
void write_data(uchar date) //写数据
{ rs=1;
rw=0;
en=0;
P0=date;
delay(5);
en=1;
delay(5);
en=0;
}
void init() //初始化
{ en=0;
write_com(0x38);
delay(5);
write_com(0x0F);
delay(5);
write_com(0x06);
delay(5);
write_com(0x01);
delay(5);
write_com(0x80);
}
void beep() //蜂鸣器响一声函数
{
unsigned char i;
for (i=0;i<100;i++)
{
delay(1);
BEEP=!BEEP; //BEEP取反
}
BEEP=1; //关闭蜂鸣器
delay(250); //延时
}
void key0()
{
tab_key[n]=0;
n++;
if(xiugaiflag==1)
{ mima[m]=0;
m++;
}
}
void key1()
{
tab_key[n]=1;
n++;
if(xiugaiflag==1)
{ mima[m]=1;
m++;
}
}
void key2()
{
tab_key[n]=2;
n++;
if(xiugaiflag==1)
{ mima[m]=2;
m++;
}
}
void key3()
{
tab_key[n]=3;
n++;
if(xiugaiflag==1)
{ mima[m]=3;
m++;
}
}
void key4()
{
tab_key[n]=4;
n++;
if(xiugaiflag==1)
{ mima[m]=4;
m++;
}
}
void key5()
{
tab_key[n]=5;
n++;
if(xiugaiflag==1)
{ mima[m]=5;
m++;
}
}
void key6()
{
tab_key[n]=6;
n++;
if(xiugaiflag==1)
{ mima[m]=6;
m++;
}
}
void key7()
{
tab_key[n]=7;
n++;
if(xiugaiflag==1)
{ mima[m]=7;
m++;
}
}
void key8()
{
tab_key[n]=8;
n++;
if(xiugaiflag==1)
{ mima[m]=8;
m++;
}}
void key9()
{
tab_key[n]=9;
n++;
if(xiugaiflag==1)
{ mima[m]=9;
m++;
}}
bit mimacmp() //密码比较函数
{
bit flag; //位变量
uchar i;
for(i=0;i<8;i++) //8位数循环比较 如果密码正确,则flag=1;
{
if((mima==tab_key)|wnmima==tab_key)
flag=1;
else
{
flag=0;
i=8;
}
}
return(flag); //返回flag
}
void queren()
{ if(n==8) c=mimacmp();
else c=0;
if(c==1)
{ num=0;
write_com(0x80);
for(b=0;b<16;b++)
{
write_data(table11);
delay(5);
}
ZZ=1;
FZ=0;
delay(2000);
ZZ=0;
FZ=0; }
else { n=0;
if(num==0)
{ write_com(0x80);
for(b=0;b<16;b++)
{
write_data(table7);
delay(5);
}
delay(1000);
write_com(0x80);
for(b=0;b<16;b++) //重新显示
{
write_data(table2);
delay(5);
}
write_com(0x80+0x40);
for(b=0;b<16;b++)
{
write_data(table3);
delay(5);
tab_key=0x0f;
}
write_com(0x80+0x40+8);
num++;
}
else if(num==1)
{ write_com(0x80);
for(b=0;b<16;b++)
{ write_data(table8);
delay(5);
}
delay(1000);
write_com(0x80);
for(b=0;b<16;b++) //重新显示
{
write_data(table2);
delay(5);
}
write_com(0x80+0x40);
for(b=0;b<16;b++)
{
write_data(table3);
delay(5);
tab_key=0x0f;
}
write_com(0x80+0x40+8);
num++;
}
else if(num==2)
{ write_com(0x80);
for(b=0;b<16;b++)
{
write_data(table9);
delay(5);
}
write_com(0x80+0x40);
for(b=0;b<16;b++)
{ write_data(table10);
delay(5);}while(1);
}
}
}
void Disp(void)
{
switch(a[2])
{
case 0x16: write_data(table[0]);key0();break;
case 0x0c: write_data(table[1]);key1();break;
case 0x18: write_data(table[2]);key2();break;
case 0x5e: write_data(table[3]);key3();break;
case 0x08: write_data(table[4]);key4();break;
case 0x1c: write_data(table[5]);key5();break;
case 0x5a: write_data(table[6]);key6();break;
case 0x42: write_data(table[7]);key7();break;
case 0x52: write_data(table[8]);key8();break;
case 0x4A: write_data(table[9]);key9();break;
case 0x19: n=0; //取消(返回)
write_com(0x80);
for(b=0;b<16;b++)
{
write_data(table2);
delay(5);
}
write_com(0x80+0x40);
for(b=0;b<16;b++)
{
write_data(table3);
delay(5);tab_key=0x0f;
}
write_com(0x80+0x40+8); break;
case 0x07: n=0;xiugaiflag=1; //修改密码
write_com(0x01);
write_com(0x80);
for(b=0;b<16;b++)
{
write_data(table4);
delay(5);
}
write_com(0x80+0x40);
for(b=0;b<16;b++)
{
write_data(table5);
delay(5);tab_key=0x0f;
}
write_com(0x80+0x40+8); break;
case 0x15: if(xiugaiflag==1)
{n=0;
xiugaiflag=0;
m=0;
write_com(0x01);
write_com(0x80);
for(b=0;b<16;b++)
{
write_data(table6);
delay(10);
}
delay(1000);
write_com(0x80);
for(b=0;b<16;b++)
{
write_data(table2);
delay(5);
}
write_com(0x80+0x40);
for(b=0;b<16;b++)
{
write_data(table3);
delay(5);
tab_key=0x0f; }
write_com(0x80+0x40+8);}break;
case 0x0d: queren();break;
}
}
bit DeCode(void) //红外解码
{
uchar i,j;
uchar temp; //储存解码出的数据
for(i=0;i<4;i++) //连续读取4个用户码和键数据码
{
for(j=0;j<8;j++) //每个码有8位数字
{
temp=temp>>1; //temp中的各数据位右移一位,因为先读出的是高位数据
TH0=0; //定时器清0 //12除以晶振
TL0=0; //定时器清0
TR0=1; //开启定时器T0
while(IR==0) //如果是低电平就等待
; //低电平计时
TR0=0; //关闭定时器T0
LowTime=TH0*256+TL0; //保存低电平宽度
TH0=0; //定时器清0
TL0=0; //定时器清0
TR0=1; //开启定时器T0
while(IR==1) //如果是高电平就等待
;
TR0=0; //关闭定时器T0
HighTime=TH0*256+TL0; //保存高电平宽度
if((LowTime<370)||(LowTime>640))
return 0; //如果低电平长度不在合理范围,则认为出错,停止解码
if((HighTime>420)&&(HighTime<620)) //如果高电平时间在560微秒左右,即计数560/1.085=516次
temp=temp&0x7f; //(520-100=420, 520+100=620),则该位是0
if((HighTime>1300)&&(HighTime<1800)) //如果高电平时间在1680微秒左右,即计数1680/1.085=1548次
temp=temp|0x80; //(1550-250=1300,1550+250=1800),则该位是1
}
a=temp; //将解码出的字节值储存在a
}
if(a[2]=~a[3]) //验证键数据码和其反码是否相等,一般情况下不必验证用户码
return 1; //解码正确,返回1
}
void main()
{ init();
for(b=0;b<16;b++)
{
write_data(table2); //第一行显示INPUT THE PASSPORD:
delay(5);
}
write_com(0x80+0x40);
for(b=0;b<16;b++)
{
write_data(table3);
delay(5);
}
write_com(0x80+0x40+8);
delay(10);
EA=1; //开启总中断
EX0=1; //开外中断0
ET0=1; //定时器T0中断允许
IT0=1; //外中断的下降沿触发
TMOD=0x01; //使用定时器T0的模式1
TR0=0; //定时器T0关闭
while(1); //等待红外信号产生的中断
}
void Int0(void) interrupt 0
{
EX0=0; //关闭外中断0,不再接收二次红外信号的中断,只解码当前红外信号
TH0=0; //定时器T0的高8位清0
TL0=0; //定时器T0的低8位清0
TR0=1; //开启定时器T0
while(IR==0); //如果是低电平就等待,给引导码低电平计时
TR0=0; //关闭定时器T0
LowTime=TH0*256+TL0; //保存低电平时间
TH0=0; //定时器T0的高8位清0
TL0=0; //定时器T0的低8位清0
TR0=1; //开启定时器T0
while(IR==1); //如果是高电平就等待,给引导码高电平计时
TR0=0; //关闭定时器T0
HighTime=TH0*256+TL0; //保存引导码的高电平长度
if((LowTime>7800)&&(LowTime<8800)&&(HighTime>3600)&&(HighTime<4700))
{
//如果是引导码,就开始解码,否则放弃,引导码的低电平计时
//次数=9000us/1.085=8294, 判断区间:8300-500=7800,8300+500=8800.
if(DeCode()==1) // 执行遥控解码功能
{
beep();//蜂鸣器响一声 提示解码成功
Disp();
}
}
EX0=1; //开启外中断EX0
}
|