找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2740|回复: 8
收起左侧

求助 DS1302在LCD12864上显示的时钟的数字在闪烁,就好像乱码,看不到一个数字那样

[复制链接]
ID:356979 发表于 2018-6-22 23:36 | 显示全部楼层 |阅读模式
/*        TSCLK  -  P10
        TIO    -  P11
        TRST   -  P12   */
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar a,miao,fen,shi,ri,yue,nian,week,temp,flag,key1n;

#define yh 0x80  //第一行的初始位置
#define er 0x90 //第二行初始位置
#define san 0x88
#define si 0x98
void write_week(uchar week);

/*12864端口定义*/
#define LCD_data  P0             //数据口
sbit LCD_RS  =  P3^5;            //寄存器选择输入
sbit LCD_RW  =  P3^6;            //液晶读/写控制
sbit LCD_EN  =  P3^4;            //液晶使能控制
sbit LCD_PSB =  P3^7;            //串/并方式控制
sbit wela    =  P2^6;
sbit dula    =  P2^7;

sbit SCLK=P1^0;
sbit IO=P1^1;   
sbit RST=P1^2;   
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit key=P3^3;
sbit key1=P3^0;
sbit key2=P3^1;
sbit key3=P3^2;
uchar code dis1[]={"20"} ;
uchar code dis2[]={""};
uchar code dis3[]={"    "};
uchar code dis4[]={"      "};

#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

void delay(int ms)//延时函数(2ms)
{
    while(ms--)
        {
      uchar i;

          for(i=0;i<250;i++)  
           {
            _nop_();                          
                _nop_();
                _nop_();
                _nop_();
           }
        }
}

bit lcd_busy() //检查LCD忙状态
{                          
    bit result;
    LCD_RS = 0;
    LCD_RW = 1;
    LCD_EN = 1;
    delayNOP();
    result = (bit)(P0&0x80);
    LCD_EN = 0;
    return(result);
}

void lcd_wcmd(uchar cmd) //写指令数据
{                          
   while(lcd_busy());
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_EN = 0;
    _nop_();
    _nop_();
    P0 = cmd;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;  
}

void lcd_wdat(uchar dat) //写显示数据
{                          
   while(lcd_busy());
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_EN = 0;
    P0 = dat;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;
}

void lcd_init()//LCD初始化设定
{

    LCD_PSB = 1;         //并口方式

    lcd_wcmd(0x34);      //扩充指令操作
    delay(5);
    lcd_wcmd(0x30);      //基本指令操作
    delay(5);
    lcd_wcmd(0x0C);      //显示开,关光标
    delay(5);
    lcd_wcmd(0x01);      //清除LCD的显示内容
    delay(5);

}




void lcd_pos(uchar X,uchar Y)  /*设定显示位置    */
{                          
   uchar  pos;
   if (X==0)
     {X=0x80;}
   else if (X==1)
     {X=0x90;}
   else if (X==2)
     {X=0x88;}
   else if (X==3)
     {X=0x98;}
   pos = X+Y ;  
   lcd_wcmd(pos);     //显示地址

}

/*DS1302*/
void write_byte(uchar dat) //写一个字节
{
        ACC=dat;
        RST=1;
        for(a=8;a>0;a--)  //循环8次移位
        {
                IO=ACC0;
                SCLK=0;          //先把时钟线拉低
                SCLK=1;          //把时钟线拉高,锁存数据
                ACC=ACC>>1;
        }
}

uchar read_byte() //读一个字节
{
        RST=1;
        for(a=8;a>0;a--)
        {
                ACC7=IO;
                SCLK=1;
                SCLK=0;
                ACC=ACC>>1;

        }
        return (ACC);
}

void write_1302(uchar add,uchar dat)//向DS1302写函数,指定写入地址、数据
{

        RST=0;
        SCLK=0;
        RST=1;
        write_byte(add);
        write_byte(dat);
        SCLK=1;
        RST=0;         //数据传送中止
}

uchar read_1302(uchar add)        //从DS1302读取数据函数,指定读取数据来源地址
{
        uchar temp;
        RST=0;         //芯片处于复位状态
        SCLK=0;         //清零
        RST=1;        //芯片开始工作
        write_byte(add);
        temp=read_byte();
        SCLK=1;
        RST=0;
        return(temp);
}

uchar BCD_Decimal(uchar bcd) //BDC码转为十进制函数,输入BCD,返回十进制
{
        uchar Decimal;
        Decimal=bcd>>4;
        return(Decimal=Decimal*10+(bcd&=0x0F));
}

void ds1302a_init()
{
        RST=0;
        SCLK=0;
        //write_1302(0x80,miao|0x00);//允许写
        write_1302(0x8e,0x00);

        write_1302(0xc0,0xfe);
        write_1302(0xc2,0xff);
        write_1302(0x80,0x20);
        write_1302(0x82,0x10);
        write_1302(0x84,0x12);
        write_1302(0x86,0x06);
        write_1302(0x88,0x06);
        write_1302(0x8a,0x18);
        write_1302(0x8e,0x80);
}

/*void ds1302b_init()
{
        RST=0;
        SCLK=0;
        write_1302(0x80,ri|0x00);
}*/

void write_sfm(uchar dat)//写时分秒
{
        uchar gw,sw;          
        //lcd_pos(1,0) ;
        //lcd_wcmd(er);
        gw=dat%10;
        sw=dat/10;
        lcd_wdat(0x30+sw);
        lcd_wdat(0x30+gw);
                  
        /*lcd_wdat(0x30+shi/10);
        lcd_wdat(0x30+shi%10);
        lcd_wdat(':');
        lcd_wdat(' ');
        lcd_wdat(0x30+fen/10);
        lcd_wdat(0x30+fen%10);
        lcd_wdat(':');
        lcd_wdat(' ');
        lcd_wdat(0x30+miao/10);
        lcd_wdat(0x30+miao%10);*/
       
       

       
                               
}

void write_nyr(uchar dat)        //写年月日
{
    uchar gw,sw;
        //lcd_pos(0,1);
        //lcd_wcmd(yh);
        gw=dat%10;
        sw=dat/10;
        lcd_wdat(0x30+sw);
        lcd_wdat(0x30+gw);
       
       
        /*lcd_wdat(0x30+nian/10);
        lcd_wdat(0x30+nian%10);
        lcd_wdat('-');
        lcd_wdat('-');
        lcd_wdat(0x30+yue/10);
        lcd_wdat(0x30+yue%10);
        lcd_wdat('-');
        lcd_wdat('-');
        lcd_wdat(0x30+ri/10);
        lcd_wdat(0x30+ri%10);*/
       
          
       

}

void write_week(uchar week)//写星期函数
{                  
        lcd_pos(0,6);//lcd_wcmd(yh+0x0b);
        lcd_wdat(' ');
        switch(week)
        {
                case 1:lcd_wdat('M');//delay(5);
                           lcd_wdat('O');//delay(5);
                           lcd_wdat('N');
                           break;
          
                case 2:lcd_wdat('T');//delay(5);
                           lcd_wdat('U');//delay(5);
                           lcd_wdat('E');
                           break;
               
                case 3:lcd_wdat('W');//delay(5);
                            lcd_wdat('E');//delay(5);
                            lcd_wdat('D');
                           break;
               
                case 4:lcd_wdat('T');//delay(5);
                           lcd_wdat('H');//delay(5);
                           lcd_wdat('U');
                           break;
               
                case 5:lcd_wdat('F');//delay(5);   
                           lcd_wdat('R');//delay(5);
                           lcd_wdat('I');
                           break;
               
                case 6:lcd_wdat('S');//delay(5);
                           lcd_wdat('T');//delay(5);
                           lcd_wdat('A');
                           break;
               
                case 7:lcd_wdat('S');//delay(5);
                           lcd_wdat('U');//delay(5);
                           lcd_wdat('N');
                           break;
                }
       
}

void write_name(uint *s1)//写姓名
{       
        lcd_pos(2,1);//lcd_wcmd(san);
        lcd_wdat(':');
        while(*s1!=0)
        {
                lcd_wdat(*s1);
                s1++;
                delay(5);
        }       
}

