LCD1602液晶秒表C51程序

发布者:Enchanted2021最新更新时间:2015-01-22 来源: 51hei关键字:LCD1602  液晶秒表  C51程序 手机看文章 扫描二维码
随时随地手机看文章

此程序是基于51hei单片机开发板上面写的,如需要移植到自己的电路上,修改相应的端口即可  ***********************************************************************

  * @file     main.c
  * @author   xr
  * @date     2014年5月8日22:11:33 -- 2014年5月9日12:03:49
  * @version  V1.2.3
  * @brief    LCD1602液晶跑表  单片机STC89C52RC MCU 晶振 11.0592MHZ
  ***********************************************************************
  */
  
#include
 
/* 系统时钟 */
#define SYS_XTAL (11059200UL/12)
 
/* 定时器T0重载值 */
unsigned char thr0, tlr0;
unsigned char thr1, tlr1;
/* 跑表计数 */
unsigned char timer[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; //分别表示跑表的各个位上的数字
bit flag10ms = 0;
extern bit stopflag;//跑表走停标志位
 
extern void InitalLCD1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str);
extern void KeyDriver();
extern void KeyScan();
 
void DisplayTimer();
void ConfigTimer0(unsigned int xms);
void ConfigTimer1(unsigned int xms);
 
/* 主函数main() */
void main(void)
{  
    ConfigTimer0(10);                    //定时10ms
    ConfigTimer1(1);
    InitalLCD1602();
    
    LcdShowStr(0, 0, "stopwatch");
    LcdShowStr(2, 1, "0000000.00s");     //液晶初始化显示
    LcdShowStr(10, 0, "stop!");
    
    while (1)
    {
        KeyDriver();
        DisplayTimer();
        
        if ((flag10ms == 1) && (stopflag == 1))
        {
            flag10ms = 0;
            timer[0]++;
            if (timer[0] > 9)
            {
                timer[0] = 0;
                timer[1]++;
                if (timer[1] > 9)
                {
                    timer[1] = 0;
                    timer[2]++;
                    if (timer[2] > 9)
                    {
                        timer[2] = 0;
                        timer[3]++;
                        if (timer[3] > 9)
                        {
                            timer[3] = 0;
                            timer[4]++;
                            if (timer[4] > 9)
                            {
                                timer[4] = 0;
                                timer[5]++;
                                if (timer[5] > 9)
                                {
                                    timer[5] = 0;
                                    timer[6]++;
                                    if (timer[6] > 9)
                                    {
                                        timer[6] = 0;
                                        timer[7]++;
                                        if (timer[7] > 9)
                                        {
                                            timer[7] = 0;
                                            timer[8]++;
                                            if (timer[8] > 9)
                                            {
                                                timer[8] = 0;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
 
/* 将跑表时间显示到液晶上 */
void DisplayTimer()
{
    unsigned char str[20];
    /* 分解timer */
    str[0] = timer[8] + '0';
    str[1] = timer[7] + '0';
    str[2] = timer[6] + '0';
    str[3] = timer[5] + '0';
    str[4] = timer[4] + '0';
    str[5] = timer[3] + '0';
    str[6] = timer[2] + '0';
    str[7] = '.';
    str[8] = timer[1] + '0';
    str[9] = timer[0] + '0';
    str[10] = '\0';
    LcdShowStr(2, 1, str);
}
 
/* 定时器T0配置 */
void ConfigTimer0(unsigned int xms)
{
    unsigned long tmp;
    tmp = (SYS_XTAL * xms) / 1000;
    tmp = 65536-tmp + 18;
    thr0 = (unsigned char)(tmp >> 8) ;
    tlr0 = (unsigned char)tmp;
    TMOD &= 0xF0;                   //清零T0控制位
    TMOD |= 0x01;                   //定时器方式1
    TH0 = thr0;
    TL0 = tlr0;
    TR0 = 1;                        //开启timer0
    ET0 = 1;                        //开启T0中断
    EA  = 1;                        //开启总中断
}
 
/* 配置定时器T1 */
void ConfigTimer1(unsigned int xms)
{
    unsigned long tmp;
    tmp = (SYS_XTAL * xms) / 1000;
    tmp = 65536 - tmp + 18;
    thr1 = (unsigned char)(tmp >> 8);
    tlr1 = (unsigned char)tmp;
    TMOD &= 0x0F;
    TMOD |= 0x10;
    TH1 = thr1;
    TL1 = tlr1;
    TR1 = 1;
    ET1 = 1;
    EA  = 1;
}
 
/* 定时器T0中断服务 */
void Timer0_ISP() interrupt 1
{   
    TH0 = thr0;
    TL0 = tlr0;
    flag10ms = 1; //定时10ms
}
 
/* 定时器T1中断服务 */
void Timer1_ISP() interrupt 3
{
    TH1 = thr1;
    TL1 = tlr1; //定时1ms  
    KeyScan();
}
 
 /**
  ***********************************************************************
  * @file     Lcd1602.c
  * @author   xr
  * @date     2014年5月7日13:33:17
  * @version  V1.2.3
  * @brief    LCD1602液晶底层驱动
  ***********************************************************************
  */
  
#include
 
//LCD1602_IO
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_EN = P1^5;
 
#define LCD1602_DB P0
 
/* 液晶忙碌等待 */
void LCD1602Wait()
{
    unsigned char sta;
    LCD1602_DB = 0xFF;//总线拉高,检测液晶状态字
    
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    
    do
    {
        LCD1602_EN = 1;
        sta = LCD1602_DB;
        LCD1602_EN = 0;//避免液晶输出数据
    } while (sta & 0x80);//状态字最高位STA7 == 0空闲,1忙碌
}
 
/* 液晶写命令 */
void LCD1602WriteCmd(unsigned char cmd)
{
    LCD1602Wait();
    
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_EN = 0;
    LCD1602_DB = cmd;
    LCD1602_EN = 1;
    LCD1602_EN = 0;
}
 
/* 液晶写数据 */
void LCD1602WriteData(unsigned char dat)
{
    LCD1602Wait();
    
    LCD1602_RS = 1;
    LCD1602_RW = 0;
    LCD1602_EN = 0;
    LCD1602_DB = dat;
    LCD1602_EN = 1;
    LCD1602_EN = 0;
}
 
/* 液晶初始化 */
void InitalLCD1602()
{
    LCD1602WriteCmd(0x38);
    LCD1602WriteCmd(0x0C);
    LCD1602WriteCmd(0x06);
    LCD1602WriteCmd(0x01);//清屏
}
 
/* 写数据到液晶上,字符串str,坐标(x, y),地址addr */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str)
{
    unsigned char addr;
    
    if (y == 0)
    {
        addr = 0x00 + x;
    }
    else
    {
        addr = 0x40 + x;
    }
    LCD1602WriteCmd(addr | 0x80);
    while (*str != '\0')
    {
        LCD1602WriteData(*str++);
    }
}
 
 /**
  ***********************************************************************
  * @file     keyboard.c
  * @author   xr
  * @date     2014年5月8日22:11:33 -- 2014年5月9日12:03:49
  * @version  V1.2.3
  * @brief    按键驱动  单片机STC89C52RC MCU 晶振 11.0592MHZ
  ***********************************************************************
  */
  
#include
 
/* 按键输出输入端口定义 */
sbit KEY_IN1 = P2^4;
sbit KEY_IN2 = P2^5;
sbit KEY_IN3 = P2^6;
sbit KEY_IN4 = P2^7;
sbit KEY_OUT1 = P2^3;
sbit KEY_OUT2 = P2^2;
sbit KEY_OUT3 = P2^1;
sbit KEY_OUT4 = P2^0;
 
extern unsigned char timer[9]; //分别表示跑表的各个位上的数字
/* 按键当前状态 */
unsigned char volatile keySta[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};
/* 按键对应标准PC键盘编码 */
const unsigned char code keyCodeMap[4][4] = {
                                 {'1', '2', '3', 0x26},   /* 数字键 1, 2, 3 和 向上键 */
                                 {'4', '5', '6', 0x25},   /* 数字键 4, 5, 6 和 向左键 */
                                 {'7', '8', '9', 0x28},   /* 数字键 7, 8, 9 和 向下键 */
                                 {'0', 0x1B, 0x0D, 0x27}  /* 数字键 0 和 向右键 */
                    };
 
bit stopflag = 0;//跑表走停标志位 0 停止,1运行
                    
void KeyAction(unsigned char keycode);
void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str);
                    
/* 按键驱动函数 */
void KeyDriver()
{
    /* 上一次按键的备份值 */
    static unsigned char keybackup[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};
    unsigned char i, j;
 
    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            if (keySta[i][j] != keybackup[i][j])  //当前按键状态和上一次的按键状态不同
            {  //按键有动作
                if (keybackup[i][j] != 0) //上一次按键是弹起
                {
                    KeyAction(keyCodeMap[i][j]); //当前按键是想、按下
                }
                keybackup[i][j] = keySta[i][j]; //备份当前按键值
            }
        }
    }
}    
 
/* 按键扫描函数 */
void KeyScan()
{
   unsigned char i = 0;
   static unsigned char keyout = 0;//按键行索引
   static unsigned char keybuf[4][4] = {{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, 
                                        {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}        
                                        };
   /* 按键消抖 */
   keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN1;
   keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN2;
   keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN3;
   keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN4;
   
   /* 更新按键的值 */
   for (i = 0; i < 4; i++)
   {
        if ((keybuf[keyout][i] & 0x1F) == 0x1F)
        {
            //五次检测按键的值都是1
            keySta[keyout][i] = 1;
        }
        else if ((keybuf[keyout][i] & 0x1F) == 0x00)
        {
            //五次检测的按键值都是0
            keySta[keyout][i] = 0;
        }
   }
   /* 按键行索引++ */
   keyout++;
   keyout &= 0x03;//到4归零
   /* 根据按键索引选择行按键进行扫描 */
   switch (keyout)
   {
       case 0: KEY_OUT1 = 0; KEY_OUT4 = 1;//选择第一行按键
       case 1: KEY_OUT2 = 0; KEY_OUT1 = 1;
       case 2: KEY_OUT3 = 0; KEY_OUT2 = 1;
       case 3: KEY_OUT4 = 0; KEY_OUT3 = 1;
       default: break;
   }
}
 
/* 按键动作函数 */
void KeyAction(unsigned char keycode)
{
    unsigned char i = 0;
    
    if (keycode == 0x1B)       //ESC
    {
        /* 跑表复位 */
        stopflag = 0;
        for (i = 0; i < 9; i++)
        {
            timer[i] = 0;
        }
        LcdShowStr(2, 1, "0000000.00s");
        LcdShowStr(10, 0, "reset!");
    }
    else if (keycode == 0x0D)  //回车键 跑表走停
    {
        if (stopflag == 0)
        {
            stopflag = 1;
            LcdShowStr(10, 0, "start!");
        }
        else
        {
            stopflag = 0;
            LcdShowStr(10, 0, "stop! "); //多写入一个空格
        }
    }
}
关键字:LCD1602  液晶秒表  C51程序 引用地址:LCD1602液晶秒表C51程序

上一篇:Proteus--51系列汇编
下一篇:32*32LED点阵屏的KeilC51程序(基于STC12C5A60S2,8个大字)

推荐阅读最新更新时间:2024-03-16 13:51

51单片机6自由度机械臂调试程序,带LCD1602PWM显示
以前学习51的时候为了调试机械臂角度编写的程序,用在开发板上也比较方便,但是由于是普通的舵机,不是总线的,所以需要自己洞洞板焊一个供电带电路。 单片机源程序如下: #include reg52.h #include lcd1602.h #define uchar unsigned char #define uint unsigned int sbit duoji0=P2^0; //PWM输出 sbit duoji1=P2^1; sbit duoji2=P2^2; sbit duoji3=P2^3; sbit duoji4=P3^1; sbit duoji5=P3^0; #define GPIO_KEY P1
[单片机]
实时时钟芯片DS1302的C51程序列子
/*********************************************************************/ /* 实时时钟模块 时钟芯片型号:DS1302 */ /*/ /*********************************************************************/ sbit T_CLK = P2^7; /*实时时钟时钟线引脚 */ sbit T_IO = P1^4; /*实时时钟数据线引脚 */ sbit T_RST = P1^5; /*实时时钟复位线引脚 */ /*****************************************
[单片机]
51单片机驱动ADC0832模数转换程序-lcd1602显示
/*这个芯应用不多*/ #include reg51.h #define uchar unsigned char #define uint unsigned int uchar Chan0Value,Chan1Value; sbit RS=P1^0; //1602各控制脚 sbit RW=P1^1; sbit EN=P1^2; sbit Cs0832= P2^0; //0832各控制脚 sbit Clk0832= P3^6; sbit Di0832= P3^7; sbit Do0832= P3^7; void delay1ms(unsigned int ms)//延时1毫秒(不够精确的) { int i,j; for(
[单片机]
LCD1602&DS1302时钟测试程序+仿真图分享
comments : 1、八线制驱动LCD1602B:PB0-PB7为数据线,PD3/PD4/PD6控制LCD1602B的RS,RW,EN。 2、设置和读取DS1302内部时钟,并通过LCD1602显示。 3、进行此实验请插上JP1、JP2的所有8个短路块,PC2、PC3、PC4、PC7短路块。 4、DS1302芯片接口占用JTAG仿真接口,在做实验时需要关闭mega16的JTAG功能,否则 不正常显示。 仿真原理图如下(proteus仿真工程文件可到本帖附件中下载) 单片机源程序如下: #include iom16v.h #include macros.h #include ds1302.h #include L
[单片机]
<font color='red'>LCD1602</font>&DS1302时钟测试<font color='red'>程序</font>+仿真图分享
AVR M16 实验之二 LCD1602显示
/********************************************************************** * 文件名称: main.c * 程序作者: kidcao1987 * 程序版本: V1.0 * 功能描述: 装好LCD1602,用在LCD1602上显示,这里建议再外接上电源。 This a LCD demo! www.CEPARK.com Keep moving!! By:kicao1987 * 编译器:WinAVR-20090313 * 芯片:ATmega16,外部11.0592MHZ晶振 * 技术支持:http://bbs.cepark.com *****************
[单片机]
msp430单片机控制lcd1602显示C程序
//MSP430写的1602液晶显示程序2011/8/26//硬件连接 //P4 数据口 P3.7---E P3.6---RW P3.5----RS #include msp430x14x.h #define uint unsigned int #define rw(x) P3OUT=(P3OUT&(~BIT6))|(x?BIT6:0); unsigned char table0 = hankouxueyuan ; unsigned char table1 = dianzisheji ; //**************延时**
[单片机]
单片机MQ-2烟雾检测+ADC0809 AD转换+lcd1602显示程序
单片机源程序如下: /*============================================================ // //程序编写:刘先生 接线:D0--D7接P0.0-P0.7 ST---P2.3 EOC--P2.2 OE---P2.1 CLK--P2.0 本程序源码只供学习参考,不得应用于商业用途,如有需要请联系作者。 =============================================================*/ #include reg52.H //器件配置文件 #include intr
[单片机]
单片机MQ-2烟雾检测+ADC0809 AD转换+<font color='red'>lcd1602</font>显示<font color='red'>程序</font>
C51 INT0中断程序
//INT0中断程序 #include reg52.h void delay(unsigned int x); main() { IT0=1; //下降沿触发 EX0=1; //开INT0中断 EA=1; P1=0xff; while(1) { } } void int0() interrupt 0 { IT0=0; //关中断, P1=~P1; delay(20000); //延时 IT0=1; //开中断 } void delay(unsigned int x) //延时 { unsigned int i; for(i=0;i x;i++) {} }
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved