找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4269|回复: 7
打印 上一主题 下一主题
收起左侧

求解:为什么ds1302上电第一次可以按键调时之后就不行了

[复制链接]
跳转到指定楼层
楼主
ID:199790 发表于 2017-5-11 23:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*时钟显示1602独立键盘(P1口)设置时钟(K1设置时分秒星期年月日,K2加一,K3减一)        */
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int

//DS1302控制端口定义
sbit CE=P3^5;
sbit SDA=P3^4;
sbit SCLK=P3^6;

//LCD1602控制端口定义
sbit LCD_RS = P2^6;
sbit LCD_RW = P2^5;
sbit LCD_EN = P2^7;

//独立按键定义

sbit K1=P1^0;        //功能键
sbit K2=P1^1;        //增大键
sbit K3=P1^2;        //减小键
sbit K4=P1^3;
bit k=0;

//屏幕初始化图标
uchar code table1[]={" 20  -  -        "};
uchar code table2[]={"      :  :     "};

//星期LOGO

uchar code table3[]={"MON TUE WED THU FRI SAT SUN"};

//初始化 年 月 日 星期 时 分 秒
char year_h,year_l,month_h,month_l,day_h,day_l,hour_h,hour_l,min_h,min_l,sec_h,sec_l,date=1;
uchar year,month,day,hour,min,sec;
uchar K1num=0;

//声明延时函数毫秒级
void delay1ms(uint ms);
/*******************************************************************************************
* 以下为DS1302驱动程序 *
*******************************************************************************************/

uchar DS1302_Read(uchar address)
{
        uchar i,temp=0x00;
        CE=0;
        SDA=1;
        SCLK=0;
        CE=1;
        for (i=0;i<8;i++) //循环8次 写入地址数据
        {
                SCLK=0;
                SDA=address&0x01; //每次传输低字节
                address>>=1; //右移一位
                SCLK=1;
        }
        delay1ms(1);
        if(SDA)
                temp|=0x80;        //每次传输低字节
                SCLK=0;
                temp>>=1;
        for (i=0;i<7;i++) //循环8次 读取数据
        {
                SCLK=0;
                if(SDA)
                temp|=0x80;        //每次传输低字节
                SCLK=1;
                temp>>=1;        //右移一位
        }
        SCLK=1;
        CE=0;
        SDA=0;
        return temp;        //返回
}

void DS1302_Write(uchar address,uchar dat)
{
        uchar i;
        CE=0;
        SCLK=0;
        CE=1;
        for (i=0;i<8;i++) //循环8次 写入地址数据
        {
                SCLK=0;
                _nop_();
                SDA=address&0x01; //每次传输低字节
                address>>=1; //右移一位
                SCLK=1;
                _nop_();
        }
        for (i=0;i<8;i++) //循环8次 写入数据
        {
                SCLK=0;
                _nop_();
                SDA=dat&0x01; //每次传输低字节
                dat>>=1; //右移一位        DSCLK=1
                SCLK=1;
                _nop_();
        }
        CE=0;
        _nop_();
}

void DS1302_initW()        //初始化时间设置(写)
{
        DS1302_Write(0x8e,0x00);        //写保护关
        DS1302_Write(0x80,sec);        //秒
        DS1302_Write(0x82,min);        //分
        DS1302_Write(0x84,hour);        //时
        DS1302_Write(0x86,day);        //日
        DS1302_Write(0x88,month);        //月
        DS1302_Write(0x8a,date);        //周
        DS1302_Write(0x8c,year);        //年
        DS1302_Write(0x8e,0x80);        //写保护开
}

void DS1302_initR()
{
        sec=DS1302_Read(0x81);        //读秒数据
        min=DS1302_Read(0x83);        //读分钟数据
        hour=DS1302_Read(0x85);        //读小时数据
        date=DS1302_Read(0x8b);        //读星期数据
        day=DS1302_Read(0x87);        //读日数据
        month=DS1302_Read(0x89);//读月数据
        year=DS1302_Read(0x8d);        //读年数据
}

/*******************************************************************************************
* 以上为DS1302驱动程序 *
*******************************************************************************************/
/*******************************************************************************************
* 以下为LCD1602驱动显示程序 *
*******************************************************************************************/

void delay1ms(uint ms)        //延时程序1ms
{
        uint i,j;
        for(i=ms;i>0;i--)
        for(j=110;j>0;j--);
}

void LCD_writecom(uchar com) //写命令
{
        LCD_RS=0;
        LCD_RW=0;
        LCD_EN=1;
        delay1ms(2);
        P0=com;
        LCD_EN=0;
        delay1ms(2);
}

void LCD_writedat(uchar dat)        //写数据
{
        LCD_RS=1;
        LCD_RW=0;
        LCD_EN=1;
        delay1ms(2);
        P0=dat;
        LCD_EN=0;
        delay1ms(2);
}