void write_num(uint *s2)//学号
{
        lcd_pos(3,1);//lcd_wcmd(si);
        lcd_wdat(':');
        while(*s2!=0)
        {
                lcd_wdat(*s2);
                s2++;
                delay(5);
        }       

}

void Clr_Screen()//清屏命令
{
  //考虑到前面出现0x34
   lcd_wcmd(0x01);
   delay(100);
  }


void init()//串口初始化
{
        TMOD=0x11;//00000001定时计数器0选择方式1,16位定时计数器
        TH0=0;   
        TL0=0;
        EA=1;        //开全局中断
        ET0=1;        //定时计数器0中断使能控制位
        TR0=1;        //定时器T0开始计数

}

void cmg(void)//数码管锁存函数
{
        dula=1;
        P0=0x00;
        dula=0;
        wela=1;
        P0=0x00;
        wela=0;
}

void keyscan()
{
        if(key1==0)
        {
                delay(5);
                if(key1==0)
                {
                        while(!key1);
                        key1n++;
                        if(key1n==9)
                                key1n=1;
                        switch(key1n)
                        {
                                case 1: TR0=0;         //miao
                                                lcd_wcmd(0x90+4);
                                                lcd_wcmd(0x0f);
                                                temp=(miao)/10*16+(miao)%10        ;
                                                write_1302(0x8e,0x00);
                                                   write_1302(0x80,0x80|temp);//miao
                                                   write_1302(0x8e,0x80);
                                                   break;
                                case 2: lcd_wcmd(0x90+2); //fen
                                            lcd_wcmd(0x0f);
                                                break;
                                case 3: lcd_wcmd(0x90);        //shi
                                                lcd_wcmd(0x0f);
                                                break;
                                case 4: lcd_wcmd(0x80+7); //week
                                                lcd_wcmd(0x0f);
                                                break;
                            case 5: lcd_wcmd(0x80+5);  //ri
                                                lcd_wcmd(0x0f);
                                                break;
                                case 6: lcd_wcmd(0x80+3);         //yue
                                                lcd_wcmd(0x0f);
                                                break;
                                case 7: lcd_wcmd(0x80+1);        //nian
                                                lcd_wcmd(0x0f);
                                                break;
                                case 8: lcd_wcmd(0x0c);
                                                TR0=1;
                                                temp=(miao)/10*16+(miao)%10;//将十进制变成十六进制
                                                   write_1302(0x8e,0x00);
                                                   write_1302(0x80,0x00|temp);//miao
                                                   write_1302(0x8e,0x80);
                                    break;
                        }
                }
        }
       
               

        if(key1n!=0)//当key1按下以下。再按以下键才有效
        {
       
                if(key2==0)  //上调键
                {
                        delay(5);
                        if(key2==0)
                        {
                                while(!key2);
                                switch(key1n)
                                {
                                        case 1: miao++;
                                                        if(miao==60)
                                                                miao=0;
                                                        write_sfm(miao);
                                                        lcd_pos(1,4);
                                                        temp=(miao)/10*16+(miao)%10;
                                                           write_1302(0x8e,0x00);
                                                           write_1302(0x80,0x80|temp);
                                                           write_1302(0x8e,0x80);
                                                        lcd_wcmd(0x90+4);
                                                        break;
                                        case 2: fen++;
                                                        if(fen==60)
                                                                fen=0;
                                                        write_sfm(fen);
                                                        temp=(fen)/10*16+(fen)%10;
                                                           write_1302(0x8e,0x00);
                                                           write_1302(0x82,temp);
                                                           write_1302(0x8e,0x80);
                                                        lcd_wcmd(0x90+2);
                                                        break;
                                        case 3: shi++;
                                                        if(shi==24)
                                                                shi=0;
                                                        write_sfm(shi);
                                                        temp=(shi)/10*16+(shi)%10;
                                                           write_1302(0x8e,0x00);
                                                           write_1302(0x84,temp);
                                                           write_1302(0x8e,0x80);
                                        lcd_wcmd(0x90);
                                                        break;
                                        case 4: week++;
                                                        if(week==8)
                                                        week=0;
                                                        write_week(week);
                                                        lcd_wcmd(0x80+7);
                                                        lcd_wcmd(0x80+6) ;
                                                        break;
                                        case 5: ri++;
                                                        if(ri==31)
                                                                ri=0;
                                                        write_nyr(ri);
                                                        temp=(ri)/10*16+(ri)%10;
                                                           write_1302(0x8e,0x00);
                                                           write_1302(0x86,temp);
                                                           write_1302(0x8e,0x80);
                                                        lcd_wcmd(0x80+5);
                                                        break;
                                        case 6: yue++;
                                                        if(yue==13)
                                                        yue=0;
                                                        write_nyr(yue);
                                                        temp=(yue)/10*16+(yue)%10;
                                                           write_1302(0x8e,0x00);
                                                           write_1302(0x88,temp);
                                                           write_1302(0x8e,0x80);
                                                        lcd_wcmd(0x80+3);
                                                        break;
                                        case 7:
                                                        nian++;
                                    if(nian==100)
                                                        nian=0;
                                                        write_nyr(nian);
                                                        temp=(nian)/10*16+(nian)%10;
                                                           write_1302(0x8e,0x00);
                                                           write_1302(0x8a,temp);
                                                           write_1302(0x8e,0x80);
                                                        lcd_wcmd(0x80+1);
                                                        break;
                                }
                        }
        }
        if(key3==0)
        {
                delay(5);
                if(key3==0)
                {
                        while(!key3);
                        switch(key1n)
                        {
                                 case 1: miao--;
                                                if(miao==-1)
                                                        miao=59;                                                       
                                                write_sfm(miao);
                                                lcd_wcmd(0x90+4);
                                                break;

                                 case 2:fen--;
                                        if(fen==-1)
                                                           fen=59;
                                                write_sfm(fen);
                                            temp=(fen)/10*16+(fen)%10;
                                                   write_1302(0x8e,0x00);
                                                   write_1302(0x82,temp);
                                                   write_1302(0x8e,0x80);
                                                lcd_wcmd(0x90+2);
                                                break;
                                 case 3:shi--;
                                                   if(shi==-1)
                                                        shi=23;
                                                write_sfm(shi);
                                                temp=(shi)/10*16+(shi)%10;
                                                   write_1302(0x8e,0x00);
                                                   write_1302(0x84,temp);
                                                   write_1302(0x8e,0x80);
                                                lcd_wcmd(0x90);
                                                break;
                                case 4: week--;
                                                if(week==-1)
                                                        week=7;
                                                write_week(week);
                                                lcd_wcmd(0x80+7);
                                                lcd_wcmd(0x80+6);
                                                break;
                                case 5: ri--;
                                                if(ri==-1)
                                                        ri=30;
                                                write_nyr(ri);
                                                temp=(ri)/10*16+(ri)%10;
                                                   write_1302(0x8e,0x00);
                                                   write_1302(0x86,temp);
                                                   write_1302(0x8e,0x80);
                                                  lcd_wcmd(0x80+5);
                                                break;
                                case 6: yue--;
                                                if(yue==-1)
                                                        yue=12;
                                                write_nyr(yue);
                                                temp=(yue)/10*16+(yue)%10;
                                                   write_1302(0x8e,0x00);
                                                   write_1302(0x88,temp);
                                                   write_1302(0x8e,0x80);
                                                lcd_wcmd(0x80+3);
                                                break;       
                                case 7: nian--;
                                                 if(nian==-1)
                                                        nian=99;
                                                write_nyr(nian);
                                            temp=(nian)/10*16+(nian)%10;
                                                   write_1302(0x8e,0x00);
                                                   write_1302(0x8a,temp);
                                                   write_1302(0x8e,0x80);
                                                lcd_wcmd(0x80+1);
                                                break;
                                }
                         }

                }
        }
}



   main()//主函数
{
    uchar i;
       
    delay(10);                 //延时
    wela=0;
        dula=0;
    cmg();//数码管锁存

        ds1302a_init();
        //ds1302b_init();
        init();       
    lcd_init();                //初始化LCD            

       
    lcd_pos(0,0);             //设置显示位置为第一行的第1个字符
     i = 0;
    while(dis1[i] != '\0')
     {                         //显示字符
       lcd_wdat(dis1[i]);
       i++;
     }

    lcd_pos(1,0);             //设置显示位置为第二行的第1个字符
     i = 0;
    while(dis2[i] != '\0')
     {
       lcd_wdat(dis2[i]);      //显示字符
       i++;
     }        

         lcd_pos(2,0);             //设置显示位置为第三行的第1个字符
     i = 0;
    while(dis3[i] != '\0')
     {
       lcd_wdat(dis3[i]);      //显示字符
       i++;
     }

         lcd_pos(3,0);             //设置显示位置为第四行的第1个字符
     i = 0;
    while(dis4[i] != '\0')
     {
       lcd_wdat(dis4[i]);      //显示字符
       i++;
     }        
                
     while(1)
         {
                 keyscan();
         }
         
}


void timer0() interrupt 1  //中断函数
{
        miao = BCD_Decimal(read_1302(0x81));
        fen = BCD_Decimal(read_1302(0x83));
        shi  = BCD_Decimal(read_1302(0x85));
        ri  = BCD_Decimal(read_1302(0x87));
        yue = BCD_Decimal(read_1302(0x89));
        nian=BCD_Decimal(read_1302(0x8d));
        week=BCD_Decimal(read_1302(0x8b));
       
        lcd_pos(1,4);       
        write_sfm(miao);

        lcd_pos(1,3);
        lcd_wdat(':');

        lcd_pos(1,2);
        write_sfm(fen);
       
        lcd_pos(1,1);
        lcd_wdat(':');

        lcd_pos(1,0);
        write_sfm(shi);

        lcd_pos(0,5);
        write_nyr(ri);

        lcd_pos(0,4);
        lcd_wdat('-');
        lcd_wdat('-');

        lcd_pos(0,3);
    write_nyr(yue);

        lcd_pos(0,2);
        lcd_wdat(0x2d);
        lcd_wdat(0x2d);

        lcd_pos(0,1);
        write_nyr(nian);

       
}


回复

使用道具 举报

ID:356979 发表于 2018-6-22 23:43 | 显示全部楼层
弄了很久都不行,有没有大神可以帮帮忙
回复

