求大神帮我看看是怎么回事??关于智能电子钟LCD显示

2019-07-15 13:58发布

本帖最后由 岚翎 于 2016-5-28 12:50 编辑

小弟在做单片机课程设计--智能电子钟LCD显示,跟着书本例子打出来的代码,但是lcd液晶屏显示错误 ,求大神帮我看看是怎么回事,小弟感激不尽!!!!
程序代码如下:
#include<reg51.h>
#include<absacc.h>                  //定义绝对地址访问
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit T_CLK = P1^3;        //DS1302时钟线引脚
sbit T_IO = P1^4;        //DS1302数据线引脚
sbit T_RST = P1^2;        //DS1302复位线引脚
sbit RS = P2^7;        //定义LCD的控制线
sbit RW = P2^6;        
sbit EN = P2^5;   
sbit ACC7 = ACC^7;
sbit ACC0 = ACC^0;
uchar datechar[] = {"DATE:"};  
uchar timechar[] = {"TIME:"};
uchar datebuffer[10] = {0x32,0x30,0,0,0x2d,0,0,0x2d,0,0};  //定义日历显示缓冲区  
uchar timebuffer[8] = {0,0,0x3a,0,0,0x3a,0,0};  //定义时间显示缓冲区
uchar weekbuffer = {0x30};  //定义星期显示缓冲区
/***********************************************************************************
*名称:WriteB
*功能:往DS1302写入1Byte数据
*输入:ucDa写入的数据
*返回值:无
************************************************************************************/
void WriteB(uchar ucDa)
{
        uchar i;
        ACC = ucDa;
        for(i=8; i>0; i--)
        {
                T_IO = ACC0;                   //相当于汇编中的RRC
                T_CLK = 1;
                T_CLK = 0;
                ACC = ACC >> 1;
        }
}
/***********************************************************************************
*名称:ReadB
*功能:从DS1302读取1Byte数据
*输入:ucDa写入的数据
*返回值:ACC
************************************************************************************/  
uchar ReadB(void)
{
        uchar i;
        for(i=8; i>0; i--)
        {
                ACC = ACC >> 1;
                ACC7 = T_IO; T_CLK = 1; T_CLK = 0;   //相当于汇编中的RRC
        }
        return(ACC);
}
/***********************************************************************************
*名称:v_W1302
*功能:单字写,向DS1302某地址写入命令/数据,先写地址,后写命令/数据
*调用:WriteB()
*输入:ucAddr:DS1302地址,ucDa:要写的数据
*返回值:无
************************************************************************************/
void v_W1302(uchar ucAddr ,uchar ucDa)
{
        T_RST = 0;
        T_CLK = 0;
        _nop_();_nop_();
        T_RST = 1;
        _nop_();_nop_();
        WriteB(ucAddr);                   //地址,命令
        WriteB(ucDa);                   //写一字节数据
        T_CLK = 1;
        T_RST = 0;
}
/***********************************************************************************
*名称:uc_R1302
*功能:单字节读,向DS1302读取某地址数据,先写地址,后写命令/数据
*调用:WriteB(),ReadB()
*输入:ucAddr:DS1302地址
*返回值:ucDa读取的数据
************************************************************************************/
uchar uc_R1302(uchar ucAddr)
{
        uchar ucDa = 0;
        T_RST = 0;T_CLK = 0;
        T_RST = 1;
        WriteB(ucAddr);                      //写地址
        ucDa = ReadB();                  //读一字节命令/数据
        T_CLK = 1; T_RST = 0;
        return(ucDa);
}
/***************检查忙函数*******************/
void fbusy()
{        P0 = 1;
        P0 = 0Xff; RS = 0; RW = 1;
        EN = 1; EN = 0;
        while ((P0&0x80)) { EN = 0; EN = 1;}  //忙,等待
}
/*******************写命令函数*******************/
void wc51r(uchar j)
{
        fbusy();         //读状态
        EN = 0; RS = 0; RW = 0;
        EN = 1;
        P0 = 1;
        P0 = j;
        EN = 0;
}
/**************写数据函数***************/
void wc51ddr(uchar j)
{
        fbusy();          //读状态
        EN = 0; RS = 1; RW = 0;
        EN = 1;
        P0 = 1;
        P0 = j;
        EN = 0;
}
/*******************LCD1602初始化函数*******************/
void init()
{
        wc51r(0x01);                         //清屏
        wc51r(0x38);                         //使用8位数据,显示两行,使用5*7的字型
        wc51r(0x0c);                         //显示器开,光标关,字符不闪烁
        wc51r(0x06);                         //字符不动,光标自动右移一格
}
/*******************延时函数*******************/
void delay(uint i)
{
        uint y,j;
        for (j=0;j<i;j++)
                {
                        for(y=0;y<0xff;y++)        {;}
                }
}
void main(void)
{
        uchar i;
        uchar data temp;
        delay(10);
        init();
        wc51r(0x80);
        for(i=0;i<5;i++) wc51ddr(datechar);     //第一行显示DATA:
        wc51r(0xc0);
        for(i=0;i<5;i++) wc51ddr(timechar);     //第二行显示TIME:
        v_W1302(0x8e,0);         //打开写保护
        v_W1302(0x8c,0x13);  //向DS1302写入日期13-12-21,时间16:25:30 星期六
        v_W1302(0x8A,0x06);
        v_W1302(0x88,0x12);
        v_W1302(0x86,0x21);
        v_W1302(0x84,0x16);
        v_W1302(0x82,0x25);
        v_W1302(0x80,0x30);
        v_W1302(0x8e,0x80);           //关闭写保护
        while(1)
        {
                temp = uc_R1302(0x8d);           //读年,分成十位和各位,转换成字符,放入日历显示缓冲区
                datebuffer[2] = 0x30+temp/16; datebuffer[3] = 0x30+temp%16;
                temp = uc_R1302(0x8B);           //读星期,转换成字符,放入星期显示缓冲区
                weekbuffer = 0x30 + temp;
                temp = uc_R1302(0x89);           //读月,分成十位和各位,转换成字符,放入日历显示缓冲区
                datebuffer[5] = 0x30+temp/16; datebuffer[6] = 0x30+temp%16;
                temp = uc_R1302(0x87);           //读日,分成十位和各位,转换成字符,放入日历显示缓冲区
                timebuffer[8] = 0x30+temp/16; datebuffer[9] = 0x30+temp%16;
                temp = uc_R1302(0x85);           //读小时,分成十位和各位,转换成字符,放入时间显示缓冲区
                temp = temp&0x7f;
                timebuffer[0] = 0x30+temp/16; datebuffer[1] = 0x30+temp%16;
                temp = uc_R1302(0x83);           //读分,分成十位和各位,转换成字符,放入时间显示缓冲区
                timebuffer[3] = 0x30+temp/16; datebuffer[4] = 0x30+temp%16;
                temp = uc_R1302(0x81);           //读秒,分成十位和各位,转换成字符,放入时间显示缓冲区
                temp = temp&0x7f;
                timebuffer[6] = 0x30+temp/16; datebuffer[7] = 0x30+temp%16;
                wc51r(0x86);           //第一行后面显示日历
                for(i=0;i<10;i++) wc51ddr(datebuffer);
                wc51r(0xc6);           //第二行后面显示时间
                for(i=0;i<8;i++) wc51ddr(datebuffer);
                wc51ddr(0x20);
                wc51ddr(weekbuffer);        //后面显示星期
        }
}   

#include<reg51.h>
#include<absacc.h>                  //定义绝对地址访问
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit T_CLK = P1^0;        //DS1302时钟线引脚
sbit T_IO = P1^1;        //DS1302数据线引脚
sbit T_RST = P1^2;        //DS1302复位线引脚
sbit RS = P2^7;        //定义LCD的控制线
sbit RW = P2^6;        
sbit EN = P2^5;   
sbit ACC7 = ACC^7;
sbit ACC0 = ACC^0;
uchar datechar[] = {"DATE:"};  
uchar timechar[] = {"TIME:"};
uchar datebuffer[10] = {0x32,0x30,0,0,0x2d,0,0,0x2d,0,0};  //定义日历显示缓冲区  
uchar timebuffer[8] = {0,0,0x3a,0,0,0x3a,0,0};  //定义时间显示缓冲区
uchar weekbuffer = {0x30};  //定义星期显示缓冲区
/***********************************************************************************
*名称:WriteB
*功能:往DS1302写入1Byte数据
*输入:ucDa写入的数据
*返回值:无
************************************************************************************/
void WriteB(uchar ucDa)
{
        uchar i;
        ACC = ucDa;
        for(i=8; i>0; i--)
        {
                T_IO = ACC0;                   //相当于汇编中的RRC
                T_CLK = 1;
                T_CLK = 0;
                ACC = ACC >> 1;
        }
}
/***********************************************************************************
*名称:ReadB
*功能:从DS1302读取1Byte数据
*输入:ucDa写入的数据
*返回值:ACC
************************************************************************************/  
uchar ReadB(void)
{
        uchar i;
        for(i=8; i>0; i--)
        {
                ACC = ACC >> 1;
                ACC7 = T_IO; T_CLK = 1; T_CLK = 0;   //相当于汇编中的RRC
        }
        return(ACC);
}
/***********************************************************************************
*名称:v_W1302
*功能:单字写,向DS1302某地址写入命令/数据,先写地址,后写命令/数据
*调用:WriteB()
*输入:ucAddr:DS1302地址,ucDa:要写的数据
*返回值:无
************************************************************************************/
void v_W1302(uchar ucAddr ,uchar ucDa)
{
        T_RST = 0;
        T_CLK = 0;
        _nop_();_nop_();
        T_RST = 1;
        _nop_();_nop_();
        WriteB(ucAddr);                   //地址,命令
        WriteB(ucDa);                   //写一字节数据
        T_CLK = 1;
        T_RST = 0;
}
/***********************************************************************************
*名称:uc_R1302
*功能:单字节读,向DS1302读取某地址数据,先写地址,后写命令/数据
*调用:WriteB(),ReadB()
*输入:ucAddr:DS1302地址
*返回值:ucDa读取的数据
************************************************************************************/
uchar uc_R1302(uchar ucAddr)
{
        uchar ucDa = 0;
        T_RST = 0;T_CLK = 0;
        T_RST = 1;
        WriteB(ucAddr);                      //写地址
        ucDa = ReadB();                  //读一字节命令/数据
        T_CLK = 1; T_RST = 0;
        return(ucDa);
}
/***************检查忙函数*******************/
void fbusy()
{        P0 = 1;
        P0 = 0Xff; RS = 0; RW = 1;
        EN = 1; EN = 0;
        while ((P0&0x80)) { EN = 0; EN = 1;}  //忙,等待
}
/*******************写命令函数*******************/
void wc51r(uchar j)
{
        fbusy();         //读状态
        EN = 0; RS = 0; RW = 0;
        EN = 1;
        P0 = 1;
        P0 = j;
        EN = 0;
}
/**************写数据函数***************/
void wc51ddr(uchar j)
{
        fbusy();          //读状态
        EN = 0; RS = 1; RW = 0;
        EN = 1;
        P0 = 1;
        P0 = j;
        EN = 0;
}
/*******************LCD1602初始化函数*******************/
void init()
{
        wc51r(0x01);                         //清屏
        wc51r(0x38);                         //使用8位数据,显示两行,使用5*7的字型
        wc51r(0x0c);                         //显示器开,光标关,字符不闪烁
        wc51r(0x06);                         //字符不动,光标自动右移一格
}
/*******************延时函数*******************/
void delay(uint i)
{
        uint y,j;
        for (j=0;j<i;j++)
                {
                        for(y=0;y<0xff;y++)        {;}
                }
}
void main(void)
{
        uchar i;
        uchar data temp;
        delay(10);
        init();
        wc51r(0x80);
        for(i=0;i<5;i++) wc51ddr(datechar);     //第一行显示DATA:
        wc51r(0xc0);
        for(i=0;i<5;i++) wc51ddr(timechar);     //第二行显示TIME:
        v_W1302(0x8e,0);         //打开写保护
        v_W1302(0x8c,0x13);  //向DS1302写入日期13-12-21,时间16:25:30 星期六
        v_W1302(0x8A,0x06);
        v_W1302(0x88,0x12);
        v_W1302(0x86,0x21);
        v_W1302(0x84,0x16);
        v_W1302(0x82,0x25);
        v_W1302(0x80,0x30);
        v_W1302(0x8e,0x80);           //关闭写保护
        while(1)
        {
                temp = uc_R1302(0x8d);           //读年,分成十位和各位,转换成字符,放入日历显示缓冲区
                datebuffer[2] = 0x30+temp/16; datebuffer[3] = 0x30+temp%16;
                temp = uc_R1302(0x8B);           //读星期,转换成字符,放入星期显示缓冲区
                weekbuffer = 0x30 + temp;
                temp = uc_R1302(0x89);           //读月,分成十位和各位,转换成字符,放入日历显示缓冲区
                datebuffer[5] = 0x30+temp/16; datebuffer[6] = 0x30+temp%16;
                temp = uc_R1302(0x87);           //读日,分成十位和各位,转换成字符,放入日历显示缓冲区
                timebuffer[8] = 0x30+temp/16; datebuffer[9] = 0x30+temp%16;
                temp = uc_R1302(0x85);           //读小时,分成十位和各位,转换成字符,放入时间显示缓冲区
                temp = temp&0x7f;
                timebuffer[0] = 0x30+temp/16; datebuffer[1] = 0x30+temp%16;
                temp = uc_R1302(0x83);           //读分,分成十位和各位,转换成字符,放入时间显示缓冲区
                timebuffer[3] = 0x30+temp/16; datebuffer[4] = 0x30+temp%16;
                temp = uc_R1302(0x81);           //读秒,分成十位和各位,转换成字符,放入时间显示缓冲区
                temp = temp&0x7f;
                timebuffer[6] = 0x30+temp/16; datebuffer[7] = 0x30+temp%16;
                wc51r(0x86);           //第一行后面显示日历
                for(i=0;i<10;i++) wc51ddr(datebuffer);
                wc51r(0xc6);           //第二行后面显示时间
                for(i=0;i<8;i++) wc51ddr(datebuffer);
                wc51ddr(0x20);
                wc51ddr(weekbuffer);        //后面显示星期
        }
}  


UC截图20160515193516.png
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
2条回答
chenwei6991627
1楼-- · 2019-07-15 15:02
应该是解码部分有问题把
岚翎
2楼-- · 2019-07-15 15:21
本帖最后由 岚翎 于 2016-5-28 13:05 编辑
chenwei6991627 发表于 2016-5-27 09:17
应该是解码部分有问题把

恩恩,非常感谢。但是我还是不怎么懂ds1302和lcd1602的具体原理,因为之前老师没教过,现在都是自学的,所以有点模糊,希望多多指教

一周热门 更多>