S3F9454/94C4/94C8通用可调时间的四位数码管时间显示例程
文章来源: 本站原创   更新时间: 2014-06-23
;--------------------------------------
;程序中所有分号后面的都是注释语句
;#号表示一个常量名字或数据
;-----------------------------------------------------
.include "s3c9454.reg" ;必须加入寄存器定义文件,这个文件是OPENICE自带的
;-----------------------------------------------------
;以下为程序运行所用变量定义
DIGIT1 EQU 00H ;LED-A位数据定义
DIGIT2 EQU 01H ;LED-B位数据定义
DIGIT3 EQU 02H ;LED-C位数据定义
DIGIT4 EQU 03H ;LED-D位数据定义
SEG1 EQU 04H ;SEG-A位显示码
SEG2 EQU 05H ;SEG-B位显示码
SEG3 EQU 06H ;SEG-C位显示码
SEG4 EQU 07H ;SEG-D位显示码

TMRFLAG EQU 08H ;定时标志寄存器
LED_LOOP EQU 09H ;显示循环计数器
TMR_05S EQU 0AH ;0.5S计时器

HOURS EQU 0BH ;小时
MINUTES EQU 0CH ;分钟
SECONDS EQU 0DH ;秒

KEY_TMRL EQU 0EH ;按键定时器低位
KEY_TMRH EQU 0FH ;按键定时器高位
FLASH_TMR EQU 10H ;闪烁显示定时器
KEY_LOOP EQU 11H ;键操作循环计数器

RUNFLAG EQU 12H ;程序运行标志寄存器

KEY_DELAY EQU 13H ;键操作等待计时器
;--------------------------------------------
;位操作定义
CK_164 BIT P0.0 ;P0.0是164时钟驱动线
DT_164 BIT P0.1 ;P0.1是164数据驱动线

SMG_D1 BIT P0.5 ;P0.5是数码管驱动位线1
SMG_D2 BIT P0.4 ;P0.4是数码管驱动位线2
SMG_D3 BIT P0.3 ;P0.3是数码管驱动位线3
SMG_D4 BIT P0.2 ;P0.2是数码管驱动位线4

SET_KEY BIT P2.0 ;P20是SET-KEY
UP_KEY BIT P1.0 ;P10是UP-KEY
DOWN_KEY BIT P1.1 ;P11是DOWN-KEY

SET_KEY_CODE .EQU 1
UP_KEY_CODE .EQU 2
DOWN_KEY_CODE .EQU 4

FLAG_KEY_DOWN BIT RUNFLAG.0 ;有KEY按下标志

FLAG_05S BIT TMRFLAG.0 ;0.5S定时标志
FLAG_FH BIT TMRFLAG.1 ;闪烁小时显示标志
FLAG_FM BIT TMRFLAG.2 ;闪烁分钟显示标志
FLAG_1S BIT TMRFLAG.3 ;定时1S标志位
FLAG_FLASH_05S BIT TMRFLAG.4 ;闪烁显示05S定时标志

DP BIT SEG2.7 ;点是定义在第2位数码管的B7位
;--------------------------------------------------------
         ;9454只有一个中断向量地址,在0000H,这里设置中断服务程序INT_9454
        ORG 0000H ;ORG表示定义一个绝对的ROM地址,0000H地址
        .VECTOR $,INT_9454 ;一个向量地址占用2个字节,$表示是在当前地址处定义,也可以采用直接的绝地址定义,
                                ;如:.VECTOR 0000H,INT_9454,两者效果相同
;------------------------------------------------------------
;显示编码予定义
DIGIT_CODE:
                             ;表格开始地址是0000h
       DB 03fh ;0
       DB 006h ;1
       DB 05bh ;2
       DB 04fh ;3
       DB 066h ;4
       DB 06dh ;5
       DB 07dh ;6
       DB 007h ;7
       DB 07fh ;8
       DB 06fh ;9
       DB 077h ;A
       DB 07Ch ;B
       DB 039h ;C
       DB 05Eh ;D
       DB 079h ;E
       DB 071h ;F
       DB 0FFH ;全显示
       DB 00H ;不显示(黑屏) 表格结束地址是0012H

