⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file12.asm

📁 单片机学习系统附的实验源代码
💻 ASM
字号:
;多功能数字钟,可以设置时/分,不能设置秒
;准点报时。定时报时等
;现象,程序下载完成以后,数码显示000000,同时,最后两个数码管开始显示
;秒,同时,有两个led指示灯按照每秒一次的闪烁,
;用户可以利用三个按键来输入时/分,左边第一个输入时,中间的那个输入分
;第三个用来切换,输入时的增/减,按一次第三个按键,程序自动设置成
;增加/减少方式,比如我们在输入时的时候,应该输入12,结果输入了13,那
;我们只要按一次最右边的那个按键(模式设置),然后按最左边的这个(设置时)
;就可以调整为12了,分的设置也一样!
;每到正点都会发出短鸣,到了12:00会发出特殊的定时蜂鸣!

    beep   bit  p3.7            ;蜂鸣器定义
    
	segdata equ p0      ;数据 输出
	sege    equ p2.7    ;显示 选中
	segb    equ p2.6    ;位 选
	segd    equ p2.5    ;段 选
	
	key1   bit   p3.5           ;按键定义
	key2   bit   p3.4
	key3   bit   p3.3
	key    equ   56h

    time_h equ 57h              ;定时初值高位
    time_l  equ 58h             ;低位
         
    t_h      equ   60h          ;时分秒对应的地址
    t_s      equ   61h
    t_m     equ   62h
    time    equ   63h           ;时钟计数单元
    timer_h    equ   64h        ;定时时单元
	timer_m   equ   65h         ;定时分单元

    timset bit     00h          ;设置时间标志 

    disstart equ 70h            ;显示单元首地址
		
	int_data   equ  45h         ;中断数据地址
	count_data equ  44h         ;计数单元地址
	timer_data equ  43h         ;定时地址

;  **************     以上为预定义部分

;  **************     以下程序开始

	org 00h           ;   程序开始地址
	jmp main          ;   跳转到代码开始处
	
	org 1bh           ;   定时器 T1 中断服务程序入口
	jmp tim1
	
	
	org 030h                  ;主程序开始的地址  30H
   main:mov sp,#30h           ;首先定义堆栈
        lcall rest            ;初始化
        lcall pro_set         ;设置定时器开始工作
   lpp: lcall time_set        ;接受用户设置时间
	    lcall timer           ;时钟处理
        lcall time_pro        ;时间格式处理,码型变化等
        lcall  time_display   ;显示
    jmp lpp
;  *************  初始化程序 ***************************
rest:   mov a,#00h              ;累加器清零
	    mov b,#00h
	    mov p0,#0               ;数码管禁止显示
        mov t_h,#0              ;时单元
        mov t_m,#0              ;分单元
        mov t_s,#0              ;秒单元
        mov time,#00h           ;计数溢出次数,溢出20次为一秒
	    clr  timset             ;定时设置标志位,0->增加 1 ->减少
        mov  timer_h,#12        ;定时器时单元,设置定时为  12:00
        mov  timer_m,#00h       ;定时器分单元
        clr beep                ;禁止蜂鸣器
        ret                     ;返回

;   ***************      定时器 T1 中断服务程序      ****
tim1:   clr tr1                     ;首先停止定时操作      
        mov th1,time_h              ;
        mov tl1,time_l
        inc time                    ;自增
        mov a,time                  ;取得溢出次数
        cjne a,#20,retend           ;如果满20此表示到 1 秒
        cpl p1.0                    ;取反p1.0,p1.1指示秒钟
        cpl p1.1
        mov time,#00h               ;重新开始等待1秒
        inc t_s                     ;秒单元加1
retend: setb tr1                    ;定时开始
        reti                        ;中断返回

;  *****************     设置定时器初始化,定时时间为 50ms  ****
pro_set:mov dptr,#0000h             ;数据指针清零
        mov tmod,#10h               ;设置定时器1工作在方式1
        mov time_h,#3ch             ;计算定时50ms需要的初值
        mov th1,time_h              ;保存高位
        mov time_l,#0c1h            ;低位
        mov tl1,time_l              ;保存低位
        setb ea                     ;总的中断允许
        setb et1                    ;定时器1允许
        setb tr1                    ;定时器1开始运行
        ret                         ;返回

;   ******************    timer 程序主要完成数据的处理    **********

