返回主页 单片机教程XL2000开发板 单片机学习 自制编程器 单片机资料 软件下载 电子技术产品介绍如何购买 论坛



/********************************************************************************
* 标题: 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