;********************************************************************************
;/******************************************************************************* ;* 标题: xl系列单片机实验仪演示程序 数码管秒表计时 * ;* 文件: XLmb.asm * ;* 日期: 2006-1-5 * ;* 版本: 3.0 (试验通过版)可用xl600-xl1000单片机综合试验仪试验 * ;* 邮箱: sxj1974@163.com * ;* 网站: http://www.51c51.com www.8951.com * ;******************************************************************************** ;* 描述: * ;* 数码管显示秒表, 分辨率0.01s * ;* K1---控制按钮 * ;* 第一次按下时, 启动开始计时 * ;* 第二次按下时, 停止 * ;* 第三次按下时, 归零 * ;* 引用资源:数码管数据 p0口,数码管控制p2口 控制按钮 p3.2口 * ;* 秒单位,寄存器与数码管对应关系: * ;* * ;* --- 秒单位 ---------- 数码管端口 ---- 缓冲区 --------- 计时BCD码值寄存器 * ;* 十万位 P20 dis_buf[7] sec_bcd[7] * ;* 万位 P21 dis_buf[6] sec_bcd[6] * ;* 千位 P22 dis_buf[5] sec_bcd[5] * ;* 百位 P23 dis_buf[4] sec_bcd[4] * ;* 十位 P24 dis_buf[3] sec_bcd[3] * ;* 个位(1.s) P25 dis_buf[2] sec_bcd[2] * ;* 十分位(0.1s) P26 dis_buf[1] sec_bcd[1] * ;* 百分位(0.01s) P27 dis_buf[0] sec_bcd[0] * ;* * ;******************************************************************************** ;* 【版权】 Copyright(C)深圳市学林电子有限公司 www.51c51.com * ;* 【声明】 此程序仅用于学习与参考,引用请注明版权和作者信息! * ;* 【技术支持】请访问http://www.51c51.com/bbs/ 官方论坛 * ;********************************************************************************/ ORG 0080h CODE_SEG SEGMENTCODE DATA_SEG SEGMENT DATA STACK_SEGSEGMENTIDATA RSEG DATA_SEG KEY_S: DS 1 KEY_V: DS 1 DIS_DIGIT: DS 1 DIS_INDEX: DS 1 SEC_BCD: DS 8; 秒计数值, BCD码 KEY_TIMES: DS 1; K1 按下次数 DIS_BUF: DS 8; 显示缓冲区 RSEGSTACK_SEG STACK:DS20 K1BITP3.2 ;=============================================================================== CSEGAT0000H LJMPMAIN CSEGAT0000BH LJMPTIMER0 CSEGAT0001BH LJMPTIMER1 ;=============================================================================== RSEGCODE_SEG MAIN: USING0 MOVSP,#(STACK-1)
MOV P0,#0FFH; 初始化端口 MOV P2,#0FFH MOV TMOD,#011H; MOV TH1,#0DCH CLR A MOV TL1,A MOV TH0,#0FCH MOV TL0,#017H LCALLCLR_TIME; 清零计时值 MOV DIS_DIGIT,#07FH; 上电时选通P27数码管 CLR A MOV DIS_INDEX,A MOV KEY_TIMES,A MOV KEY_V,#01H MOV IE,#08AH; 使能timer0, timer1中断 SETB TR0 CLR TR1 MAIN_LP: LCALLSCAN_KEY; 键扫描 JZ MAIN_LP; 无键返回 MOVR7,#10; 延时10ms LCALLDELAYMS; 延时去抖动 LCALLSCAN_KEY; 再次扫描 JZMAIN_LP; 无键返回 MOV KEY_V,KEY_S; 保存键值 LCALLPROC_KEY; 键处理 SJMPMAIN_LP; 调回主循环 ;=============================================================================== CLR_TIME: CLR A MOV SEC_BCD,A; 清零所有计时值 MOV SEC_BCD+01H,A MOV SEC_BCD+02H,A MOV SEC_BCD+03H,A MOV SEC_BCD+04H,A MOV SEC_BCD+05H,A MOV SEC_BCD+06H,A MOV SEC_BCD+07H,A LJMP UPDATE_DISBUF; 更新显示缓冲区 ;=============================================================================== SCAN_KEY: CLR A MOV KEY_S,A MOV C,K1; 读按键状态 RLC A ORL KEY_S,A MOV A,KEY_S XRL A,KEY_V; RET ;=============================================================================== PROC_KEY: MOV A,KEY_V JB ACC.0,END_PROC_KEY INC KEY_TIMES MOV A,KEY_TIMES CJNE A,#01H,PROC_KEY1 SETB TR1; KEY_TIMES =1,第一次按下K1, 启动开始计时 RET PROC_KEY1: MOV A,KEY_TIMES CJNE A,#02H,PROC_KEY2 CLR TR1; KEY_TIMES =2, 第二次按下K1, 停止计时 RET PROC_KEY2: LCALLCLR_TIME; 第三次按下K1, 清零计时值 CLR A MOV KEY_TIMES,A; 清零KEY_TIMES END_PROC_KEY: RET ;=============================================================================== TIMER0: ; 定时器0中断服程序, 用于数码管的动态扫描 ; DIS_INDEX --- 显示索引, 用于标识当前显示的数码管和缓冲区的偏移量 ; DIS_DIGIT --- 位选通值, 传送到P2口用于选通当前数码管的数值, 如等于0xfe时, ;选通P2.0口数码管 ; DIS_BUF --- 显于缓冲区基地址 PUSH ACC PUSH PSW PUSH AR0 MOV TH0,#0FCH MOV TL0,#017H MOV P2,#0FFH; 先关闭所有数码管 MOV A,#DIS_BUF; 获得显示缓冲区基地址 ADD A,DIS_INDEX; 获得偏移量 MOV R0,A; R0 =基地址 + 偏移量 MOV A,@R0; 获得显示代码 MOV P0,A; 显示代码传送到P0口 MOV P2,DIS_DIGIT; MOVA,DIS_DIGIT; 位选通值右移(P20<-P27), 下次中断时选通下一位数码管 RRA MOVDIS_DIGIT,A INCDIS_INDEX; DIS_INDEX加1, 下次中断时显示下一位 ANLDIS_INDEX,#0x07; 当DIS_INDEX等于8(0000 1000)时, 清0 POP AR0 POP PSW POP ACC RETI ;=============================================================================== TIMER1: PUSH ACC PUSH B PUSH DPH PUSH DPL PUSHPSW PUSHAR7 ORL TH1,#0DCH; 恢复定时器初值 CLR A MOV R7,A MOV A,#LOW (SEC_BCD) MOV R0,A; 计时值寄存器地址到R0 TIMER_INC:; INC @R0; 计时值加1 MOV A,@R0 CLR C SUBB A,#10; JC END_INC; 如果低位不满10, 则结束 MOV @R0,#00H; 低位满10, 清零低位 INCR0; 指向高位 INC R7; CJNE R7,#08H,TIMER_INC; 如果达到最高位, 则结束 END_INC: LCALLUPDATE_DISBUF POPAR7 POPPSW POP DPL POP DPH POP B POP ACC RETI ;=============================================================================== UPDATE_DISBUF: ; 根据计时寄存器的值更新显示缓冲区 MOV DPTR,#DIS_CODE; 保存表格地址 MOV A,sec_bcd MOV DPTR,#dis_code MOVC A,@A+DPTR; 获得显示代码 MOV dis_buf,A; 更新显示缓冲区 MOV A,sec_bcd+01H MOVC A,@A+DPTR MOV dis_buf+01H,A MOV A,sec_bcd+02H MOVC A,@A+DPTR ANL A,#07FH; 显示小数点 MOV dis_buf+02H,A MOV A,sec_bcd+03H MOVC A,@A+DPTR MOV dis_buf+03H,A MOV A,sec_bcd+04H MOVC A,@A+DPTR MOV dis_buf+04H,A MOV A,sec_bcd+05H MOVC A,@A+DPTR MOV dis_buf+05H,A MOV A,sec_bcd+06H MOVC A,@A+DPTR MOV dis_buf+06H,A MOV A,sec_bcd+07H MOVC A,@A+DPTR MOV dis_buf+07H,A RET ; END OF UPDATE_DISBUF ;=============================================================================== DELAYMS: ; 延时子程序 ; 传入参数:R7 --- 延时值(MS) ; 返回值:无 MOVA,R7 JZEND_DLYMS DLY_LP1: MOVR6,#185 DLY_LP2: NOP NOP NOP DJNZR6,DLY_LP2 DJNZR7,DLY_LP1 END_DLYMS: RET ;=============================================================================== DIS_CODE: db 28h,7eh,0a2h,62h,74h,61h,21h,7ah,20h,60h,0ffh END
|