微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 1602显示温度跟时钟,开始好好地,怎么跑到40秒,会出现.....

1602显示温度跟时钟,开始好好地,怎么跑到40秒,会出现.....

时间:10-02 整理:3721RD 点击:
1602显示温度跟时钟,开始好好地,怎么跑到40秒,会出现乱码,这是为什么,下面是程序,我检测过了,关掉时钟,温度正常显示,关掉温度,时钟正常跑,但同时开,就不是那么如意,我觉得应该是主函数有问题,或是温度显示的那个display有问题,我划了红线了,请看看, 谢谢!

#include<reg52.h>
#include <math.h>
#define uint unsigned int
#define uchar unsigned char
sbit lcd_rs=P2^6;                                                        
sbit lcd_rw=P2^5;                                                        
sbit en=P2^7;
uchar code table[]="  2013-08-08 MON";
uchar code table1[]="00:00:03  +33.00";
sbit ds=P3^7;
uint i,tt,shi,fen,miao,num;
void write_com(uchar com);
void write_date(uchar date);
void delay(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
void init1602()
{       
        shi=00;
        fen=00;
        miao=03;
        write_com(0x0c);
        write_com(0x38);
        write_com(0x06);
        write_com(0x01);
        write_com(0x80);
        for(i=0;i<16;i++)
        {
                write_date(table);
                delay(5);
        }
        write_com(0x80+0x40);
                for(i=0;i<16;i++)
        {
                write_date(table1);
                delay(5);
        }
        TMOD=0x01;
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        ET0=1;
        TR0=1;
        EA=1;
}
void write_sfm(uchar add,uchar date)
{
        uchar sh,ge;
        sh=date/10;
        ge=date%10;
        write_com(0x80+0x40+add);
        write_date(0x30+sh);
        write_date(0x30+ge);
}
void timer0() interrupt 1
{
           TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        tt++;
        if(tt==20)
        {
                tt=0;
                miao++;
                if(miao==60)
                {
                        miao=0;
                        fen++;
                        if(fen==60)
                        {        fen=0;
                                shi++;
                                if(shi==24)
                                {
                                        shi=0;
                                }
                                write_sfm(0,shi);        
                        }
                        write_sfm(3,fen);
                }
                write_sfm(6,miao);
        }
}
void write_com(uchar com)
{
        lcd_rw=0;
        lcd_rs=0;
        P0=com;
        en=1;
        delay(5);
        en=0;
        delay(5);
}
void write_date(uchar date)
{
        lcd_rw=0;
        lcd_rs=1;
        P0=date;
        en=1;
        delay(5);
        en=0;
        delay(5);
}
/**//*****************************DS18B20*******************************/
/**//*****************************DS18B20*******************************/
//初始化DS18B20
//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动
void dsinit()
{
    //对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于为8us
          uint i;  
    ds=0;
    i=100;   //拉低约800us, 符合协议要求的480us以上
    while(i>0) i--;
    ds=1;    //产生一个上升沿, 进入等待应答状态
    i=4;
    while(i>0) i--;
}
void dswait()
{
     uint i;
     while(ds);  
     while(~ds);  //检测到应答脉冲
     i=4;
     while(i>0) i--;
}       
/**//*****************************DS18B20*******************************/
/**//*****************************DS18B20*******************************/
void writebyte(uchar dat)
{
    uint i;
    uchar j;
    bit b;
    for(j=0;j<8;j++)
    {
        b=dat&0x01;
        dat>>=1;
       //写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1
      if(b)   
       {
           ds=0;
           i++;
                   i++;  //拉低约16us, 符号要求15~60us内
           ds=1;   
           i=8;
                   while(i>0) i--;  //延时约64us, 符合写时隙不低于60us要求
        }
      else  //写"0", 将DQ拉低60us~120us
       {
            ds=0;
            i=8;
                        while(i>0) i--;  //拉低约64us, 符号要求
            ds=1;
            i++;
                        i++;  //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了
        }
    }
}
//向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
//之后DS18B20则会输出持续一段时间的一位数据
bit readbit()
{
    uint i;
    bit b;
    ds=0;
    i++;   //延时约8us, 符合协议要求至少保持1us
    ds=1;
    i++;
        i++;  //延时约16us, 符合协议要求的至少延时15us以上
    b=ds;
    i=8;
    while(i>0) i--;  //延时约64us, 符合读时隙不低于60us要求
    return b;
}
//读取一字节数据, 通过调用readBit()来实现
uchar readbyte()
{
   uint i;
   uchar j,dat;
   dat=0;
   for(i=0;i<8;i++)
   {
        j=readbit();
        //最先读出的是最低位数据
        dat=(j<<7)|(dat>>1);
   }
   return dat;
}
/**//*****************************DS18B20*******************************/
/**//*****************************DS18B20*******************************/
//向DS18B20发送温度转换写命令
void sendchangecmd()
{
    dsinit();
        dswait();          //初始化DS18B20, 无论什么命令, 首先都要发起初始化
    delay(1);       //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号
    writebyte(0xcc); //写入跳过序列号命令字 Skip Rom
    writebyte(0x44); //写入温度转换命令字 Convert T
}
//向DS18B20发送读取数据命令
void sendreadcmd()
{
    dsinit();
        dswait();
    delay(1);
    writebyte(0xcc); //写入跳过序列号命令字 Skip Rom
    writebyte(0xbe); //写入读取数据令字 Read Scratchpad
}
/**//*****************************DS18B20*******************************/
/**//*****************************DS18B20*******************************/
//获取当前温度值
int gettemp()
{
   uint temper;
    int temp; //存放温度数值
    float t;
    uchar templ, temph;
    sendreadcmd();
    //连续读取两个字节数据
     templ=readbyte();
     temph=readbyte();
    //将高低两个字节合成一个整形变量
    //计算机中对于负数是利用补码来表示的
    //若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的value
    temper=temph;
    temper<<=8;
    temper|=templ;
    temp=temper;
   //使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度
   t = temp * 0.0625;
   //将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入
    //如t=11.0625, 进行计数后, 得到temp = 1106, 即11.06 度
    //如t=-11.0625, 进行计数后, 得到temp = -1106, 即-11.06 度
    temp =t * 100 +(temp > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5
   return temp;
}
/**//*****************************DS18B20*******************************/
/**//*****************************DS18B20*******************************/
void writeString(uchar * str, uchar length)
{
    uchar i;
   for(i=0;i<length;i++)
     {
       write_date(str);
     }
}
void display(uint temp)
{
    uchar count;
    uchar dates[]={0, 0, 0, 0, 0};
    uint tmp=abs(temp);
    dates[0]=tmp/10000;
    dates[1]=tmp%10000/1000;
    dates[2]=tmp%1000/100;
    dates[3]=tmp%100/10;
    dates[4]=tmp%10;
   if(dates[0]==0)
        {       
                write_com(0x80+0x4a);
                write_date('+');
                write_date(0x30+dates[1]);
                write_date(0x30+dates[2]);
                write_date('.');
                write_date(0x30+dates[3]);
                write_date(0x30+dates[4]);
        }
  
}
/**//*****************************DS18B20*******************************/
/**//*****************************DS18B20*******************************/
void main()
{
        uchar i;
      init1602();
        sendchangecmd();
      while(1)
    {  
               
                  delay(800); //温度转换时间需要750ms以上
                write_com(0x80+0x40+9);
                display(gettemp());
                sendchangecmd();
        
    }
}

有没有会弄得啊~

谁能看一下啊,只看主程序就行,看看那个delay(800),是不是跟定时器冲突啊~

也许是电路问题吧,我试过信号线不上拉电阻有时候会乱码的

问什么开始没事呢,还有,它的连线应该是内部连线吧,不太可能是上拉电阻的事,是吧,顺便问一下,中断跟主程序是怎么跑的,是不是在执行主程序的时候,中断程序虽然断了,但是外部时钟还是照样跑,谢谢~~

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

网站地图

Top