51单片机的多路温度采集系统程序

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

51单片机的多路温度采集系统程序
ORG 0000H
AJMP MAIN;
BUF EQU 40H ;显示缓冲区
MOTATA EQU 50H ;AD0809数据存放于此
WH EQU 48H ;温度上限数据存放区
WL EQU 58H ;温度下限数据存放区
BUFF1S EQU 38H;
BUFF1MS EQU 39H;
BUFF5S EQU 3AH;
INNAL EQU 3CH;
ALARMBUF EQU 33H
BUFFH EQU 31H ;八路LED报警信号红灯
BUFFL EQU 32H ;八路LED报警信号绿灯
BACK EQU 34H ;利用与BUF地址的重复修改路数
CHANNEL EQU 35H
TEMPBUF EQU 36H
READ_AD BIT 30H ;是否要读写AD0809的标志位
DISPIN BIT 31H;
SETWARN BIT 32H
SOLIDISP BIT 33H
ENTER BIT P1.2
SETH BIT 35H
SETL BIT 36H
SETIN BIT P1.3
ABYTEIN BIT p1.1
ORG 0003H
AJMP INT_0;
ORG 000BH
LJMP INT_T0
ORG 0100H
MAIN: MOV SP, #70H ;设置堆栈位置
SETB READ_AD ;初始化标志位
SETB EA ;开总中断
CLR SETWARN ;清除温度设置标志位
SETB SETIN ;当其为0时表示要进行通道数采集
LCALL INITWARN ;初始化温度上下限
LCALL INIT_2 ;初始化2#工作寄存器区
;主循环,启动ADC0809,从第一个通道开始读取
LOOP: JNB READ_AD,DIS ;若不读AD0809,则调显示,次标
志位也表示1s延时结束
;延时已
完毕,则计算要显示的温度路数及温度值
送缓冲区
LCALL WARN ;报警
CLR READ_AD ;清楚标志位
LCALL READ ;读取一次AD0809
LCALL DLY1MS ;此处加1ms的延时,
否则数码管会因中断的存在而产生闪动 LCALL ADJUST ;调整显示
;在此完成键盘检测及显示任务DIS: LCALL DISPLAY;
LCALL KEYCHK ;调键盘检测子程序
CJNE A,#0FFH, AKEY ;若有键按下,则跳转
LJMP LOOP ;若没有则循环AKEY: LCALL KEYFUNC;
CJNE A,#0FFH,CALLRPD ;验证按下的键是否为数字键,若是则处理输入
LJMP LOOP ;不为数字键则返回循环
CALLRPD: LCALL KEYRPD;
SJMP LOOP;
;*********初始化2#工作寄存器区************
INIT_2: PUSH PSW ;初始化2号工作寄存器区
SETB RS1;
CLR RS0 ;选择2号工作寄存器区
MOV R2, #00H ;存放要显示的路数
CLR DISPIN ;初始化路显示标志位;
MOV R0, #MOTATA ;R0充当指向MOTATA的指针
POP PSW;
RET;
;*******调整指针*********
PADJUST:
ONADJUST: DJNZ R2,INADJUST;
RET;返回
INADJUST: INC R0;
SJMP ONADJUST;
;*************计算并调整显示缓存区的数据*******
ADJUST: PUSH PSW ;保护
SETB RS1;
CLR RS0 ;选择2号工作寄存器区
CJNE R2,#08H,NE08;
GE08: MOV R2,#00H;
MOV R0,#MOTATA;
SJMP LESS08;
NE08: JNC GE08;
LESS08: JB SETWARN, DISPWARN ;若在设定温度,则也不调整显示
JB SOLIDISP, ADJEND ;若为固定显示,则跳过调整
JB DISPIN,DLY_5S ;若有键盘值输入,则延时5秒来暂时固定显示
INC R0 ;调整R0,
使其指向下一个要显示的温度值地址 INC R2 ;调整R2
mov channel,r2;
SJMP ADJEND;
DLY_5S: DJNZ BUFF5S,ADJEND;
CLR DISPIN;
LJMP ADJEND
DISPWARN: JB SETH,DISHIGH ;若在调整上限值则跳转到上限温度显示
JB SETL,DISLOW ;若在调整下限值则跳转到下限温度显示
SJMP ADJEND ;若不在调整则显示
输入路数的当前检测温度值
DISLOW: MOV R0,#WL ;将指针调整到温度上限存放区
SJMP ADAPT ;跳转到指针调整处
DISHIGH:MOV R0,#WH ;将指针调整到温度下限存放区
ADAPT: MOV R2,CHANNEL ;调整R2的值为通道数
LCALL PADJUST ;指针指向R2 ADJEND: LCALL LOADTEMP ;将当前指针指向数据放到缓冲区
POP PSW;
RET;
;**************** 将当前指针指向数据放到缓冲区******** LOADTEMP: LCALL COMPUTE ;调用COMPUTE得到要显示的当前温度值
MOV R1,#BUF;
MOV A,channel;
MOV @R1,A ;将路数送入显示缓冲区
INC R1 ;调整到要
显示温度值的缓冲区
JB SETH,DISPH ;若设定温度上限,则显示H
JB SETL,DISPL ;若设定温度下限,则显示L
Mov a,#10h ;消隐
SJMP DISP2
DISPH: MOV A,#11H
SJMP DISP2
DISPL: MOV A,#12H
DISP2: mov @r1,a;
INC R1;
MOV A,R5;
ANL A,#0FH;
MOV @R1,A ; 最低位 INC R1;
MOV A,R5;
ANL A,#0F0H;
SWAP A;
MOV @R1,A ;次低位 ,应当在此处添加小数点
INC R1;
MOV A,R4;
ANL A,#0FH;
MOV @R1,A ;次高位 INC R1;
MOV A,R4;
ANL A,#0F0H;
SWAP A;
MOV @R1,A ;最高位
RET;
;*************读取一次0809的内容***********
READ: MOV R6,#08H ;用中断的方式读取一次AD0809
MOV R0,#MOTATA ;0号工作寄存器区
MOV DPTR,#0FFFEH ;A0作为地址
MOV A,#00H ;表示先检测第一个通道
MOV INNAL,A ;将检测的路数保存
MOVX @DPTR,A ;开启ADC0809 SETB EX0 ;开外部中断0
RET ;若已读取完毕,则返回
;**********************显示子程序************
;要显示的数据入口为BUF(6位);1号工作寄存器区
DISPLAY: PUSH PSW ;压栈保护
SETB RS0;
CLR RS1 ;切换工作寄存器区到 1
MOV R0,#BUF
MOV R7,#06H
MOV R1,#01H
NEXTDIS: MOV A,@R0
MOV DPTR,#TABLE
MOVC A,@A+DPTR ;取段码
CJNE R7,#03H,NODIP ;显示小数点
ANL A,#07FH
NODIP: MOV DPTR,#0FFDCH
MOVX @DPTR,A ;送段码
MOV DPTR,#0FFDDH
MOV A,R1
MOVX @DPTR,A ;送位码
RL A
MOV R1,A
LCALL DLY1MS
INC R0 ;调整显示
DJNZ R7,NEXTDIS;
POP PSW;
RET
;**************************延时1ms****************************
DLY1MS: MOV BUFF1MS,#0F9H
DJNZ BUFF1MS,$
RET
;*************************按键检查子程序******************** KEYCHK:MOV A,#00H ;查看是否有键按下
MOV DPTR,#0FFDDH
MOVX @DPTR,A
MOV DPTR,#0FFDEH
MOVX A,@DPTR
CPL A
ANL A,#0FH
JNZ TEST ;若有键按下则检测,无则返回。

MOV A,#0FFH
RET
TEST: LCALL KEYTEST
LCALL DISPLAY
LCALL KEYTEST
CJNE A,BACK,NOKEYD
WAIT: LCALL DISPLAY;
MOV A,#00H ;等待键抬起
MOV DPTR,#0FFDDH
MOVX @DPTR,A
MOV DPTR,#0FFDEH
MOVX A,@DPTR
CPL A
ANL A,#0FH
JNZ WAIT ;若键未抬起,则继续等待
MOV A,BACK ;将检测到的键值送给A
SJMP CHKEND
NOKEYD: MOV A,#0FFH
CHKEND: RET
;**********************按键检测子程序******************** KEYTEST: MOV R0,#0FEH
MOV R1,#00H
MOV R2,#08H
NEXTL: MOV A,R0
MOV DPTR,#0FFDDH
MOVX @DPTR,A
MOV DPTR,#0FFDEH
MOVX A,@DPTR
CPL A
ANL A,#0FH
JNZ KEYDWN ;看按下的键是否在当前列
DJNZ R2,GOSCAN ;看是否扫描完毕,若没有则调整继续扫描
SJMP TSTEND ;若扫描完毕,则返回。

GOSCAN: MOV A,R0
RL A
MOV R0,A
INC R1
SJMP NEXTL
KEYDWN: MOV R3,#00H
LL0: RRC A
JC LL1
INC R3
SJMP LL0
LL1: MOV A,R3
MOV B,A
MUL AB
ADD A,R1 ;A中返回的为按下的键的代码
RET
TSTEND: MOV A,#0FFH
RET
;***********延时1s*******************
DLY_1S: MOV TMOD,#01H;
SETB ET0;
MOV TH0,#0F0H ;10ms
MOV TL0,#0D8H;
MOV buff1s,#100;
SETB TR0;
RET;
;*********定时器T0中断服务程序**********
INT_T0:CLR TR0 ;关计数器
DJNZ buff1s ;NEXT_10MS;若不到1s继续
SETB READ_AD;若到了,则置标志位
cpl p1.0;
clr et0;
SJMP T0_END;
NEXT_10MS: MOV TMOD,#01H
MOV TH0,#0F0H ;定时10ms
MOV TL0,#0D8H
SETB TR0
T0_END: RETI
;*************计算子程序,完成一路计算**************** COMPUTE: MOV A,@R0;
MOV B,#04H ;测得的温度数乘以4
MUL AB;
MOV R6,B;
MOV R7,A;
LCALL HB2 ;调用子程序转化为压缩BCD码,R4,R5为出口
RET;
HB2: CLR ;BCD码初始化
MOV R4,A
MOV R5,A
MOV R3,#10H ;转换双字节十六进制整数
HB3: MOV A,R7 ;从高端移出待转换数的一位到CY中
RLC A
MOV R7,A
MOV A,R6
RLC A
MOV R6,A
MOV A,R5 ;BCD码带进位自身相加,相当于乘2
ADDC A,R5
DA A ;十进制调整
MOV R5,A
MOV A,R4
ADDC A,R4
DA A
MOV R4,A
DJNZ R3,HB3 ;处理完16bit
RET;
;********报警子程序*********
WARN: MOV R0,#MOTATA ;R0指向MOTATA
MOV R1,#WH ; R1指向WH
MOV R7,#08H ;R7为循环次数
WLOOP:MOV A,@R0
MOV ALARMBUF,@R1 ;与指令相适应的必要中转
CJNE A,ALARMBUF,RED
GEHIGH: CLR C ;红灯信号
LJMP NEXTRED
RED : JNC GEHIGH ;读入数值比预设大
SETB C
NEXTRED:MOV A,BUFFH
RLC A ;压入红灯信号
MOV BUFFH,A
MOV A,R1 ;调整R1指向WL
ADD A,#10H
MOV R1,A
MOV ALARMBUF,@R1
MOV A,@R0
CJNE A,ALARMBUF,GREEN
LSLOW: CLR C ;绿灯信号
LJMP NEXTGRN
GREEN: JC LSLOW ;读入数值比预设小
SETB C
NEXTGRN:MOV A,BUFFL
RLC A
MOV BUFFL,A
MOV A,R1
SUBB A,#10H
MOV R1,A
INC R1
INC R0
DJNZ R7,WLOOP
MOV A,BUFFH ;将红灯报警信息送出
MOV DPTR,#0FBFFH ;红灯信号对应地址p2.2
MOVX @DPTR,A
MOV A,BUFFL ;将绿灯报警信息送出
MOV DPTR,#0F7FFH ;绿灯信号对应地址p2.3
MOVX @DPTR,A
RET
;************键位调整程序************
KEYFUNC: MOV DPTR,#KEYTABLE
ANL A,#0FH ;消除键位干扰
MOVC A,@A+DPTR ;调整跳转位置
CJNE A,#0AH,K1
MOV A,#0FFH
SETB SETIN
SETB SETH ;表示要设定温度报警上限值 CLR SETL
RET;
K1: CJNE A,#04H,K2
MOV A,#0FFH
SETB SETIN
SETB SETL ;表示要设定温度报警下限值 CLR SETH
RET
K2: CJNE A,#0FH,K3
MOV A,#0FFH
JB SETWARN,ENDISP
SETB SETWARN
CLR ABYTEIN
CLR SETH
CLR SETL
CLR ENTER
RET
ENDISP: CLR SETWARN;
CLR SETH;
CLR SETL;
RET;
K3: CJNE A,#0EH,K4
MOV A,#0FFH
JB SOLIDISP,ENSOLID;
SETB SOLIDISP
RET
ENSOLID: CLR SOLIDISP
RET
K4: CJNE A,#0CH,K5
MOV A,#0FFH;
CLR SETIN;
CLR SETH;
CLR SETL;
RET;
K5: CJNE A,#0DH,K6
MOV A,#0FFH
SETB ENTER
RET;
K6: RET
KEYTABLE: db 07h,04h,08h,05h,09h,06,0Ah
; 0, 1 ,2 ,3 ,4 ,5 ,6
db 04h,01h,00h,02h,0Fh,03h,0Eh,0Ch,0Dh
; 7 ,8 ,9 ,10 ,11,12, 13, 14 ,15
;*********实现对各个设定键的响应**********
KEYRPD: JB SETWARN,WARNSET ;根据SOLIDISP的值调显示
PUSH PSW;
SETB RS1;
CLR RS0 ;选择2号工作寄存器区
MOV R0,#MOTATA;
MOV CHANNEL,A ;将读入的值放入通道缓冲
MOV R2,A;
MOV BACK,A;
MOV BUF,A;
LCALL PADJUST ;调整R0,使其指向R2通道的温度值 SETB DISPIN ;5s计时的标志位
MOV BUFF5S,#05H ;初始化5s计时
MOV R2,CHANNEL;
POP PSW;
RET ;调整完毕,返回
WARNSET:JNB SETIN,INSET ;若未设定通道,先进行设定
LJMP SETTEMP ;若已设定则跳转到温度设定处INSET: MOV CHANNEL,A
RET
SETTEMP:JB SETH,HIGHSET ;设定温度警告上限
JB SETL,LOWSET ;设定温度警告下限
RET
HIGHSET: LCALL READTEMP
MOV R0,#WH ;调整R0使其指向温度上限存储区
LJMP STORESET
LOWSET: LCALL READTEMP
MOV R0,#WL ; 调整R0使其指向温度下限存储区STORESET:MOV A ,TEMPBUF;
LCALL COMPACT ;将输入的数转化为16进制数存储(未改变R0)
MOV R2,CHANNEL ;送入要调整到的位置
LCALL PADJUST ;调用调整子程序
MOV @R0 ,A ; 将温度值送到相应的位置
RET
READTEMP: JB ABYTEIN,READLOW;若已经有一位读入则读取低位READHIGH: SWAP A;
MOV TEMPBUF,A;
SETB ABYTEIN;
RET;
READLOW: ORL A,TEMPBUF;
MOV TEMPBUF,A;
CLR ABYTEIN;
RET;
;**********将输入温度值转化为16进制数********** COMPACT: MOV R2,A;
ANL A,#0FH ;分离出十进制数的低位
SWAP A;
MOV R3,A;
MOV A,R2;
ANL A,#0F0H ;分离出十进制数的高位
SWAP A;
MOV R2,A;
LCALL BH2 ;将双字节BCD码转化为十六进制整数
MOV A,R2 ;将R2R3中的数除以4
CLR C;
RRC A;
MOV R2,A;
MOV A,R3;
RRC A;
MOV R3,A
MOV A,R2;
RRC A;
MOV A,R3
RRC A ;转换完毕A中为要得到的16进制数
RET;
;*********双字节BCD码整数转换成双字节十六进制整数********* BH2: MOV A,R3 ;将低字节转换成十六进制
LCALL BCDH
MOV R3,A
MOV A,R2 ;将高字节转换成十六进制
LCALL BCDH
MOV B,#100 ;扩大一百倍
MUL AB
ADD A,R3 ;和低字节按十六进制相加
MOV R3,A
CLR A
ADDC A,B
MOV R2,A
RET
;*******单字节BCD码整数转换成单字节十六进制整数
BCDH: MOV B,#10H ;分离十位和个位
DIV AB
MOV R4,B ;暂存个位
MOV B,#10 ;将十位转换成十六进制
MUL AB
ADD A,R4 ;按十六进制加上个位
RET
;********初始化WH和WL********
INITWARN: MOV R0,#WH;
MOV A,#0AFH;
MOV R7,#08H;
INITHIGH: MOV @R0,A;
DJNZ R7,HIGHINC;
SJMP ENDHIGH;
HIGHINC: INC R0;
SJMP INITHIGH;
ENDHIGH: MOV R0,#WL;
MOV A,#04BH;
MOV R7,#08H;
INITLOW: MOV @R0,A;
DJNZ R7,LOWINC;
SJMP ENDLOW;
LOWINC: INC R0;
SJMP INITLOW;
ENDLOW: RET;
;***********外部中断0的服务程序**********
;完成一个循环的数据读取
INT_0: CLR EX0 ; 若转换完毕关中断
MOV DPTR,#0FFFEH;
MOVX A,@DPTR ;读取转换完毕后的数
MOV @R0,A ;将转换完毕的数保存
DJNZ R6,READNEXT;若未读取完毕则调整后继续
LCALL DLY_1S;
SJMP EX0_END;
READNEXT: INC R0;
INC INNAL;
MOV A,INNAL;
MOVX @DPTR,A ;再次启动AD0809
SETB EX0 ;开外部中断0
EX0_END: RETI;
TABLE: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H
DB 80H,90H,88H,83H,0C6H,0A1H,86H,8EH
DB 0FFH,089H,0C7H;
END。

相关文档
最新文档