最新1602LCD显示秒表汇编汇总
1602lcd显示的秒表
目录1 概述 01.1 1602LCD研究的历史背景和意义 01.2 1602LCD研究的发展和现状 02 课题方案设计 02.1系统设计目的 02.2系统结构模块论证 (1)2.2.1 显示部分 (1)3 系统硬件设计 (1)3.1 总体设计 (1)3.2 单片机运行的最小系统 (2)3.2.1 电源电路 (2)3.2.2晶振电路 (2)3.2.3复位电路 (3)3.3 显示电路 (4)3.3.1引脚说明: (4)3.4 单片机STC89C52 (5)3.4.1主要特性 (5)3.4.2功能特性概述 (6)3.4.3主要引脚及芯片基本工作条件说明 (6)4 系统软件设计 (7)4.1 总流程图 (7)4.2 最小系统检测电路程序 (8)4.3 编程调试界面 (9)4.4 Proteus仿真结果 (9)5软硬件联调及调试结果 (10)5.1 实物图 (10)5.2 调试结果 (11)结束语 (12)参考文献 (12)附录2 1602LCD设计的秒表PCB图 (14)附录3 1602LCD设计的秒表Proteus仿真图 (15)附录4 1602LCD设计的秒表C语言程序清单 (15)附录5 基于单片机的1602LCD设计的秒表元器件目录表 (21)1 概述1.1 1602LCD研究的历史背景和意义LCD1602是16字乘以2行的字符型液晶模板。
其特点是:(1)位数多,可显示32位。
(2)显示内容丰富,可显示所有数字、字母、符号等192种ASCII码对应的字符。
(3)程序简单1.2 1602LCD研究的发展和现状液晶显示模块具有体积小、功耗低、显示内容丰富、超薄轻巧等优点,在袖珍式仪表和低功耗应用系统中得到广泛的应用。
目前字符型液晶显示模块已经是单片机应用设计中最常用的信息显示器件。
LCD1602液晶显示模块,它可以显示两行,每行16个字符,采用单+SV电源供电,外围电路配置简单,价格便宜,具有很高的性价比。
LCD1602-51单片机汇编程序.
1602汇编程序,刃单片机汇编程序,仅需修改引脚定义即可。
晶振大小12M,程序测试完全正确。
内部包含写数据、写命令(包括读忙和不读忙、初始化等子函数。
调用时先给LCD_DAT赋值,给出需要写入的数据或命令,然后调用。
;端口引脚定义区LCD_RS BIT P2.4 ;1602数据命令选择端口LCD_RW BIT P2.5 ;1602 读写选择端口LCD_EN BIT P2.6 ;1602 使能端口LCD_DATA EQU P0 ;1602 数据端口;变量声明区ALL_FLAG EQU 20H ;标志位LCD_FLAG EQU AL「FLAG.7 ;1602 读忙标志位LCD_DAT EQU 30H ;1602 数据命令字DELAYED EQU 31H 涎时字广★★★****★★★★★★★*★*★★**★*★★★*★*★★★★★*★*★*★1602读命令函数,高位存至LCD_LAG中★★★★★★★★★★★★★★★★★★★★★if******************* /LCD_R_DATA:MOV LCD_DATA,#OFFHSETB L CD RWNOPSETB L CD_ENNOPMOV Acc丄CD_DATAMOV C,Acc.7MOV LCD_FLAG,CCLR LCD_ENNOPJB LCD_FLAG ,L CD_BUSYRET/★****★***★*★***********************★*★*★*1602写数据函数,数据存在LCD_DAT★ if*************************************** /LCD_W_DATA:LCALLLCD_R_DATASETB L CD_RSNOPMOV LCD_DATA丄CD_DATSETB L CD_ENNOPCLR LCD_ENRET/* 1602LCD_DAT,检测忙信号LCD_W_CMD:LCALLLCD_R_DATACLR LCD_RSCLR LCD_RWNOPMOV LCD_DATA, LCD_DAT SETB L CD_ENNOPCLR LCD_ENRET /* 1602 与命令函数,命令存在LCD_DAT,不检测忙信号LCD CMD: 才***********才********************才才*****7写命令函数,命令存F在CLR LCD RWNOPMOV LCD_DATA, LCD_DAT SETB L CD_ENNOPCLR LCD_ENRET/***************************************** 4 QCC初始化函数★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★*/ LCD INIT:MOV DELAYED,#30LCALL DELAY_MSMOV LCD_DAT,#38HLCALL LCD_CMDMOV DELAYED,#10LCALL DELAY_MSMOV LCD_DAT,#38HLCALL LCD_CMDMOV DELAYED,#10LCALL DELAY_MSMOV LCD_DAT,#38HLCALL LCD CMDMOV DELAYED,#®LCALL DELAY_MSMOV LCD_DAT,#038HLCALL LCD_W_CMDMOV LCD_DAT,#08HLCALL LCD_W_CMDMOV LCD_DAT,#01HLCALL LCD_W_CMDMOV LCD_DAT,#06HLCALL LCD_W_CMDMOV LCD_DAT,#OCHLCALL LCD_W_CMDRET****************************************延时函数,延时时间为DELAYEDP.5毫秒0-100毫秒的延时***************************************** /DELAY_MS:MOV R7QELAYEDD1: MOV R6,#0F8HD2: DJNZ R6,D2DJNZ R7,D1RET广****************************************延时函数,延时时间为DELAYED*2微秒0-500微秒的延时***************************************** /DELAY_US:MOV R乙ADU1:DJNZ R7,DU1RET。
1602LCD显示的秒表 C语言程序
源程序代码://名称:用1602LCD设计的秒表//说明:首先按下K1键时开始计时,自此按下时暂停,第三次按下时继续累积计时,再次按下时停止计时,K2键用于清零秒表。
//#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define delayNOP ( ) ﹛_nop_( ); _nop_( ); _nop_( ); _nop_( );﹜//LCD控制函数void LCD_Initialize( );void LCD_Set_POS(uchar);void LCD_Write_Date(uchar);void Display_String(uchar﹡,uchar);sbit K1 = P1^0;sbit K2 = P1^1;sbit BEEP = P3^0;sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;uchar KeyCount = 0;uchar code msg1[] = ﹛〞Second Watch 0 〞﹜;uchar code msg2[] = ﹛〞>>>> 0 〞﹜;uchar code Prompts[] [16] ={﹛〞:: 1- - - - > 〞﹜,﹛〞:: 1- - - - > ::2 〞﹜,﹛〞:: 1 - >2 ::3- - > 〞﹜,﹛〞:: 1 - >2 ::3- - >4 〞﹜};// 计时缓冲与显示缓冲uchar Time_Buffer[] ={0,0,0,0};uchar LCD_Display_Buffer[]={〞00: 00: 00:00〞}; //// 蜂鸣器//void Beep ()﹛uchar i,j = 70;for (i = 0;i< 180;i++ )﹛while(--j);BEEP = ~BEEP;﹜BEEP = 0;﹜//// 延时//void DelayX(uint ms){uchar i;while(ms--) for (i= 0;i< 120;i++);﹜//// 显示计时//void Show_Second( ){uchar i;LCD_Set_POS(0x45); //设置LCD显示起点for(i = 3;i != 0xff ;i--);{//将两位整数的1/100s,秒,分,时转换为8位数字字符LCD_Display_Buffer[2﹡i+1] = Time_Buffer[i] / 10 + ˊ0 ˊ;LCD_Display_Buffer[2﹡i] = Time_Buffer[i] % 10 + ˊ0 ˊ;//在 = 3,2,1,0时分别显示时,分,秒,1/100sLCD_Writer_Date(LCD_Display_Buffer[2﹡i+1])LCD_Writer_Date(LCD_Display_Buffer[2﹡i])LCD_Writer_Date(ˊ: ˊ)}}//// Time0中断//Void Time0( ) interrupt 1 using 0{THO = -10000 / 256;TLO = -10000 % 256;Time_Buffer[0] ++if(Time_Buffer[0] == 100){Time_Buffer[0] = 0; Time_Buffer[1]++;}if(Time_Buffer[1] == 60) //秒{Time_Buffer[1] = 0; Time_Buffer[2]++;}if(Time_Buffer[2] == 60) //分{Time_Buffer[2] = 0; Time_Buffer[3]++;}if(Time_Buffer[3] == 24) //时Time_Buffer[3] = 0;}////主函数//void main( ){uchar i;IE = 0x82;TMOD = 0x01;THO = -10000 / 256;TLO = -10000 % 256;LCD_Initialize( );Display_String(msg1,0x00);Display_String(msg2,0x40);While(1){if(k1 == 0){DelayX(100);i = ++KeyCount;switch (i){case 1:case 3: TRO = 1;Display_String(Prompts[i-1],0);Break;case 2:case 4: TRO = 0;Display_String(Prompts[i-1],0);break;default:TRO = 0;break;}While (K1 == 0); // 等待释放K1键Beep( );}elseif(K2 == 0){TRO = 0;KeyCount = 0;for(i = 0;i < 4; i++)Time_Buffer [i] = 0; // 清零计数缓冲Display_String(msg1,0);Beep( );DelayX(100);while (K2 == 0); // 等待释放K2键}Show_Second( );}}//// 1602LCD显示驱动函数//#include 〈reg51.h〉#include 〈intrins.h〉#define uchar unsigned char#define uint unsigned int#define DellayNOP( )﹛_nop_( ); _nop_( ); _nop_( ); _nop_( );﹜sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;bit LCD_Busy_Check( );void LCD_Initialize( );void LCD_Set_POS(uchar);void LCD_Write_Command(uchar);void LCD_Write_ Date(uchar);//// 延时//void DelayMS(uint ms){uchar t;while(ms--) for (t =0;t < 120;t++);}//// LCD忙检查//bit LCD_Busy_Check( );{bit Rsult;LCD_RS = 0; LCD_RW = 1; LCD_EN = 1;DelayNOP( );Result = (bit)(p0 ﹠ 0x80);LCD_EN = 0return Result;}//// 向LCD写指令//void LCD_Write_Command(uchar cmd);{while(LCD_Busy_Check() );LCD_RS = 0; LCD_RW = 0; LCD_EN = 0;_nop_( ); _nop_( );pO = cmd; DelayNOP( );LCD_EN = 1;DelayNOP( );LCD_EN = 0;}//// 向LCD写数据//void LCD_Write_Date(uchar str);{while(LCD_Busy_Check() );LCD_RS = 1; LCD_RW = 0; LCD_EN = 0;pO = str; DelayNOP( ); LCD_EN = 1;DelayNOP( );LCD_EN = 0;}//// 初始化LCD//void LCD_Initialize( );{DelayMS(5); LCD_Write_Command(0x38);DelayMS(5); LCD_Write_Command(0x0c);DelayMS(5); LCD_Write_Command(0x06);DelayMS(5); LCD_Write_Command(0x01);DelayMS(5);}//// 设置显示位置//void LCD_Set_POS(uchar Poition){LCD_Write_Command(Position ︱ 0x80);}////显示函数,在LCD指定行上显示字符串//void Display_String(uchar﹡str,uchar LineNO) {uchar k;LCD_Set_POS(LineNO);for (k = 0;k < 16;k++) LCD_Write_Date(str[k]) }。
单片机LCD1602A秒表程序
ORG 0030H
MAIN:
ACALL SET_LCD
;LCD 初始化设置子程序
TOOP:
ACALL WR_THL ACALL RESET_18B20
;将报警上下线写入暂存寄存器 ;18B20 复位子程序
JNB FLAG,TOOP1
;18B20 不存在
ACALL MEU_OK
;显示"OK"菜单
ACALL RE_THL
6
嵌入式应用软件园,版权所有,请勿转载/销售。
第 2 章 程序功能
1.1 程序功能 程序中包含 LCM 用到的所有函数:初始化、写指令、写数据、判
忙碌、清屏幕。 在单片机的 P1 端口上接有 LCD 模块,用来显示计时时间。P3.3、
P3.4 端口分别接有按键 K1、K2,做秒表的计时控制按钮。 K1:暂停和起动秒表。只能暂停和起动二次。 K2:重新开始计时,计时值从 0 开始。
1.2 操作方法 1. 按一下 K2 键,准备计时。 2. 按一下 K1 键,计时开始。 3. 按一下 K1 键,暂停计时。 4. 按一下 K1 键,计时开始,在第 2 步的基础上累计时。 5. 按一下 K1 键,暂停计时。 6. 重复第 1~5 步,循环使用秒表。
7
1.3 原理图
嵌入式应用软件园,版权所有,请勿转载/销售。
MOV A,#0CCH
;跳过 ROM 匹配
ACALL WRITE_18B20
;调写入子程序
MOV A,#44H
;发出温度转换命令
ACALL WRITE_18B20
;调写入子程序
ACALL RESET_18B20
;调复位子程序
MOV A,#0CCH
;跳过 ROM 匹配
TX-1C1602液晶显示时间年月日可调
#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit dula=P2^6;sbit wela=P2^7;sbit rs=P3^5;sbit lcden=P3^4;sbit s1=P3^0;sbit s2=P3^1;sbit s3=P3^2;sbit rd=P3^7;uchar s1num;uint count;char miao,shi,fen,tian,yue,xqi,x,nian; uchar code table[]=" 2013-01-01 1 "; uchar code table1[]=" 12:00:00"; void delay(uchar z){uchar x,j;for(x=z;x>0;x--)for(j=110;j>0;j--);}void write_com(uchar com)//写指令{rs=0;lcden=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_date(uchar date)//写数据{rs=1;lcden=0;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void init() // 初始化{uchar num;dula=0;wela=0;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);for(num=0;num<17;num++){write_date(table[num]);delay(10);}write_com(0x80+0x40);for(num=0;num<10;num++)write_date(table1[num]);delay(10);TMOD=0X02; //设定时器0为工作方式2 TH0=0x06; //初值为12Mhe0.25msTL0=0x06;EA=1;ET0=1;TR0=1;nian=13;yue=1;tian=1;xqi=1;shi=12;}void write_sfm(uchar add,uchar date) //定位显示第二行{uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void write_sfm1(uchar add,uchar date) //定位显示第一行{uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_date(0x30+shi);write_date(0x30+ge);}void write_sfm2(uchar add,uchar xqi) //定位显示星期{write_com(0x80+add);write_date(0x30+xqi); //0x30的意思是数据从码表中0开始}void keyscan() //键盘扫描{rd=0;if(s1==0){delay(5);if(s1==0);{s1num++;while(!s1);if(s1num==1){TR0=0;write_com(0x80+0x40+11);write_com(0x0f);}if(s1num==2){write_com(0x80+0x40+8);}if(s1num==3){write_com(0x80+0x40+5);}if(s1num==4){write_com(0x80+12);}if(s1num==5){write_com(0x80+9);}if(s1num==6){write_com(0x80+6);}if(s1num==7){write_com(0x80+14);}if(s1num==8){s1num=0;write_com(0x0c);TR0=1;}}}if(s1num!=0){if(s2==0){delay(5);if(s2==0){while(!s2);if(s1num==1){miao++;if(miao==60)miao=0;write_sfm(10,miao);write_com(0x80+0x40+11);}if(s1num==2){fen++;if(fen==60)fen=0;write_sfm(7,fen);write_com(0x80+0x40+8);}if(s1num==3){shi++;if(shi==24)shi=0;write_sfm(4,shi);write_com(0x80+0x40+5);}if(s1num==4){tian++;if(tian==31)tian=1;write_sfm1(11,tian);write_com(0x80+12);}if(s1num==5){yue++;if(yue>=13)yue=1;write_sfm1(8,yue);write_com(0x80+9);}if(s1num==6){nian++;if(nian>=99)nian=1;write_sfm1(5,nian);write_com(0x80+6);}if(s1num==7){xqi++;if(xqi>=8)xqi=1;write_sfm2(14,xqi);write_com(0x80+14);}}}if(s3==0){delay(5);if(s3==0){while(!s3);if(s1num==1){miao--;if(miao==-1)miao=59;write_com(0x80+0x40+10);write_sfm(10,miao);}if(s1num==2){fen--;if(fen==-1)fen=59;write_sfm(7,fen);write_com(0x80+0x40+8);}if(s1num==3){shi--;if(shi==-1)shi=23;write_sfm(4,shi);write_com(0x80+0x40+4);}if(s1num==4){tian--;if(tian==-1)tian=31;write_sfm1(11,tian);write_com(0x80+11);}if(s1num==5){yue--;if(yue==0)yue=12;write_sfm1(8,yue);write_com(0x80+9);}if(s1num==6){nian--;if(nian==0)nian=99;write_sfm1(5,nian);write_com(0x80+6);}}}}}char tianshu() //以月份来判断天数{switch (yue){case 1:x=32;break;case 2:if( ((0 == nian%4)&&(0 != nian%10)) ||(0 == nian %40) )//判断平年或闰年x=30;else x=29;break;case 3:x=32;break;case 4:x=31;break;case 5:x=32;break;case 6:x=31;break;case 7:x=32;break;case 8:x=31;break;case 9:x=31;break;case 10:x=32;break;case 11:x=31;break;case 12:x=32;break;}return x;}void main() //主函数{init();while(1){keyscan();}}void t0()interrupt 1 //to定时器{count++;if(count==4000){count=0;miao++;if(miao>=60){miao=0;fen++;if(fen>=60){fen=0;shi++;if(shi==24){shi=0;tian++;if(tian>=(tianshu())){ tian=1;yue++;if(yue>=13){yue=1;nian++;write_sfm1(5,nian);}write_sfm1(8,yue);}xqi++;if(xqi>=8)xqi=1;write_sfm2(14,xqi);write_sfm1(11,tian);}write_sfm(4,shi) ;}write_sfm(7,fen) ;}write_sfm(10,miao) ;}}。
C52单片机LCD1602显示时钟
/**********LCD1602液晶屏显示:时-分-秒,D0-D7对应P0口P0_0-P0_7************/#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcden=P3^4; //使能端:en=1,读取;en=下降沿,执行指令sbit lcdrs=P3^5; //数据/指令选择端:rs=1,为数据;rs=0,为指令。
sbit lcdrw=P3^6; //读写控制端:rw=1,读;rw=0,写int W1,W2,W3,W4,W5,W6,W7;/***********延时函数******************/void delayms(uint time){uint i;for(;time>0;time--){for(i=0;i<124;i++){;}}}/*******************lcd写入指令子函数********************/void lcd_wcom(uchar com){lcdrs=0; // rs=0,指令lcdrw=0; // rw=0,写入P0=com; // 把指令送入P0口delayms(5); //延时一小会,让1602准备接收数据--------代替忙检测函数lcden=1; //使能端下降沿,把指令送入1602的8为数据口delayms(2);lcden=0;}/************************lcd写入数据函数************************/void lcd_wdata (uchar dat){lcdrs=1; // RS=1,数据lcdrw=0; // rw=0,写入P0=dat; // 把要显示的数据送入P0口delayms(5); //延时一小会,让1602准备接收数据--------代替忙检测函数lcden=1; //使能端下降沿,把指令送入1602的8为数据口delayms(2);lcden=0;}/******************LCD初始化子函数****************************/void lcd_init() //初始化,写入指令{lcdrw=0; //rw=0,写lcden=1;lcden=0; //下降沿,执行指令lcd_wcom(0x38); //写指令,8位数据,双列lcd_wcom(0x0c); //开启显示屏,关光标,光标不闪烁lcd_wcom(0x06); //显示地址递增,即写一个数据后,显示位置右移一位lcd_wcom(0x01); //清屏}/**********************LCD显示子函数****************************/void lcd_display(int i,int j){lcd_wcom(0x80+i-1);switch(j){case 0: lcd_wdata('0');delayms(2); break;case 1: lcd_wdata('1');delayms(2); break;case 2: lcd_wdata('2');delayms(2); break;case 3: lcd_wdata('3');delayms(2); break;case 4: lcd_wdata('4');delayms(2); break;case 5: lcd_wdata('5');delayms(2); break;case 6: lcd_wdata('6');delayms(2); break;case 7: lcd_wdata('7');delayms(2); break;case 8: lcd_wdata('8');delayms(2); break;case 9: lcd_wdata('9');delayms(2); break;default: lcd_wdata(':');delayms(2); break;}}/***************定时器T0初始化子函数**********************/void initTimer0 (void){TMOD = 0x01; //模式1,16位T0,定时10msTH0 = 0xD8; //初值TL0 = 0xF0;EA = 1; //开总中断ET0 = 1; //允许T0中断TR0 = 1; //启动T0}/*****************************定时器T0中断子程序****************************/ void Timer0 (void) interrupt 1{int time;int a;time++;a=time;W1=a%10;a/=10;W2=a%10;a/=10;W3=a%6;a/=6;W4=a%10;a/=10;W5=a%6;a/=6;W6=a%10;a/=10;W7=a%10;a/=10;}/**************************主函数*******************************/void main(){initTimer0(); //初始化lcd_init();while(1){//lcd_display(10,W1);//lcd_display(9,':');lcd_display(8,W2);lcd_display(7,W3);lcd_display(6,':');lcd_display(5,W4);lcd_display(4,W5);lcd_display(3,':');lcd_display(2,W6);lcd_display(1,W7);}}。
第10章 用LCD1602显示的秒表设计
10.2 硬件设计
图10-2 用LCD1602显示的秒表电路原理图
3
10.3 程序设计
开始 初始化 初始显示
按键1是否按下? N
Y
按键1次数加1
按键1次数等于1、3
按键1次数等于2、4
开定时器
关定时器
显示第1次(或第3次) 按下的提示信息
显示第2次(或第4次) 按下的提示信息
break
break
秒计数单元=60? N
分计数单元=60? N
时计数单元=24? N
中断返回
Y 秒计数器清零,分加1
Y 分计数器清零,时加1
Y 时计数器清零
图10-4 定时器中断程序
5
10.4 仿真与实验结果
图10-5 1602LCD显示的秒表Proteus仿真电路
6
10.4 仿真与实验结果
图10-6 多孔板实验结果
第10章用LCD1602显示的秒表设计
10.1 项目任务 10.2 硬件设计 10.3 程序设计 10.4 仿真与实验结果
1
ቤተ መጻሕፍቲ ባይዱ
10.1 项目任务
用STC89C52单片机与LCD1602液晶显示器设计并制作一个秒 表,实现秒表的计时、暂停与清零等基本功能,每秒自动加1, 至59秒后再回到00,如此循环。运用“开始”、“暂停”、 “复位”按键实现对秒表计时的控制。
7
按键2是否按下? N
Y
关定时器
清零计时缓冲单元
显示清零提示信息
执行beep子程序
执行beep子程序
显示秒信息
图10-3 1602LCD显示的秒表主程序流程图
程序清单见课程设计指导书或配套仿真软件
4
单片机LCD1602显示年月日时钟带星期和闹钟#(优选.)
长春工业大学测控技术与仪器专业单片机LCD1602显示年月日时钟带星期和闹钟,可识别闰年下载文档即可完全复制#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcdrs = P0^7; //液晶引脚定义sbit led_cs = P0^6;sbit lcden = P0^5;sbit boom = P3^6;sbit key1 = P3^5;sbit key2 = P3^4;sbit key3 = P3^3;sbit keyE = P3^2;ucharnum,key1num,key2num,count,hour,min,sec,day,mon,year,shi,fen,miao ,week;char ye1,ye2;uchar code cg_1602[]={ 0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00,0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,};//"年月日"/*延时函数*/void delay(uint xms){uint i,j;for(i=xms;i>0;i--)for(j=114;j>0;j--);}/*1602液晶*/void write_com(uchar com)//写命令{lcdrs=0;lcden=0;P2=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date)//写数据{lcdrs=1;lcden=0;P2=date;delay(5);lcden=1;delay(5);lcden=0;}void write_by_xy(uchar x,uchar y)//坐标定位{uchar address;if(y==0)address=0x80+x;//y=0,写第一行elseaddress=0xc0+x;//y=1,写第二行write_com(address);}/*void write_char(uchar x,uchar y,uchar date)//坐标定位显示{write_by_xy(x,y);//先定位write_data(date);//后写数}*/void write_string(uchar x,uchar y,uchar *s)//写字符串{write_by_xy(x,y);//设定显示位置while(*s)//write character{P2=*s;write_data(*s);}}void write_sfm(uchar add,uchar date)//写时分秒函数{uchar hour,ge;hour=date/10;//分解一个2位数的十位和个位ge=date%10;write_com(0x80+add);//设置显示位置write_data(0x30+hour);//送去液晶显示十位write_data(0x30+ge); //送去液晶显示个位}void write_cg()//写入固定汉字和符号{write_com(0x40); //设定CGRAM地址for(num=0;num<24;num++) //将自定义字型码写入CGRAM中{write_data(cg_1602[num]);}write_com(0xc4);//年{write_data(0);write_com(0xc7);//月{write_data(1);}write_com(0xca);//日{write_data(2);}write_string(2,0,":");write_string(5,0,":");write_string(0x0a,0,":");write_string(0x0d,0,":");write_string(0x0c,1,"W");write_string(0x0d,1,"K");}void init_1602()//初始化{led_cs=0;hour=23;min=59;sec=55;key1num=0;count=0;day=28;mon=2;ye1=2 0;ye2=13;year=ye1*100+ye2;boom=0;shi=0;fen=0;miao=0;week=7;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_string(0,1,"2013");write_string(5,1,"02");write_string(8,1,"28");write_sfm(8,shi);write_sfm(0x0b,fen);write_sfm(0x0e,miao);write_sfm(0,hour);write_sfm(3,min);write_sfm(6,sec);write_sfm(0x48,day);write_sfm(0x45,mon);write_sfm(0x40,ye1);write_sfm(0x42,ye2);write_sfm(0x4e,week);write_cg();TMOD=0x01;//设置定时器0工作模式1 TH0=(65536-50000)/256;//定时器装初值TL0=(65536-50000)%256;EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0}/*键盘扫描函数*/void keyscan()//按键扫描函数{//keyE =0;if(key1==0){delay(5);if(key1==0)//确认功能键被按下{key1num++;//功能键按下次数记录while(!key1);//释放确认if(key1num==1)//第一次被按下时{TR0=0; //关闭定时器write_com(0x80+7);//光标定位到秒位置write_com(0x0f); //光标开始闪烁}if(key1num==2)//第二次按下光标闪烁定位到分钟位置{write_com(0x80+4);}if(key1num==3)//第三次按下光标闪烁定位到小时位置{write_com(0x80+1);}if(key1num==4)//第四次按下光标闪烁定位到日位置{write_com(0x80+0x49);}if(key1num==5)//第五次按下光标闪烁定位到月位置{write_com(0x80+0x46);}if(key1num==6)//第六次按下光标闪烁定位到年2位置{write_com(0x80+0x43);}if(key1num==7)//第七次按下光标闪烁定位到年1位置{write_com(0x80+0x41);}if(key1num==8)//第八次按下光标闪烁定位到星期位置{write_com(0x80+0x4f);}if(key1num==9)//第九次按下{key1num=0;//记录按键数清零write_com(0x0c);//取消光标闪烁TR0=1; //启动定时器使时钟开始走}}}if(key1num!=0)//只有功能键被按下后,增加和减小键才有效{if(key2==0){delay(5);if(key2==0)//增加键确认被按下{while(!key2);//按键释放if(key1num==1)//若功能键第一次按下{sec++; //则调整秒加1if(sec==60)//若满60后将清零sec=0;write_sfm(6,sec);//每调节一次送液晶显示一下write_com(0x80+7);//显示位置重新回到调节处}if(key1num==2)//若功能键第二次按下{min++;//则调整分钟加1if(min==60)//若满60后将清零min=0;write_sfm(3,min);//每调节一次送液晶显示一下write_com(0x80+4);//显示位置重新回到调节处}if(key1num==3)//若功能键第三次按下{hour++;//则调整小时加1if(hour==24)//若满24后将清零hour=0;write_sfm(0,hour);;//每调节一次送液晶显示一下write_com(0x80+1);//显示位置重新回到调节处}if(key1num==4)//若功能键第四次按下{day++;//则调整日加1if(day>31)//若大于31后将置一day=1;write_sfm(0x48,day);//每调节一次送液晶显示一下write_com(0x80+0x48);//显示位置重新回到调节处}if(key1num==5)//若功能键第五次按下{mon++;//则调整月加1if(mon>12)//若大于12后将置一mon=1;write_sfm(0x45,mon);//每调节一次送液晶显示一下write_com(0x80+0x45);//显示位置重新回到调节处}if(key1num==6)//若功能键第六次按下{ye2++;//则调整年加1if(ye2==0x0a)//若满99后将清零ye2=0;year=ye1*100+ye2;write_sfm(0x42,ye2);//每调节一次送液晶显示一下write_com(0x80+0x42);//显示位置重新回到调节处}if(key1num==7)//若功能键第七次按下{ye1++;//则调整年加100if(ye1==0x0a)//若满99后将清零ye1=0;year=ye1*100+ye2;write_sfm(0x40,ye1);//每调节一次送液晶显示一下write_com(0x80+0x40);//显示位置重新回到调节处}if(key1num==8)//若功能键第八次按下{week++;//则调整周加一if(week>7)//若大于7后置一week=1;write_sfm(0x4f,week);//每调节一次送液晶显示一下write_com(0x80+0x4f);//显示位置重新回到调节处}}}if(key3==0){delay(5);if(key3==0)//确认减小键被按下{while(!key3);//按键释放if(key1num==1)//若功能键第一次按下{sec--;//则调整秒减1if(sec==-1)//若减到负数则将其重新设置为59sec=59;write_sfm(6,sec);//每调节一次送液晶显示一下write_com(0x80+7);//显示位置重新回到调节处}if(key1num==2)//若功能键第二次按下{min--;//则调整分钟减1if(min==-1)//若减到负数则将其重新设置为59min=59;write_sfm(3,min);//每调节一次送液晶显示一下write_com(0x80+4);//显示位置重新回到调节处}if(key1num==3)//若功能键第三次按下{hour--;//则调整小时减1if(hour==-1)//若减到负数则将其重新设置为23 hour=23;write_sfm(0,hour);//每调节一次送液晶显示一下write_com(0x80+1);//显示位置重新回到调节处}if(key1num==4)//若功能键第四次按下{day--;//则调整日减1if(day==0)//若日为零时将置一day=31;write_sfm(0x48,day);//每调节一次送液晶显示一下write_com(0x80+0x49);//显示位置重新回到调节处}if(key1num==5)//若功能键第五次按下{mon--;//则调整月减1if(mon==0)//若月为零将置一mon=12;write_sfm(0x45,mon);//每调节一次送液晶显示一下write_com(0x80+0x45);//显示位置重新回到调节处}if(key1num==6)//若功能键第六次按下{ye2--;//则调整年减1if(ye2<0)//若小于零后将设置为99ye2=99;year=ye1*100+ye2;write_sfm(0x42,ye2);//每调节一次送液晶显示一下write_com(0x80+0x42);//显示位置重新回到调节处}if(key1num==7)//若功能键第七次按下{ye1--;//则调整年减100if(ye1<0)//若小于零后将设置为99ye1=99;year=ye1*100+ye2;write_sfm(0x40,ye1);//每调节一次送液晶显示一下write_com(0x80+0x40);//显示位置重新回到调节处}if(key1num==8)//若功能键第八次按下{week--;//则调整周减一if(week==0)//若等于0后将置7week=7;write_sfm(0x4f,week);//每调节一次送液晶显示一下write_com(0x80+0x4f);//显示位置重新回到调节处}}}}if(keyE==0){delay(5);if(keyE==0)//确认功能键被按下{key2num++;//功能键按下次数记录while(!keyE);//释放确认if(key2num==1)//第一次被按下时{TR0=0; //关闭定时器write_com(0x80+0x0f);//光标定位到秒位置write_com(0x0f); //光标开始闪烁}if(key2num==2)//第二次按下光标闪烁定位到分钟位置{write_com(0x80+0x0c);}if(key2num==3)//第三次按下光标闪烁定位到小时位置{write_com(0x80+9);}if(key2num==4)//第八次按下{key2num=0;//记录按键数清零write_com(0x0c);//取消光标闪烁TR0=1; //启动定时器使时钟开始走}}}if(key2num!=0)//只有功能键被按下后,增加和减小键才有效{if(key2==0){delay(5);if(key2==0)//增加键确认被按下{while(!key2);//按键释放if(key2num==1)//若功能键第一次按下{miao++; //则调整秒加1if(miao==60)//若满60后将清零miao=0;write_sfm(0x0e,miao);//每调节一次送液晶显示一下write_com(0x80+0x0e);//显示位置重新回到调节处}if(key2num==2)//若功能键第二次按下{fen++;//则调整分钟加1if(fen==60)//若满60后将清零fen=0;write_sfm(0x0b,fen);//每调节一次送液晶显示一下write_com(0x80+0x0b);//显示位置重新回到调节处}if(key2num==3)//若功能键第三次按下{shi++;//则调整小时加1if(shi==24)//若满24后将清零shi=0;write_sfm(8,shi);;//每调节一次送液晶显示一下write_com(0x80+8);//显示位置重新回到调节处}}}if(key3==0){delay(5);if(key3==0)//确认减小键被按下{while(!key3);//按键释放if(key2num==1)//若功能键第一次按下{miao--;//则调整秒减1if(miao==-1)//若减到负数则将其重新设置为59miao=59;write_sfm(0x0e,miao);//每调节一次送液晶显示一下write_com(0x80+0x0e);//显示位置重新回到调节处}if(key2num==2)//若功能键第二次按下{fen--;//则调整分钟减1if(fen==-1)//若减到负数则将其重新设置为59fen=59;write_sfm(0x0b,fen);//每调节一次送液晶显示一下write_com(0x80+0x0b);//显示位置重新回到调节处}if(key2num==3)//若功能键第三次按下{shi--;//则调整小时减1if(shi==-1)//若减到负数则将其重新设置为23shi=23;write_sfm(8,shi);//每调节一次送液晶显示一下write_com(0x80+8);//显示位置重新回到调节处}}}}}/*主函数*/void main(){led_cs=0;init_1602();while(1){keyscan();}}/*中断函数*/void timer0() interrupt 1//定时器0中断服务程序{TH0=(65536-50000)/256;//再次装定时器初值TL0=(65536-50000)%256;count++; //中断次数累加if(count==20) //20次50毫秒为1秒{count=0;sec++;if(sec==60)//秒加到60则进位分钟{sec=0;//同时秒数清零min++;if(min==60)//分钟加到60则进位小时{min=0;//同时分钟数清零hour++;//boom=1;//delay(5);//boom=0;if(hour==24)//小时加到24则小时清零{hour=0;day++;week++;if(week>7){week=1;}if(mon==1){if(day>31)day=1;mon++;}}if(mon==2){if((year%4==0 && year%100!=0)||year%4==0) {if(day>29){day=1;mon++;}}else if(day>28){day=1;mon++;}}if(mon==3)if(day>31) {day=1; mon++;}}if(mon==4) {if(day>30) {day=1; mon++;}}if(mon==5) {if(day>31) {day=1; mon++;}if(mon==6) {if(day>30) {day=1; mon++;}}if(mon==7) {if(day>31) {day=1; mon++;}}if(mon==8) {if(day>31) {day=1;}}if(mon==9) {if(day>30) {day=1; mon++;}}if(mon==10) {if(day>31) {day=1; mon++;}}if(mon==11) {if(day>30) {mon++;}}if(mon==12){if(day>31){day=1;mon=1;ye2++;}}}write_sfm(0x4e,week);write_sfm(0x48,day);write_sfm(0x45,mon);write_sfm(0x40,ye1);write_sfm(0x42,ye2);}write_sfm(0,hour);//小时若变化则重新写入}write_sfm(3,min);//分钟若变化则重新写入}write_sfm(6,sec); //秒若变化则重新写入if((hour==shi && min==fen) && sec==miao) {boom=1;delay(5);boom=0;}}最新文件仅供参考已改成word文本。
LCD1602液晶秒表C51程序
LCD1602液晶秒表C51程序此程序是基于51hei单片机开发板上面写的,如需要移植到自己的电路上,修改相应的端口即可,开发板完整的电路图下载: 点这里(注意:只需要看1602部分即可,其他部分可以忽略)/*************************************************** *********************** @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); //定时10msConfigTimer1(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; //定时器方式1TH0 = thr0;TL0 = tlr0;TR0 = 1; //开启timer0ET0 = 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; //定时1msKeyScan();}/*************************************************** *********************** @file Lcd1602.c* @author xr* @date 2014年5月7日13:33:17* @version V1.2.3* @brief LCD1602液晶底层驱动************************************************* ***********************/#include ;//LCD1602_IOsbit 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}};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(){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){//五次检测按键的值都是1keySta[keyout][i] = 1;}else if ((keybuf[keyout][i] & 0x1F) == 0x00) {//五次检测的按键值都是0keySta[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显示屏设计一个具有复位功能的秒表
今日做一个简单1602应用案例—-设计一个秒表。
要求:具有秒表启动和复位功能按键,秒表计时时间实时显示在LCD1602。
1.系统的硬件电路原理图:2.系统的程序设计2.1 头文件、全局变量和函数的声明#include “LCD_1602.h”#includeunsigned char Disp_Buffer[10];//这个可以稍微设置大一点,不影响结果显示,显示的时候遇到字符串结束标志就结束//定义二个位变量,分别对应按键开始按键和停止复位按键sbit key_set=P3^2;sbit key_reset=P3^3;unsigned char TIme_count=0;unsigned int TIme_S=0;void TImer_inial();//定时器初始化void delay(unsigned int i);//延时函数void start();//启动秒表void stop();//停止复位秒表void second_cal_show();//秒的计算与显示2.2 主程序主程序主要完成显示屏的初始化和初始化显示、定时器的初始化,注意定时初始化的时候不启动。
启动有开始按键控制,不按下开始键不启动定时器。
初始化完了,在while循环中调用start();确定是否启动定时器,调用stop();根据按键状态确定是否停止秒表并复位;调用second_cal_show(); 进行秒的计算和显示。
void main(){InitLcd1602();LcdShowStr(0, 0, “Current : 0 S”);LcdShowStr(0, 1, “Last: 0 S”);TImer_inial();while(1){start();stop();second_cal_show();}}2.3 子程序2.3.1 初始定时器:定时器T0工作在模式1,定时器定时时间0.02秒。
void timer_inial(){TMOD = 0X01;//TH0=0XB8;//定时0.02sTL0=0X00;}2.3.2 延时函数:软件延时,主要用按键软件消抖//延时函数void delay(unsigned int i){unsigned int k;for(k=0;k2.3.3 启动函数:检测按键是否按下,按键如果按下则启动定时器T0,并从0开始计数。
单片机:LCD(1602)动态显示(汇编)
单片机:LCD(1602)动态显示(汇编)2009年06月13日星期六 15:31作者:gguoqing 出处:伟纳电子/mcu_view.asp?id=15显示内容:CHINESE *;* NEWYEAR *;**;* 显示方式:*;* 1、LCD第一行显示:CHINESE *;* LCD第二行显示:NEWYEAR *;* 2、先将两行字符写入DDRAM中,然后从右至左逐字移出显示。
*;* 3、在指定位置停留1.6秒后,闪烁2次,清屏。
*;* 4、反复循环上述显示方式。
* ;***************************************************** **************LCD_RS EQU P1.0LCD_RW EQU P1.1LCD_EN EQU P1.2;***************************************************** **************ORG 0000HAJMP MAINORG 0030H;***************************************************** **************MAIN:MOV SP,#60HACALL LCD_INIT ;LCD初始化MAIN1:ACALL CLR_LCD ;清LCDMOV A,#90H ;在第一行第17列的位置ACALL LCD_CMDMOV DPTR,#LINE1 ;第一行字符串的起始地址送入DPTR。
ACALL WRITEMOV A,#0D0H ;在第二行第17列的位置ACALL LCD_CMDMOV DPTR,#LINE2 ;第二行字符串的起始地址送入DPTR。
ACALL WRITEMOV R3,#10H ;向左移动16格LOOPA:MOV A,#18H ;字符同时左移一格ACALL LCD_CMDMOV R5,#03H ;延时375MSACALL DELAY125MSDJNZ R3,LOOPAACALL DELAY4 ;延时1.6sACALL DELAY4MOV R4,#02H ;设置闪烁次数ACALL FLASH ;开始闪烁AJMP MAIN1LINE1:DB " CHINESE ",00HLINE2:DB " NEW YEAR ",00H;***************************************************** **********;LCD初始化设定子程序;***************************************************** **********LCD_INIT:ACALL DELAY5MS ;延时15MSACALL DELAY5MS ;等待LCD电源稳定ACALL DELAY5MSMOV A,#38H ;16*2显示,5*7点阵,8位数据ACALL LCD_CMD_NC ;不进行LCD忙检测ACALL DELAY5MSMOV A,#38H ;16*2显示,5*7点阵,8位数据ACALL LCD_CMD_NC ;不进行LCD忙检测ACALL DELAY5MSMOV A,#38H ;16*2显示,5*7点阵,8位数据ACALL LCD_CMD_NC ;不进行LCD忙检测ACALL DELAY5MSMOV A,#08H ;显示关ACALL LCD_CMD ;进行LCD忙检测MOV A,#01H ;清除屏幕ACALL LCD_CMD ;进行LCD忙检测MOV A,#0CH ;显示开,关光标ACALL LCD_CMD ;进行LCD忙检测RET;***************************************************** **********;清LCD子程序;***************************************************** **********CLR_LCD:MOV A,#01H ;清除屏幕ACALL LCD_CMD ;进行LCD忙检测RET;***************************************************** **********;写指令数据到LCD;RS=L,RW=L,D0-D7=指令码,E=高脉冲;***************************************************** **********LCD_CMD:CALL CHECKBUSYLCD_CMD_NC:CLR LCD_RSCLR LCD_RWMOV P0,ASETB LCD_ENNOPNOPNOPNOPCLR LCD_ENRET;***************************************************** **********;写显示数据到LCD;RS=H,RW=L,D0-D7=数据,E=高脉冲;***************************************************** **********LCD_WDATA:ACALL CHECKBUSYSETB LCD_RSCLR LCD_RWMOV P0,ASETB LCD_ENNOPNOPNOPNOPCLR LCD_ENRET;***************************************************** **********;检测LCD控制器忙状态;读数据;RS=L,RW=H,E=H,输出:D0-D7=数据;P0.7=1,LCD忙,等待。
1602显示秒表
/**********************BST-V51实验开发板例程************************* 平台:BST-V51 + Keil U3 + STC89C52* 名称:1602显示秒表******************************************************************* ** 描述:** ** 上电后液晶屏先显示信息,接着按下K3,定时开始,再次按下** ** K3暂停,第3次按下显示累积计时,第4次按下暂停计时,任何时候按下K4* * ** 计数清零。
** ** *************************************************************************/#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intuchar KeyCount=0;sbit K3 = P3^6;sbit K4 = P3^7;sbit BEEP = P2^3; //蜂鸣器uchar code cdis1[ ] = {" STOPWA TCH 0 "};uchar code cdis2[ ] = {" BST-V51 "};uchar code cdis3[ ] = {"TIME "};uchar code cdis4[ ] = {" BEGIN COUNT 1 "};uchar code cdis5[ ] = {" PAUSE COUNT 2 "};uchar code cdis6[ ] = {" BEGIN COUNT 3 "};uchar code cdis7[ ] = {" PAUSE COUNT 4 "};uchar code cdis8[ ] = {" "};sbit LCD_RS = P1^0;sbit LCD_RW = P1^1;sbit LCD_EN = P2^5;#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};uchar display[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00};uchar display2[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/********************************************************* 延时函数*********************************************************/void Delay(uint num)//延时函数{while( --num );}/********************************************************* 蜂鸣器响一声**********************************************************/ void beep(){unsigned char y;for (y=0;y<180;y++){BEEP=!BEEP; //BEEP取反Delay(70);}BEEP=1; //关闭蜂鸣器}/********************************************************* 延时函数1*********************************************************/ void delay1(int ms){unsigned char n;while(ms--){for(n = 0; n<250; n++){_nop_();_nop_();_nop_();_nop_();}}}/*********************************************************** ** 检查LCD忙状态* * lcd_busy为1时,忙,等待。
最新1602LCD显示秒表汇编汇总
1602L C D显示秒表汇编//******************************************************************** *******//; K2=P3.3 K4=P3.5;* 1602LCD显示秒表 *;* K2 --- 控制按键 *;* 按一下计时,再按一下暂停计时 *;*;* K4 --- 清零按键: *;* 在任何状态下,按一下K4,均可清零。
*;* *;---------------------------------------;晶振 11.0592M;定时器0,方式1;计时中断程序每隔10ms中断一次;---------------------------------------TLOW EQU 0CH ;定时器初值THIGH EQU 0DCHHOUR EQU 30HMIN EQU 31HSEC EQU 32HSEC0 EQU 33H ;10ms计数值KEY_D EQU 34H ;为键当前的端口状况KEY_S EQU 35H ;为键上次的端口状况X EQU 36H ;LCD 地址变量KEY_C EQU 37H ;键计数单元;K1 EQU P3.2K2 EQU P3.3;K3 EQU P3.4K4 EQU P3.5BEEP EQU P2.4RS EQU P3.5 ;LCD控制端口定义 RW EQU P3.6EN EQU P3.7;---------------------------------------------------- ORG 0000HJMP STARTORG 0BHJMP T0_INT;---------------------------------------------------- START: MOV R3,#00HMOV SP,#60HCLR ENCALL SET_LCDCALL INIT ;初始化变量MOV KEY_S,#01HCALL INIT_TIMER ;初始化定时器 ; CALL MENULOOP: CALL CONV ;时间计数处理CALL SKEYMOV KEY_S,KEY_DJZ XPMOV A, KEY_SJB ACC.0,XPCLR AMOV B,AINC R3MOV A,R3MOV B,#2DIV ABMOV A,BCALL BZJZ XPPSETB TR0 ;启动中断MOV DPTR,#MADJ ;显示执行信息CALL P_KEYSJMP XPXPP:CLR TR0MOV DPTR,#MADJ1CALL P_KEYXP: JB K4,LOOP ;判清零键是否按?MOV R3,#00HCALL BZJMP START;-----------------------------------------------------P_KEY: MOV A,#1 ;第一行显示CALL LCD_PRINTRET;-------------------------------------------------------SKEY: CLR A ;判是否有键按下子程序MOV KEY_D,AMOV C,K2RLC AORL KEY_D,AMOV A,KEY_DXRL A,KEY_S ;有键按下,A 中内容不为零 RET;--------------------------------------------------------;LMESS1: DB " ",0 ;LCD 第一行显示消息;LMESS2: DB "TIME ",0 ;LCD 第二行显示消息;--------------------------------------------------------INIT: CLR A ;初始化控制变量MOV SEC,AMOV MIN,AMOV HOUR,AMOV KEY_D,AMOV KEY_S,ASETB BEEPCLR TR0RET;------------------------------------------------------------INIT_TIMER: ;初始化定时器接口MOV TMOD,#01H ;设置定时器0 工作模式为模式1 MOV IE, #82H ;启用定时器0 中断产生MOV TL0,#TLOWMOV TH0,#THIGHRET;-------------------------------------------------------------T0_INT:PUSH ACC ;定时器0计时中断程序MOV TL0,#TLOWMOV TH0,#THIGHINC SEC0MOV A,SEC0 ;10ms 计数值加1CJNE A,#100,TTMOV SEC0,#0INC SEC ;秒加1MOV A,SECCJNE A,#60,TTINC MIN ;分加1MOV SEC,#0MOV A,MINCJNE A,#60,TTINC HOUR ;时加1MOV MIN,#0MOV A,HOURCJNE A,#24,TTMOV SEC,#0 ;秒、分、时单元清0MOV MIN,#0MOV HOUR,#0TT: POP ACCRETI;-------------------------------------------------------; 在第二行显示数字;-------------------------------------------------------SHOW_DIG2: ;在 LCD 的第二行显示数字 MOV B,#10 ;设置被除数DIV AB ;结果A存商数,B存余数ADD A,#30H ;A为十位数,转换为字符PUSH B ;B放入堆栈暂存MOV B,X ;设置 LCD 显示的位置CALL LCDP2 ;由 LCD 显示出来POP B ;MOV A,B ;B为个位数ADD A,#30H ;转换为字符INC X ;LCD 显示位置加1MOV B,X ;设置 LCD 显示的位置CALL LCDP2 ;由 LCD 显示出来RET;-------------------------------------------;转换为 ASCII 码并显示;-------------------------------------------CONV:MOV A,HOUR ;加载小时数据MOV X,#5 ;设置位置CALL SHOW_DIG2 ;显示数据INC X ;MOV A,#':' ;MOV B,X ;CALL LCDP2 ;MOV A,MIN ;加载分钟数据INC X ;设置位置CALL SHOW_DIG2 ;显示数据INC X ;MOV A,#':' ;MOV B,X ;CALL LCDP2 ;MOV A,SEC ;加载秒数数据INC X ;设置位置CALL SHOW_DIG2 ;显示数据INC X ;MOV A,#':' ;MOV B,X ;CALL LCDP2 ;MOV A,SEC0 ;加载秒数数据INC X ;设置位置CALL SHOW_DIG2RET;---------------------------------------------------------; LCD CONTROL;---------------------------------------------------------SET_LCD: ;对 LCD 做初始化设置及测试 CLR ENCALL INIT_LCD ;初始化 LCDMOV R5,#10CALL DELAYMOV DPTR,#MMENU ;指针指到显示消息1MOV A,#1 ;显示在第一行CALL LCD_PRINTMOV DPTR,#SLF ;指针指到显示消息2MOV A,#2 ;显示在第二行CALL LCD_PRINTRET;----------------------------------------------------------INIT_LCD1: ;LCD 控制指令初始化MOV A,#38H ;双列显示,字形5*7点阵CALL WCOM ;call delay1MOV A,#0CH ;开显示,显示光标,光标不闪烁 CALL WCOM ;call delay1MOV A,#01H ;清除 LCD 显示屏CALL WCOM ;call delay1RET;---------------------------------------------------------- ENABLE: ;写指令CLR RS ;RS=L,RW=L,E=高脉冲CLR RW ;D0-D7=指令码SETB ENACALL DELAY1CLR ENRET;----------------------------------------------------------LCD_PRINT: ;在LCD的第一行或第二行显示字符CJNE A,#1,LINE2 ;判断是否为第一行LINE1: MOV A,#80H ;设置 LCD 的第一行地址 CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#80H ;设置 LCD 的第一行地址CALL WCOM ;写入命令JMP FILLLINE2: MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#0C0H ;设置 LCD 的第二行地址CALL WCOMFILL: CLR A ;填入字符MOVC A,@A+DPTR ;由消息区取出字符CJNE A,#0,LC1 ;判断是否为结束码RETLC1: CALL WDATA ;写入数据INC DPTR ;指针加1JMP FILL ;继续填入字符RET;-------------------------------------------------------CLR_LINE: ;清除该行 LCD 的字符MOV R0,#16CL1: MOV A,#' 'CALL WDATADJNZ R0,CL1RET;-------------------------------------------------------DE: MOV R7,#250 ;延时500微秒DJNZ R7,$RET;-------------------------------------------------------EN1:CLR RWSETB EN ;短脉冲产生启用信号CALL DECLR ENCALL DERET;------------------------------------------------------INIT_LCD: ;8位I/O控制 LCD 接口初始化 MOV P1,#38H ;双列显示,字形5*7点阵call enablecall delay1MOV P1,#38H ;双列显示,字形5*7点阵call enablecall delay1MOV P1,#38H ;双列显示,字形5*7点阵call enablecall delay1CALL INIT_LCD1RET;-----------------------------------------------------WCOM: ;以8位控制方式将命令写至LCD MOV P1,A ;写入命令call enableRET;-----------------------------------------------------WDATA: ;以8位控制方式将数据写至LCD MOV P1,A ;写入数据SETB RS ;设置写入数据CALL EN1RET;-----------------------------------------------------;第二行显示字符;----------------------------------------------------- LCDP2: ;在LCD的第二行显示字符 PUSH ACC ;MOV A,B ;设置显示地址ADD A,#0C0H ;设置LCD的第二行地址 CALL WCOM ;写入命令POP ACC ;由堆栈取出ACALL WDATA ;写入数据RET;---------------------------------------------------- DELAY: ;延时10MSMOV R6,#50D1: MOV R7,#100DJNZ R7,$DJNZ R6,D1DJNZ R5,DELAYRET;----------------------------------------------------- DELAY1: ;延时5MSMOV R6,#25D2: MOV R7,#100DJNZ R7,$DJNZ R6,D2RET;----------------------------------------------------- BZ: ;蜂鸣器MOV R6,#100B1: CALL DEXCPL BEEPDJNZ R6,B1MOV R5,#10CALL DELAYRETDEX: MOV R7,#180DE1: NOPDJNZ R7,DE1RET;------------------------------------------------- MMENU: DB " SECOND-CLOCK 0 ",0slf: DB "TIME ",0 ;LCD 第二行显示消息MADJ: DB " BEGIN COUNT ",0MADJ1: DB " PAUST COUNT ",0END。
1602液晶显示(年月日时分秒星期)
电子钟—1602液晶显示(年月日时分秒星期)/* 以下是电子钟的c51源程序,用1602液晶显示,虽然程序很庞大,但容易看懂。
改程序花了我两三天的时间才弄好的,现在放在此分享。
*/#include<AT89X52.H>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define T 49998#define T1 64536sbit rs=P2^0;sbit rw=P2^1;sbit en=P2^2;uchar key,n,loca=0,allow=0,cout;uchar week;uchar time[6]={0,6,15,12,30,0}; //对应、月、日、时、分、秒?uint year=2009;void delay(uint ms){uint i;for(;ms>0;ms--){for(i=246;i>0;i--);}}void timer0() interrupt 1{TH0=(65536-T)/256;TL0=(65535-T)%256;n++;}void time_addsec(){if(20<=n){n=0;time[5]++; //产生秒}}uchar key_scan(){uchar i,j,key,temp;uchar code scan[]={0xfe,0xfd,0xfb,0xf7};uchar code keyb[]={0x7e,0xbe,0xde,0xee,0x7d,0xbd,0xdd,0xed,0x7b,0xbb,0xdb,0xeb,0x77,0xb7,0xd7,0xe7};for(i=0;i<4;i++){P3=scan[i];_nop_();temp=P3;if(temp!=scan[i]){for(j=0;j<16;j++){if(keyb[j]==P3){delay(50);// while(keyb[j]==P3);//松手操作// delay(20);// while(keyb[j]==P3);key=j+1;break;}if(keyb[j] != P3){key=0;}}}}return key;}bit lcd_bz()//1602检忙{bit v;rs=0;rw=1;en=1;_nop_();v=(bit)(P0&0x80);en=0;return v;}void lcd_wcmd(uchar cmd)//1602写命令{while(lcd_bz());rs=0;rw=0;en=0;_nop_();P0=cmd;_nop_();en=1;_nop_();_nop_();en=0;_nop_();rs=0;}void lcd_wdat(uchar dat)//1602写数据{while(lcd_bz());rs=1;rw=0;en=0;_nop_();P0=dat;_nop_();en=1;_nop_();;en=0;}void lcd_wstr(uchar *str)//1602写字符串{uchar i;for(i=0;str[i]!='\0';i++){lcd_wdat(str[i]);}}void lcd_pos(uchar pos)//光标定位{while(lcd_bz());lcd_wcmd(pos|0x80);}/*void lcd_cur(){switch(loca){case 0 : lcd_pos(0x46); case 1 : lcd_pos(0x49); case 2 : lcd_pos(0x05); case 3 : lcd_pos(0x08); case 4 : lcd_pos(0x0b); }}*/void lcd_rmove()//光标右移{if(1==allow){if(loca >= 0 && loca < 5) {loca++;}}}void lcd_lmove(){if(1==allow){if(loca > 0 && loca <= 5) {loca--;}}}void lcd_addtime()//调时间加{uint dat ;if(1==allow)switch(loca){case 0 :{dat=year;dat++;year=dat;delay(100);break;}case 1 :{dat=time[1];dat++;if(dat>12)dat=1;time[1]=dat;delay(100);break; }case 2 :{dat=time[2];dat++;if(dat>30)dat=1;time[2]=dat;delay(100);break; }case 3 :{dat=time[3];dat++;if(dat>24)dat=1;time[3]=dat;delay(100);break; }case 4 :{dat=time[4];dat++;if(dat>60)dat=1;time[4]=dat;delay(100);break; }case 5 :{dat=time[5];dat++;if(dat>60)dat=1;time[5]=dat;delay(100);break; }}}void lcd_detime()//调时间减{int dat ;if(1==allow)switch(loca){case 0 :{dat=year;dat--;if(dat<0)dat=2000;year=dat;delay(100);break;}case 1 :{dat=time[1];dat--;if(dat<0)dat=12;time[1]=dat;delay(100);break; }case 2 :{dat=time[2];dat--;if(dat<0)dat=30;time[2]=dat;delay(100);break; }case 3 :{dat=time[3];dat--;if(dat<0)dat=23;time[3]=dat;delay(100);break; }case 4 :{dat=time[4];dat--;if(dat<0)dat=59;time[4]=dat;delay(100);break; }case 5 :{dat=time[5];dat--;if(dat<0)dat=59;time[5]=dat;delay(100);break;}}}void function(){uchar key=key_scan();switch(key){case 5 : lcd_lmove();break;case 6 : lcd_rmove();break;case 7 : lcd_addtime();break;case 8 : lcd_detime();break;case 9 : lcd_wcmd(0x0f);allow=1;break; //显示光标case 10 : lcd_wcmd(0x0c);allow=0;break; //关闭光标}}bit year_tell() //判断是否闰年是1 否0{if((year%4 == 0 && year%100 !=0) || year%400 == 0) return 1;else return 0;}uint count1(uint year , uchar mon , uchar day)//以下count1到count3都是为了计算对应的星期{uint m;switch(mon){case 1 : m=366-day; break;case 2 : m=335-day; break;case 3 : m=306-day; break;case 4 : m=275-day; break;case 5 : m=245-day; break;case 6 : m=214-day; break;case 7 : m=184-day; break;case 8 : m=153-day; break;case 9 : m=122-day; break;case 10 : m=92-day; break;case 11 : m=61-day; break;case 12 : m=31-day; break;default : ;}if(!(year%4 == 0 && year%100 != 0 || year%400 == 0)){if(mon<=2){m=m-1;}}return(m);}uint count2(uint year , uchar mon , uchar day){uint m;if(year%4 == 0 && year%100 != 0 || year%400 == 0){m=366-count1(year , mon , day);}else{m=365-count1(year , mon , day);}return m;}uint count3(uint year1 , uint year2){uint m=0;uchar i;uint n=year2-year1;for(i=1;i<n;i++){if((year1+i)%4 == 0 && (year1+i)%100 != 0 || (year1+i)%400 == 0) {m+=366;}else{m+=365;}}return m;}uchar week_tell()//判断对应的星期{uchar w;w=(count1(1901,1,7)+count2(year,time[1],time[2])+count3(1901,year)+1)%7; if(w!=0)return w;else return 7;}void timecount()//时间计算{if(time[5]>=60) //sec{time[5]=0;time[4]++;}if(time[4]>=60)//min{time[4]=0;time[3]++;}if(time[3]>=24)//hour{time[3]=0;time[2]++; //day}switch(time[1]) //mon{case 1 : if(time[2]>=31){time[2]=0; time[1]++;}case 2 :if(1==year_tell()){if(time[2]>29){time[2]=0; time[1]++;}}else{if(time[2]>28){time[2]=0; time[1]++;}}case 3 : if(time[2]>=31){time[2]=0; time[1]++;}case 4 : if(time[2]>=30){time[2]=0; time[1]++;}case 5 : if(time[2]>=31){time[2]=0; time[1]++;}case 6 : if(time[2]>=30){time[2]=0; time[1]++;} case 7 : if(time[2]>=31){time[2]=0; time[1]++;} case 8 : if(time[2]>=31){time[2]=0; time[1]++;} case 9 : if(time[2]>=30){time[2]=0; time[1]++;} case 10 : if(time[2]>=31){time[2]=0; time[1]++;} case 11 : if(time[2]>=30){time[2]=0; time[1]++;} case 12 : if(time[2]>=31){time[2]=0; time[1]++;} }if(time[1]>12){time[1]=0;year++;}}/*void lcd_clear(){lcd_wcmd(0x01);_nop_();}*/void lcd_display(uchar p)//液晶显示{uchar i,j;uchar str_com[14];str_com[13]=year/1000;str_com[12]=(year/100)%10;str_com[11]=(year%100)/10;str_com[10]=year%10;str_com[9]=time[1]/10;str_com[8]=time[1]%10;str_com[7]=time[2]/10;str_com[6]=time[2]%10;str_com[5]=time[3]/10;str_com[4]=time[3]%10;str_com[3]=time[4]/10;str_com[2]=time[4]%10;str_com[1]=time[5]/10;str_com[0]=time[5]%10;if(0==p)//非设定状态{lcd_pos(0x07);for(i=0,j=0;i<8;i++,j++){if(2==i || 5==i){lcd_wdat(':');j--;}elselcd_wdat(str_com[j]+48);}lcd_pos(0x49);for(i=6,j=6;i<16;i++,j++){if(8==i || 11==i){lcd_wdat('-');j--;}elselcd_wdat(str_com[j]+48);}delay(1 );lcd_wcmd(0x06);lcd_pos(0x4c);switch(week_tell()){case 1 : lcd_wstr("Mon");break;case 2 : lcd_wstr("Tue");break;case 3 : lcd_wstr("Wen");break;case 4 : lcd_wstr("Thu");break;case 5 : lcd_wstr("Fri");break;case 6 : lcd_wstr("Sat");break;case 7 : lcd_wstr("Sun");break;}delay(1 );lcd_wcmd(0x04);}else if(1==p)//时间设定状态{lcd_pos(0x07);lcd_wdat(str_com[0]+48);lcd_wdat(str_com[1]+48);switch(loca) //下面是让光标定在选择位,以便光标稳定的闪烁{case 0 : lcd_pos(0x43);break; case 1 : lcd_pos(0x46);break; case 2 : lcd_pos(0x49);break; case 3 : lcd_pos(0x01);break; case 4 : lcd_pos(0x04);break; case 5 : lcd_pos(0x07);break; }}}void lcd_init()//液晶初始化{delay(15);lcd_wcmd(0x38);delay(5);lcd_wcmd(0x38);delay(5);lcd_wcmd(0x38);while(lcd_bz());lcd_wcmd(0x0e);while(lcd_bz());lcd_wcmd(0x01);}void init(){TMOD=0x11;TH0=(65536-T)/256;TL0=(65536-T)%256;TH1=T1;TL1=T1;EA=1;TR0=1;ET0=1;TR1=0;ET1=1;}main(){init();lcd_init();while(1){// delay(3);// lcd_clear();delay(1 );lcd_wcmd(0x04);time_addsec();timecount();function();lcd_display(1);cout++;if(cout>=50){cout=0;lcd_display(0);}}}//程序到此结束,估计看了有点晕,不过没关系,程序是没有错的,定时很准,经调试在几个小时之后也达到分秒不差,晶振是12M。
通过51单片机及lcd1602实现可记录十组的秒表功能
#include<stdlib.h> //包含随机函数rand()的定义文件
#include<intrins.h> //包含_nop_()函数定义的头文件
sbit RS=P2^6; //寄存器选择位,将RS位定义为P2.0引脚
***************************************************/
void WriteData(unsigned char y)
{
while(BusyTest()==1);
RS=1; //RS为高电平,RW为低电平时,可以写入数据
E=1; //E置高电平
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四个机器周期,给硬件反应时间
E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令
}
/*****************************************************
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
unsigned char BusyTest(void)
{
bit result;
RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态
void WriteInstruction (unsigned char dictate)
{
while(BusyTest()==1); //如果忙就等待
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1602L C D显示秒表汇编//******************************************************************** *******//; K2=P3.3 K4=P3.5;* 1602LCD显示秒表 *;* K2 --- 控制按键 *;* 按一下计时,再按一下暂停计时 *;*;* K4 --- 清零按键: *;* 在任何状态下,按一下K4,均可清零。
*;* *;---------------------------------------;晶振 11.0592M;定时器0,方式1;计时中断程序每隔10ms中断一次;---------------------------------------TLOW EQU 0CH ;定时器初值THIGH EQU 0DCHHOUR EQU 30HMIN EQU 31HSEC EQU 32HSEC0 EQU 33H ;10ms计数值KEY_D EQU 34H ;为键当前的端口状况KEY_S EQU 35H ;为键上次的端口状况X EQU 36H ;LCD 地址变量KEY_C EQU 37H ;键计数单元;K1 EQU P3.2K2 EQU P3.3;K3 EQU P3.4K4 EQU P3.5BEEP EQU P2.4RS EQU P3.5 ;LCD控制端口定义 RW EQU P3.6EN EQU P3.7;---------------------------------------------------- ORG 0000HJMP STARTORG 0BHJMP T0_INT;---------------------------------------------------- START: MOV R3,#00HMOV SP,#60HCLR ENCALL SET_LCDCALL INIT ;初始化变量MOV KEY_S,#01HCALL INIT_TIMER ;初始化定时器 ; CALL MENULOOP: CALL CONV ;时间计数处理CALL SKEYMOV KEY_S,KEY_DJZ XPMOV A, KEY_SJB ACC.0,XPCLR AMOV B,AINC R3MOV A,R3MOV B,#2DIV ABMOV A,BCALL BZJZ XPPSETB TR0 ;启动中断MOV DPTR,#MADJ ;显示执行信息CALL P_KEYSJMP XPXPP:CLR TR0MOV DPTR,#MADJ1CALL P_KEYXP: JB K4,LOOP ;判清零键是否按?MOV R3,#00HCALL BZJMP START;-----------------------------------------------------P_KEY: MOV A,#1 ;第一行显示CALL LCD_PRINTRET;-------------------------------------------------------SKEY: CLR A ;判是否有键按下子程序MOV KEY_D,AMOV C,K2RLC AORL KEY_D,AMOV A,KEY_DXRL A,KEY_S ;有键按下,A 中内容不为零 RET;--------------------------------------------------------;LMESS1: DB " ",0 ;LCD 第一行显示消息;LMESS2: DB "TIME ",0 ;LCD 第二行显示消息;--------------------------------------------------------INIT: CLR A ;初始化控制变量MOV SEC,AMOV MIN,AMOV HOUR,AMOV KEY_D,AMOV KEY_S,ASETB BEEPCLR TR0RET;------------------------------------------------------------INIT_TIMER: ;初始化定时器接口MOV TMOD,#01H ;设置定时器0 工作模式为模式1 MOV IE, #82H ;启用定时器0 中断产生MOV TL0,#TLOWMOV TH0,#THIGHRET;-------------------------------------------------------------T0_INT:PUSH ACC ;定时器0计时中断程序MOV TL0,#TLOWMOV TH0,#THIGHINC SEC0MOV A,SEC0 ;10ms 计数值加1CJNE A,#100,TTMOV SEC0,#0INC SEC ;秒加1MOV A,SECCJNE A,#60,TTINC MIN ;分加1MOV SEC,#0MOV A,MINCJNE A,#60,TTINC HOUR ;时加1MOV MIN,#0MOV A,HOURCJNE A,#24,TTMOV SEC,#0 ;秒、分、时单元清0MOV MIN,#0MOV HOUR,#0TT: POP ACCRETI;-------------------------------------------------------; 在第二行显示数字;-------------------------------------------------------SHOW_DIG2: ;在 LCD 的第二行显示数字 MOV B,#10 ;设置被除数DIV AB ;结果A存商数,B存余数ADD A,#30H ;A为十位数,转换为字符PUSH B ;B放入堆栈暂存MOV B,X ;设置 LCD 显示的位置CALL LCDP2 ;由 LCD 显示出来POP B ;MOV A,B ;B为个位数ADD A,#30H ;转换为字符INC X ;LCD 显示位置加1MOV B,X ;设置 LCD 显示的位置CALL LCDP2 ;由 LCD 显示出来RET;-------------------------------------------;转换为 ASCII 码并显示;-------------------------------------------CONV:MOV A,HOUR ;加载小时数据MOV X,#5 ;设置位置CALL SHOW_DIG2 ;显示数据INC X ;MOV A,#':' ;MOV B,X ;CALL LCDP2 ;MOV A,MIN ;加载分钟数据INC X ;设置位置CALL SHOW_DIG2 ;显示数据INC X ;MOV A,#':' ;MOV B,X ;CALL LCDP2 ;MOV A,SEC ;加载秒数数据INC X ;设置位置CALL SHOW_DIG2 ;显示数据INC X ;MOV A,#':' ;MOV B,X ;CALL LCDP2 ;MOV A,SEC0 ;加载秒数数据INC X ;设置位置CALL SHOW_DIG2RET;---------------------------------------------------------; LCD CONTROL;---------------------------------------------------------SET_LCD: ;对 LCD 做初始化设置及测试 CLR ENCALL INIT_LCD ;初始化 LCDMOV R5,#10CALL DELAYMOV DPTR,#MMENU ;指针指到显示消息1MOV A,#1 ;显示在第一行CALL LCD_PRINTMOV DPTR,#SLF ;指针指到显示消息2MOV A,#2 ;显示在第二行CALL LCD_PRINTRET;----------------------------------------------------------INIT_LCD1: ;LCD 控制指令初始化MOV A,#38H ;双列显示,字形5*7点阵CALL WCOM ;call delay1MOV A,#0CH ;开显示,显示光标,光标不闪烁 CALL WCOM ;call delay1MOV A,#01H ;清除 LCD 显示屏CALL WCOM ;call delay1RET;---------------------------------------------------------- ENABLE: ;写指令CLR RS ;RS=L,RW=L,E=高脉冲CLR RW ;D0-D7=指令码SETB ENACALL DELAY1CLR ENRET;----------------------------------------------------------LCD_PRINT: ;在LCD的第一行或第二行显示字符CJNE A,#1,LINE2 ;判断是否为第一行LINE1: MOV A,#80H ;设置 LCD 的第一行地址 CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#80H ;设置 LCD 的第一行地址CALL WCOM ;写入命令JMP FILLLINE2: MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM ;写入命令CALL CLR_LINE ;清除该行字符数据MOV A,#0C0H ;设置 LCD 的第二行地址CALL WCOMFILL: CLR A ;填入字符MOVC A,@A+DPTR ;由消息区取出字符CJNE A,#0,LC1 ;判断是否为结束码RETLC1: CALL WDATA ;写入数据INC DPTR ;指针加1JMP FILL ;继续填入字符RET;-------------------------------------------------------CLR_LINE: ;清除该行 LCD 的字符MOV R0,#16CL1: MOV A,#' 'CALL WDATADJNZ R0,CL1RET;-------------------------------------------------------DE: MOV R7,#250 ;延时500微秒DJNZ R7,$RET;-------------------------------------------------------EN1:CLR RWSETB EN ;短脉冲产生启用信号CALL DECLR ENCALL DERET;------------------------------------------------------INIT_LCD: ;8位I/O控制 LCD 接口初始化 MOV P1,#38H ;双列显示,字形5*7点阵call enablecall delay1MOV P1,#38H ;双列显示,字形5*7点阵call enablecall delay1MOV P1,#38H ;双列显示,字形5*7点阵call enablecall delay1CALL INIT_LCD1RET;-----------------------------------------------------WCOM: ;以8位控制方式将命令写至LCD MOV P1,A ;写入命令call enableRET;-----------------------------------------------------WDATA: ;以8位控制方式将数据写至LCD MOV P1,A ;写入数据SETB RS ;设置写入数据CALL EN1RET;-----------------------------------------------------;第二行显示字符;----------------------------------------------------- LCDP2: ;在LCD的第二行显示字符 PUSH ACC ;MOV A,B ;设置显示地址ADD A,#0C0H ;设置LCD的第二行地址 CALL WCOM ;写入命令POP ACC ;由堆栈取出ACALL WDATA ;写入数据RET;---------------------------------------------------- DELAY: ;延时10MSMOV R6,#50D1: MOV R7,#100DJNZ R7,$DJNZ R6,D1DJNZ R5,DELAYRET;----------------------------------------------------- DELAY1: ;延时5MSMOV R6,#25D2: MOV R7,#100DJNZ R7,$DJNZ R6,D2RET;----------------------------------------------------- BZ: ;蜂鸣器MOV R6,#100B1: CALL DEXCPL BEEPDJNZ R6,B1MOV R5,#10CALL DELAYRETDEX: MOV R7,#180DE1: NOPDJNZ R7,DE1RET;------------------------------------------------- MMENU: DB " SECOND-CLOCK 0 ",0slf: DB "TIME ",0 ;LCD 第二行显示消息MADJ: DB " BEGIN COUNT ",0MADJ1: DB " PAUST COUNT ",0END。