微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 这段程序到底出了什么问题?!求解!

这段程序到底出了什么问题?!求解!

时间:10-02 整理:3721RD 点击:
这是用1602液晶+1838红外遥控+ds18b20+ds1302做的一个万年历...刚上电的时候液晶显示的时钟正常行走,可是只要红外遥控一按下按键,整个程序就停止了,时间显示就一直定在那里!我找了好多天都找不到什么问题!求大神解答!
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit rs=P1^0;    //位声明
sbit rw=P1^1;
sbit IO=P2^0;
sbit SCLK=P2^1;
sbit DQ=P2^2;
sbit RST=P2^4;
sbit en=P2^5;
sbit dula=P2^6;
sbit wela=P2^7;
sbit IR=P3^2;
//sbit beep=P2^3;
uchar lowtime,hightime; //储存低,高电平脉宽
uchar a[4];  //储存用户码,键码
int temper; //储存温度的值
uchar code table1[]="WELCOME!";     //初始显示
uchar code table2[]="Loading...";
uchar code table3[]="20  -  -  ";
uchar code table4[]="  :  :  ";
uchar numt;
/************************基本定义*************************/
/**********************延时函数定义***********************/
void delayms(uint xms)  //延时若干毫秒
{
uint i,j;
for(i=xms;i>0;i--)
  for(j=110;j>0;j--);
}
void delayus(uint x)
{
uint i,j;
for(i=0;i<x;i++)
  for(j=0;j<1;j++);
}
/****************************end***************************/
/**************************ds1302部分**********************/
void write_byte1302(uchar dat) //写8位的数据
{
uchar i;
SCLK=0;
for(i=0;i<8;i++)
{
  IO=dat&0x01;
  SCLK=1;
  SCLK=0;
  dat>>=1;
}
}
void write_1302(uchar cmd,uchar dat)   //写入字节数据
{
RST=0;
SCLK=0;
RST=1;
write_byte1302(cmd);
write_byte1302(dat);
SCLK=1;
RST=0;
}
uchar read_byte1302()    //读8位数据
{
uchar i,dat;
for(i=0;i<8;i++)
{
  dat>>=1;
  if(IO==1)
   dat|=0x80;
  SCLK=1;
  SCLK=0;
}
return dat;
}
uchar read_1302(uchar cmd)   //读字节数据
{
uchar dat;
RST=0;
SCLK=0;
RST=1;
write_byte1302(cmd);
dat=read_byte1302();
SCLK=1;
RST=0;
return dat;
}
/******************************end******************************/
/**************************ds18b20部分*************************/
uchar reset_18b20()  //ds18b20复位
{
uchar num;
DQ=0;
delayus(29);
DQ=1;
delayus(3);
num=DQ;
delayus(25);
return (num);
}
uchar read_bit()  //读一位数据
{
uchar i;
DQ=0;
DQ=1;
for(i=0;i>3;i++);
return (DQ);
}
void write_bit(uchar dat)  //写一位数据
{
DQ=0;
if(dat==1)
  DQ=1;
delayus(5);
DQ=1;
}
uchar read_byte()  //读一个字节数据
{
uchar dat=0;
uchar i;
for(i=0;i<8;i++)
{
  if(read_bit())
   dat|=0x01<<i;
  delayus(1);
}
return (dat);
}
void write_byte(uchar dat)   //写一个字节数据
{
uchar i,j;
for(i=0;i<8;i++)
{
  j=((dat>>i)&0x01);
  write_bit(j);
  delayus(1);
}
}
int read_temp()    //读取温度的值
{
uchar templ,temph;
int temp;
reset_18b20();
write_byte(0xcc);
write_byte(0x44);
delayus(10000);
reset_18b20();
write_byte(0xcc);
write_byte(0xbe);
templ=read_byte();
temph=read_byte();
temp=templ+temph*256;
return (temp);
}
/***************************end***************************/
/*************************红外遥控部分********************/
bit IR_jiema(void)  //解四个字节的码并把码分别储存到数组a中
{
uchar i,j;
uchar temp;
for(i=0;i<4;i++)
{
  for(j=0;j<8;j++)
  {
   temp=temp>>1;
   TH0=0;
   TL0=0;
   TR0=1;
   while(IR==0);
   TR0=0;
   lowtime=TH0*256+TL0;
   TH0=0;
   TL0=0;
   TR0=1;
   while(IR==1);
   TR0=0;
   hightime=TH0*256+TL0;
   if((lowtime<370)||(lowtime>640))
    return 0;
   if((hightime>420)&&(hightime<620))
    temp=temp&0x7f;  //0
   if((hightime>1300)&&(hightime<1800))
    temp=temp|0x80;  //1
  }
a[i]=temp;
}
if(a[2]=~a[3])  //键码与键的反码校验
  return 1;
}
/*************************end****************************/
/*************************1602部分***********************/
void write_com(uchar com)
{
rs=0;
P0=com;
delayms(1);
en=1;
delayms(1);
en=0;
}
void write_date(uchar date)
{
rs=1;
P0=date;
delayms(1);
en=1;
delayms(1);
en=0;
}
void write_temp(uchar add,uchar date)
{
write_com(0x80+0x40+add);
write_date(date);
}
void write_clk(uchar add,uchar date)
{
write_com(0x80+add);
write_date(0x30+date);
}
/****************************end*************************/
/*************************初始化***********************/
void init_1602()
{
uchar num;
rw=0;
en=0;
dula=0;
wela=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
write_com(0x80+4);
for(num=0;num<8;num++)
{
  write_date(table1[num]);
  delayms(1);
}
delayms(2000);
write_com(0x80+4);
for(num=0;num<10;num++)
{
  write_date(table2[num]);
  delayms(1);
}
delayms(3000);
write_com(0x01);
}
void init_1302()
{
write_1302(0x8e,0x00);
write_1302(0x90,0xa5);
write_1302(0x80,((55/10)<<4|(55%10)));//秒
write_1302(0x82,((59/10)<<4|(59%10)));//分
write_1302(0x84,((22/10)<<4|(22%10)));//时
write_1302(0x86,((29/10)<<4|(29%10)));//日
write_1302(0x88,((7/10)<<4|(7%10)));//月
write_1302(0x8c,(13/10)<<4|(13%10));//年
write_1302(0x8a,(1/10)<<4|(1%10));//星期
write_1302(0x8e,0x80);
}
void init_1838()    //红外遥控初始化
{
EA=1;
EX0=1;
ET0=1;
IT0=1;
TMOD=0x01;
TH0=0;
TL0=0;
TR0=0;
}
/*********************************end******************************/
/******************************显示部分*****************************/
void display_1302_18b20()
{
  uint readvalue;
  uint sec,sec1,sec2,min,min1,min2,hr,hr1,hr2,date,date1,date2,mon,mon1,mon2,year,year1,year2,day;
   
  readvalue=read_1302(0x81);//读秒
  sec=((readvalue&0x70)>>4)*10+(readvalue&0x0f);//转化秒
  sec1=sec/10;
  sec2=sec%10;
  write_clk(0x46,sec1);//写秒
  write_clk(0x47,sec2);
  readvalue=read_1302(0x83);//读分
  min=((readvalue&0x70)>>4)*10+(readvalue&0x0f);//转化分
  min1=min/10;
  min2=min%10;
  write_clk(0x43,min1);//写分
  write_clk(0x44,min2);
  readvalue=read_1302(0x85);//读时
  hr=((readvalue&0x70)>>4)*10+(readvalue&0x0f);//转化时
  hr1=hr/10;
  hr2=hr%10;
  write_clk(0x40,hr1);//写时
  write_clk(0x41,hr2);
  readvalue=read_1302(0x87);//读日
  date=((readvalue&0x70)>>4)*10+(readvalue&0x0f);//转化日
  date1=date/10;
  date2=date%10;
  write_clk(0x09,date1);//写日
  write_clk(0x0a,date2);
  readvalue=read_1302(0x89);//读月
  mon=((readvalue&0x70)>>4)*10+(readvalue&0x0f);//转化月
  mon1=mon/10;
  mon2=mon%10;
  write_clk(0x06,mon1);//写月
  write_clk(0x07,mon2);
  readvalue=read_1302(0x8d);//读年
  year=((readvalue&0x70)>>4)*10+(readvalue&0x0f);//转化年
  year1=year/10;
  year2=year%10;
  write_clk(3,year1);//写年
  write_clk(4,year2);
  readvalue=read_1302(0x8b);     //写星期
  day=((readvalue&0x70)>>4)*10+(readvalue&0x0f);
  switch (day)
  {
   case 1:write_com(0x80+0x0c);
       write_date('M');
       write_com(0x80+0x0d);
       write_date('O');
       write_com(0x80+0x0e);
       write_date('N');
       break;
   case 2:write_com(0x80+0x0c);
       write_date('T');
       write_com(0x80+0x0d);
       write_date('U');
       write_com(0x80+0x0e);
       write_date('E');
       break;
   case 3:write_com(0x80+0x0c);
       write_date('W');
       write_com(0x80+0x0d);
       write_date('E');
       write_com(0x80+0x0e);
       write_date('D');
       break;
   case 4:write_com(0x80+0x0c);
       write_date('T');
       write_com(0x80+0x0d);
       write_date('H');
       write_com(0x80+0x0e);
       write_date('U');
       break;
   case 5:write_com(0x80+0x0c);
       write_date('F');
       write_com(0x80+0x0d);
       write_date('R');
       write_com(0x80+0x0e);
       write_date('I');
       break;
   case 6:write_com(0x80+0x0c);
       write_date('S');
       write_com(0x80+0x0d);
       write_date('A');
       write_com(0x80+0x0e);
       write_date('T');
       break;
   case 7:write_com(0x80+0x0c);
       write_date('S');
       write_com(0x80+0x0d);
       write_date('U');
       write_com(0x80+0x0e);
       write_date('N');
       break;
  }
  temper=read_temp();     //显示温度
if(temper<0)     
{
  write_temp(0x0b,'-');
  temper=0-temper;
}
else
write_temp(0x0b,'+');
write_temp(0x0c,0x30+(temper>>4)%100/10);   //温度十位
write_temp(0x0d,0x30+(temper>>4)%10);    //温度个位
write_temp(0x0e,'.');
write_temp(0x0f,0x30+((temper&0x000f)*62.5)/100);  //温度小数点后一位

  
}
void display_1838()   //红外解码显示
{
//uchar num;
if(a[2]==0x44)
{
  write_com(0x80);
  write_date(0x0f);
}
}
/******************************end*************************/
/****************************主函数**************************/
void main()
{
uchar num;
init_1602();
init_1838();
write_com(0x80+1);
for(num=0;num<10;num++)
{
  write_date(table3[num]);
  delayms(1);
}
write_com(0x80+0x40);
for(num=0;num<8;num++)
{
  write_date(table4[num]);
  delayms(1);
}
init_1302();
while(1)
{
  display_1302_18b20();
}
}
void Int0() interrupt 0    //外部中断
{
EX0=0;
TH0=0;
TL0=0;
TR0=1;
while(IR==0);
TR0=0;
lowtime=TH0*256+TL0;
TH0=0;
TL0=0;
TR0=1;
while(IR==1);
TR0=0;
hightime=TH0*256+TL0;
if((lowtime>7800)&&(lowtime<8800)&&(hightime>3600)&&(hightime<4700))
{
  if(IR_jiema()==1)
  {
   display_1838();
  }
}
EX0=1;
}

