找回密码
 立即注册

QQ登录

只需一步,快速开始

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

LCD1602电子时钟

[复制链接]
跳转到指定楼层
楼主
/*******************************************************************************
* 实验名                           : 定时器实验
* 使用的IO             :
* 实验效果       :1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒,按K2选择
*选择设置加1。
*        注意                                        :
*******************************************************************************/
#include<reg51.h>       
#include"lcd.h"
sbit K1=P3^0;
sbit K2=P3^1;
sbit K3=P3^2;
void Delay1ms(unsigned int c);
void TimerConfiguration();
void Int0Configuration();
unsigned char Time;                        //用来计时间的值
unsigned char SetPlace;                //设置修改位
/*******************************************************************************
* 函 数 名         : main
* 函数功能                   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void main(void)
{
        unsigned char hour=13,minute=14,second=00;
        unsigned char H2[]="  I LOVE YOU!!! ";                           //可以改成任意16个字符。
        unsigned int i;
        TimerConfiguration();
        Int0Configuration();
        LcdInit();
        LcdWriteCom(0x84);
        LcdWriteData('0'+hour/10);
        LcdWriteData('0'+hour%10);
        LcdWriteData(':');
        LcdWriteData('0'+minute/10);
        LcdWriteData('0'+minute%10);
        LcdWriteData(':');
        LcdWriteData('0'+second/10);
        LcdWriteData('0'+second%10);
        LcdWriteCom(0xc0);
        for(i=0;i<16;i++)                                  //第2行显示的字符
        {   
                LcdWriteData(H2);                 
        }
        while(1)
        {
                if(TR0==0)
                {        if(K1==0)                        //检测按键K1是否按下
                        {
                                Delay1ms(10);        //消除抖动
                                if(K1==0)
                                {  
                                        SetPlace++;
                                        Delay1ms(100);
                                        if(SetPlace>=3)
                                                SetPlace=0;                                       
                                }
                                while((i<50)&&(K1==0))         //检测按键K1是否松开
                                {
                                        Delay1ms(1);
                                        i++;
                                }
                                i=0;                        
                        }
                        switch(SetPlace)
                                {case 0 :
                                        {LcdWriteCom(0x8b);                   //定位置
                                         LcdWriteCom(0x0f);
                                         Delay1ms(100);
                                         if(K2==0)                //检测按键K2是否按下
                                                {
                                                Delay1ms(10);        //消除抖动
                                                if(K2==0)
                                                        {
                                                        second++;
                                                        Delay1ms(100);
                                                        if(second>=60)
                                                        second=0;
                               
                                                        }
                                                }
                                         LcdWriteCom(0x8a);                   //定位置
                                         LcdWriteData('0'+second/10);
                                         LcdWriteData('0'+second%10);
                                         LcdWriteCom(0x8b);
                                         }break;
                                case 1 :
                                        {LcdWriteCom(0x88);                   //定位置
                                         LcdWriteCom(0x0f);
                                         Delay1ms(100);
                                         if(K2==0)                //检测按键K2是否按下
                                                {
                                                Delay1ms(10);        //消除抖动
                                                if(K2==0)
                                                        {
                                                        minute++;
                                                        Delay1ms(100);
                                                        if(minute>=60)
                                                        minute=0;
                               
                                                        }
                                                }
                                         LcdWriteCom(0x87);                   //定位置
                                         LcdWriteData('0'+minute/10);
                                         LcdWriteData('0'+minute%10);
                                         LcdWriteCom(0x88);
                                         }break;
                                case 2 :
                                        {LcdWriteCom(0x85);                   //定位置
                                         LcdWriteCom(0x0f);
                                         Delay1ms(100);
                                         if(K2==0)                //检测按键K2是否按下
                                                {
                                                Delay1ms(10);        //消除抖动
                                                if(K2==0)
                                                        {
                                                        hour++;
                                                        Delay1ms(100);
                                                        if(hour>=24)
                                                        hour=0;
                               
                                                        }
                                                }
                                         LcdWriteCom(0x84);                   //定位置
                                         LcdWriteData('0'+hour/10);
                                         LcdWriteData('0'+hour%10);
                                         LcdWriteCom(0x85);
                                         }break;
                                }   
                }       
               
                else
                {
                LcdWriteCom(0x0c);         
                if(Time>=20)         //一秒钟来到改变数值
                {
                        Time=0;
                        second++;
                        if(second==60)
                        {
                                second=0;
                                minute++;
                                if(minute==60)
                                {
                                        minute=0;
                                        hour++;
                                        if(hour==24)
                                        {
                                                hour=0;       
                                        }
                                }                               
                        }                                       
                }       
            //--显示时钟--//
                LcdWriteCom(0x84);
                LcdWriteData('0'+hour/10);
                LcdWriteData('0'+hour%10);
                LcdWriteData(':');
                LcdWriteData('0'+minute/10);
                LcdWriteData('0'+minute%10);
                LcdWriteData(':');
                LcdWriteData('0'+second/10);
                LcdWriteData('0'+second%10);
                }
        }                               
}
/*******************************************************************************
* 函 数 名       : Delay1ms()
* 函数功能                 : 延时1ms
* 输    入       : c
* 输    出       : 无
*******************************************************************************/                  
void Delay1ms(unsigned int c)   //误差 0us
{
    unsigned char a,b;
        for (; c>0; c--)
        {
                for(b=199;b>0;b--)
                {
                        for(a=1;a>0;a--);
                }
        
        }
   
}
/*******************************************************************************
* 函 数 名         : TimerConfiguration()
* 函数功能                   : 配置定时器值
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/                  
void TimerConfiguration()
{
    TMOD = 0x01;         //选择工作方式1
    TH0 = 0x3C;                 //设置初始值         50ms
    TL0 = 0xB0;
    EA = 1;                         //打开总中断
    ET0 = 1;                 //打开定时器0中断
    TR0 = 1;                 //启动定时器0
}
/*******************************************************************************
* 函 数 名         : Timer0()
* 函数功能                   : 定时器0中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/                  
void Timer0() interrupt 1
{
        TH0 = 0x3C;         //设置初始值  50ms
    TL0 = 0xB0;
        Time++;
}
/*******************************************************************************
* 函 数 名         : Int0Configuration()
* 函数功能                   : 配置外部中断0
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/                  
void Int0Configuration()
{
        //设置INT0
        IT0=1;//跳变沿出发方式(下降沿)
        EX0=1;//打开INT0的中断允许。
        EA=1;//打开总中断       
}
/*******************************************************************************
* 函 数 名         : Int0() interrupt 0
* 函数功能                   : 外部中断0的中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/                  
void Int0() interrupt 0                 
{
        Delay1ms(10);
        if(K3==0)
        {
                TR0=~TR0;
                SetPlace=0;
        }
}
书上原来的程序,可以实现1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒,按K2选择加1。 但是进入设置后,正在设置的哪一位没有光标提示,不够人性化。我在原程序的基础上,加以修改,进入设置功能后,正在设置哪一位,有了光标闪烁提示。

IMG_20170226_103248.jpg (1.24 MB, 下载次数: 129)

IMG_20170226_103248.jpg

IMG_20170226_103248_1.jpg (1.24 MB, 下载次数: 98)

IMG_20170226_103248_1.jpg

IMG_20170226_103248_6.jpg (1.23 MB, 下载次数: 104)

IMG_20170226_103248_6.jpg

IMG_20170226_103255.jpg (1.28 MB, 下载次数: 110)

IMG_20170226_103255.jpg

IMG_20170226_103255_2.jpg (1.3 MB, 下载次数: 132)

IMG_20170226_103255_2.jpg

IMG_20170226_103255_7.jpg (1.28 MB, 下载次数: 96)

IMG_20170226_103255_7.jpg

IMG_20170226_103307.jpg (1.41 MB, 下载次数: 91)

IMG_20170226_103307.jpg

IMG_20170226_103309.jpg (1.4 MB, 下载次数: 111)

IMG_20170226_103309.jpg

秒1.jpg (1.24 MB, 下载次数: 131)

秒1.jpg

秒2.jpg (1.25 MB, 下载次数: 89)

秒2.jpg

秒3.jpg (1.29 MB, 下载次数: 109)

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

使用道具 举报

沙发
ID:161933 发表于 2017-2-26 21:22 | 只看该作者
我把这个 程序 在实验板上运行了4个小时,感觉慢了好几分钟,请大家看看,误差产生在哪里?
回复

使用道具 举报

板凳
ID:1 发表于 2017-2-27 00:27 | 只看该作者
慢了好几分钟,可能是由晶振的误差导致的。你可以在软件中进行补偿。楼主 lcd.h 能帖出来一下吗?
回复

使用道具 举报

地板
ID:161933 发表于 2017-3-1 18:15 | 只看该作者
admin 发表于 2017-2-27 00:27
慢了好几分钟,可能是由晶振的误差导致的。你可以在软件中进行补偿。楼主 lcd.h 能帖出来一下吗?

#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义            
**********************************/
#define LCD1602_4PINS