使用道具 举报

ID:303383 发表于 2018-6-23 08:44 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

ID:295783 发表于 2018-6-23 10:39 | 显示全部楼层
你的程序太长了 我给你一点建议你自己查一下
1.有没有进行初始化 清零
2.延时问题 必须要有延时 我记得动态显示好像是一直不停的显示 是动态的 很快 所以肉眼看到的是静止的 延时不能太长
3.如果你加了按键功能的话 看看有没有按键消抖程序 这个是必须有的
希望对你有帮助
回复

使用道具 举报

ID:356979 发表于 2018-6-23 23:07 | 显示全部楼层
程序新手 发表于 2018-6-23 10:39
你的程序太长了 我给你一点建议你自己查一下
1.有没有进行初始化 清零
2.延时问题 必须要有延时 我记得动 ...

初始化是有的,就是它显示是乱码,不是说小时的太快,有对应的向时钟显示,比如显示了02到03之间它会闪到其他数字,而且有些就不是02、03、04的顺序显示下去的
回复

使用道具 举报

ID:356979 发表于 2018-6-23 23:27 | 显示全部楼层
今晚弄它突然就行了,但是显示年的时候用按键调的时候出现了两种情况,第一是调完之后时钟继续走时,那个年还是显示原来没调的那个数,第二就是在调节时,一按加键或减键时它不是从原来的那个数一直加或减的进行,在这种情况下调完就可以正确显示,
回复

使用道具 举报

ID:261000 发表于 2018-6-24 12:29 | 显示全部楼层
建议一段一段查,,先查端口驱部分,,硬件也要查一下,io口加上拉电阻“10K。看看。
回复

使用道具 举报

ID:357739 发表于 2018-6-24 13:18 | 显示全部楼层
先检查电路有没有问题,连的线是串行还是并行的
回复

使用道具 举报

ID:357839 发表于 2018-6-24 16:06 来自手机 | 显示全部楼层
有没有可能是你的晶振的频率调的不合适 或者LCD时钟频率
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表