你的程序是停在while 那吧

可是红外解码就要那样阿? 不是吗?

扫了一眼,其他的不知道有什么错,这个肯定是错的“if(a[2]=~a[3])  //键码与键的反码校验”,少一个“=”

试过了,不关那里的事阿,那只是检验功能键码解码是否正确而已,一个"="就可是了...

这么长的程序,别人是很难给你查错的,自己要懂得调试才行。像这样的问题几乎都是有while形成死循环造成的,要验证这个很简单,给每个while循环一个跳出循环的条件就行了,比如while(IR && (TH0 < 100));,while(!IR && (TH0 < 100));

while循环本来就给了它跳出来的条件了阿,像while(IR==0);那样,就是只要检测到它是低电平的话就跳出来啦;

调试程序就必须要懂得大胆怀疑小心求证,如果IR一直是低电平就会形成死循环了,不要说它肯定不会一直低电平

我对这种问题。我查错的方法是,用一个IO口接上led、对程序分析下,一步步放置LED的端口测试。想看程序有没有执行到那一步,就在那一步里面加一个LED亮就行了。一步步分析查证,很容易就知道自己卡在哪个死循环了

这个方法不错,我去试一下~谢谢啦~

求帮忙!

我觉得应该想办法分开一点一点地调试,不能好几百行一块调。最好能先插分成若干个小程序,一个一个地调,最后在连起来。不然很难看出问题。

我那些模块一个个都可以实现我所需要的功能的阿,就是拼起来的时候就不行了

那是不是中断里的程序写得太长了,如果到了下一次中断,这一次的中断还没有运行完,那会出问题。中断里的有些函数看看是不是可以移出中断。

额,,应该不会吧,我在进入中断服务函数的时候第一行就已经把中断关掉,然后执行完下面的指令在最后一行再重新开启中断的阿~~~

你QQ号多少?~ 加QQ联系吧~以后有空也可以交流交流~

1678853793 杨韧 北航电子

有没有大神能帮帮我阿

你这样真的很难看出哪里出问题,建议下次写程序的时候用模块化编程,容易发现问题,也容易管理

好的~谢谢你的建议~

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top