"); //-->
使用1602_LCD AT89S52 18B20 Keilc51编译调试实现的温度上下限可设定范围报警,时间可调显示,一天可设三个闹钟,八首音乐,一个秒表,4*4按键另加三个按键
全汇编实现(估计大家现在是不喜欢ASM了),呵呵,,程序差不多写满AT89S52 的8K BYTES 了
硬件电路比较简单,主要靠程序上的实现
在学校那时候可是花了咱近半个多月的时间。
不过程序写得比较乱,组织得也不好,很多还可以优化的地方,由于那时在学校赶时间,就没来得及优化修改了。。
;********************************************************
;使用1602_LCD AT89S52 18B20实现的温度报警,时间可调显示,
;一天可设三个闹钟,八首音乐,一个秒表,
;全汇编实现,程序差不多写满8K BYTES 了
;硬件电路比较简单,主要靠程序上的实现
;完成时间____2006\09\27\sml
;********系统初始化***********************
T2CON EQU 0C8H
CP_RL2 BIT 0C8H.0
C_T2 BIT 0C8H.1
TR2 BIT 0C8H.2
EXEN2 BIT 0C8H.3
TCLK BIT 0C8H.4
RCLK BIT 0C8H.5
EXF2 BIT 0C8H.6
TF2 BIT 0C8H.7
RCAP2H EQU 0CBH
RCAP2L EQU 0CAH
TH2 EQU 0CDH
TL2 EQU 0CCH
ET2 BIT IE.5
ORG 00H
JMP INPORT
ORG 0BH
LJMP TM0
ORG 001BH
LJMP INTT0
ORG 002BH
LJMP TIME_T2
ORG 30H
INPORT:
TMP_H EQU 29H ;温度高字节
TMP_L EQU 28H
TEMPHEAD EQU 6BH
DI_DA DATA 21H
SEC DATA 22H
MIN DATA 23H
HOUR DATA 24H
RS EQU P3.5;确定具体硬件的连接方式
RW EQU P3.4 ;确定具体硬件的连接方式
E EQU P3.3 ;确定具体硬件的连接方式
;秒表暂RAM单元定义
WATCH_H EQU 4DH
WATCH_M EQU 4EH
WATCH_S EQU 4FH
WATCH_MS EQU 50H
WATCH_H_H EQU 51H
WATCH_H_L EQU 52H
WATCH_M_H EQU 53H
WATCH_M_L EQU 54H
WATCH_S_H EQU 55H
WATCH_S_L EQU 56H
WATCH_MS_H EQU 57H
WATCH_MS_L EQU 58H
ALARM1_H EQU 59H
ALARM1_M EQU 5AH
ALARM2_H EQU 5BH
ALARM2_M EQU 5CH
ALARM3_H EQU 5DH
ALARM3_M EQU 5EH
ALARM1_H_H EQU 5FH
ALARM1_H_L EQU 60H
ALARM2_H_H EQU 61H
ALARM2_H_L EQU 62H
ALARM3_H_H EQU 63H
ALARM3_H_L EQU 64H
ALARM1_M_H EQU 65H
ALARM1_M_L EQU 66H
ALARM2_M_H EQU 67H
ALARM2_M_L EQU 68H
ALARM3_M_H EQU 69H
ALARM3_M_L EQU 6AH
STOPWATCH_FLAG1 EQU 04H
CLR 04H
ALARM1_ON_OR_OFF EQU 07H
ALARM2_ON_OR_OFF EQU 06H
ALARM3_ON_OR_OFF EQU 05H
;TEMPERATURE_ALARM_BEEP_FLAG EQU 04H;在温度CONTROL时,要考虑到这条件进去
KEY_SET EQU P0.3
KEY_UP EQU P0.4
KEY_DOWN EQU P0.5
DS18B20_FLAG EQU PSW.0;开始时要查18B20存在否
SET_FLAG EQU 01H
FLASH_FLAG EQU 02H
K_ON EQU 03H;是个位标志哦
SETB K_ON
SETB FLASH_FLAG
SETB SET_FLAG
CLR 07H
CLR 06H
CLR 05H
MOV A,#0
MOV 25H,A
MOV 26H,A
MOV 32H,A
MOV 33H,A
MOV R4,#14;
MOV TMOD,#11H
MOV TL0,#0B0H
MOV TH0,#3CH
SETB ET0
SETB TR0
SETB ET1
MOV DI_DA,#00H
CLR C_T2 ;
CLR CP_RL2;允许重载
;T2MOD的TO2是T2输出允许
MOV RCAP2H,#0D9H ;预先值高 10ms 12MHZ
MOV RCAP2L,#0B8H
MOV TH2,#0D9H
MOV TL2,#0B8H
SETB ET2
SETB EA
LCD_INIT://lcd的初化配置
;15MS
MOV R6,#30
LCALL DELAY_BY_R6 ;15ms
MOV P1,#38H ;写38h
LCALL WRITE_NOT_CHECK_BUSY
MOV R6,#10
LCALL DELAY_BY_R6 ;5ms
MOV P1,#38H
LCALL WRITE_NOT_CHECK_BUSY
MOV R6,#10
LCALL DELAY_BY_R6 ;5ms
;-----设转初始值
SETB E
MOV P1,#00000001B ;清屏并光标复位
LCALL ENABLE;调用写入命令子程序
MOV P1,#00111000B ;8位2行5x7点阵
LCALL ENABLE ;调用写入命令子程序
MOV P1,#00001100B ;显示器开、光标开、光标允许闪烁
LCALL ENABLE ;调用写入命令子程序
MOV P1,#00000110B;文字不动,光标自动右移
LCALL ENABLE ;调用写入命令子程序
STORE_DEFINE_DATA: ;把自定义字符存入CGRAM
MOV P1,#40H ;CGRAM起始地址
LCALL ENABLE
MOV R2,#8
MOV DPTR,#DEFINE_DATA
MOV R3,#0
NEXTP:
MOV A,R3
MOVC A,@A+DPTR
MOV P1,A
LCALL WRITE_DATA_TO_LCD
INC R3
DJNZ R2,NEXTP
;****************主程序*******************
START:
LCALL RESET
JNB 70h,MAIN1
MOV P1,#0C0H ;写入显示起始地址(第二行第一个位置)
LCALL ENABLE ;调用写入命令子程序(写入字符串前要查忙)
DS18B20_NOT_READY:
LCALL DISPLAY_18B20_ERROR
LOOP1:
LCALL RESET
JNB 70h,MAIN1
JMP LOOP1 ;如果栓测不到18b20程序下面不执行
MAIN1:
MOV R1,#4 ;清单元数据
MOV R0,#21H
CLEAR:MOV A,#0
MOV @R0,A
INC R0
DJNZ R1,CLEAR
MOV R1,#30
MOV R0,#4DH
CLEAR1:MOV A,#0
MOV @R0,A
INC R0
DJNZ R1,CLEAR1
MOV R1,#9
MOV R0,#6BH
CLEAR2:MOV A,#0
MOV @R0,A
INC R0
DJNZ R1,CLEAR2
MOV R1,#6
MOV R0,#40H
CLEAR3:MOV A,#0
MOV @R0,A
INC R0
DJNZ R1,CLEAR3
BACKK:
MOV P1,#00000001B ;清屏并光标复位
LCALL ENABLE;调用写入命令子程序
LCALL DISPLAY_WATING ;等待第一次结果.
LCALL SKIP_ROM
LCALL TEMP_CONV
LCALL DELAY_600MS
MOV P1,#00000001B ;清屏并光标复位
LCALL ENABLE;调用写入命令子程序
MAIN :
LCALL RESET
LCALL SKIP_ROM
LCALL RELCALL_EPROM ;调入温度限值
MAIN_MAIN:
LCALL READ_TEMP ;读18b20的内部温度
JB 70h,DS18B20_NOT_READY ;中途失败!
LCALL DATA_CONV ; 数据转换,同时有温度比较和报警动作标志K_ON=1则对应开机器
LCALL DISPLAY_18B20_TEMP
LCALL DISPLAY_TIME
LCALL CONTROL
LCALL ALARM_COMPARE
JNB KEY_SET,S1;KEY_SET是设定上下限的标志按钮P0.3。。。
LCALL TIME_ADJ
LCALL MUSIC
JMP MAIN_MAIN
S1:LCALL DELAY_2MS ;延时消抖
JB KEY_SET,MAIN
JNB KEY_SET,$;等待按键放开
LCALL KEY ;有键输入
AJMP MAIN
MUSIC:MOV A,#0F0H
MOV P2,A
MOV A,P2
CJNE A,#0F0H,KEYIN1
RET
KEYIN1:MOV R3,#0F7H;令第四行为0
MOV R1,#00H
SCAN: MOV A,R3
MOV P2,A
MOV A,P2
MOV R4,A;读回的值暂放R4中
SETB C
MOV R5,#04H;四列要扫描
K: RLC A
JNC DONE
INC R1
INC R1
DJNZ R5,K
MOV A,R3
SETB C
RRC A
MOV R3,A
JC SCAN
RET
DONE:MOV A,P2
XRL A,R4
JZ DONE
MOV A,R1
MOV DPTR,#FUNCTION_TAB
JMP @A+DPTR
FUNCTION_TAB:
AJMP FU0
AJMP FU1
AJMP FU2
AJMP FU3
AJMP FU4
AJMP FU5
AJMP FU6
AJMP FU7
AJMP FU8
AJMP FU9
AJMP FU10
AJMP FU11
AJMP FU12
AJMP FU13
AJMP FU14
AJMP FU15
FU0:
RET
FU1:
RET
FU2:
RET
FU3:
RET
FU4:
RET
FU5:;SETB P0.1
;CLR TEMPERATURE_ALARM_BEEP_FLAG
RET
FU6:
;MOV P1,#00000001B ;清屏并光标复位
;LCALL ENABLE;调用写入命令子程序
LCALL DISPLAY_ALARM_CLOCK_1;程序在后面加,只显示"ALARM_CLOCK_1"
ALARM_K:JB ALARM1_ON_OR_OFF,DISPLAY__ON
LCALL DISPLAY_ALARM_OFF
LJMP ALARM_DATACON_DIS
DISPLAY__ON:LCALL DISPLAY_ALARM_ON
;下面是转换
ALARM_DATACON_DIS:
MOV A,ALARM1_H
SWAP A
ANL A,#0FH
MOV ALARM1_H_H,A
MOV A,ALARM1_H
ANL A,#0FH
MOV ALARM1_H_L,A
MOV A,ALARM1_M
SWAP A
ANL A,#0FH
MOV ALARM1_M_H,A
MOV A,ALARM1_M
ANL A,#0FH
MOV ALARM1_M_L,A
;下面是显示闹钟值
MOV P1,#11000101B
LCALL ENABLE
MOV DPTR,#LED_DATA
MOV R1,ALARM1_H_H //已经是压缩型BCD码了,
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#LED_DATA
MOV R1,ALARM1_H_L //已经是压缩型BCD码了,
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#MAO
MOV R1,#0;从字串中的第一个开始显示
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#LED_DATA
MOV R1,ALARM1_M_H //已经是压缩型BCD码了,
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#LED_DATA
MOV R1,ALARM1_M_L //已经是压缩型BCD码了
MOV R0,#1
LCALL DISPLAY
;再下面就是判P0.30.40.5了
LOOPP: JB P0.4,PANP05;转判P0.5;;;;;;;;;
LCALL DELAY2S
JB P0.4,ADJ_ALARM_H ;如果一S之后为放开了,其实是在1S前就放开了的,则知道是调闹钟的小时值的
JNB P0.4,$;1S后还未放开,则等,1S后已经放开,则早就放开,所以进行不同操作
CPL ALARM1_ON_OR_OFF;如果一S后还为0则取反ALARM1_ON_OR_OFF标志,关掉闹钟
LJMP ALARM_K
ADJ_ALARM_H:MOV A,ALARM1_H
ADD A,#1
DA A
MOV ALARM1_H,A
CJNE A,#24H,ALARM_NEXT
MOV A,#0
MOV ALARM1_H,A
ALARM_NEXT:LJMP ALARM_DATACON_DIS;跳到先转换数据,再显示
PANP05:JB P0.5,PAN03; 如果此时P0.5也为1,则转判P0.3
LCALL DELAY2S
JNB P0.5,$;等放开
MOV A,ALARM1_M
ADD A,#1
DA A
MOV ALARM1_M,A
CJNE A,#60H,ALARM_NEXT
MOV A,#0
MOV ALARM1_M,A
LJMP ALARM_DATACON_DIS
PAN03: JB P0.3,LOOPP
LCALL DELAY2S
JB P0.3,DISPLAY_ALARM2 ;如果一S之后为放开了,其实是在1S前就放开了的,则知道是设闹钟2
JNB P0.3,$;
LJMP BACKK;如果长久按P0.3则跳出到主程序中去
;下面是设置第二个闹钟
DISPLAY_ALARM2:
LCALL DISPLAY_ALARM_CLOCK_2
ALARM_K1:JB ALARM2_ON_OR_OFF,DISPLAY__ON_2
LCALL DISPLAY_ALARM_OFF
LJMP ALARM_DATACON_DIS_2
DISPLAY__ON_2:LCALL DISPLAY_ALARM_ON
ALARM_DATACON_DIS_2:
MOV A,ALARM2_H
SWAP A
ANL A,#0FH
MOV ALARM2_H_H,A
MOV A,ALARM2_H
ANL A,#0FH
MOV ALARM2_H_L,A
MOV A,ALARM2_M
SWAP A
ANL A,#0FH
MOV ALARM2_M_H,A
MOV A,ALARM2_M
ANL A,#0FH
MOV ALARM2_M_L,A
;下面是显示闹钟值
MOV P1,#11000101B
LCALL ENABLE
MOV DPTR,#LED_DATA
MOV R1,ALARM2_H_H //已经是压缩型BCD码了,,
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#LED_DATA
MOV R1,ALARM2_H_L //已经是压缩型BCD码了,,
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#MAO
MOV R1,#0;从字串中的第一个开始显示
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#LED_DATA
MOV R1,ALARM2_M_H //已经是压缩型BCD码了,
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#LED_DATA
MOV R1,ALARM2_M_L //已经是压缩型BCD码了,,
MOV R0,#1
LCALL DISPLAY
;顺序执行下面的
LOOPPP: JB P0.4,PANP05_2;转判P0.5;;;;;;;;;还没有写此句程序呢后面
LCALL DELAY2S
JB P0.4,ADJ_ALARM_2_H ;如果一S之后为放开了,其实是在1S前就放开了的,则知道是调闹钟的小时值的
JNB P0.4,$;1S后还未放开,则等,1S后已经放开,则早就放开,所以进行不同操作
CPL ALARM2_ON_OR_OFF;如果一S后还为0则取反ALARM1_ON_OR_OFF标志,关掉闹钟
LJMP ALARM_K1
ADJ_ALARM_2_H:
MOV A,ALARM2_H
ADD A,#1
DA A
MOV ALARM2_H,A
CJNE A,#24H,ALARM_NEXT_2
MOV A,#0
MOV ALARM2_H,A
ALARM_NEXT_2:LJMP ALARM_DATACON_DIS_2;跳到先转换数据,再显示
PANP05_2:JB P0.5,PAN03_2; 如果此时P0.5也为1,则转判P0.3
LCALL DELAY2S
JNB P0.5,$;等放开
MOV A,ALARM2_M
ADD A,#1
DA A
MOV ALARM2_M,A
CJNE A,#60H,ALARM_NEXT_2
MOV A,#0
MOV ALARM2_M,A
LJMP ALARM_DATACON_DIS_2
PAN03_2: JB P0.3,LOOPPP
LCALL DELAY2S
JB P0.3,DISPLAY_ALARM3 ;如果一S之后为放开了,其实是在1S前就放开了的,则知道是设闹钟2
JNB P0.3,$;
LJMP BACKK;如果长久按P0.3则跳出到主程序中去
;下面是设置第三个闹钟
DISPLAY_ALARM3:
LCALL DISPLAY_ALARM_CLOCK_3
ALARM_K2:JB ALARM3_ON_OR_OFF,DISPLAY__ON_3
LCALL DISPLAY_ALARM_OFF
LJMP ALARM_DATACON_DIS_3
DISPLAY__ON_3:LCALL DISPLAY_ALARM_ON
ALARM_DATACON_DIS_3:
MOV A,ALARM3_H
SWAP A
ANL A,#0FH
MOV ALARM3_H_H,A
MOV A,ALARM3_H
ANL A,#0FH
MOV ALARM3_H_L,A
MOV A,ALARM3_M
SWAP A
ANL A,#0FH
MOV ALARM3_M_H,A
MOV A,ALARM3_M
ANL A,#0FH
MOV ALARM3_M_L,A
;下面是显示闹钟值
MOV P1,#11000101B
LCALL ENABLE
MOV DPTR,#LED_DATA
MOV R1,ALARM3_H_H //已经是压缩型BCD码了
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#LED_DATA
MOV R1,ALARM3_H_L //已经是压缩型BCD码了,,
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#MAO
MOV R1,#0;从字串中的第一个开始显示
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#LED_DATA
MOV R1,ALARM3_M_H //已经是压缩型BCD码了,
MOV R0,#1
LCALL DISPLAY
MOV DPTR,#LED_DATA
MOV R1,ALARM3_M_L //已经是压缩型BCD码了
MOV R0,#1
LCALL DISPLAY
;顺序执行下面的
LOOPPPP: JB P0.4,PANP05_3;转判P0.5;;;;;;;;;还没有写此句程序呢后面
LCALL DELAY2S
JB P0.4,ADJ_ALARM_3_H ;如果一S之后为放开了,其实是在1S前就放开了的,则知道是调闹钟的小时值的
JNB P0.4,$;1S后还未放开,则等,1S后已经放开,则早就放开,所以进行不同操作
CPL ALARM3_ON_OR_OFF;如果一S后还为0则取反ALARM1_ON_OR_OFF标志,关掉闹钟
LJMP ALARM_K2
ADJ_ALARM_3_H:
MOV A,ALARM3_H
ADD A,#1
DA A
MOV ALARM3_H,A
CJNE A,#24H,ALARM_NEXT_3
MOV A,#0
MOV ALARM3_H,A
ALARM_NEXT_3:LJMP ALARM_DATACON_DIS_3;跳到先转换数据,再显示
PANP05_3:JB P0.5,PAN03_3; 如果此时P0.5也为1,则转判P0.3
LCALL DELAY2S
JNB P0.5,$;等放开
MOV A,ALARM3_M
ADD A,#1
DA A
MOV ALARM3_M,A
CJNE A,#60H,ALARM_NEXT_3
MOV A,#0
MOV ALARM3_M,A
LJMP ALARM_DATACON_DIS_3
PAN03_3: JB P0.3,LOOPPPP
LCALL DELAY2S
JB P0.3,TO_FU6 ;如果一S之后为放开了,其实是在1S前就放开了的,则知道是设闹钟2
JNB P0.3,$;
LJMP BACKK;如果长久按P0.3则跳出到主程序中去
TO_FU6:LJMP FU6
;下面是主程序要调用的比较当前时钟与闹钟值
ALARM_COMPARE:
JNB ALARM1_ON_OR_OFF,ALARM2_COMPARE
MOV A,ALARM1_H
CJNE A,HOUR,ALARM2_COMPARE
MOV A,ALARM1_M
CJNE A,MIN,ALARM2_COMPARE
;CLR P0.1
;SETB TEMPERATURE_ALARM_BEEP_FLAG;置位此标志,为1时在后面的CONTROL中SETB P0.1时要考虑此标志为1则不要SETB P0.1了
CLR ALARM1_ON_OR_OFF
MOV A,#0
MOV ALARM1_H,A;响应闹钟后要清0
MOV ALARM1_M,A
LCALL FU12
LCALL DELAY2S
MOV A,#0F0H
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。