用 LCD1602 显示的秒表
扫描二维码
随时随地手机看文章
给 STC89C51 安一个 LCD1602 液晶显示器。写一段程序,使得 STC89C51 有计时、显示功能。
当给 STC89C51 一个连续的高电平时,单片机开始计时,同时在显示器上显示计时的秒数;
当结束高电平时,计时停止,但是显示器上保留计时数值。
当下一个高电平来到,显示器接着上次的时间继续计时。
简单的讲就是说显示器显示几个间断的高电平持续的时间之和。
再设一个脚实现清零。
这个题目,实际上就是设计一个采用液晶显示的秒表。
悬赏分:100 | 解决时间:2011-3-28 09:42
原题网址:http://zhidao.baidu.com/question/237573382.html
================================================
回答:
LCD1602 和 51单片机的之间,如果采用常规接法,共需要 11 条线;
如果不用读出,RW 就可以直接接地,使 LCD 永远处于写入状态,这样的电路如下所示:
如果觉得 LCD1602 占用单片机的引脚太多,可以只用 6 条引线来实现对液晶屏的驱动。
驱动 LCD1602,很简单,关键是要写好“写指令”和“写数据”两个函数,其它的设置、显示等等,就不难了。
晶振选用 11.0592 / 12MHz,均可。
实现脉冲长度计时、显示的程序如下:
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define LCD_IO P2
sbit LCD_RS = P3^0;
sbit LCD_RW = P3^7;
sbit LCD_EN = P3^1;
sbit sw1 = P3^2;
sbit sw2 = P3^3;
uchar count;
uint sec;
uchar code LCD_line1[] = "Pulse Continued:";
uchar code LCD_line2[] = " 00000 s ";
//---------------------------------------------------
void delay(uint z)
{
uint x, y;
for(x = z; x > 0; x--) for(y = 10; y > 0; y--);
}
//---------------------------------------------------
void W_LCD_Com(uchar com) //写指令
{
LCD_RS = 0; LCD_EN = 0; // LCD_RS和R/W同时为低电平时,可以写入指令
LCD_IO = com; delay(5); //下面用EN输入一个高脉冲
LCD_EN = 1; delay(5); LCD_EN = 0;
}
//---------------------------------------------------
void W_LCD_Dat(uchar dat) //写数据
{
LCD_RS = 1; LCD_EN = 0; // LCD_RS为高,LCD_RW为低时,可以写入数据
LCD_IO = dat; delay(5); //下面用EN输入一个高脉冲
LCD_EN = 1; delay(5); LCD_EN = 0;
}
//---------------------------------------------------
void W_LCD_STR(uchar *s) //写字符串
{
while(*s > 0) {W_LCD_Dat(*s); s++;}
}
//---------------------------------------------------
void init()
{
W_LCD_Com(0x38);
W_LCD_Com(0x0c);
W_LCD_Com(0x06);
W_LCD_Com(0x01);
W_LCD_Com(0x80); W_LCD_STR(LCD_line1);
W_LCD_Com(0xC0); W_LCD_STR(LCD_line2);
TMOD = 0x01;
TH0 = (65536 - 50000) / 256;
TL0 = (65536 - 50000) % 256;
TR0 = 1;
ET0 = 1;
EX0 = 1;
EX1 = 1;
PX1 = 1;
EA = 1;
}
//---------------------------------------------------
void W_LCD_X1_Dat(uint sec)
{
W_LCD_Com(0xc0 + 7);
W_LCD_Dat(0x30 + sec / 10000);
W_LCD_Dat(0x30 + (sec % 10000) / 1000);
W_LCD_Dat(0x30 + (sec % 1000) / 100);
W_LCD_Dat(0x30 + (sec % 100) / 10);
W_LCD_Dat(0x30 + sec % 10);
}
//---------------------------------------------------
void main()
{
init();
while(1);
}
//-------------------------------------------
void timer0() interrupt 1
{
TL0 = (65536-50000) % 256;
TH0 = (65536-50000) / 256;
count++;
if(count == 20) {
count = 0;
sec++;
W_LCD_X1_Dat(sec);
}
}
//-------------------------------------------
void X0_INT() interrupt 0
{
while(sw1 == 0);
}
//-------------------------------------------
void X1_INT() interrupt 2
{
while(sw2 == 0);
count = 0;
sec = 0;
W_LCD_X1_Dat(sec);
}