timer:  mov a,t_s               ;取得秒单元数据
        cjne a,#60,tend         ;秒不到60返回
        mov t_s,#00h            ;清除秒单元
        inc t_m                 ;为分单元加1
        mov a,t_m               ;取得分单元数据
        cjne a,#60,tend         ;分不等于60返回
        mov t_m,#00h            ;分单元清零
        setb beep               ;整点短鸣提示
        lcall delay             ;鸣叫延时
        clr beep                ;停止蜂鸣器
        inc t_h                 ;同时为时单元加1
        mov a,t_h               ;取得时单元数据
        cjne a,#24,timetest     ;如果不等于24,查看定时
        mov t_h,#00h            ;时单元清零
        jmp tend                ;返回
     
timetest:cjne a,timer_h,tend    ;不等于定时的时单元,返回
         mov a,t_m              ;取得定时的分单元
         cjne a,timer_m,tend    ;当前分不等于定时的分单元,返回
         setb beep              ;定时到,蜂鸣提示
         lcall delay                      
         clr beep
         lcall delay
         setb beep
         lcall delay
         clr beep               ;连续发出短音提示
   tend: ret                    ;返回

;  ************    time_display  程序主要为显示时间值用    *************

time_display:mov r0,#disstart   ;取得显示单元首地址
             mov r1,#01h        ;从第一个数码管开始
             mov r2,#06h        ;共6个数码管
             clr sege          ;显示选中
       dislp:mov segdata,@r0    ;获得当前单元数据
             setb segd
             nop
             clr segd
             inc r0             ;指向下一个单元   
             mov segdata,r1     ;数码显示
             setb segb
             nop
             clr segb
             
             mov a,r1           ;为下一个数准备
             rl a               ;下一个单元
             mov r1,a           ;保存
             lcall delay3ms     ;为了保证数码管亮度,
                                ;但要防止闪烁,延时3ms
             
             djnz r2,dislp      ;重复显示,直到全部数据刷新过
             ret                ;返回

;    *******    time_pro   时间处理,主要为 bcd码转换,查表   ***********
time_pro: lcall bcd             ;BCD码转换
          mov r0,#disstart      ;获得显示单元首地址
          mov r2,#06h           ;需要转换的个数
     prlp:mov a,@r0             ;取得当前需要转换的数据
          mov dptr,#tab_nu      ;获得表头
          movc a,@a+dptr        ;获得转换后的数据
          mov @r0,a             ;存回去
          inc r0                ;指向下一个
          djnz r2,prlp          ;重复转换,直到6个全部完成
          ret                   ;返回

;  ****************  码型变换   **************************************** 
bcd:      mov r0,#disstart      ;获得首地址
          mov a,t_s             ;获得待转化的低位
          mov b,#10             ;转化进制,如果要进行十进制转换 改为 10
          div ab                ;计算 A/B
          mov @r0,b             ;第一位转换完毕,保存低位转化后的数据
          inc r0                ;自增
          mov @r0,a             ;保存高位
          inc r0                ;取第二个数据地址
          mov a,t_m             ;获得第二个需要转换的数据
          mov b,#10             ;十六进制
          div ab                ;计算
          mov @r0,b             ;存低位
          inc r0                
          mov @r0,a             ;存高位
          inc r0                ;第三位
          mov a,t_h             ;获得数据
          mov b,#10             ;十六进制
          div ab                ;计算
          mov @r0,b             ;存低位
          inc r0                 
          mov @r0,a             ;存高位
          ret                   ;完毕,返回
;***************************************************************************************

; * ********   time_set  设置时间 *******************************************************
; *                                                                                                                               *
; *          检测用户按键,1-> 设置时单元  2-> 设置分单元,3->设置增减方式                    *
; *          如果需要增加 时,先将方式设置为 增加(默认为减),即,按下 KEY3一下,    *
; *          然后按 KEY1 ,如果要减少时单元,需要再次按下KEY3,然后按KEY1;            *
; *          分的设置也是如此。                                                                                       *
;***************************************************************************************
time_set:mov p0,#00h            ;禁止数码管显示
         mov p2,#255            ;防止按键时闪烁
         lcall pro_key          ;查找用户按键情况
         mov a,key              ;查找键值
         jz tsend               ;如果等于0,表示没用按键,直接返回
         cjne a,#1,tset1        ;是否等于1?没有到下一个处理程序
         mov key,#00h           ;等于1,表示设置时 请零,否则会引起重复设置
         jb timset,tset10       ;时间设置标志位,1 ->减少,0->增加
         mov a,t_h              ;标志位 0 ,增加,取得时单元
         cjne a,#23,ts1         ;如果时单元不等于23,转移到增加操作
         jmp tsend              ;等于23 直接返回
   ts1:  inc t_h                ;时单元增加1
	     jmp tsend              ;返回

  tset10:mov a,t_h              ;这里处理为减少的情况
         jz tsend               ;如果时单元为0,直接返回
         dec t_h                ;否则,数据减1
         jmp tsend              ;返回,以下关于分的设置一样
    tset1:cjne a,#2,tset2       ;如果按键不是 2 则 转移到下一个处理
         mov key,#00h           ;是2,表示设置  分
         jb timset,tset20       ;其余同上
         mov a,t_m
         cjne a,#59,ts2
         jmp tsend
     ts2:inc t_m
         jmp tsend

  tset20:mov a,t_m
         jz tsend
         dec t_m
         jmp tsend

   tset2:cjne a,#3,tsend        ;等于 3 表示设置标志
         mov key,#00h           ;清零
         cpl timset             ;标志取反
  tsend: ret                    ;返回

;******** 定时器 T0 设置 **************
;定时器工作在方式1,为提高精度,总定时时间为50ms,
;定时器溢出20次为1秒,

pro_timer:
	mov tmod,#01h      ;设置定时器为定时方式1
	mov th0,#0ffh      ; 初始化定时初值
	mov tl0,#0a1h      ;
	setb ea            ;总中断允许
	setb et0           ;定时器0 允许
	setb tr0           ;开始定时
   ret                 ;返回
; *****************************************

; ***************   软件延时    *************

delay:push psw            ; 保存原来的寄存器内容
      clr psw.3           ;
	  clr psw.4           ; 设置新的寄存器组
	  mov r0,#2           ; 延时参数1
	  mov r1,#250         ; 延时参数2 
	  mov r2,#2           ; 延时参数3
  dl1:djnz r0,dl1         ; 延时循环1
      mov r0,#250         ;
  dl2:djnz r1,dl1         ; 延时循环2
      mov r0,#240         ;
      mov r1,#248         ;
  dl3:djnz r2,dl1         ; 延时循环3
	  nop                 ; 定时精度调整
	  pop psw             ;  恢复原来的寄存器
      ret                                 ;   返回
;*****************************************
pro_key:                 ;键盘查询子程序
	setb key1            ;首先输出高电平,检测低电平的到来
	setb key2            ;不同电路,可能检测方式不一样
	setb key3
	jb key1,ke1          ;如果用户没有按第一个键,到第下个处理部分,
	mov key,#1           ;表示用户按了第一个键
	lcall delay20ms      ;软件延时,防止干扰
	jmp pro_key          ;重新查询,直到用户释放按键
ke1:jb key2,ke2          ;处理第二个按键,如果没有到下一个处理部分
    mov key,#2           ;以下和第一个处理单元相似。
	lcall delay20ms
	jmp pro_key
ke2:jb key3,ke3
    mov key,#3
	lcall delay20ms
	jmp pro_key
ke3:ret
;************  定时20 ms  *************
delay20ms:  
        push psw              ; 保存原来的寄存器单元
        clr psw.3             ; 设置新的寄存器
	    clr psw.4             ; 
	    mov r0,#2             ; 延时参数1 
		mov r1,#250           ; 延时参数2
		mov r2,#1             ; 延时参数3
    de1:djnz r0,de1           ; 延时循环1
    	mov r0,#250           ; 重新设置循环数据
    de2:djnz r1,de1           ; 开始第二道循环 
        mov r0,#240           ;
        mov r1,#248           ; 
    de3:djnz r2,de1           ; 第三道循环
		nop                   ;  修正定时精度
		pop psw               ;  恢复原来的寄存器组
        ret                   ;  返回
;***********  end  *******************
;*********** 延时 3ms ****************
delay3ms:
	  push psw
	  clr  psw.3
	  setb  psw.4
	  mov r0,#250
	  mov r1,#3
   d5:djnz r0,d5
      mov r0,#250
      djnz r1,d5
      pop psw
   ret
;************************************************************************************
;这是数字显示表格,其中 带小数点的数字比不带小数点的数字大16
; 比如 0 的显示代码为 0;那么 0.的显示代码为 16;如此类推

tab_nu: 
             db 0c0h, 0f9h,  0a4h, 0b0h,   99h ,  92h ,  82h, 0f8h ; 数字0-7 不带小数点代码
             db 80h ,  90h,  88h ,  83h ,  0c6h,  0a1h,  86h, 8eh  ; 数字8-f   不带小数点代码
             db 40h ,  79h,  24h ,  30h ,  19h ,  12h ,  02h, 78h  ; 数字0-7  带小数点代码
             db 00h ,  10h,  08h ,  03h ,  46h ,  21h ,  06h, 0eh  ; 数字8-f   带小数点代码

      end             ; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -