本带LCD的时间控制器,是在本人毕业时间《基于单片机的时间控制器的设计》的基础上进行修改的。
使得时间的控制和修改更容易,更直观。并扩展了红外遥控的功能,但由于条件限制,并没有把此功能
的程序加上。
按键说明:
K1 设置当前时间/按键超过1s,则置整点报时标志
K2 显示控制时间/小时加
K3 设置控制时间/分钟加
K4 控制ON/OFF设置/确定
K5 控制开/关
ELEC 继电器
SPK 蜂鸣器
Y_LED 继电器工作指示
C_LED 被控电器指示灯
W_LED 计时工作指示灯
D_LED 整点报时指示灯
实物图:
程序代码:
;=============================
; 带LCD的时间控制器
; DIPS082-LCD
; KS0066-控制器
;=============================
LO EQU 24 ; 加载低字节
HI EQU 99 ; 加载高字节
;-----------------------------
CO EQU 200 ; 5ms中断计数时间常数
; 计数200次表示1s
ALB EQU 20H.0 ; 控制设置标志
CLOCK EQU 20H.1 ; 整点报时标志
HOUR EQU 30H ; 存放小时变量
MIN EQU 31H ; 存放分钟变量
SEC EQU 32H ; 存放秒钟变量
DEDA EQU 33H ; 5ms计数值
SEC0 EQU 34H ; 存放旧的秒数
;-----------------------------
DDRAM EQU 35H ; LCD地址变量
COM EQU 22H ; LCD指令寄存器
DAT EQU 21H ; LCD数据寄存器
COUNT EQU 22H ; 计数器
HH EQU 36H ; 控制设置小时变量
MM EQU 37H ; 控制设置分钟变量
;-----------------------------
; KEY4.....
K1 EQU P2.1 ; 设置当前时间
K2 EQU P2.0 ; 显示控制时间/小时加
K3 EQU P3.6 ; 设置控制时间/分钟加
K4 EQU P3.7 ; 控制ON/OFF设置/确定
K5 EQU P3.1 ; 控制开/关
;-----------------------------
; LCD .....
RS EQU P3.4 ; 寄存器选择
RW EQU P3.5 ; 读写控制
E EQU P3.3 ; LCD使能
;-----------------------------
ELEC EQU P3.0 ; 继电器
SPK EQU P2.2 ; 蜂鸣器
Y_LED EQU P2.6 ; 继电器工作指示
C_LED EQU P2.4 ; 被控电器指示灯
W_LED EQU P2.3 ; 计时工作指示灯
D_LED EQU P2.5 ; 整点报时指示灯
;-----------------------------
ORG 0000H ; 程序代码由地址0
JMP START ; 跳至主函数开始执行
ORG 000BH ; 定时器TIMER0中断地址
JMP T0_INT ; 跳至TIMER0中断启始地址
;#############################
; 主程序
;#############################
START:
CLR Y_LED ; 继电器工作指示关
CLR ELEC ; 继电器关
CLR CLOCK ; 清除整点报时标志
SETB D_LED ; 整点报时指示灯关
;-----------------------------
CLR ALB ; 清除控制标志
MOV HH,#0 ; 内定的控制时间为--00:00
MOV MM,#0
LCALL SET_LCD ; LCD初始化
LCALL BZ ; 蜂鸣器连续两次发音
LCALL BZ
LCALL LED_BL ; LED闪动,表示工作开始
LCALL INIT ; 初始化变量
LCALL INIT_TIMER ; 初始化定时器
LCALL MENU ;
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
; 循环程序
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
LOOP:
LCALL TIME_PRO ; 时间计时处理
; 按键扫描............
JB K1,L1 ; 未按下K1键则继续扫描
; K1.....时间设置/设整点报时
; K1 : ADJ TIME K2:HOUR K3:MIN K4: OK
LCALL D_LAY ; 1s延时
JNB K1,LL ; 按键超过1s,则设整点报时
LCALL BZ ; LED闪动
MOV DPTR,#MADJ ; 现实执行消息
MOV A,#1 ;
LCALL LCD_PRINT ; 在LCD显示字符
LCALL SET_TIME ; 设置目前时间
LCALL MENU ; 菜单
JMP LOOP ; 继续循环
;.............................
L1: JB K2,L2 ; 未按下K2键则继续扫描
; K2............控制时间显示
JNB K2,$ ; 等待K2键释放
LCALL BZ ; 蜂鸣器发音
MOV DPTR,#MLAL ; 显示控制消息
MOV A,#1 ;
LCALL LCD_PRINT ; 在LCD显示字符
LCALL LOOK_ATIME ; 查看控制时间
LCALL DELAY ; 延时
LCALL LED_BL ; 工作LED闪动
LCALL LED_BL ;
LCALL MENU ; 菜单
JMP LOOP ; 继续循环
;.............................
L2: JB K3,L3 ; 未按下K3键则继续扫描
; K3.....控制时间设置
; K3 : ADJ ATIME K2:HOUR K3:MIN K4: OK
JNB K3,$ ; 等待K3键释放
LCALL BZ ; 蜂鸣器发音
MOV DPTR,#MAADJ ; 显示控制消息
MOV A,#1 ;
LCALL LCD_PRINT ; 在LCD显示字符
LCALL SET_ATIME ; 控制时间设置
LCALL LED_BL ; 工作LED闪动
LCALL LED_BL
LCALL MENU ; 菜单
JMP LOOP ; 继续循环
LL: SJMP L6
;.............................
L3: JB K4,L4 ; 未按下K4键则继续扫描
; K4.......控制开关/确定
JNB K4,$ ; 等待K4键释放
CPL ALB ; 控制设置标志取反
JNB ALB,L31 ; 没有控制标志,则发音一声
; ALARM ON....................
CLR C_LED ; 控制指示灯亮
LCALL BZ ; 有控制标志,则蜂鸣器发音三声
LCALL BZ
LCALL BZ
JMP LOOP ; 返回
L31:
; ALARM OFF...................
SETB C_LED ; 控制指示灯灭
LCALL BZ ; 蜂鸣器发音一声
JMP LOOP ; 返回
;.............................
L4: JB K5,L5 ; 未按下K4键则继续扫描
;K5.........电器控制开/关
JNB K5,$ ; 等待K5键释放
CPL Y_LED ; LED取反
CPL ELEC
LCALL BZ ; 蜂鸣器发音一声
L5: JMP LOOP ; 返回
L6: CPL CLOCK ; 值整点报时标志
CPL D_LED ; 整点报时指示灯亮
LCALL DELAY
JMP LOOP ; 返回
;-----------------------------
LMESS1: DB "Wlecome!",0
LMESS2: DB " happy! ",0
;=============================
; 初始化控制变量子程序
;=============================
INIT:
MOV DEDA,#0 ; 5ms计数值清除为0
MOV SEC0,#0 ; 旧的秒数清除为0
MOV SEC,#0 ; 秒钟变量清除为0
MOV MIN,#0 ; 分钟变量清除为0
MOV HOUR,#1 ; 小时变量清除为1
RET ; 子程序返回
;=============================
;初始化定时器接口子程序
;=============================
INIT_TIMER:
MOV TMOD,#00000000B ; 设置定时器T0工作方式为方式0
MOV IE, #10000010B ;
MOV TL0,#LO ; 加载低字节
MOV TH0,#HI ; 加载高字节
SETB TR0 ; 启动定时器T0开始计时
RET
;*****************************
; 定时器0中断服务程序
;*****************************
T0_INT: ; 中断程序每隔5ms中断一次
PUSH ACC ; 累加器放入堆栈
MOV TL0,#LO ; 加载低字节
MOV TH0,#HI ; 加载高字节
INC DEDA ; 5ms计数值加1
; 1 SEC TIME OUT CHECK
MOV A,DEDA ; 5ms计数值
CJNE A,#CO,TT ; 是否1s到了?
MOV DEDA,#0 ; DEDA值0
CPL W_LED ; LED灯亮灭变换
INC SEC ; 秒计数加1
MOV A,SEC ; 秒数据放在累加器里,用于比较
CJNE A,#60,TT ; 是否到1 min?
; 1 MIN TIME OUT
INC MIN ; 分计数加1
MOV SEC,#0 ; 秒计数清除为0
MOV A,MIN
CJNE A,#60,TT ; 是否到1 h ?
; 1 HOUR TIME OUT
INC HOUR ; 小时计数加1
MOV MIN,#0 ; 分计数清除为0
MOV A,HOUR
CJNE A,#24,TT ; 是否24 h到了?
MOV SEC,#0 ; 秒钟变量清0
MOV MIN,#0 ; 分钟变量清0
MOV HOUR,#0 ; 小时变量清0
TT:
POP ACC ; 将累加器由堆栈取出
RETI ; 中断返回
;=============================
; 设置当前时间
; K2:HH K3:MM K4:OK
;=============================
; K2:HH K3:MM K4:OK
SET_TIME:
CLR TR0 ; 关定时器0
MOV SEC,#0 ; 秒钟变量清0
; SCAN 3 KEY TO ADJ...........
S0:
JB K2,S1 ; 未按下K2键则继续扫描
; 小时调整
LCALL BZ ; 蜂鸣器发音一声
INC HOUR ; 小时加1
MOV A,HOUR ; 小时值放在累加器中,用于比较
CJNE A,#24,S11 ; 是否24 h到了?
MOV HOUR,#0 ; 小时变量清0
S11:
LCALL CONV ; 转换LCD显示数据
MOV R5,#20 ;
LCALL DELAY ; 延时
JMP S0 ; 继续程序执行
;....................
S1: JB K3,S2 ; 未按下K3键则继续扫描
; 分钟调整
LCALL BZ ; 蜂鸣器发音一声
INC MIN ; 分钟加1
MOV A, MIN ; 分钟值放在累加器中,用于比较
CJNE A,#60,S21 ; 是否60 min到了?
MOV MIN,#0 ; 分钟变量清0
S21:
LCALL CONV ; 转换LCD显示数据
MOV R5,#20 ; 20*10ms
LCALL DELAY ; 延时
JMP S0 ; 继续程序执行
;.....................
S2: JB K4,S0 ; 未按下K4键则继续扫描
JNB K4,$ ; 有键按下则等待放开
; K4 KEYED OK ..........
LCALL BZ ; 设置完成,蜂鸣器发音两声
LCALL BZ ;
SETB TR0 ; 启动定时器
RET
;=============================
; LCD第一行显示程序
;=============================
; A:DIG X: LCD X POS
; SHOW ON LCD LINE1
SHOW_DIG:
MOV B,#10 ; 设置被除数
DIV AB ; 除法运算,结果A存商数,B存余数
ADD A,#30H ; A为十位数,转换为字符
PUSH B ; B放入堆栈暂存起来
MOV B,DDRAM ; 设置LCD显示的位置
LCALL LCDP1 ; 由LCD显示出来
POP B ; B由堆栈取出来
MOV A,B ; B为个位数
ADD A,#30H ; 转换为字符
INC DDRAM ; LCD显示位置加1
MOV B,DDRAM ; 设置LCD显示位置
LCALL LCDP1 ; 由LCD显示出来
RET
;=============================
; LCD第二行显示程序
;=============================
; A:DIG X: LCD X POS
; SHOW ON LCD LINE2
SHOW_DIG2:
MOV B,#10 ; 设置被除数
DIV AB ; 除法运算,结果A存商数,B存余数
ADD A,#30H ; A为十位数,转换为字符
PUSH B ; B放入堆栈暂存起来
MOV B,DDRAM ; 设置LCD显示的位置
LCALL LCDP2 ; 由LCD显示出来
POP B ; B由堆栈取出来
MOV A,B ; B为个位数
ADD A,#30H ; 转换为字符
INC DDRAM ; LCD显示位置加1
MOV B,DDRAM ; 设置LCD显示位置
LCALL LCDP2 ; 由LCD显示出来
RET
;=============================
; 转换显示当前时间子程序
; 时时:分分:秒秒
;=============================
CONV:
; SHOW HOUR...............显示小时数据
MOV A,HOUR ; 小时数据放在A中
MOV DDRAM,#0 ; 设置要显示的地址
LCALL SHOW_DIG2 ; 在第二行显示
INC DDRAM ; 显示地址加1
MOV A,#':' ; 加载" : "
MOV B,DDRAM ; LCD显示地址放入B中
LCALL LCDP2 ; LCD第二行显示程序
; SHOW MIN...............显示分钟数据
MOV A,MIN ; 分钟数据放在A中
INC DDRAM ; 显示地址加1
LCALL SHOW_DIG2 ; 在第二行显示
INC DDRAM ; 显示地址加1
MOV A,#':' ; 加载" : "
MOV B,DDRAM ; LCD显示地址放入B中
LCALL LCDP2 ; LCD第二行显示程序
; SHOW SEC...............显示秒钟数据
MOV A,SEC ; 秒钟数据放在A中
INC DDRAM ; 显示地址加1
LCALL SHOW_DIG2 ; 在第二行显示
RET
;****************************
; LCD初始化设置程序
; 并测试
;****************************
SET_LCD:
LCALL INIT_LCD ; 初始化LCD
MOV R5,#10 ; 10*10ms
LCALL DELAY ; 延迟一下
MOV DPTR,#LMESS1 ; 指针指在显示消息1
MOV A,#1 ; 显示在第一行上
LCALL LCD_PRINT ; 显示执行消息1于LCD第一行
MOV DPTR,#LMESS2 ; 指针指在显示消息2
MOV A,#2 ; 显示在第二行上
LCALL LCD_PRINT ; 显示执行消息2于LCD第二行
RET
;****************************
; LCD控制指令初始化设置
;****************************
INIT_LCD:
MOV COM,#38H ; 双行显示,8位数据,5X8点阵
LCALL W_COM
MOV COM,#06H ; 输入方式设置:AC自动加1
LCALL W_COM
MOV COM,#0CH ; 显示开,光标关
LCALL W_COM
MOV COM,#01H ; 清LCD显示屏
LCALL W_COM
RET
;****************************
; 清出LCD的第一行字符
;****************************
CLR_LINE1:
MOV COM,#80H ; 设置第一行地址
LCALL W_COM ; 写入地址
MOV R0,#8 ; 设置计数值
C1: MOV DAT,#' ' ; 载入空格符至LCD
LCALL W_DAT ; 输出字符至LCD
DJNZ R0,C1 ; 计数结束
RET
;****************************
; 在LCD显示字符
;****************************
; A=LINE 1 OR 2
; DPTR = MESSAGE POINTER
LCD_PRINT:
CJNE A,#1,LINE2 ; 判断是否为第一行
LINE1: MOV COM,#80H ; 设置LCD的第一行地址
LCALL W_COM ; 写入命令
LCALL CLR_LINE ; 清除该行字符数据
MOV COM,#80H ; 设置LCD的第一行地址
LCALL W_COM ; 写入命令
JMP FILL ; 填入字符
LINE2: MOV COM,#0C0H ; 设置LCD的第二行地址
LCALL W_COM ; 写入命令
LCALL CLR_LINE ; 清除该行字符数据
MOV COM,#0C0H ; 设置LCD的第二行地址
LCALL W_COM ; 写入命令
FILL:
CLR A ; A清零
MOVC A,@A+DPTR ; 由消息区取出字符
CJNE A,#0,LC1 ; 判断是否为结束码
RET
LC1:
MOV DAT,A ; 将数据放入LCD数据寄存器
LCALL W_DAT ; 写入数据
INC DPTR ; 指针加 1
JMP FILL ; 继续填入字符
RET
;****************************
; LCD清出显示
;****************************
CLR_LINE:
MOV R0,#8 ; 设置个数
CL1: MOV DAT,#' ' ; 载入空格符至LCD
LCALL W_DAT ; 输出字符至LCD
DJNZ R0,CL1 ; 计数结束
RET
;****************************
; 判断忙标志程序
;****************************
B_LCD: PUSH ACC ; 把ACC压入堆栈
CLR RS ; RS=1
SETB RW ; RW=1
B_LCD1: MOV P1,#0FFH ; P1口置"1"
SETB E ; E =1
MOV A,P1 ; 从P1口读出数据
NOP ; 空操作
CLR E ; E =0
JB ACC.7,B_LCD1 ; 判断忙标志
POP ACC ; 把ACC弹出堆栈
RET
;***************************
; 写命令到LCD程序
;***************************
W_COM: LCALL B_LCD ; 判断忙标志
CLR RS ; RS=0
CLR RW ; RW=0
SETB E ; E =1
MOV P1,COM ; 写入指令到P1口
CLR E ; E =0
RET
;***************************
; 写数据到LCD程序
;***************************
W_DAT: LCALL B_LCD ; 判断忙标志
SETB RS ; RS=1
CLR RW ; RW=0
SETB E ; E =1
MOV P1,DAT ; 写入数据
CLR E ; E =0
RET
;============================
; LCD第一行显示程序
;============================
LCDP1:
; LINE 1
PUSH ACC ; 将A放入堆栈
MOV A,B ; 设置显示地址
ADD A,#80H ; 设置LCD的第一行地址
MOV COM,A ; 把地址放入指令寄存器
LCALL W_COM ; 写入命令
POP ACC ; 由堆栈中取出A
MOV DAT,A ; 把数据放入数据寄存器
LCALL W_DAT ; 写入数据
RET
;============================
; LCD第二行显示程序
;============================
LCDP2:
; LINE 1
PUSH ACC ; 将A放入堆栈
MOV A,B ; 设置显示地址
ADD A,#0C0H ; 设置LCD的第二行地址
MOV COM,A ; 把地址放入指令寄存器
LCALL W_COM ; 写入命令
POP ACC ; 由堆栈中取出 A
MOV DAT,A ; 把数据放入数据寄存器
LCALL W_DAT ; 写入数据
RET
;****************************
; 延时程序
;****************************
; 总延迟 R5*10 ms
DELAY:
MOV R6,#50 ; R6存入50
D1: MOV R7,#100 ; R7存入100
DJNZ R7,$ ; R7不为零,则继续
DJNZ R6,D1 ; R6不为零,则继续
DJNZ R5,DELAY ; R5不为零,则继续
RET
; 1s 延时
D_LAY: MOV R5,#100
LCALL DELAY
RET
;****************************
; 工作LED闪动程序
;****************************
LED_BL:
MOV R4,#4 ; R4存入4
LE0: CPL W_LED ; 位反向
MOV R5,#10 ; 延迟 100 ms
LCALL DELAY ; 延时
DJNZ R4, LE0 ;
RET
;;***************************
; 菜单程序
;****************************
MMENU: DB "Now_Time",0 ; 正常走时第一显示
MADJ: DB "2H 3M 4K",0 ; 调时时第二显示
MLAL: DB "CtrlTime",0 ; 查看控制时间时第一显示
MAADJ: DB "2H 3M 4K",0 ; 调时时第二显示
MENU: ;LCD显示菜单
MOV DPTR,#MMENU ; 存入菜单地址
MOV A,#1 ;
LCALL LCD_PRINT ; 在LCD显示字符
RET
;****************************
; 发音程序
;****************************
BZ:
MOV R6,#0 ; R6值零
B1: LCALL DEX ; 短暂延迟
CPL SPK ; 蜂鸣器取反
DJNZ R6,B1 ;
MOV R5,#10 ; 10*10ms
LCALL DELAY ; 延时
RET
;--------------------
DEX: MOV R7,#180 ; 短暂延迟
DE1: NOP ; 空操作
DJNZ R7,DE1 ;
RET
;============================
; 查看已设置的控制时间
;============================
LOOK_ATIME:
; 显示小时数...............
MOV A,HH ; 调小时数据
MOV DDRAM,#0 ; 设置显示地址
LCALL SHOW_DIG2 ; 在第二行显示
INC DDRAM ; 显示地址加 1
MOV A,#':' ; 加载" : "
MOV B,DDRAM ; LCD显示地址放入B中
LCALL LCDP2 ; LCD第二行显示
; 显示分钟数...............
MOV A,MM ; 调小时数据
INC DDRAM ; 显示地址加 1
LCALL SHOW_DIG2 ; 在第二行显示
INC DDRAM ; 显示地址加 1
MOV A,#':' ; 加载" : "
MOV B,DDRAM ; LCD显示地址放入B中
LCALL LCDP2 ; LCD第二行显示
; 显示秒钟数...............
MOV A,#0 ; 设置秒为 00
INC DDRAM ; 显示地址加 1
LCALL SHOW_DIG2 ; 在第二行显示
RET
;============================
; 设置控制时间
; K2:HH K3:MM K4:OK
;============================
; K2:HH K3:MM K4:OK
SET_ATIME:
LCALL LOOK_ATIME ; 加载控制时间数据
; SCAN 3 KEY TO ADJ.........
AS0:
JB K2,AS1 ; 未按下K2键则继续扫描
; K2......... 调整小时
LCALL BZ ; 蜂鸣器响一声
INC HH ; 小时加1
MOV A, HH ; 小时值放在累加器中,用于比较
CJNE A,#24,AS11 ; 是否到24h?
MOV HH,#0 ; 小时清0
AS11:
LCALL LOOK_ATIME ; 加载控制时间数据
MOV R5,#20 ; 20*10ms
LCALL DELAY ; 延时
JMP AS0 ; 继续按键扫描
;....................
AS1: JB K3,AS2 ; 未按下K2键则继续扫描
; K3........ 分钟调整
LCALL BZ ; 蜂鸣器响一声
INC MM ; 分钟加1
MOV A,MM ;
CJNE A,#60,AS21 ; 是否到 60 min ?
MOV MM,#0 ; 分钟数清0
AS21:
LCALL LOOK_ATIME ; 加载控制时间数据
MOV R5,#20 ; 20*10ms
LCALL DELAY ; 延时
JMP AS0 ; 继续按键扫描
;.....................
AS2: JB K4,AS0 ; 未按下K4键则继续扫描
; K4........ 设置完成
JNB K4,$ ; 等K4键放开
SETB ALB ; 设置控制标志
CLR C_LED ; 控制指示灯亮
LCALL BZ ; 蜂鸣器发音三声
LCALL BZ ;
LCALL BZ
RET
;============================
; 更新时间并检查控制时间
;============================
TIME_PRO:
; UPDATE TIME...........
MOV A,SEC ; 加载当前秒数
MOV B,SEC0 ; 载入旧秒数
CJNE A,B,TI1 ; 是否过了1 s ?
JMP TI2 ; 检查是否启动控制器
TI1: LCALL CONV ; LCD显示时间数据
MOV SEC0,SEC ; 记录旧的秒数
TI2:
; 检查是否启动控制器
JB ALB,TI3 ; 有启动标志,则比较时间
JB CLOCK,TI4 ; 有启动标志,则比较时间
RET
TI3:
; 检查闹钟时间是否到了....
MOV A,HOUR ; 当前小时时间
MOV B,HH ; 控制小时时间
CJNE A,B,BK ; 检查控制小时时间
MOV A,MIN ; 当前分钟时间
MOV B,MM ; 控制分钟时间
CJNE A,B,BK ; 检查控制分钟时间
; TIME MATCH.................
LCALL TIME_OUT ; 到点工作程序
SJMP BK
; 检查是否为整点
TI4:
MOV A,SEC
CJNE A,#0,BK ; 秒是否为0?
MOV A,MIN ; 分是否为0?
CJNE A,#0,BK
MOV A,HOUR
TI40: LCALL BZ ; 多少时间就发音多少次
DEC A
MOV R5,#40
LCALL DELAY
CJNE A,#0,TI40
LCALL LED_BL ; W_LED闪烁
CPL CLOCK
CPL D_LED
BK:
RET
;****************************
; 到点工作程序
;****************************
TIME_OUT:
CPL Y_LED ; 继电器
CPL ELEC ; 被控制器件
M1: LCALL LED_BL ; 工作灯闪烁
LCALL BZ ; 蜂鸣器发音
; K4..........停止
JB K4,M1 ; 未按下K4键则继续扫描
JNB K4,$ ; 等待K4键释放
NOP
NOP
LCALL LED_BL ; 工作灯闪烁
CLR ALB ; 清除控制标志
SETB C_LED ; 关闭控制标志灯
RET
END
;-- 结束 --
;---------------------------
上一篇:单片机设计的电子琴
下一篇:内藏T6963C控制器的液晶模块的显示
推荐阅读最新更新时间:2024-03-16 15:00
- 热门资源推荐
- 热门放大器推荐