📄 quansu.txt
字号:
ADNUMB EQU 30H;
DBUF0 DATA 50H;
ORG 00000H;
MOV SP, 60H;
LCALL CODEBLANK; 显示RAM区置"空"。
;LCALL DISCODE_N; 显示全灭。
ADSTART:
NOP;
NOP;
LCALL KEYOP;
JNB F0, ADSTART0; 没有键按下,转跳到开始。
MOV B, A;
CLR C;
SUBB A, #08H;
JNC ADSTART0; 输入的键值大于07,无效转跳到开始。
MOV A, B; 将输入的通道号保存在内存"ADNUMB"单元。
MOV ADNUMB, A;
LCALL BELL50; R
;LCALL BELL_2; 有输入且输入合法,蜂鸣器响2声。
MOV R2, #COUNT_1;
MOV R0, #CODEBUF;
MOV @R0, #7CH; 字型码显示缓存区放第一个字型"U"。
INC R0;
MOV DPTR, #DISTAB; 输入的AD0809通道号(0~7)的字型码
MOV A, ADNUMB; 放在显示缓存区,第二位字型。
MOVC A, @A+DPTR;
MOV @R0, A;
INC R0;
MOV @R0, #10H; 字型码显示缓存区放第三位字型"-"。
ADSTART0:
MOV DPTR, #0003H; 锁存通道号"ADNUMB"0~7,启动AD0809进行转换。
MOV A, ADNUMB; 取通道号,通道号在内存"ADNUMB"单元。
MOVX @DPTR, A;
ADEOC:
MOV DPTR, #0007H; 循环读取EOC信号。
MOVX A, @DPTR;
JNB ACC.4, ADEOC; 根据EOC信号,A/D 转换是否结束。
MOV DPTR, #0003H; 转换结束,读取转换结果。
MOVX A, @DPTR;
CLR C
SUBB A , #20 ; 数值与规定浓度比较。
JC GREEN
RED:
MOV A, #010H; 当数值大于规定浓度点亮红灯,启动蜂鸣器,彩灯闪烁。
OUT0:
LCALL TIME_100MS;
MOV P1, A;
LCALL TIME_100MS;
MOV P2, A;
LCALL TIME_100MS;
MOV P3, A;
LCALL TIME_100MS;
RL A;
JNB ACC.7, OUT0 ; 循环闪烁
MOV A, #0F0H; L12-L15 4盏红灯亮起
LCALL TIME_100MS;
MOV P2, A;
LCALL TIME_100MS;
LCALL BELL_10; 蜂鸣器响起
LJMP NEXT1;
GREEN:
MOV A, #001H; 当数值小于规定浓度点亮绿灯,彩灯闪烁。
OUT1:
LCALL TIME_100MS;
MOV P1, A;
LCALL TIME_100MS;
MOV P2, A;
LCALL TIME_100MS;
MOV P3, A;
LCALL TIME_100MS;
RL A;
JNB ACC.3, OUT1;
MOV A, #00FH
LCALL TIME_100MS;
MOV P2, A; L8-L11 4盏绿灯亮起
LCALL TIME_100MS;
LJMP NEXT1
NEXT1:
MOV DPTR, #0003H; 转换结束,读取转换结果。
MOVX A, @DPTR;
MOV DBUF0, A; A中A/D转换数值,暂存到DBUF0,DBUF0。
ANL A, #0F0H; A中16进制高4位的显示字型码,放到字型码显示
SWAP A; 缓存区的第四位。(前3位U X _ ,后面是 XX YYY)
MOV DPTR, #DISTAB;
MOVC A, @A+DPTR;
MOV R0, #CODEBUF; (R0 一直没有被使用, 所以可以不必重新赋值,为了
INC R0; 可靠对R0,重新赋值)
INC R0;
INC R0;
MOV @R0, A;
MOV A, DBUF0;
ANL A, #0FH; A中A/D转换数值,16进制低4位的显示字型码,
MOVC A, @A+DPTR; 放到字型码显示缓存区的第五位
INC R0;
MOV @R0, A;
MOV A, DBUF0; A中A/D转换数值,进行除法转换位3位十进制
LCALL HEXDIV; 数,暂存在DBUF中,百、十、个。
MOV R0, #CODEBUF; R0 一直没有被使用, 所有不必重新赋值。
INC R0;
INC R0;
INC R0;
INC R0;
INC R0; 将3位十进制数的显示字型码放CODEBUF中。
MOV R1, #DBUF1; 数值的百位放到第6位。
MOV A, @R1;
MOVC A, @A+DPTR;
MOV @R0, A;
INC R1; 数值的十位放到第7位。
INC R0;
MOV A, @R1;
MOVC A, @A+DPTR;
MOV @R0, A;
INC R1; 数值的个位放到第8位。
INC R0;
MOV A, @R1;
MOVC A, @A+DPTR;
MOV @R0, A;
MOV R0, #CODEBUF; 对字型码显示缓存区的字型加小数点。
INC R0;
INC R0;
MOV A, @R0; "-"后面加小数点。
ORL A, #01H;
MOV @R0, A;
INC R0;
INC R0;
MOV A, @R0; 16进制数后面加小数点。
ORL A, #01H;
MOV @R0, A;
INC R0;
INC R0;
INC R0;
MOV A, @R0; 10进制数后面加小数点。
ORL A, #01H;
MOV @R0, A;
MOV R7, #02H; 多次循环显示,AD采样时间大大延长
ADLOOP0: ;
MOV R6, #0FFH;
ADLOOP1:
LCALL DISCODE_N;
DJNZ R6, ADLOOP1;
DJNZ R7, ADLOOP0;
LJMP ADSTART
;*************************************************************************
;字型码显示子程序:
;显示字型码数据缓存区的N个单元。
CODEBUF EQU 38H; 要显示的单元地址
COUNT_1 EQU 08H; 显示的单元个数。
DISCODE_N:
SETB RS0;
SETB RS1;
MOV R2, #COUNT_1;
MOV R0, #CODEBUF;
MOV R3, #80H; 数码显示位置,从左边开始显示。
DISCODE1:
MOV A, @R0; 取显示单元第一个字型码
MOV DPTR, #0000H; 送字型码显示。
MOVX @DPTR, A;
MOV A, R3; 送显示位
MOV DPTR, #0001H;
MOVX @DPTR, A;
RR A; 修改显示位。
MOV R3, A;
INC R0; 修改显示单元地址
NOP;
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP; 关断显示,字型码变换时,全部显示关断。
NOP; 关断的作用是,字型与其显示的位是对应的,
;当显示下一位时,字型与位不可能同时改变,
CLR A; 如果先改变字型,在没有改变"位"时,那么
MOV DPTR, #0001H; 在原来的位显示了下一位的字型。采用关断的
MOVX @DPTR, A; 方法是:显示一位字型(持续10个NOP时间),所有
;位不显示,当显示字型改变设置后,使其对应位显示。
DJNZ R2, DISCODE1;
CLR RS0;
CLR RS1;
RET;
;************************************************************************
;共阴数码管显示字型码表。
;字型表共28个,表地址00~1BH,数字0~9(10个),字母A~F (6个),
;字母H、L、P、U、c、Y(6个),符号-、_、二、三、小数点、"空"(6个)。
;"空"字型码=00,字型码地址=1BH
DISTAB:
DB 0FCH,60H,0DAH,0F2H,66H; 表地址00~04H,数字0~4字型码。
DB 0B6H,0BEH,0E0H,0FEH,0F6H; 表地址05~09H,数字5~9字型码。
DB 0EEH,3EH,9CH,7AH,9EH,8EH; 表地址0A~0FH,字母A~F字型码。
DB 6EH,1CH,0CEH,7CH,0F0H,76H; 表地址10~15H,字母H、L、P、U、c、Y字型码。
DB 02H,10H,12H,92H,01H,00H; 表地址16~1BH,符号-、_、二、三、小数点、"空"
;二进制转换十进制
DBUF1 EQU 40H;
HEXDIV:
MOV R1, #DBUF1; A中的内容变为10进制
MOV B, #100;
DIV AB; 除以100,求得百位。
MOV @R1, A; 百位放在缓存区第一位
MOV A ,B
MOV B, #10;
DIV AB; 除以10,求得十位。
INC R1;
MOV @R1, A; 十位放在缓存区第二位
INC R1;
MOV A, B;
MOV @R1, A; 个位放在缓存区第三位
RET;
;***************************************************************************
;按键处理子程序:
;F0=1表示有键按下,键值在A中。程序使用R2、R3、R4、R5。子程序使用11区,退出时恢复为00区。
;使用R2~R5,MCS-51没有PUSH R 及POP R 指令,使用改变R0~R7映射区。
KEYOP:
SETB RS0; 改变R0~R7映射区。
SETB RS1;
CLR F0; 清标志F=1时有键盘输入。
MOV R2, #00H; R2键值(00~1BH)。
MOV R3, #00H;
MOV R4, #06H; 列数,决定扫描次数
MOV R5, #01111111B; 从第一(D7)列开始。
K_AGAIN:
MOV A, R5; 输出扫描列
MOV DPTR, #0002H;
MOVX @DPTR, A;
NOP;
NOP;
MOVX A, @DPTR; 输入行值。
ORL A, #0FH; 将输入的值变为××××1111,
CPL A; 求反,输入的值变为××××0000,
JNZ K_OPRAT; 求反后,如果不是全"0",表示有键按下。
MOV A, R5; 如果是全"0",表示没有键按下。
RR A;
MOV R5, A; 扫描列右移,表示扫描下一列,保存在R5。
MOV A, R2;
ADD A, #04H; 扫描列每移动一位,R2的值增加04(每列4行)。
MOV R2, A;
DJNZ R4, K_AGAIN; 6列是否扫描完,扫描6行,一次扫描结束。
CLR F0; 没有键按下,强调F0=0,退出子程序。
LJMP KEYEND;
;有键按下处理。
K_OPRAT:
CPL A; 恢复键值。
SWAP A; 4位键值置换到低4位。
SETB C;
K_NEXT:
RRC A;
JNC K_OP1; 移出行位值=0,由R3得到行值。
INC R3;
CJNE R3, #04H, K_NEXT; 行值为00~03,当R3=4,表示4行查找结束。
MOV R3, #00H;
LJMP K_AGAIN;
;有键按下,找到行值后出来。
K_OP1:
MOV A, R3; 由列值、行值得到键值。
ADD A, R2;
SETB F0; 设置有键输入标志F0。
KEYEND:
CLR RS0; 恢复R0~R7映射区。
CLR RS1;
RET;
;END
;*************************************************************************
;蜂鸣器响2声
BELL_2:
LCALL BELL50;
LCALL TIME_100MS;
LCALL BELL50;
RET;
;*************************************************************************
;蜂鸣器响10声
BELL_10:
MOV R0,#10
LCALL BELL50;
LCALL TIME_100MS;
DJNZ R0,BELL_10
RET;
;*************************************************************************
;蜂鸣器响50ms。
;使用的DPTR、A 保护。
BELL50:
PUSH DPH;
PUSH DPL;
PUSH A;
MOV A, #0FEH; 蜂鸣器响,持续时间30ms。(蜂鸣器响的时间可以
MOV DPTR, #0002H; 在1ms、2ms···,作为防抖应当在20ms以上。
MOVX @DPTR, A;
LCALL TIME_50ms;
MOV A, #0FFH;
MOVX @DPTR, A;
POP A;
POP DPL
POP DPH;
RET;
;*************************************************************************
;延时100ms子程序
;内层循环256×(2+1+1)=1ms
;整个延时大约100×1=100ms。
TIME_100ms:
MOV R6, #64H;
T1MS100:
LCALL TIME_1MS;
DJNZ R6, T1MS100;
RET;
;*************************************************************************
;延时50ms子程序,内层循环256×(2+1+1)=1ms
;整个延时大约50×1=50ms。
TIME_50ms:
MOV R6, #32H;
T1MS50:
LCALL TIME_1MS;
DJNZ R6, T1MS50;
RET;
;************************************************************************
;延时1ms子程序
TIME_1ms:
MOV R7, #00H; (一个循环256×4=1000微秒)
TIME_1ms0:
NOP;
NOP;
DJNZ R7, TIME_1MS0;
RET;
;************************************************************************
;显示缓存区内容置为"1BH",其显示代码为"空"。
CODEBLANK:
DISBUF EQU 38H; 要显示的单元地址。
COUNT EQU 08H; 显示连续单元的个数。
MOV A, #00H;
MOV R0, #DISBUF;
MOV R2, #COUNT;
RAMBLANK0:
MOV @R0, A;
INC R0;
DJNZ R2, RAMBLANK0;
RET;
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -