/******************************************************************************** * 标题: xl系列单片机实验仪演示程序 1602液晶秒表程序 * * 文件: XLlcdmb.asm * * 日期: 2006-1-5 * * 版本: 3.0 (试验通过版)可用xl600-xl1000单片机综合试验仪试验 * * 邮箱: sxj1974@163.com * * 网站: http://www.51c51.com www.8951.com * ******************************************************************************** ;功能描述: * ; 1602LCD显示秒表 * ;1602液晶引脚定义 LCD_RS P2.0 LCD_RW P2.1 LCD_EN P2.2 LCD数据 p0口 * ; K3 p3.4--- 控制按键 * ; 第一次按下时,开始计时,第二次按下时,暂停计时。 * ; 第三次按下时,累计计时,第四次按下时,暂停计时。 * ; K4 p3.5 --- 清零按键:喇叭:P3.7口 * ; 在任何状态下,按一下K4,均可清零。 * ;可同时显示:时、分、秒、毫秒(带有两位ms级显示) * ******************************************************************************** * 【版权】 Copyright(C)深圳市学林电子有限公司 www.51c51.com * * 【声明】 此程序仅用于学习与参考,引用请注明版权和作者信息! * * 【技术支持】请访问http://www.51c51.com/bbs/ 官方论坛 * ********************************************************************************/
TLOW EQU 00H ;10ms定时初值 THIGH EQU 0DCH
HOUR EQU 30H ;时存放单元 MIN EQU 31H ;分存放单元 SEC EQU 32H ;秒存放单元 SEC0 EQU 33H ;10MS计数值存放单元 KEY_S EQU 34H ;为键当前的端口状况 KEY_V EQU 35H ;为键上次的端口状况 KEY_C EQU 36H ;键计数单元 LCD_X EQU 37H ;LCD 地址变量
BEEP EQU P3.7 ;蜂鸣器控制端口 LCD_RS EQU P2.0 ;LCD控制端口 LCD_RW EQU P2.1 LCD_EN EQU P2.2 ;---------------------------------------------------- ;按键的独立键端口定义 ;---------------------------------------------------- K1 EQU P3.2 K2 EQU P3.3 K3 EQU P3.4 ;功能键 K4 EQU P3.5 ;复位键
;---------------------------------------------------- ;你可根据使用开发板的型号来选择独立键端口定义 ;---------------------------------------------------- ORG 0000H JMP MAIN ORG 0BH JMP T0_INT ORG 0080H ;---------------------------------------------------- MAIN: MOV SP,#60H ;设堆栈初值 MOV KEY_V,#01H ;设初值 CALL INIT_LCD ;初始化LCD CALL SET_LCD1 ;第一行显示信息
MOV R5,#30 CALL MENU ;第二行滚动显示网址 MAIN1: CALL DELAY100 ;停留3S。 DJNZ R5,MAIN1
;JMP $
CALL INIT_LCD ;初始化LCD CALL SET_LCD1 ;第一行显示信息 CALL SET_LCD2 ;第二行显示信息 CALL INIT ;初始化变量 CALL INIT_TIMER ;初始化定时器 LOOP: CALL CONV ;时间数据处理 JB K4,LOOP1 ;判清零键是否按下 CALL BEEP_BL ;蜂鸣器响一声 JNB K4,$ ;等待K4键释放 JMP MAIN ;软件复位 LOOP1: CALL SKEY ;判是否有键按下 JZ LOOP ;无键按下转LOOP MOV KEY_V,KEY_S ;交换数据 CALL P_KEY ;功能键处理 JMP LOOP ;------------------------------------------------------- ;判是否有键按下子程序
;有键按下,A 中内容不为零 ;无键按下,A 中内容则为零 ;------------------------------------------------------- SKEY: CLR A MOV KEY_S,A MOV C,K3 RLC A ORL KEY_S,A MOV A,KEY_S XRL A,KEY_V RET ;-------------------------------------------------------- ;功能键处理子程序
;根据K3键按下的次数来执行相应的功能 ;-------------------------------------------------------- P_KEY: MOV A,KEY_V JB ACC.0,P_KEY4 ; INC KEY_C ;键按下次数加1 MOV A,KEY_C CJNE A,#01H,P_KEY1 ;K3键是否第一次按下? SETB TR0 ;启动中断 MOV DPTR,#MADJ ;显示执行信息 MOV A,#1 ;LCD第一行显示信息字符串 CALL LCD_PRINT CALL BEEP_BL ;蜂鸣器响一声 RET P_KEY1: MOV A,KEY_C CJNE A,#02H,P_KEY2 ;K3键是否第二次按下? CLR TR0 ;停止中断 MOV DPTR,#MADJ1 ;显示执行信息 MOV A,#1 ;LCD第一行显示信息字符串 CALL LCD_PRINT CALL BEEP_BL ;蜂鸣器响一声 RET P_KEY2: MOV A,KEY_C CJNE A,#03H,P_KEY3 ;K3键是否第三次按下? SETB TR0 ;启动中断 MOV DPTR,#MADJ2 ;显示执行信息 MOV A,#1 ;LCD第一行显示信息字符串 CALL LCD_PRINT CALL BEEP_BL ;蜂鸣器响一声 RET P_KEY3: MOV A,KEY_C CJNE A,#04H,P_KEY4 ;K3键是否第四次按下? CLR TR0 ;关闭中断 MOV DPTR,#MADJ3 ;显示执行信息 MOV A,#1 ;LCD第一行显示信息字符串 CALL LCD_PRINT CALL BEEP_BL P_KEY4: RET ;-------------------------------------------------------- ;设置LCD初始化显示 ;-------------------------------------------------------- SET_LCD1: MOV DPTR,#LMESS1 ;指针指到显示信息1 MOV A,#1 ;显示在第一行 CALL LCD_PRINT RET SET_LCD2: MOV DPTR,#LMESS2 ;指针指到显示信息2 MOV A,#2 ;显示在第二行 CALL LCD_PRINT RET
LMESS1: DB " STOPWATCH 0 ",0 ;LCD 第一行显示 LMESS2: DB "TIME ",0 ;LCD 第二行显示
;-------------------------------------------------------- ;LCD 初始化子程序
;8位数据传送方式,双行显示,字形5*7点阵。 ;开显示,不显示光标。 ;-------------------------------------------------------- INIT_LCD: CALL DELAY5MS ;延时15MS CALL DELAY5MS CALL DELAY5MS MOV A,#38H ;双行显示,字形5*7点阵,8位数据。 CALL WCOM_NC ;不检测忙信号 CALL DELAY5MS MOV A,#38H ;双行显示,字形5*7点阵 CALL WCOM_NC ;不检测忙信号 CALL DELAY5MS MOV A,#38H ;双行显示,字形5*7点阵 CALL WCOM_NC ;不检测忙信号 CALL DELAY5MS
MOV A,#38H ;双行显示,字形5*7点阵 CALL WCOM ;检测忙信号 CALL DELAY5MS MOV A,#0CH ;开显示,不显示光标,光标不闪烁。 CALL WCOM CALL DELAY5MS MOV A,#01H ;清除 LCD 显示屏 CALL WCOM CALL DELAY5MS RET ;-------------------------------------------------------- ;初始化控制变量 ;-------------------------------------------------------- INIT: CLR A MOV KEY_C,A MOV SEC0,A MOV SEC,A MOV MIN,A MOV HOUR,A MOV KEY_S,A MOV KEY_V,A SETB BEEP CLR TR0 RET ;-------------------------------------------------------- ;初始化定时器子程序
;设置定时器0 工作模式为模式1 ;启用定时器0 产生中断 ;-------------------------------------------------------- INIT_TIMER: MOV TMOD,#01H MOV IE, #82H MOV TL0,#TLOW MOV TH0,#THIGH RET ;-------------------------------------------------------- ;定时器0计时中断服务子程序
;定时器0,方式1 ;10ms中断一次 ;-------------------------------------------------------- T0_INT: PUSH ACC MOV TL0,#TLOW MOV TH0,#THIGH INC SEC0 MOV A,SEC0 ;10MS 计数值加1 CJNE A,#100,TT MOV SEC0,#0 INC SEC ;秒加1 MOV A,SEC CJNE A,#60,TT INC MIN ;分加1 MOV SEC,#0 MOV A,MIN CJNE A,#60,TT INC HOUR ;时加1 MOV MIN,#0 MOV A,HOUR CJNE A,#24,TT MOV SEC0,#0 MOV SEC,#0 ;秒、分、时单元清零 MOV MIN,#0 MOV HOUR,#0 TT: POP ACC RETI
;-------------------------------------------------------- ;时间数据转换为 ASCII 码并显示 ;-------------------------------------------------------- CONV: MOV A,HOUR ;加载小时数据 MOV LCD_X,#5 ;设置位置 CALL SHOW_DIG2 ;显示数据 INC LCD_X ; MOV A,#':' ;显示“:” MOV B,LCD_X ; CALL LCDP2 ; MOV A,MIN ;加载分钟数据 INC LCD_X ;设置位置 CALL SHOW_DIG2 ;显示数据 INC LCD_X ; MOV A,#':' ;显示“:” MOV B,LCD_X ; CALL LCDP2 ; MOV A,SEC ;加载秒数数据 INC LCD_X ;设置位置 CALL SHOW_DIG2 ;显示数据 INC LCD_X ; MOV A,#':' ;显示“:” MOV B,LCD_X ; CALL LCDP2 ; MOV A,SEC0 ;加载秒数数据 INC LCD_X ;设置位置 CALL SHOW_DIG2 RET ;-------------------------------------------------------- ;在LCD1602的第二行显示数字 ;-------------------------------------------------------- SHOW_DIG2: MOV B,#10 ;设置被除数 DIV AB ;结果A存商数,B存余数 ADD A,#30H ;A为十位数,转换为字符 PUSH B ;B放入堆栈暂存 MOV B,LCD_X ;设置 LCD 显示的位置 CALL LCDP2 ;由 LCD 显示出来 POP B ; MOV A,B ;B为个位数 ADD A,#30H ;转换为字符 INC LCD_X ;LCD 显示位置加1 MOV B,LCD_X ;设置 LCD 显示的位置 CALL LCDP2 ;由 LCD 显示出来 RET ;-------------------------------------------------------- ;在LCD的第二行显示字符 ;-------------------------------------------------------- LCDP2: PUSH ACC ;入栈保护 MOV A,B ;设置显示地址 ADD A,#0C0H ;设置LCD的第二行地址 CALL WCOM ;写入命令 POP ACC ;由堆栈取出A CALL WDATA ;写入数据 RET ;-------------------------------------------------------- ;在LCD的第一行或第二行显示字符 ;-------------------------------------------------------- LCD_PRINT: CJNE A,#1,LINE2 ;判断是否为第一行 LINE1: MOV A,#80H ;设置 LCD 的第一行地址 CALL WCOM ;写入命令 CALL CLR_LINE ;清除该行字符数据 MOV A,#80H ;设置 LCD 的第一行地址 CALL WCOM ;写入命令 JMP FILL LINE2: MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM ;写入命令 CALL CLR_LINE ;清除该行字符数据 MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM FILL: CLR A ;填入字符 MOVC A,@A+DPTR ;由信息区取出字符 CJNE A,#0,LC1 ;判断是否为结束码 RET LC1: CALL WDATA ;写入数据 INC DPTR ;指针加1 JMP FILL ;继续填入字符 RET ;-------------------------------------------------------- ;清除 LCD 指定行的字符 ;“空白”的ASCII代码为20H。 ;-------------------------------------------------------- CLR_LINE: MOV R0,#24 CL1: MOV A,#20H ;' ' CALL WDATA DJNZ R0,CL1 RET
;-------------------------------------------------------- ;写控制指令子程序
;写控制指令到LCD ;传入参数: ACC(要写入的指令) ;RS=L,RW=L,E=高脉冲,D0-D7=指令码 。 ;-------------------------------------------------------- WCOM: ACALL CHECKBUSY WCOM_NC: MOV P0,A ;写入指令 CLR LCD_EN NOP NOP CLR LCD_RS CLR LCD_RW SETB LCD_EN ACALL DEL_250 CLR LCD_EN RET ;-------------------------------------------------------- ;写数据子程序
;写显示数据到LCD ;传入参数: ACC(要写入的数据) ;RS=H,RW=L,E=高脉冲,D0-D7=数据码 。 ;-------------------------------------------------------- WDATA: ACALL CHECKBUSY MOV P0,A ;写入数据 CLR LCD_EN NOP NOP SETB LCD_RS CLR LCD_RW SETB LCD_EN CALL DEL_250 CLR LCD_EN RET
DEL_250: MOV R7,#125 ;延时250微秒 DJNZ R7,$ RET ;-------------------------------------------------------- ;检测LCD控制器忙碌状态
;正常读写操作之前必须检测LCD控制器状态 ;BUSY FLAG(P0.7)=1时,忙,不能接收MCU送来的指令和数据。 ;BUSY FLAG(P0.7)=0时,闲,能够接收MCU送来的指令和数据。 ;读数据时 ;RS=L,RW=H,E=H,输出:D0-D7=数据 ;-------------------------------------------------------- CHECKBUSY: PUSH ACC MOV P0,#0FFH ;置P0口为输入状态 CLR LCD_EN NOP NOP SETB LCD_RW CLR LCD_RS SETB LCD_EN BUSYLOOP: NOP JB P0.7,BUSYLOOP CLR LCD_EN POP ACC RET
;-------------------------------------------------------- ;蜂鸣器响一声子程序 ;驱动交流蜂鸣器 ;-------------------------------------------------------- BEEP_BL: MOV R6,#150 BL1: CALL BL2 CPL BEEP DJNZ R6,BL1 CALL DELAY5MS CALL DELAY5MS CALL DELAY5MS RET
BL2: MOV R7,#180 BL3: NOP DJNZ R7,BL3 RET ;-------------------------------------------------------- ;延时5MS子程序 ;-------------------------------------------------------- DELAY5MS: MOV R6,#25 DEL1: MOV R7,#100 DJNZ R7,$ DJNZ R6,DEL1 RET ;--------------------------------------------------------
MADJ: DB " BEGIN COUNT 1 ",0 MADJ1: DB " PAUSE COUNT 2 ",0 MADJ2: DB " BEGIN COUNT 3 ",0 MADJ3: DB " PAUSE COUNT 4 ",0
;-------------------------------------------------------- ;第二行滚动显示网址子程序 ;-------------------------------------------------------- MENU: MOV A,#06H ;移动光标(光标加1) CALL WCOM CALL DELAY5MS
MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM ;写入命令 CALL CLR_LINE ;清除该行字符数据
MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM MOV DPTR,#CHAR
FILL1: CLR A ;填入字符 MOVC A,@A+DPTR ;由信息区取出字符 CJNE A,#0,LC2 ;判断是否为结束码 RET
LC2: CALL WDATA ;写入数据 INC DPTR ;指针加1 CALL DELAY100 CALL DELAY100 JMP FILL1 ;继续填入字符 RET CHAR: DB " www.51c51.com ",0 ;-------------------------------------------------- ;延时100MS子程序 ;-------------------------------------------------- DELAY100: MOV r7,#200 DL1: MOV r6,#250 DL2: DJNZ R6,DL2 DJNZ R7,DL1 RET ;-------------------------------------------------- END
|