PICアセンブラで7セグダイナミック制御

7セグを五桁も使用したプログラムソースです。晒します。

注意:700行超えてます。

;_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
;--PROPGRAM NAME:TIMER
;--DATE:2010.10.25
;--NAME:RAIDEN
;--STATUS:実験中
;--PURPUSE:ミニッツボート用
;
;_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

LIST P=16F883
#INCLUDE

;7セグデータ変換テーブルABCDEFG*
#DEFINE D_1 B'00100010'
#DEFINE D_2 B'01011110'
#DEFINE D_3 B'01110110'
#DEFINE D_4 B'11100010'
#DEFINE D_5 B'11110100'
#DEFINE D_6 B'11111000'
#DEFINE D_7 B'10100110'
#DEFINE D_8 B'11111110'
#DEFINE D_9 B'11100110'
#DEFINE D_0 B'10111110'

#DEFINE TONE D'60' ;TIMER0カウント回数(255-60=195)
;#DEFINE MSCNT D'9' ;下以外のときのカウンタ定数
;#DEFINE SCNT D'5' ;s10の時のカウンタ定数
#DEFINE SIGCNT D'5' ;スタート合図のダイナミック制御用カウンタ定数

;変数宣言
CBLOCK 20H
W_TEMP
S_TEMP
FSR_TEMP
PTCNT1
PTCNT2
PTCNT3
SEGCHK ;7SEG表示用の変数
CNT ;スタートカウンタ変数
FLAG ;7SEGのどの桁を表示するか判定するフラグ
;T0FLAG ;TIMER0フラグ
GFLAG ;ゴールフラグ

;カウンタ変数
MS10
MS100
S1
S10
M1
MS10TEMP1 ;最初にゴールしたほうのタイム
MS100TEMP1
S1TEMP1
S10TEMP1
M1TEMP1
MS10TEMP2 ;最後にゴールしたほうのタイム
MS100TEMP2
S1TEMP2
S10TEMP2
M1TEMP2


ENDC

ORG 0
GOTO INI
ORG 4

;-----------------------
;割込み
;-----------------------
INT
MOVWF W_TEMP ;Wreg退避
SWAPF STATUS,W
MOVWF S_TEMP ;STATUS退避
SWAPF FSR,W
MOVWF FSR_TEMP ;FSR待避

BCF INTCON,TMR0IF ;割り込み許可
;MOVLW B'00011111'
;MOVWF PORTA
CLRF PORTA

;タイムカウント
INCF MS10,F ;MS10カウンタ+1
MOVF MS10,W ;WレジスタにMSCNTを格納
SUBLW D'10' ;MS10-9の結果をWに格納
BTFSS STATUS,Z ;ゼロフラグが1の時次の命令をスキップ
GOTO EXIT
CLRF MS10

INCF MS100,F ;MS10カウンタ+1
MOVF MS100,W ;WレジスタにMSCNTを格納
SUBLW D'10' ;MS10-MSCNTの結果をWに格納
BTFSS STATUS,Z ;ゼロフラグが1の時次の命令をスキップ
GOTO EXIT
CLRF MS100

INCF S1,F ;MS10カウンタ+1
MOVF S1,W ;WレジスタにMSCNTを格納
SUBLW D'10' ;MS10-MSCNTの結果をWに格納
BTFSS STATUS,Z ;ゼロフラグが1の時次の命令をスキップ
GOTO EXIT
CLRF S1

INCF S10,F ;MS10カウンタ+1
MOVF S10,W ;WレジスタにMSCNTを格納
SUBLW D'6' ;MS10-MSCNTの結果をWに格納
BTFSS STATUS,Z ;ゼロフラグが1の時次の命令をスキップ
GOTO EXIT
CLRF S10

INCF M1,F ;MS10カウンタ+1
MOVF M1,W ;WレジスタにMSCNTを格納
SUBLW D'10' ;MS10-MSCNTの結果をWに格納
BTFSS STATUS,Z ;ゼロフラグが1の時次の命令をスキップ
GOTO EXIT
CLRF M1
EXIT
;CLRF T0FLAG ;割り込みフラグをゼロクリア
BSF INTCON,T0IE ;TIMER0割り込み許可
MOVLW TONE
MOVWF TMR0
SWAPF FSR_TEMP,W ;FSR復帰
MOVWF FSR
SWAPF S_TEMP,W ;STATUS復帰
MOVWF STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W ;Wreg復帰
RETFIE ;割り込み許可で戻る

;-----------------------
;初期設定
;-----------------------
INI
CLRF PORTA
CLRF PORTB
CLRF PORTC
BSF STATUS,RP0
MOVLW B'10000000'
MOVWF TRISB
CLRF TRISA
CLRF TRISC
MOVLW B'01110100'
MOVWF OSCCON
CLRF ANSEL
CLRF ANSELH ;すべてデジタル入出力
MOVLW B'10000111'
MOVWF OPTION_REG
BCF STATUS,RP0

MOVLW B'10000000'
MOVWF INTCON
MOVLW TONE
MOVWF TMR0
MOVLW D_0
MOVWF PORTC
;CLRF T0FLAG
MOVLW B'00000001'
MOVWF FLAG
;BSF INTCON,T0IE ;タイマ0割り込み許可
CLRF SEGCHK ;変数の初期化
CLRF CNT
;CLRF T0FLAG
CLRF GFLAG
CLRF MS10
CLRF MS100
CLRF S1
CLRF S10
CLRF M1
;MOVLW D'5'
;MOVWF MS10
;MOVLW D'6'
;MOVWF MS100
;MOVLW D'7'
;MOVWF S1
;MOVLW D'8'
;MOVWF S10
;MOVLW D'9'
;MOVWF M1
CLRF PORTA
;MOVLW B'00011111'
;MOVWF PORTA
MOVLW B'00111100'
MOVWF PORTB
GOTO MAIN

;-----------------------
;プログラム本体
;-----------------------
;7セグ表示(数十ミリ秒感覚で点灯する)
;何桁目を表示するか判定
;-----------------------
MAIN
;BTFSC T0FLAG,0 ;割り込みしたか?
;GOTO MAIN
SEGMENT
BTFSS FLAG,0 ;FLAGの0ビット目が1なら次の命令をスキップ
GOTO NF1
CALL KETA1
GOTO SCHK
NF1
BTFSS FLAG,1 ;FLAGの1ビット目が0なら次の命令をスキップ
GOTO NF2
CALL KETA2
GOTO SCHK
NF2
BTFSS FLAG,2 ;FLAGの2ビット目が0なら次の命令をスキップ
GOTO NF3
CALL KETA3
GOTO SCHK
NF3
BTFSS FLAG,3 ;FLAGの3ビット目が0なら次の命令をスキップ
GOTO NF4
CALL KETA4
GOTO SCHK
NF4
BTFSS FLAG,4 ;FLAGの4ビット目が0なら次の命令をスキップ
GOTO SCHK
CALL KETA5
GOTO SCHK ;スタートボタンチェック
KETA1
MOVF MS10,W ;1桁目
MOVWF SEGCHK
CALL SEG0
BSF PORTA,0
MOVF SEGCHK,W ;SEGCHKをWに格納
MOVWF PORTC ;PORTCに出力
MOVLW B'00000010'
MOVWF FLAG
CALL T1MS
;MOVLW B'00000001'
;MOVWF T0FLAG ;割り込みフラグ1
RETURN
KETA2
MOVF MS100,W ;2桁目
MOVWF SEGCHK
CALL SEG0
BSF PORTA,1
MOVF SEGCHK,W ;SEGCHKをWに格納
MOVWF PORTC ;PORTCに出力
MOVLW B'00000100'
MOVWF FLAG
CALL T1MS
;MOVLW B'00000001'
;MOVWF T0FLAG ;割り込みフラグ1
RETURN
KETA3
MOVF S1,W ;3桁目
MOVWF SEGCHK
CALL SEG0
BSF PORTA,2
MOVF SEGCHK,W ;SEGCHKをWに格納
MOVWF PORTC ;PORTCに出力
BSF PORTC,0
MOVLW B'00001000'
MOVWF FLAG
CALL T1MS
;MOVLW B'00000001'
;MOVWF T0FLAG ;割り込みフラグ1
RETURN
KETA4
MOVF S10,W ;4桁目
MOVWF SEGCHK
CALL SEG0
BSF PORTA,3
MOVF SEGCHK,W ;SEGCHKをWに格納
MOVWF PORTC ;PORTCに出力
MOVLW B'00010000'
MOVWF FLAG
CALL T1MS
;MOVLW B'00000001'
;MOVWF T0FLAG ;割り込みフラグ1
RETURN
KETA5
MOVF M1,W ;5桁目
MOVWF SEGCHK
CALL SEG0
BSF PORTA,4
MOVF SEGCHK,W ;SEGCHKをWに格納
MOVWF PORTC ;PORTCに出力
BSF PORTC,0
MOVLW B'00000001'
MOVWF FLAG
CALL T1MS
;MOVLW B'00000001'
;MOVWF T0FLAG ;割り込みフラグ1
RETURN

SCHK
;MOVLW B'00011111'
;MOVWF PORTA
CLRF PORTA
BTFSS PORTB,7 ;スタートボタンONのとき次の命令をスキップ
GOTO MAIN
BTFSS PORTB,7
GOTO MAIN
BTFSS PORTB,7
GOTO MAIN
GOTO SIGNAL

;-----------------------
;スタート合図
;-----------------------
SIGNAL
BCF INTCON,T0IE ;タイマー0割り込み禁止
BTFSC GFLAG,0 ;GFLAGの0ビット目が0のとき次の命令をスキップ
GOTO TSTOP
CLRF SEGCHK ;変数の初期化
CLRF CNT
CLRF GFLAG
CLRF MS10
CLRF MS100
CLRF S1
CLRF S10
CLRF M1

; BCF PORTB,2
; CALL T200MS
; BSF PORTB,2
; BCF PORTB,3
; CALL T200MS
; BSF PORTB,3
; BCF PORTB,4
; CALL T200MS
; BSF PORTB,4
MOVF SIGCNT,W
MOVWF CNT
SLOOP
; BCF PORTB,2
; CALL T10MS
; BSF PORTB,2
; BCF PORTB,3
; CALL T10MS
; BSF PORTB,3
; BCF PORTB,4
CALL T800US
; BSF PORTB,4
; BCF PORTB,5
; CALL T10MS
; BSF PORTB,5
DECFSZ CNT,F ;CNT-1=0なら次の命令をスキップ
GOTO SLOOP
MOVLW B'00111100'
MOVWF PORTB
MOVLW B'00000001'
MOVWF GFLAG
BSF INTCON,T0IE ;TIMER0割り込み許可
MOVLW TONE
MOVWF TMR0
GOTO MAIN

;タイム計測ストップ
TSTOP
BCF INTCON,T0IE
MOVLW 0FFH
MOVWF CNT
TSLP1
CALL KETA1
BCF PORTA,0
CALL KETA2
BCF PORTA,1
CALL KETA3
BCF PORTA,2
CALL KETA4
BCF PORTA,3
CALL KETA5
BCF PORTA,4
DECFSZ CNT,F
GOTO TSLP1
MOVLW 0FFH
MOVWF CNT
TSLP2
CALL KETA1
BCF PORTA,0
CALL KETA2
BCF PORTA,1
CALL KETA3
BCF PORTA,2
CALL KETA4
BCF PORTA,3
CALL KETA5
BCF PORTA,4
DECFSZ CNT,F
GOTO TSLP2
; BTFSS PORTB,7
; GOTO TSLP
; BTFSS PORTB,7
; GOTO TSLP
MOVLW B'00000001' ;初期化
MOVWF FLAG
CLRF SEGCHK ;変数の初期化
CLRF CNT
CLRF GFLAG
CLRF MS10
CLRF MS100
CLRF S1
CLRF S10
CLRF M1
CLRF PORTA
MOVLW B'00111100'
MOVWF PORTB
GOTO MAIN

;-----------------------
;ゴールチェック
;-----------------------
GOALCHK
BTFSS PORTB,0
GOTO PORT1
GOTO CHKF
;GOTO MAIN
PORT1
BTFSS PORTB,1
GOTO MAIN
GOTO CHKF
;GOTO MAIN
CHKF
BTFSS GFLAG,0 ;GFLAG0ビット目が1なら次の命令をスキップ
GOTO DISP
GOTO CNTS
DISP
BTFSS GFLAG,1 ;GFLAG0ビット目が1なら次の命令をスキップ
GOTO DIS7SEG
MOVLW B'00000100'
MOVWF GFLAG
BCF INTCON,T0IE ;タイマー0割り込み禁止
MOVF MS10,W
MOVWF MS10TEMP1 ;タイムデータ保持
MOVF MS100,W
MOVWF MS100TEMP1
MOVF S1,W
MOVWF S1TEMP1
MOVF S10,W
MOVWF S10TEMP1
MOVF M1,W
MOVWF M1TEMP1
BSF INTCON,T0IE ;タイマー0割り込み許可
;RETURN ;CALLで戻る
GOTO MAIN
DIS7SEG
BTFSS GFLAG,2 ;GFLAGの2ビット目が1なら次の命令をスキップ
GOTO MAIN
BCF INTCON,T0IE ;TIMER0割り込み禁止
MOVF MS10,W
MOVWF MS10TEMP2 ;タイムデータ保持
MOVF MS100,W
MOVWF MS100TEMP2
MOVF S1,W
MOVWF S1TEMP2
MOVF S10,W
MOVWF S10TEMP2
MOVF M1,W
MOVWF M1TEMP2

MOVLW D'10'
MOVWF CNT
MOVF MS10TEMP1,W
MOVWF MS10
MOVF MS100TEMP1,W
MOVWF MS100
MOVF S1TEMP1,W
MOVWF S1
MOVF S10TEMP1,W
MOVWF S10
MOVF M1TEMP1,W
MOVWF M1
DISLP1
CALL KETA1 ;先にゴールしたほうのタイムを表示
;CALL T10MS
BCF PORTA,0
CALL KETA2
;CALL T10MS
BCF PORTA,1
CALL KETA3
;CALL T10MS
BCF PORTA,2
CALL KETA4
;CALL T10MS
BCF PORTA,3
CALL KETA5
;CALL T10MS
BCF PORTA,4
DECFSZ CNT,F
GOTO DISLP1

MOVLW D'10'
MOVWF CNT
MOVF MS10TEMP2,W
MOVWF MS10
MOVF MS100TEMP2,W
MOVWF MS100
MOVF S1TEMP2,W
MOVWF S1
MOVF S10TEMP2,W
MOVWF S10
MOVF M1TEMP2,W
MOVWF M1
DISLP2
CALL KETA1 ;後にゴールしたほうのタイムを表示
;CALL T10MS
BCF PORTA,0
CALL KETA2
;CALL T10MS
BCF PORTA,1
CALL KETA3
;CALL T10MS
BCF PORTA,2
CALL KETA4
;CALL T10MS
BCF PORTA,3
CALL KETA5
;CALL T10MS
BCF PORTA,4
DECFSZ CNT,F
GOTO DISLP2
CLR
CLRF SEGCHK ;変数の初期化
CLRF CNT
MOVLW B'00000001'
MOVWF FLAG
CLRF GFLAG
CLRF MS10
CLRF MS100
CLRF S1
CLRF S10
CLRF M1
CLRF MS10TEMP1
CLRF MS100TEMP1
CLRF S1TEMP1
CLRF S10TEMP1
CLRF M1TEMP1
CLRF MS10TEMP2
CLRF MS100TEMP2
CLRF S1TEMP2
CLRF S10TEMP2
CLRF M1TEMP2
MOVLW TONE
MOVWF TMR0
;RETURN
GOTO MAIN
;タイム計測開始
CNTS
MOVLW B'00000010'
MOVWF GFLAG
CLRF MS10
CLRF MS100
CLRF S1
CLRF S10
CLRF M1
BSF INTCON,T0IE ;TIMER0割り込み許可
MOVLW TONE
MOVWF TMR0

;RETURN
GOTO MAIN
;-----------------------
;7セグ表示データ判定
;-----------------------
SEG0
MOVLW D'0'
SUBWF SEGCHK,W ;SEGCHK-0
BTFSS STATUS,Z ;引き算の結果が0の時は次の命令をスキップ
GOTO SEG1
MOVLW D_0
MOVWF SEGCHK
RETURN
SEG1
MOVLW D'1'
SUBWF SEGCHK,W ;SEGCHK-0
BTFSS STATUS,Z ;引き算の結果が0の時は次の命令をスキップ
GOTO SEG2
MOVLW D_1
MOVWF SEGCHK
RETURN
SEG2
MOVLW D'2'
SUBWF SEGCHK,W ;SEGCHK-0
BTFSS STATUS,Z ;引き算の結果が0の時は次の命令をスキップ
GOTO SEG3
MOVLW D_2
MOVWF SEGCHK
RETURN
SEG3
MOVLW D'3'
SUBWF SEGCHK,W ;SEGCHK-0
BTFSS STATUS,Z ;引き算の結果が0の時は次の命令をスキップ
GOTO SEG4
MOVLW D_3
MOVWF SEGCHK
RETURN
SEG4
MOVLW D'4'
SUBWF SEGCHK,W ;SEGCHK-0
BTFSS STATUS,Z ;引き算の結果が0の時は次の命令をスキップ
GOTO SEG5
MOVLW D_4
MOVWF SEGCHK
RETURN
SEG5
MOVLW D'5'
SUBWF SEGCHK,W ;SEGCHK-0
BTFSS STATUS,Z ;引き算の結果が0の時は次の命令をスキップ
GOTO SEG6
MOVLW D_5
MOVWF SEGCHK
RETURN
SEG6
MOVLW D'6'
SUBWF SEGCHK,W ;SEGCHK-0
BTFSS STATUS,Z ;引き算の結果が0の時は次の命令をスキップ
GOTO SEG7
MOVLW D_6
MOVWF SEGCHK
RETURN
SEG7
MOVLW D'7'
SUBWF SEGCHK,W ;SEGCHK-0
BTFSS STATUS,Z ;引き算の結果が0の時は次の命令をスキップ
GOTO SEG8
MOVLW D_7
MOVWF SEGCHK
RETURN
SEG8
MOVLW D'8'
SUBWF SEGCHK,W ;SEGCHK-0
BTFSS STATUS,Z ;引き算の結果が0の時は次の命令をスキップ
GOTO SEG9
MOVLW D_8
MOVWF SEGCHK
RETURN
SEG9
MOVLW D'9'
SUBWF SEGCHK,W ;SEGCHK-0
BTFSS STATUS,Z ;引き算の結果が0の時は次の命令をスキップ
GOTO MAIN
MOVLW D_9
MOVWF SEGCHK
RETURN

;-----------------------
;200MS遅延
;-----------------------
T200MS
MOVLW H'6'
MOVWF PTCNT3
T200MS3A
MOVLW H'DD'
MOVWF PTCNT2
T200MS2A
MOVLW H'FA'
MOVWF PTCNT1
T200MS1A
DECFSZ PTCNT1,F
GOTO T200MS1A

DECFSZ PTCNT2,F
GOTO T200MS2A

DECFSZ PTCNT3,F
GOTO T200MS3A

MOVLW H'37'
MOVWF PTCNT1
T200MS1B
DECFSZ PTCNT1,F
GOTO T200MS1B

NOP
RETURN

;-----------------------
;800US遅延
;-----------------------
T800US
MOVLW H'11'
MOVWF PTCNT2
T800US2A
MOVLW H'4D'
MOVWF PTCNT1
T800US1A
DECFSZ PTCNT1,F
GOTO T800US1A

DECFSZ PTCNT2,F
GOTO T800US2A

RETURN

;-----------------------
;1MS遅延
;-----------------------
T1MS
MOVLW H'87'
MOVWF PTCNT2
T1MS2A
MOVLW H'B'
MOVWF PTCNT1
T1MS1A
DECFSZ PTCNT1,F
GOTO T1MS1A

DECFSZ PTCNT2,F
GOTO T1MS2A

RETURN

END

学科展用に製作したものですが、アセンブラで7セグのダイナミック制御をしたい時とかにどうぞ。
まだまだ甘いですが、最適化が進んでないだけです。これだけあれば後から時計にするのもストップウォッチとしてさらに機能を強化するのも可能でしょうから。
というか、このプログラムを5日で完全に動作するように書き上げた私は頑張ったと思う。まぁ、人間やめたからこそできたと思うけど。