/**********************************
包含头文件
**********************************/
#include<reg51.h>

//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint
#define uint unsigned int
#endif

/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;

/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c);   //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/       
void LcdWriteData(uchar dat)        ;
/*LCD1602初始化子程序*/               
void LcdInit();                                                  

#endif
回复

使用道具 举报

5#
ID:3212 发表于 2017-3-1 20:42 | 只看该作者
admin 发表于 2017-2-27 00:27
慢了好几分钟,可能是由晶振的误差导致的。你可以在软件中进行补偿。楼主 lcd.h 能帖出来一下吗?

应该是你用了国产的1302,再使用了12pF的晶振的关系。这个情况我碰到两次,都是在晶振引脚对地加一个小电容解决的。一次加了30p的(那时候没有再小得了),另一次加12p的。都能把精度提高到1分钟/月的级别。
回复

使用道具 举报

6#
ID:3212 发表于 2017-3-1 20:43 | 只看该作者
csz9981 发表于 2017-2-26 21:22
我把这个 程序 在实验板上运行了4个小时,感觉慢了好几分钟,请大家看看,误差产生在哪里?

应该是你用了国产的1302,再使用了12pF的晶振的关系。这个情况我碰到两次,都是在晶振引脚对地加一个小电容解决的。一次加了30p的(那时候没有再小得了),另一次加12p的。都能把精度提高到1分钟/月的级别。
回复

使用道具 举报

7#
ID:161933 发表于 2017-3-2 07:37 来自触屏版 | 只看该作者
学习了,
回复

使用道具 举报

8#
ID:99130 发表于 2017-3-3 13:27 | 只看该作者
在晶振的两只脚加上30PF左右的电容,对地。快了则加大电容容量,慢了则减小
回复

使用道具 举报

9#
ID:161933 发表于 2017-5-18 21:26 | 只看该作者
middfat 发表于 2017-3-1 20:42
应该是你用了国产的1302,再使用了12pF的晶振的关系。这个情况我碰到两次,都是在晶振引脚对地加一个小电 ...

我是用的 定时器0 中断函数 实现计时的,50MS一计数,20计数为1秒,我实验了一下,26分钟,慢了87秒。平均慢3.34秒/分钟。

可以通过减少定时器初值,缩短定时器,计数周期的方法,提高走时速度吧?大家遇到这种情况,都 是怎样处理的?

请教了。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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