标题: LCD1602电子时钟 [打印本页]
作者: csz9981 时间: 2017-2-26 13:07
标题: 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_1.jpg
(1.24 MB, 下载次数: 98)
-
IMG_20170226_103248_6.jpg
(1.23 MB, 下载次数: 104)
-
IMG_20170226_103255.jpg
(1.28 MB, 下载次数: 110)
-
IMG_20170226_103255_2.jpg
(1.3 MB, 下载次数: 132)
-
IMG_20170226_103255_7.jpg
(1.28 MB, 下载次数: 96)
-
IMG_20170226_103307.jpg
(1.41 MB, 下载次数: 91)
-
IMG_20170226_103309.jpg
(1.4 MB, 下载次数: 111)
-
秒1.jpg
(1.24 MB, 下载次数: 131)
-
秒2.jpg
(1.25 MB, 下载次数: 89)
-
秒3.jpg
(1.29 MB, 下载次数: 109)
作者: csz9981 时间: 2017-2-26 21:22
我把这个 程序 在实验板上运行了4个小时,感觉慢了好几分钟,请大家看看,误差产生在哪里?
作者: admin 时间: 2017-2-27 00:27
慢了好几分钟,可能是由晶振的误差导致的。你可以在软件中进行补偿。楼主 lcd.h 能帖出来一下吗?
作者: csz9981 时间: 2017-3-1 18:15
#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
作者: middfat 时间: 2017-3-1 20:42
应该是你用了国产的1302,再使用了12pF的晶振的关系。这个情况我碰到两次,都是在晶振引脚对地加一个小电容解决的。一次加了30p的(那时候没有再小得了),另一次加12p的。都能把精度提高到1分钟/月的级别。
作者: middfat 时间: 2017-3-1 20:43
应该是你用了国产的1302,再使用了12pF的晶振的关系。这个情况我碰到两次,都是在晶振引脚对地加一个小电容解决的。一次加了30p的(那时候没有再小得了),另一次加12p的。都能把精度提高到1分钟/月的级别。
作者: csz9981 时间: 2017-3-2 07:37
学习了,
作者: 越快乐越堕落 时间: 2017-3-3 13:27
在晶振的两只脚加上30PF左右的电容,对地。快了则加大电容容量,慢了则减小
作者: csz9981 时间: 2017-5-18 21:26
我是用的 定时器0 中断函数 实现计时的,50MS一计数,20计数为1秒,我实验了一下,26分钟,慢了87秒。平均慢3.34秒/分钟。
可以通过减少定时器初值,缩短定时器,计数周期的方法,提高走时速度吧?大家遇到这种情况,都 是怎样处理的?
请教了。
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |