📄 01-15.asm
字号:
;==============================
;地址分配
;=============================
BYTECNT DATA 30H ;I2C字节计数器地址
BITCNT DATA 31H ;I2C位计数器地址
RTCADR DATA 32H ;PCF8563在I2C上从器件地址
RTCREGADR DATA 33H ;PCF8563内部寄存器地址
RECDATBUF DATA 40H ;接收数据缓冲区 (40H-45H)
SENDATBUF DATA 50H ;发送数据缓冲区
FINISH BIT 00H ;发送及接收成功标志;0成功,1表示失败
ACK BIT 20H ;接收数据非应答标志位
TIMEDATA DATA 70H ;时间设置与闹钟设定的时间临时缓冲区
KEYNAME DATA 34H ;b4~b0位记录按键值
;b7-作为按键有效标志,b7为0时,表示b4-b0位中的键值无效。
;b7为1时,表示b4-b0位记录的按键值有效,且未尚未处理,不能
;接受新按键。
;外部程序执行了按键功能后,将按键有效标志清0,允许接收新按键
;b6-保留。
KEYSTU DATA 35H ;键盘按键状态寄存器,其中b2、b1、b0分别记录最近
;三次定时中断的按键状态。
PORTDR DATA 36H ;U105(八上升沿D型触发器74HC273)芯片在内存中的影射地址
;设置影射地址的目的是为了在执行键盘扫描过程中不影响
;该输出口高3位(b7~b5)位内容
TIMEBELL DATA 37H ;蜂鸣器鸣响时间
BTIME DATA 38H ;50ms计数单元
DISPB BIT 01H ;50ms定时时间到标志
PORTA EQU 9000H ;8255A口地址
PORTB EQU 9100H ;8255B口地址
PORTC EQU 9200H ;8255C口地址
PORTS EQU 9300H ;8255控制/状态口地址
PORTD EQU 8800H ;U105(八上升沿D型触发器74HC273)地址
MOUSE DATA 3AH ;光标地址单元
CLONUM DATA 39H ;闹钟数量计数单元
CLONUM1 DATA 3DH ;闹钟序数
CLOADR1 DATA 3BH ;闹钟存储单元的首地址低四位
CLOADR2 DATA 3CH ;闹钟存储单元的首地址高四位
ALMTIME DATA 0000H ;将外部RAM的0000H~0DFH共256个单元作为定时时间
;保存区。8个单元(1个序号+6个具体时间) X 32个闹钟时间 = 224个单元
CONTROL1 EQU 50H ;定义控制寄存器1
CONTROL2 EQU 51H ;定义控制寄存器2
SEC EQU 52H ;定义秒初值存储地址
MIN EQU 53H ;定义分初值存储地址
HOUR EQU 54H ;定义时初值存储地址
DATE EQU 55H ;定义天初值存储地址
WEEK EQU 56H ;定义周初值存储地址
MONTH EQU 57H ;定义月初值存储地址
YEAR EQU 58H ;定义年初值存储地址
MINAL DATA 59H ;定义分定时初值存储地址
HOURAL DATA 5AH ;定义时定时初值存储地址
DATEAL DATA 5BH ;定义日定时初值存储地址
WEAKAL DATA 5CH ;定义星期定时初值存储地址
MONTHAL DATA 5DH ;定义月定时初值存储地址
YEARAL DATA 5EH ;定义年定时初值存储地址
ALMODE DATA 5FH ;闹钟模式地址(有1.2.3种模式 )
ALMODE1 BIT 10H ;闹钟辅助标志位(1:表示闹钟还有效;0表示无效)
TEMPER_L EQU 4BH ;用于保存读出温度的低8位
TEMPER_H EQU 4AH ;用于保存读出温度的高8位
FLAG1 EQU 4CH ;是否检测到DS18B20标志位
TEM1 EQU 4DH ;数码管个位数存放内存位置
TEM2 EQU 4EH ;数码管十位数存放内存位置
;===========================
;端口位定义
;===========================
SCL BIT P1.0 ;定义 P1.0为I2C总线串行时钟输入端
SDA BIT P1.1 ;定义P1.1为I2C总线串行数据双向输入输出端
RS BIT P1.4 ;定义P3.3为LCM寄存器选择控制端
R_W BIT P1.5 ;定义P3.4为LCM 读写控制端
E BIT P1.6 ;定义P3.5为LCM使能控制端
DB0_DB7 EQU P2 ;定义P0端口为LCD数据端口
IO BIT P1.7
;========================
;程序开始
;========================
ORG 0000H
LJMP MAIN
;ORG 0003H ;开INT0外中断
;LJMP INT0
;ORG 002BH ;定时器T2中断服务入口地址
;LJMP CTC2
ORG 0050H
PROC MAIN
MAIN:
MOV SP,#07FH ;重新设定SP起始位置
MOV DPTR,#8000H ;关闭峰鸣器
MOV A,#0FFH
MOVX @DPTR,A
MOV R0,#08H ;将080H-0FFH内部RAM清零
LOOP: MOV @R0,#0
INC R0
CJNE R0,#0,LOOP
;----------------------------------------------------------
;初始化U107(8255)可编程并行I/O接口芯片的工作方式
;----------------------------------------------------------
MOV DPTR, #PORTS ;8255控制/状态口地址
MOV A, #10011011B ;A口工作在方式0,输入;B口工作在方式0,输入;
;C口高、低半部暂时定义为输入
MOVX @DPTR, A ;送控制字寄存器
;将PD4~PD0置为高电平,使U105(74HC273)输出级截止,降低功耗。
MOV DPTR, #PORTD ;U105口地址送DPTR
MOV A, PORTDR ;读U105口在内存中的映象地址
ORL A, #1FH
MOVX @DPTR, A ;数据送U105输出口
SETB P1.3
;-----------------------------------------------------
;赋时间初值
;-------------------------------------------------
LCALL INITIAL ;初始化LCM
MOV 76H,#00H
MOV 75H,#01H
MOV 74H,#00H
MOV 73H,#01H
MOV 72H,#00H
MOV 71H,#01H
MOV 70H,#00H
;LCALL READTIME ;若时间不为零(即时间有效)则不用再赋初值
;MOV A,46H
;CJNE A,#00H,LOOP1
LCALL SENDTIME ;否则赋初值
MOV DPTR,#0000H ;清外部RAM
LOOP2:
MOV A,#00H
MOVX @DPTR,A
INC DPTR
MOVX A,@DPTR
CJNE A,#00H,LOOP2
MOV CLOADR1,#00H ;赋指针初值
MOV CLOADR2,#00H
CLR ALMODE1 ;清空闹钟模式标志位
LCALL INITIAL ;调用LCM初始化子程序
LOOP1:
LCALL READTIME ;调用时间读取子程序
MOV A,42H
CJNE A,#023H,NEXT1
CLR C
MOV A,41H
SUBB A,#059H
JNC NEXT2
CLR C
NEXT1:
LCALL DISP ;调用LCM显示子程序
LCALL TEMPER
LCALL DEL10MS ;调用50ms延时子程序
LCALL KEY ;调用键盘扫描程序
LCALL ALMCHECK ;调用闹钟与实时时间比较子程序
AJMP LOOP1 ;返回继续循环
NEXT2:
CLR ALMODE1
LCALL DISP
LCALL TEMPER
LCALL DEL10MS
AJMP LOOP1
END
;-------------------------------------------
;温度显示子程序
;----------------------------------------------
PROC TEMPER
TEMPER:
LCALL INIT_1820
LCALL RE_CONFIG
LCALL GET_TEMPER ;调用读温度子程序
;进行温度显示
;显示范围00到99度,显示精度为1度
;因为12位转化时每一位的精度为0.0625度,我们不要求显示小数所以可以抛弃29H的低4位
;将28H中的低4位移入29H中的高4位,这样获得一个新字节,这个字节就是实际测量获得的温度
MOV A,#0F0H
ANL A,4BH ; 舍去温度低位中小数点
SWAP A
MOV 4BH,A
MOV A,4BH
JNB ACC.3,TEMPER_COV1 ; 四舍五入去温度值
INC 4BH
TEMPER_COV1:
MOV A,4AH
ANL A,#07H
SWAP A
ADD A,4BH
MOV 4BH,A ; 保存变换后的温度数据
LCALL DISPLAY ;调用显示子程序
LJMP EXIT
;DS18B20复位初始化子程序
INIT_1820:
SETB IO
NOP
CLR IO
;主机发出延时537微秒的复位低脉冲
MOV R0,#0FAH
TSR1:
DJNZ R0,TSR1
SETB IO ;然后拉高数据线
NOP
NOP
NOP
MOV R0,#17H
TSR2:
JNB IO,TSR3 ;等待DS18B20回应
DJNZ R0,TSR2
LJMP TSR4 ;延时
TSR3:
SETB FLAG1 ;置标志位,表示DS1820存在
LJMP TSR5
TSR4:
CLR FLAG1 ;清标志位,表示DS1820不存在
LJMP TSR7
TSR5:
MOV R0,#0FCH
TSR6:
DJNZ R0,TSR6 ;时序要求延时一段时间
TSR7:
SETB IO
RET
RE_CONFIG:JB FLAG1,RE_CONFIG1 ; 若DS18B20存在,转RE_CONFIG1
RET
RE_CONFIG1:
MOV A,#0CCH ; 发SKIP ROM命令
LCALL WRITE_1820
MOV A,#4EH ; 发写暂存存储器命令
LCALL WRITE_1820
MOV A,#00H ; TH(报警上限)中写入00H
LCALL WRITE_1820
MOV A,#00H ; TL(报警下限)中写入00H
LCALL WRITE_1820
MOV A,#1FH ; 选择9位温度分辨率
LCALL WRITE_1820
RET
; 读出转换后的温度值
GET_TEMPER:
SETB IO
LCALL INIT_1820 ;先复位DS18B20
JB FLAG1,TSS2
RET ;判断DS1820是否存在?若DS18B20不存在则返回
TSS2:
;DS18B20已经被检测到!!!!!!!!!!!!!!!!!!
MOV A,#0CCH ;跳过ROM匹配
LCALL WRITE_1820
MOV A,#44H ;发出温度转换命令
LCALL WRITE_1820
MOV R5,#0DH
NEXT7:
LCALL DEL10MS
DJNZ R5,NEXT7
;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒
LCALL INIT_1820 ;准备读温度前先复位
MOV A,#0CCH ; 跳过ROM匹配
LCALL WRITE_1820
MOV A,#0BEH ; 发出读温度命令
LCALL WRITE_1820
LCALL READ_18200 ; 将读出的温度数据保存到35H/36H
RET
;**************************************写DS18B20的子程序(有具体的时序要求)
WRITE_1820:
MOV R2,#8 ;一共8位数据
CLR C
WR1:
CLR IO
MOV R3,#7
DJNZ R3,$
RRC A
MOV IO,C
MOV R3,#25
DJNZ R3,$
SETB IO
NOP
DJNZ R2,WR1
SETB IO
RET
;***************************************读DS18B20的程序,从DS18B20中读出两个字节的温度数据
READ_18200:
MOV R4,#2 ;将温度高位和低位从DS18B20中读出
MOV R1,#4BH ;低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)
RE00:
MOV R2,#8 ;数据一共有8位
RE01:
CLR C
SETB IO
NOP
NOP
CLR IO
NOP
NOP
NOP
SETB IO
MOV R3,#7
DJNZ R3,$
MOV C,IO
MOV R3,#23
RE20:
DJNZ R3,RE20
RRC A
DJNZ R2,RE01
MOV @R1,A
DEC R1
DJNZ R4,RE00
RET
;**********************************************************显示子程序
display:
MOV A,4BH ;将29H中的十六进制数转换成10进制
MOV B,#10 ;10进制/10=10进制
DIV AB
MOV TEM1,A ;十位在a
MOV TEM2,B ;个位在b
MOV A,#0CDH
LCALL WRITE_COM
CLR C
MOV A,#30H
ADD A,TEM1
LCALL WRITE_DATA
MOV A,#30H
CLR C
ADD A,TEM2
LCALL WRITE_DATA
MOV A,#0DFH
LCALL WRITE_DATA
EXIT:
RET
END
;-----------------------------------------
;闹钟与实时时间比较子程序
;------------------------------------------
PROC ALMCHECK
ALMCHECK:
LCALL READTIME ;读入此时时间
MOV R4,#8
LOOP1:
LCALL CLOLOCATE ;载入闹钟值子程序
MOV A,MINAL
CJNE A,41H,LOOP3 ;将第一个闹钟的时间从年到分逐一与实时时间的年到分比较若相等则报警
MOV A,HOURAL
CJNE A,42H,LOOP3
;比较闹钟模式选择,进行相应处理
MOV A,ALMODE
CJNE A,#02H,NEXT1 ;进入模式2,闹钟为一次性的
SJMP NEXT3
NEXT1:
CJNE A,#03H,NEXT2 ;进入模式3,闹钟为每日都有效
SJMP NEXT5
NEXT2:
CJNE A,#01H,NEXT3 ;进入模式1,闹钟为每周同一时间有效
SJMP NEXT4
NEXT3:
MOV A,DATEAL
CJNE A,43H,LOOP3
NEXT4:
MOV A,WEAKAL
CJNE A,44H,LOOP3
;MOV A,MONTHAL
;CJNE A,45H,LOOP3
;MOV A,YEARAL
;CJNE A,46H,LOOP3
NEXT5:
MOV C,ALMODE1
JC EXIT2
LCALL INITIAL
MOV A,#084H
LCALL WRITE_COM
MOV DPTR,#LINE7
LCALL DISP2
MOV A,#0C0H
LCALL WRITE_COM
MOV DPTR,#LINE8
LCALL DISP2
MOV A,ALMODE
CLR C
SUBB A,#01H
JC NEXT6
CLR C
SETB ALMODE1
NEXT6:
LCALL DEL5S
MOV A,KEYNAME
CJNE A,#00H,EXIT ;若有键盘输入则退出报警子程序
LCALL DEL2S ;停两秒后再报警
CJNE A,#00H,EXIT
LCALL DEL5S
EXIT:
LCALL INITIAL
;MOV DPL,CLOADR1
;MOV DPH,CLOADR2
MOV C,ALMODE1
JC EXIT2
MOV R2,#8
MOV DPTR,#0000H
MOV A,#0
LOOP2:
MOVX @DPTR,A
INC DPTR
DJNZ R2,LOOP2
;MOV CLOADR1,DPL
;MOV CLOADR2,DPH
NEXT10:
MOV A,#00H ;将键名清空
MOV KEYNAME,A
SJMP EXIT2
LOOP3:
;MOV A,#08H
;ADD A,CLOADR1
;MOV CLOADR1,A
;DJNZ R4,LOOP1
;MOV CLOADR1,#00H
EXIT2:
RET
END
;----------------------------------------------------
; 载入闹钟值子程序
;---------------------------------------------------
PROC CLOLOCATE
CLOLOCATE:
MOV DPL,CLOADR1
MOV DPH,CLOADR2
MOV DPTR,#0000H
NEXT1:MOV R5,#8
MOV R0,#059H ;提取的闹钟时间值放入以#059H为首的缓冲区内
LOOP: MOVX A,@DPTR
MOV @R0,A
INC DPTR
INC R0
DJNZ R5,LOOP
EXIT:
RET
END
;-----------------------------------------------------
;键盘响应子程序
;----------------------------------------------------
PROC KEYDO
KEYDO:
LOOP1:
LCALL INITIAL ;初始化LCM
MOV A,#080H ;显示功能选择菜单1
LCALL WRITE_COM
MOV DPTR,#LINE1
LCALL DISP2 ;调用字符串显示子程序
MOV A,#0C0H
LCALL WRITE_COM
MOV DPTR,#LINE2
LCALL DISP2
FUN1:
LCALL KEYWAIT
MOV A,KEYNAME
CJNE A,#00H,LOOP2
SJMP FUN1
LOOP2:
CJNE A,#011H,NEXT1 ;当按下"ESC"时退出 ,否则向下运行
LCALL INITIAL
LJMP EXIT2
NEXT1:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -