;--------------------------------------
;程序中所有分号后面的都是注释语句
;#号表示一个常量名字或数据
;-----------------------------------------------------
.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
|
相关备注: |
无 |
|