void init()
{
        LCD_EN=0;
        delay1ms(15);
        LCD_writecom(0x38);        //工作方式设置(8位数据接口;两行显示;5*7点阵字符)
        LCD_writecom(0x38);
        delay1ms(5);
        LCD_writecom(0x38);
        LCD_writecom(0x06);        //输入方式设置(数据读写操作后AC自动加1;数据读写操作后画面不移动)
        LCD_writecom(0x0C);        //显示开关控制(开显示,关光标,关闪烁)
        LCD_writecom(0x01);        //清屏
}

void display1()        //初始化屏幕 格式: 20 - -           //        : :

{       
        uchar num;
        init();
        LCD_writecom(0x80);
        for(num=0;num<12;num++)
        {
                LCD_writedat(table1[num]);
                delay1ms(2);
        }
        LCD_writecom(0x80+0x40);
        for(num=0;num<15;num++)
        {
                LCD_writedat(table2[num]);
                delay1ms(2);
        }
}

void display2(uchar date)
{
        uchar num;
        LCD_writecom(0x80+12);
        if(date==1)        //星期一
        {
                for(num=0;num<3;num++)
                {
                        LCD_writedat(table3[num]);
                        delay1ms(2);
                }
        }
        if(date==2)        //星期二
        {
                for(num=4;num<7;num++)
                {
                        LCD_writedat(table3[num]);
                        delay1ms(2);
                }
        }
        if(date==3)        //星期三
        {
                for(num=8;num<11;num++)
                {
                        LCD_writedat(table3[num]);
                        delay1ms(2);
                }
        }
        if(date==4)        //星期四
        {
                for(num=12;num<15;num++)
                {
                        LCD_writedat(table3[num]);
                        delay1ms(2);
                }
        }        //星期五
        if(date==5)
        {
                for(num=16;num<19;num++)
                {
                        LCD_writedat(table3[num]);
                        delay1ms(2);
                }
        }
        if(date==6)        //星期六
        {
                for(num=20;num<23;num++)
                {
                        LCD_writedat(table3[num]);
                        delay1ms(2);
                }
        }        //星期日
        if(date==7)
        {
                for(num=24;num<27;num++)
                {
                        LCD_writedat(table3[num]);
                        delay1ms(2);
                }
        }
}

void write_sfm(uchar add,char date)        //时分秒写入显示
{
        char shi,ge;
        shi=date/16;
        ge=date%16;
        LCD_writecom(0x80+0x40+add);
        LCD_writedat(0x30+shi);
        LCD_writedat(0x30+ge);
}

void write_nyrx(uchar add,char date)        //年月日星期写入显示
{
        char shi,ge;
        shi=date/16;
        ge=date%16;
        LCD_writecom(0x80+add);
        LCD_writedat(0x30+shi);
        LCD_writedat(0x30+ge);
}

/*******************************************************************************************
* 以上为LCD1602驱动显示程序 *
*******************************************************************************************/

void display3()        //时间显示程序
{
        if(k==0)        //时间显示停止控制标志
        {
                DS1302_initR();
                write_sfm(10,sec);
                write_sfm(7,min);
                write_sfm(4,hour);
                write_nyrx(3,year);
                write_nyrx(6,month);
                write_nyrx(9,day);
                display2(date);
        }
}

void keyscan()        //键盘扫描
{
        display3();
        if(K1==0)
        {
                delay1ms(5);
                if(K1==0)
                {
                        K1num++;        //K1按键计数
                        while(!K1);
                        k=1;
                        DS1302_Write(0x8e,0x00);        //写保护关
                        DS1302_Write(0x80,0x80);    //时间暂停
                        switch(K1num)
                        {                         
                        case 1:
                        LCD_writecom(0x80+0x40+11);                       
                        LCD_writecom(0x0f);
                        k=1;        //时间暂停显示
                        break;
                        case 2:
                        LCD_writecom(0x80+0x40+8);break;
                        case 3:
                        LCD_writecom(0x80+0x40+5);break;
                        case 4:
                        LCD_writecom(0x80+14);break;
                        case 5:
                        LCD_writecom(0x80+10);break;
                        case 6:
                        LCD_writecom(0x80+7);break;
                        case 7:
                        LCD_writecom(0x80+4);break;
                        case 8:
                        LCD_writecom(0x0c);                       
                        DS1302_initW();        //将设置的时间日期等写入DS1302中
                        k=0;        //时间继续走
                        K1num=0;        //K1按键计数清零
                        DS1302_Write(0x80,0x00);   //时间继续
                //        DS1302_Write(0x8e,0x80);        //写保护开

                        break;
                        }
                }

        }
        if(K1num!=0)        //如果K1按下进行以下操作
        {
                if(K2==0)        //K1按下进行K2按键检测
                {
                        delay1ms(5);
                        if(K2==0)
                        {
                                while(!K2);
                                switch(K1num)
                        {        //秒++
                        case 1:       
                                sec_h=sec/16;
                                sec_l=sec%16;
                                sec_l++;
                        if(sec_l==10)
                        {
                                sec_l=0;
                                sec_h++;
                        }
                        if(sec_h==6)
                        sec_h=0;
                        sec=sec_h*16+sec_l;
                        write_sfm(10,sec);
                        LCD_writecom(0x80+0x40+11);
                        break;
                        case 2:

                                min_h=min/16;        //分++
                                min_l=min%16;
                                min_l++;
                                if(min_l==10)
                                {
                                        min_l=0;
                                        min_h++;
                                }
                                if(min_h==6)
                                min_h=0;
                                min=min_h*16+min_l;
                                write_sfm(7,min);
                                LCD_writecom(0x80+0x40+8);
                                break;
                               
                        case 3:
                                hour_h=hour/16;
                                hour_l=hour%16;        //时++
                                if(hour_h==2)
                                {
                                if(hour_l>3)
                                {
                                        hour_h=0;
                                        hour_l=0;
                                }
                                }
                                hour_l++;
                                if(hour_l==10)
                                {
                                        hour_l=0;
                                        hour_h++;
                                }
                                if((hour_h==2)&&(hour_l>3))
                                {
                                        hour_h=0;
                                        hour_l=0;
                                }
                                hour=hour_h*16+hour_l;
                                write_sfm(4,hour);
                                LCD_writecom(0x80+0x40+5);
                                break;
                        case 4:        date++;
                                if(date==8)
                                date=1;
                                display2(date);
                                LCD_writecom(0x80+14);
                                break;
                        case 5:       
                                day_h=day/16;
                                day_l=day%16;
                                if(day_h==3)
                                {
                                if(day_l>1)
                                {
                                        day_h=0;
                                        day_l=1;
                                }
                                }
                                day_l++;
                                if(day_l==10)
                                {
                                        day_l=0;
                                        day_h++;
                                }
                                if((day_h==3)&&(day_l>1))
                                {
                                        day_h=0;
                                        day_l=1;
                                }
                                day=day_h*16+day_l;
                                write_nyrx(9,day);
                                LCD_writecom(0x80+10);
                                break;
                        case 6:
                                month_h=month/16;        //月++
                                month_l=month%16;
                                if(month_h==1)
                                {
                                if(month_l>2)
                                {
                                        month_h=0;
                                        month_l=1;
                                }
                                }
                                month_l++;
                                if(month_l==10)
                                {
                                        month_l=0;
                                        month_h++;
                                }
                                if((month_h==1)&&(month_l>2))
                                {       
                                        month_h=0;       
                                        month_l=1;       
                                }       
                                month=month_h*16+month_l;       
                                write_nyrx(6,month);       
                                LCD_writecom(0x80+7);       
                                break;       
                        case 7:
                                year_h=year/16;       
                                year_l=year%16;       
                                year_l++;       
                                if(year_l==10)       
                                {       
                                        year_l=0;       
                                        year_h++;       
                                }       
                                if(year_h==6)       
                                year_h=0;       
                                year=year_h*16+year_l;       
                                write_nyrx(3,year);       
                                LCD_writecom(0x80+4);       
                                break;


                        }       
                }       
        }       
        if(K3==0)        //K1按下进行K3按键检测       
        {       
        delay1ms(5);       
        if(K3==0)       
        {       
                while(!K3);       
                switch(K1num)       
                {       
                case 1:
                        sec_h=sec/16;       
                        sec_l=sec%16;       
                        sec_l--;       
                        if(sec_l==-1)       
                        {       
                                sec_l=9;       
                                sec_h--;       
                        }       
                        if(sec_h==-1)       
                        sec_h=5;       
                        sec=sec_h*16+sec_l;       
                        write_sfm(10,sec);       
                        LCD_writecom(0x80+0x40+11);       
                        break;       
                case 2:
                        min_h=min/16;       
                        min_l=min%16;       
                        min_l--;       
                        if(min_l==-1)       
                        {       
                                min_l=9;       
                                min_h--;       
                        }       
                        if(min_h==-1)       
                        min_h=5;       
                        min=min_h*16+min_l;       
                        write_sfm(7,min);       
                        LCD_writecom(0x80+0x40+8);       
                        break;       
                case 3:
                        hour_h=hour/16;       
                        hour_l=hour%16;       
                        hour_l--;       
                        if(hour_l==-1)       
                        {       
                                hour_l=9;       
                                hour_h--;
                        }       
                        if(hour_h==-1)       
                        {       
                                hour_h=2;       
                                hour_l=3;       
                        }       
                        hour=hour_h*16+hour_l;       
                        write_sfm(4,hour);
                        LCD_writecom(0x80+0x40+5);       
                        break;       
                case 4:
                        date--;       
                        if(date==0)       
                        date=7;       
                        display2(date);       
                        LCD_writecom(0x80+14);       
                        break;       
                        case 5:        day_l--;       
                        if(day_l==-1)
                        {       
                                day_l=9;       
                                day_h--;       
                        }       
                        if(day_h==-1)       
                        {
                                day_h=3;       
                                day_l=1;       
                        }       
                        if((day_h==0)&&(day_l==0))       
                        {       
                                day_h=3;       
                                day_l=1;       
                        }       
                        day=day_h*16+day_l;       
                        write_nyrx(9,day);       
                        LCD_writecom(0x80+10);       
                        break;       
                case 6:
                        month_l--;       
                        if(month_l==-1)       
                        {       
                                month_l=9;       
                                month_h--;       
                        }       
                        if(month_h==-1)       
                        {       
                                month_h=1;       
                                month_l=2;       
                        }       
                        if((month_h==0)&&(month_l==0))       
                        {       
                                month_h=1;       
                                month_l=2;       
                        }       
                        month=month_h*16+month_l;       
                        write_nyrx(6,month);       
                        LCD_writecom(0x80+7);       
                        break;       
                case 7:
                        year_h=year/16;       
                        year_l=year%16;       
                        year_l--;       
                        if(year_l==-1)       
                        {       
                                year_l=9;       
                                year_h--;
                        }       
                        if(year_h==-1)       
                        year_h=5;       
                        year=year_h*16+year_l;       
                        write_nyrx(3,year);       
                        LCD_writecom(0x80+4);       
                        break;


                }
        }       
        }
        if(K4==0)        //K1按下进行K2按键检测
        {
                delay1ms(5);
                if(K4==0)
                {
                        while(!K4);
                        LCD_writecom(0x0c);
                               
                                DS1302_initW();        //将设置的时间日期等写入DS1302中
                                K1num=0;        //K1按键计数清零
                                k=0;        //时间继续走                       
                       
                }       
        }       
        }
               
}

void main()
{
        display1();        //初始化屏幕显示
//        DS1302_initW();        //初始化时间日期
//        DS1302_initR();        //读取时间日期

        while(1)
        {

                keyscan();

               
        }
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:111634 发表于 2017-5-12 09:08 | 只看该作者
本帖最后由 zl2168 于 2017-5-12 12:15 编辑

冗长程序帖出来,没人有时间看的,只有自己对照正确成功案例,在理解的基础上,自己纠错,并获得收获和进步。给你介绍:
实例91  具有校正功能的时钟1302(LCD1602显示)
实例61 LCD1602显示屏显示.rar (49.26 KB, 下载次数: 8)

Proteus仿真一下,确认有效。
以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1。书中电路和程序设计有详细说明,程序语句条条有注解。
仿真电路和Hex文件能在清华出版社网站免费下载,程序源代码只能到书上看了。到图书馆借,或到新华书店翻阅,或到网上书店打折购买。
回复

使用道具 举报

板凳
ID:199869 发表于 2017-5-12 10:42 | 只看该作者
同问。怀疑是没练好?
回复

使用道具 举报

地板
ID:162136 发表于 2017-5-12 11:21 | 只看该作者
程序我下载是正常可以调时间和走时的,可能是你板上有一上跳线没有接上,如果是普中开发箱,在箱盖那里有说明。
回复

使用道具 举报

5#
ID:162136 发表于 2017-5-12 15:29 | 只看该作者
bayga456 发表于 2017-5-12 11:21
程序我下载是正常可以调时间和走时的,可能是你板上有一上跳线没有接上,如果是普中开发箱,在箱盖那里有说 ...

正在学习仿真,第一次做仿真。哈哈。这个就是楼主提供程序的仿真。LCD1602+DS1302显示时间。

20170512 LCD1602 DS1302.rar

40.81 KB, 下载次数: 6

回复

使用道具 举报

6#
ID:199861 发表于 2017-5-12 17:15 | 只看该作者
同问,不懂!
回复

使用道具 举报

7#
ID:195124 发表于 2017-5-12 22:35 | 只看该作者
被烧了吧
回复

使用道具 举报

8#
ID:199790 发表于 2017-5-12 22:59 | 只看该作者
bayga456 发表于 2017-5-12 11:21
程序我下载是正常可以调时间和走时的,可能是你板上有一上跳线没有接上,如果是普中开发箱,在箱盖那里有说 ...

确实是普中的,接线也是按照他们的,你下载进去多次调时没有问题吗?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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