LED_ON .EQU 10H ;全显示
LED_OFF .EQU 11H ;不显示
;-----------------------------------------------------------
;SMART OPTION
;有关这几个数据设置,请详细参阅9454手册的ADDRESS SPACE部分的SMART OPTION说明
;SMART OPTION定义4个字节数据在003CH--003FH这4个ROM地址
        ORG 003CH
        DB 00H
        DB 00H
        DB 0E7H ;设置内部LVR使能,用内部复位,LVR电平为2.3V
        DB 03H ;00H定义外部晶振,03H定义内部OSC
;---------------------------------------------------

;-----------------------------------------------------------
;-------<>
        ORG 0100H

RESET: ;-------------------------
        ;follow must set
        DI ;disable interrupt
        LD BTCON,#10100011B ;Watch-dog disable
        LD CLKCON,#00011000B ;selet non-divided CPU clock
        LD SP,#0C0H ;Stack pointer must be set as 0C0H

        LD P0CONH,#00001010B
        LD P0CONL,#10101010B ;设置P00--P05作为输出
        
        LD P1CON,#00000101B ;设置P10,P11作为输入带上拉
        AND P2CONL,#11111100B ;设置P20作为输入带上拉
       
        LD R0,#050H
        CALL CLR_RAM ;清RAM
      
        LD T0CON,#01001010B ;TMR0输入时钟=FXX/8, 开启T0中断
        LD T0DATA,#50 ;若OSC=3.2MHZ,则T0每4MS产生一次中断,TIME= (3.2MHZ/256)*50= 4MS
      
        EI
;----------------------------------------
        LD SECONDS,#00H
        LD MINUTES,#00H
        LD HOURS,#00H
        CLR KEY_LOOP
        CLR LED_LOOP
MAIN:
        CALL KEY_CHECK

        CALL DISPLAY_CONVERT
                        
        CALL DIGIT_CONVERT
        
        ;以下检测处理5S未有按键操作的状态
        CP KEY_LOOP,#0
        JR EQ,MAIN
        CP KEY_DELAY,#5
        JR ULT,MAIN
        ;5S内无按键操作,则复位显示状态,开始计时
        CLR KEY_LOOP
        CLR SECONDS
        CLRBIT FLAG_FH
        CLRBIT FLAG_FM
        JR MAIN
;---------------------------------------------------------
KEY_TEST:
        LD R0,#00H
        TMBIT SET_KEY
        JR NZ,CHK_KEY_INC
        OR R0,#SET_KEY_CODE
CHK_KEY_INC:
        TMBIT UP_KEY
        JR NZ,CHK_KEY_DEC
        OR R0,#UP_KEY_CODE
CHK_KEY_DEC:
        TMBIT DOWN_KEY
        JR NZ,KEY_TEST_BACK
        OR R0,#DOWN_KEY_CODE
KEY_TEST_BACK
        RET
;---------------------------------------------------------
KEY_CHECK:
        CALL KEY_TEST
        LD R1,R0
        CALL DELAY_10MS
        CALL KEY_TEST
        CP R1,R0
        JR NE,KEY_BACK
    
        CP R1,#SET_KEY_CODE
        JR EQ,CHK_SET_KEY
        
        CP R1,#UP_KEY_CODE
        JR EQ,CHK_UP_KEY
        
        CP R1,#DOWN_KEY_CODE
        JR EQ,CHK_DOWN_KEY
        
        ;无KEY按下,则复位KEY PRESS FLAG
        CLRBIT FLAG_KEY_DOWN
        CLR KEY_TMRH
        CLR KEY_TMRL
        JR KEY_BACK
;-----------------
;SET-EKY有按下处理
CHK_SET_KEY:
        TMBIT FLAG_KEY_DOWN
        JR NZ,KEY_BACK ;若上次按键未释放,则不处理本次操作
        
        SETBIT FLAG_KEY_DOWN
        CLR KEY_DELAY ;复位无按键操作定时器
        CLR KEY_TMRL ;复位KEY定时器
        CLR KEY_TMRH
         
        INC KEY_LOOP ;增量SET-KEY循环操作计数器
                
        CP KEY_LOOP,#1 ;设定闪烁显示小时
        JR EQ,SET_FLASH_M
        CP KEY_LOOP,#2 ;设定闪烁显示分钟
        JR EQ,SET_FLASH_H
        ;第3次按下,复位显示状态,开始正常计时
        CLR KEY_LOOP
        CLR SECONDS
        CLRBIT FLAG_FH
        CLRBIT FLAG_FM
        JR KEY_BACK
SET_FLASH_H:
        SETBIT FLAG_FH
        CLRBIT FLAG_FM
        JR KEY_BACK
SET_FLASH_M:
        CLRBIT FLAG_FH
        SETBIT FLAG_FM
        JR KEY_BACK
;-----------------
;UP-EKY有按下处理
CHK_UP_KEY:
        CP KEY_LOOP,#00H
        JR EQ,KEY_BACK ;KEY_LOOP=0,则SET操作未启动,不处理UP和DOWN操作
        CLR KEY_DELAY ;复位无按键操作定时器
        SETBIT FLAG_FLASH_05S ;暂停闪烁
        CALL PROC_INC_KEY
        JR KEY_BACK
;----------------
;DOWN-EKY有按下处理
CHK_DOWN_KEY:
        CP KEY_LOOP,#00H
        JR EQ,KEY_BACK ;KEY_LOOP=0,则SET操作未启动,不处理UP和DOWN操作
        CLR KEY_DELAY ;复位无按键操作定时器
        SETBIT FLAG_FLASH_05S ;暂停闪烁
        CALL PROC_DEC_KEY
        JR KEY_BACK
;-----------------
KEY_BACK:
        RET
;--------------------------------------------------------
PROC_INC_KEY:
        CP KEY_TMRH,#2 ;若UP-KEY长按超过2S,则每0.3S增量一次显示
        JR UGE,INC_03S
        ;若按下时间未到2S,则进行短按操作处理
        TMBIT FLAG_KEY_DOWN
        JR NZ,INC_BACK ;若上次键未释放,则不处理
        SETBIT FLAG_KEY_DOWN
        JR CHK_INC
;----------
INC_03S:
        SETBIT FLAG_KEY_DOWN
        CP KEY_TMRL,#75 ;0.3S
        JR ULT,INC_BACK
        CLR KEY_TMRL ;清定时器低位,准备下一次0.3S
        JR CHK_INC
;-----------
CHK_INC:
        CP KEY_LOOP,#1
        JR EQ,INC_M
INC_H:
        INC HOURS
        CP HOURS,#24 ;小时最大为23小时
        JR ULT,INC_BACK
        LD HOURS,#00H
        JR INC_BACK
INC_M:
        INC MINUTES
        CP MINUTES,#60 ;分钟最大为59分钟
        JR ULT,INC_BACK
        LD MINUTES,#00H
        JR INC_BACK
;------------
INC_BACK
        RET
;---------------------------------------------------------
PROC_DEC_KEY:
        CP KEY_TMRH,#2 ;若UP-KEY长按超过2S,则每0.3S增量一次显示
        JR UGE,DEC_03S
        ;若按下时间未到2S,则进行短按操作处理
        TMBIT FLAG_KEY_DOWN
        JR NZ,DEC_BACK ;若上次键未释放,则不处理
        SETBIT FLAG_KEY_DOWN
        JR CHK_DEC
;----------
DEC_03S:
        SETBIT FLAG_KEY_DOWN
        CP KEY_TMRL,#75 ;0.3S
        JR ULT,DEC_BACK
        CLR KEY_TMRL ;清定时器低位,准备下一次0.3S
        JR CHK_DEC
;-----------
CHK_DEC:
        CP KEY_LOOP,#1
        JR EQ,DEC_M
DEC_H:
        CP HOURS,#0
        JR UGT,_DEC_H
        LD HOURS,#24
_DEC_H:
        DEC HOURS
        JR DEC_BACK
DEC_M:
        CP MINUTES,#0
        JR UGT,_DEC_M
        LD MINUTES,#60
_DEC_M:
        DEC MINUTES
        JR DEC_BACK
;------------
DEC_BACK
        RET
;---------------------------------------------------------
;该进程把小时,分钟数据转换为数码管的4位显示数据
DISPLAY_CONVERT:
        LD R1,HOURS
        CALL CONVERT_DATA
        LD DIGIT1,R0
        LD DIGIT2,R1
        
        LD R1,MINUTES
        CALL CONVERT_DATA
        LD DIGIT3,R0
        LD DIGIT4,R1
     
DISPLAY_BACK:
        RET
;--------------------------------------------------------
;该进程把一个两位数据转换为十位和个位数据
;R1--要转换的两位数据,转换后为个位数据
;R0--转换后的十位数据
CONVERT_DATA:
        CP R1,#99
        JR ULE,CVT_ST
        LD R1,#99 ;最大限99
CVT_ST:
        LD R0,#00H
CVT_LOOP:
        CP R1,#10
        JR ULT,CVT_BACK
        SUB R1,#10
        INC R0
        JR CVT_LOOP
CVT_BACK:
        RET
;---------------------------------------------------------
;该进程把要数码管各位要显示的数据转换为显示码
DIGIT_CONVERT:
        
        LD R10,#00H ;调入显示码定义高位地址
        LD R11,#DIGIT_CODE ;调入显示码定义起始地址
        
        LD R1,DIGIT1
        LD R2,DIGIT2
        LD R3,DIGIT3
        LD R4,DIGIT4
        
        ;CP R1,#00H
        ;JR NE,LD_SEG
        ;LD R1,#LED_OFF
        
        ;CP R2,#00H
        ;JR NE,LD_SEG
        ;LD R2,#LED_OFF
        
        ;CP R3,#00H
        ;JR NE,LD_SEG
        ;LD R3,#LED_OFF
LD_SEG:
        ;检查小时闪烁显示标志位状态
        TMBIT FLAG_FH
        JR Z,LD_SEG_A
        ;每0.5S闪烁显示
        TMBIT FLAG_FLASH_05S
        JR NZ,LD_SEG_A
        LD R1,#LED_OFF
        LD R2,#LED_OFF
LD_SEG_A:
        ;调入A位显示码
        LD R11,#DIGIT_CODE ;调入显示码定义起始地址
        ADD R11,R1 ;LED-A位数据定义
        LDC R0,@RR10 ;把RR10寄存器对中的地址所指向的ROM地址字节中的数据调入到R0
        LD SEG1,R0 ;把R0寄存器中的地址所指向的ROM地址字节中的数据调入到SEG-A位显示码
        ;调入B位显示码
        LD R11,#DIGIT_CODE ;调入显示码定义起始地址
        ADD R11,R2
        LDC R0,@RR10
        ;DP定义在SEG2的B7位,为避免调入数据时造成点显示闪烁不稳定,必须予置其状态
        AND R0,#07FH
        TMBIT FLAG_05S
        JR Z,LD_SEG2
        OR R0,#80H
LD_SEG2:
        LD SEG2,R0

        ;检查分钟闪烁显示标志位状态
        TMBIT FLAG_FM
        JR Z,LD_SEG_C
        ;每0.5S闪烁显示
        TMBIT FLAG_FLASH_05S
        JR NZ,LD_SEG_C
        LD R3,#LED_OFF
        LD R4,#LED_OFF
LD_SEG_C:
        ;调入C位显示码
        LD R11,#DIGIT_CODE ;调入显示码定义起始地址
        ADD R11,R3
        LDC R0,@RR10
        LD SEG3,R0
        ;调入D位显示码
        LD R11,#DIGIT_CODE ;调入显示码定义起始地址
        ADD R11,R4
        LDC R0,@RR10
        LD SEG4,R0
;-------------
DGT_CVT_BACK:
        RET
;---------------------------------------------------------
;R0---要发送到164输出的数据
SENDTO164:
        PUSH R1
        CLRBIT CK_164
        CLRBIT DT_164
        LD R1,#08H
;----------
LOOP_164:
        ;必须先根据数据状态予置好DATA线状态
        CLRBIT DT_164
        RRC R0
        JR C,SET_1
SET_0:
        CLRBIT DT_164
        JR SEND_CLK
SET_1:
        SETBIT DT_164
;---------
;发送一个时钟信号
SEND_CLK:
        SETBIT CK_164
        NOP
        NOP
        NOP
        CLRBIT CK_164
        
        DEC R1
        JR NZ,LOOP_164
;---------
SEND_BACK:
        POP R1
        RET
;---------------------------------------------------------
;该进程通过轮询方式来分时扫描数码管的A,B,C,D各位显示
LED_SCAN:
        PUSH R0
        
        INC LED_LOOP
        ;注意在每次送数据到LED显示前,必须先关闭全部位线
        CLRBIT SMG_D1
        CLRBIT SMG_D2
        CLRBIT SMG_D3
        CLRBIT SMG_D4
         
        CP LED_LOOP,#01H
        JR EQ,SCAN_1
        CP LED_LOOP,#02H
        JR EQ,SCAN_2
        CP LED_LOOP,#03H
        JR EQ,SCAN_3
        CP LED_LOOP,#04H
        JR EQ,SCAN_4
        
        LD LED_LOOP,#00H
SCAN_1:
        LD R0,SEG1 ;调入A位显示码
        CALL SENDTO164
        SETBIT SMG_D1 ;打开1位线显示
        JR SCAN_BACK
SCAN_2:
        LD R0,SEG2 ;调入B位显示码
        CALL SENDTO164
        SETBIT SMG_D2 ;打开2位线显示
        JR SCAN_BACK
SCAN_3:
        LD R0,SEG3 ;调入C位显示码
        CALL SENDTO164
        SETBIT SMG_D3 ;打开3位线显示
        JR SCAN_BACK
SCAN_4:
        LD R0,SEG4 ;调入D位显示码
        CALL SENDTO164
        SETBIT SMG_D4 ;打开4位线显示
SCAN_BACK:
        POP R0
        RET
;---------------------------------------------------------
;TMR0-4MS中断一次
INT_9454:
        AND T0CON,#0FEH ;清T0中断标志位
        ;OR T0CON,#08H ;清T0CNT,这个是芯片手册规定的
        
        CALL LED_SCAN ;扫描LED显示
        
        ADD KEY_TMRL,#1 ;增量按键定时器
        ADC KEY_TMRH,#0
         
        INC TMR_05S
        CP TMR_05S,#125
        JR ULT,INT_BACK
        ;定时0.5S时间到
        CLR TMR_05S
        XORBIT FLAG_05S ;取反0.5S定时标志状态
        XORBIT FLAG_FLASH_05S
        
        TMBIT FLAG_05S
        JR Z,INT_BACK
        ;SETBIT FLAG_1S ;设置定时1S时间到标志
        INC KEY_DELAY ;增量无按键操作定时器
        
        INC SECONDS
        CP SECONDS,#60
        JR ULT,INT_BACK
        CLR SECONDS
        INC MINUTES
        CP MINUTES,#60
        JR ULT,INT_BACK
        CLR MINUTES
        INC HOURS
        CP HOURS,#24
        JR ULT,INT_BACK
        CLR HOURS
INT_BACK:
        IRET
;---------------------------------------------------------
;该进程清指定区段的RAM
CLR_RAM:
        CLR @R0
        DEC R0
        JR NZ,CLR_RAM
        CLR @R0
        RET
;------------------------------------------------------
DELAY_10MS:
        PUSH R15
        LD R15,#10
_10MS:
        CALL DELAY_1MS
        DEC R15
        JR NZ,_10MS
        
        POP R15
        RET
;-------------------------------------------------------
DELAY_1MS:
        PUSH R15
        LD R15,#100
_1MS:
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        DEC R15
        JR NZ,_1MS
            
        POP R15
        RET
;---------------------------------------------------------------
.END ;Programer is end

相关备注:
 
三星单片机开发网首页