qq_512275954 2018-11-12 14:31 采纳率: 0%
浏览 880
已结题

求各位大神帮忙看一下我用51单片机做的万年历程序有没有问题

AT89S52+12864+DS18B20+DS1302
,液晶只有背光亮,不显示内容


```#include<reg52.h>
#include<intrins.h>

#define ds1302_sec_add             0x80    //设置秒的地址
#define ds1302_min_add             0x82    //设置分的地址 
#define ds1302_hr_add              0x84    //设置时的地址
#define ds1302_date_add            0x86    //设置天的地址 
#define ds1302_month_add           0x88    //设置月的地址
#define ds1302_year_add            0x8c    //设置年的地址
#define ds1302_control_add         0x8e     
#define ds1302_charger_add         0x90                      
#define ds1302_clkburst_add        0xbe
#define uchar unsigned char
#define uint unsigned int

sbit E = P2^0;     //使能
sbit RW = P2^1;    //读写
sbit RS = P2^2;    //数据/命令
sbit busy=P0^7;  //检测忙
sbit DQ= P2^5;   //DS18B02单总线
sbit RST= P1^1;
sbit SCK=P1^2;
sbit IO = P1^3;
sbit PSB= P2^6;

uchar code dig[]={"0123456789"};
uchar lcdday [8];
uchar lcddisbuf[8];
uchar tempbuf[3];
uchar timebuf[6] = {23,59,59,18,11,2};           //时间,日期
uchar readbuf[6];
uchar disbuf[7];
uchar writebuf[6]; 


/*******************************延时子程序**********************************/
void delay100(int n)
{
unsigned char i;
while(n--)
for(i=0;i<100;i++);
}
/*******************************LCD 忙标志查询******************************/
void lcd_busy(void)
{
uchar busy;
P0=0xff;
RS=0;
RW=1;
do{
E=1;
busy=P0;
E=0;
}
while(busy>0x7f);
}
/*****************************写指令或数据**********************************/
void write(uchar x,uchar Data)
{
lcd_busy(); //忙查询
if(x==0)
{
RS=0;
RW=0; //写单字节命令字
}
else if(x==1)
{
RS=1;
RW=0; //写单字节数据
}
E=1;
P0=Data;
E=0;
P0=0xff;
}
/*******************************初始化LCD **********************************/
void Init_lcd(void)
{
delay100(20); //启动等待,等LCM讲入工作状态
PSB=1; //并口驱动模式
RST=0;
delay100(4);
RST=1; // 复位LCD
write(0,0x30); //8 位介面,基本指令集
write(0,0x0c); //显示打开,光标关,反白关
write(0,0x01); //清屏,将DDRAM的地址计数器归零
}
/*******汉字和字符显示,参数入口:Show(地址,显示宽度,汉字数组)************/
void Show(uchar address,uchar L,uchar STR1[])
{
uchar i;
write(0,address);
for(i=0;i<L;i++)
write(1,STR1[i]);
}
/************纯阿拉伯数字显示,参数入口:Show_dig(地址,数字)**************/
void Show_dig1(uchar address,uint number)
{
uchar shi,ge,fen;
shi=number/10;
ge=number%10;
fen=number*10%10;
write(0,address);
delay100(20);
write(1,dig[shi]);
delay100(20);
write(1,dig[ge]);
delay100(20);
write(1,dig[fen]);
}
void Show_dig(uchar address,uint number)
{
uchar shi,ge;
shi=number/10;
ge=number%10;
write(0,address);
delay100(20);
write(1,dig[shi]);
delay100(20);
write(1,dig[ge]);
}

                                               /*****************
                                                DS18B20温度传感器
                                                *****************/

/* 软件延时函数,延时时间(t*10)us */
void delay_us(uchar n)    //延时约16微妙
{
    for(;n>0;n--)
    {
    _nop_();
    }
}

void DS18B20_init()
{
       uchar i;
       DQ=1;
       delay_us(1);     //稍作延时
       DQ=0;
       delay_us(80);    //延时480到960us
       DQ=1;
       i = 0;
       while(DQ){}   //等待DS18B20拉低总线
       while(!DQ){}       
}

void write_byte(uchar dat)   //写一个字节
{
   uchar i;
   for(i=0;i<8;i++)
   {
      DQ=0;  //每写入一位数据之前先把总线拉低1us
      _nop_();
     DQ=dat&0x01;    //取最低位写入
     delay_us(7);   //延时68us,持续时间最少60us
     DQ=1;   //然后释放总线
     dat=dat>>1;    //从低位开始写
   }
   delay_us(10);
}

uchar read_byte()    //读一个字节
{
  uchar i,dat=0;
  for(i=0;i<8;i++)
  {
     DQ=0;  //先将总线拉低1us
     _nop_();
     DQ=1;  //然后释放总线
     _nop_();_nop_();
     _nop_();_nop_();
     if(DQ) dat=dat|0x80;   //每次读一位
     dat=dat>>1;       //从最低位开始读
     delay_us(4);   //读取完之后等待48us再接着读取下一个数
   }
   return dat;
}

uint read_temper ()
{    
   uchar a,b;         
   uint t=0;
   DS18B20_init();       
   delay_us(15);
   write_byte(0xcc);   //跳过ROM操作命令
   write_byte(0x44);     //发送启动温度转换命令
   DS18B20_init();       
   delay_us(15);
   write_byte(0xcc);    //跳过ROM操作命令
   write_byte(0xbe);      //发送读温度寄存器命令
   a=read_byte();    //先读低八位
   b=read_byte();      //再读高八位
   t=b;        
   t<<=8;      //左移八位
   t=t|a;      //t为16位的数,使高八位为b的值,低八位为a的值  
   return t;    //返回温度值
}

uint temper_change()
{
    uint temper;
    float tp;
    temper=read_temper();
    if(temper<0)    //考虑负温度的情况
    {
        temper=temper-1;
        temper=~temper;
        tp=temper*0.0625;  //16位温度转换成10进制的温度
        temper=tp*100+0.5;   //留两个小数点,并四舍五入
    }
    else
    {
        tp=temper*0.0625;  //16位温度转换成10进制的温度
        temper=tp*100+0.5;  //留两个小数点,并四舍五入
    }
    return temper;
}


                               /*************
                               DS1302时钟模块
                               *************/

void ds1302_write_byte(unsigned char addr, unsigned char byte)
{
        unsigned char i;
        addr = addr & 0xfe;
        SCK = 0;
        RST = 0;

        RST = 1;                                /****一个个2进制数依此输进DS1302 *****/
        for(i = 0; i < 8; i++)
        {
                IO = addr & 0x01;
                SCK = 0;
                SCK = 1;
                addr >>= 1;
        }
        for(i = 0; i < 8; i++)
        {
                IO = byte & 0x01;
                SCK = 0;
                SCK = 1;
                byte >>= 1;
        }
        SCK = 0;
        RST = 0;
}

unsigned char ds1302_read_byte(unsigned char addr)
{
        unsigned char i;
        unsigned char temp;
        addr = addr & 0xfe;        //   改为读操作
        SCK = 0;
        RST = 0;

        RST = 1;
        addr = addr + 1;             //改为读操作
        for(i = 0; i < 8; i++)
        {
                IO = addr & 0x01;
                SCK = 0;
                SCK = 1;
                addr >>= 1;
        }
        for(i = 0; i < 8; i++)
        {   
                SCK = 1;
                SCK = 0;
                temp >>= 1;
                if(IO)
                {
                        temp += 0x80;
                }
        }
        //SCK = 0;
        RST = 0;
        return temp;     //       temp:输出的时间或日期
}

void ds1302_write_time()
{
        unsigned char i;
        unsigned char temp;
        unsigned char temp1;
        for(i = 0; i < 6; i++)
        {  
         temp  = timebuf[i] / 10;   //十位
         temp1 = timebuf[i] % 10;   //个位
         writebuf[i] = (temp << 4) | temp1;//writebuf[i] = ((timebuf[i] / 10) << 4) + (timebuf[i] % 10);
        }                  //十进制转化为二进制

        ds1302_write_byte(ds1302_control_add,0x00);
        ds1302_write_byte(ds1302_hr_add,writebuf[0]); /*****   时          *****/
        ds1302_write_byte(ds1302_min_add,writebuf[1]);/*****       分         *****/
        ds1302_write_byte(ds1302_sec_add,writebuf[2]); /*****         秒      *****/
        ds1302_write_byte(ds1302_year_add,writebuf[3]); /*****          年    *****/
        ds1302_write_byte(ds1302_month_add,writebuf[4]);/*****            月   *****/
        ds1302_write_byte(ds1302_date_add,writebuf[5]); /*****              日 *****/
        ds1302_write_byte(ds1302_control_add,0x80);     
}
void ds1302_read_time()
{
        unsigned char i;

        readbuf[0] = ds1302_read_byte(ds1302_hr_add);
        readbuf[1] = ds1302_read_byte(ds1302_min_add);
        readbuf[2] = ds1302_read_byte(ds1302_sec_add);
        readbuf[3] = ds1302_read_byte(ds1302_year_add);
        readbuf[4] = ds1302_read_byte(ds1302_month_add);
        readbuf[5] = ds1302_read_byte(ds1302_date_add);

        for(i = 0; i < 6; i++)
        {           
          disbuf[i] =  ((readbuf[i] >> 4) * 10) + (readbuf[i] & 0x0f);  //想转化为10进制                  
        }
}

void welcome(int a)
{
   Show(0x80,6,"日历:"); //写数组里的内容
   delay100(30);
   Show(0x88,6,"温度:"); //写数组里的内容
   delay100(30);
   Show_dig1(0x98,a);
   Show(0x82,2,"年"); //写数组里的内容
   delay100(30);
   Show(0x84,2,"月"); //写数组里的内容
   delay100(30);
   Show(0x86,2,"日"); //写数组里的内容
   delay100(30);
   Show(0x92,2,"时"); //写数组里的内容
   delay100(30);
   Show(0x94,2,"分"); //写数组里的内容
   delay100(30);
   Show(0x96,2,"秒"); //写数组里的内容
   delay100(30);
   Show_dig(0x83,disbuf[3]);
   delay100(30);
   Show_dig(0x85,disbuf[4]);
   delay100(30);
   Show_dig(0x87,disbuf[5]);
   delay100(30);
   Show_dig(0x93,disbuf[0]);
   delay100(30);
   Show_dig(0x95,disbuf[1]);
   delay100(30);
   Show_dig(0x97,disbuf[2]);
   delay100(30);
}

void main()
{
   uchar temp;
   DS18B20_init();
   temp = temper_change();
   ds1302_read_time();
   ds1302_write_time();
   Init_lcd();
   delay100(10);
   welcome(temp);
   delay100(10);
 }
  • 写回答

7条回答 默认 最新

  • 嵌入式Linux, 嵌入式领域专家 2018-11-13 00:18
    关注

    老铁,没看到你的while(1);难道显示一次就不显示了吗?

    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料