7セグで時計表示

7セグを時計用に回転

前回の基板の7セグを下記の用に、180度回転して取り付けます。こうすると:が出来上がります。
一番左のをひっくり返すのはプログラムを簡単にするためです。

7seg20.jpg

プログラムの作成

まずは、ポートの設定と、消燈用の値定義。ここは前回とほとんど同じ。

;------------------------------------------------------------------------------
;       ポート設定
;------------------------------------------------------------------------------
SSD_NUM         EQU     6                       ; 7セグの個数
SSD_DIGIT_PORT  EQU     PA                      ; 桁切り替えのポート
SSD_DIGIT_DR    EQU     PADR
SSD_DATA_PORT   EQU     PB                      ; データ用のポート
SSD_DATA_DR     EQU     PBDR
SSD_DATA_SP     EQU     11111111B               ; 消燈

次に、7セグの点灯データ。今回は文字別にテーブル化する必要が無いため、直接作成します。
7セグを反転しているため反転用のデータと、ドット表示用のテーブルも記述。
RAMには、桁位置保存用のワークと、描画データ保存用のワークを作成。ここは前回と同じ。

;******************************************************************************
;       ROM 上のデータ
;******************************************************************************
                segment TEXT
;------------------------------------------------------------------------------
;       7 セグの点灯データ
;------------------------------------------------------------------------------
;                       *gfedcba                ; 通常
SSD_DATA_TBL:   DC.B    11000000B               ; 0
                DC.B    11111001B               ; 1
                DC.B    10100100B               ; 2
                DC.B    10110000B               ; 3
                DC.B    10011001B               ; 4
                DC.B    10010010B               ; 5
                DC.B    10000010B               ; 6
                DC.B    11111000B               ; 7
                DC.B    10000000B               ; 8
                DC.B    10010000B               ; 9
;                       g*cbafed                ; 反転
                DC.B    11000000B               ; 0
                DC.B    11111001B               ; 1
                DC.B    01100100B               ; 2
                DC.B    01110000B               ; 3
                DC.B    01011001B               ; 4
                DC.B    01010010B               ; 5
                DC.B    01000010B               ; 6
                DC.B    11111000B               ; 7
                DC.B    01000000B               ; 8
                DC.B    01010000B               ; 9
 
SSD_DOT_TBL:    DC.B    11111111B               ; ドット ON 用
                DC.B    01111111B
                DC.B    10111111B
                DC.B    01111111B
                DC.B    10111111B
                DC.B    11111111B
;******************************************************************************
;       RAM 上のデータ(初期化なし)
;******************************************************************************
                SEGMENT BSS
SSD_DIGIT:      DS.B    1                       ; 現在描画している桁
;******************************************************************************
;       RAM 上のデータ(初期化あり)
;******************************************************************************
                SEGMENT DATA
SSD_DATA:       DCB.B   SSD_NUM,SSD_DATA_SP     ; 表示データ

初期化ルーチンは、前回と全く同じです。

;******************************************************************************
;       7セグの初期化
;
;       _SsdInit
;         2004/12/30 : 初期バージョン完成
;
;       [書式]  void SsdInit(void) ;
;
;       [IN]    なし
;
;       [OUT]   なし
;
;       [DED]   R0
;******************************************************************************
                public  _SsdInit
_SsdInit:       SUB.B   R0L,R0L
                MOV.B   R0L,@SSD_DIGIT
                DEC.B   R0L
                MOV.B   R0L,@SSD_DIGIT_DR
                MOV.B   R0L,@SSD_DATA_DR
;------------------------------------------------------------------------------
;       タイマ 2 を 1ms で回す
;------------------------------------------------------------------------------
                MOV.B   #00100011B,R0L          ; GRA のコンペアマッチ
                MOV.B   R0L,@TCR2               ;   b6-b5 : インプットキャプチャで TCNT をクリア
                                                ;   b4-b3 : 立上がりエッジでカウント
                                                ;   b2-b0 : 内部クロック:φ/8 でカウント
                SUB.W   R0,R0
                MOV.W   R0,@TCNT2               ; カウンタをクリア
                MOV.B   R0L,@TIOR2              ; 出力端子無効
                INC.B   R0L                     ; タイマ割り込み有効
                MOV.B   R0L,@TIER2
                MOV.W   #CPU_CLOCK_8 / 1000,R0  ; 1ms(1000Hz) にカウンタを合わせる
                MOV.W   R0,@GRA2
                BCLR    #0,@TSR2                ; 割り込み要求ののクリア
                BSET.B  #2,@TSTR                ; ITU2 のタイマスタート
 
                RTS

文字列を、7セグ用のデータに変換します。
文字列は、時分秒を各2桁、ドットを描画する場合は'.'しない場合は' 'の7文字で渡します。

反転した7セグの場合は、テーブルを10足します。
ドットが必要な場合は、各7セグ点灯データのdpの位置をANDで0(アクティブ Low)にします。

;******************************************************************************
;       7セグの描画用に文字列変換
;
;       _SsdDraw
;         2005/01/05 : 初期バージョン完成
;
;       [書式]  void SsdDraw(char *str) ;
;
;       [IN]    char    *str    = 文字列のポインタ(000000.)
;
;       [OUT]   なし
;
;       [DED]   R0,ER1,ER2,ER3
;******************************************************************************
                public  _SsdDraw
_SsdDraw:       MOV.L   @(4,ER7),ER1            ; ER1 = *str
                SUB.L   ER2,ER2                 ; ER2 = 0
                MOV.L   #SSD_DATA,ER3           ; ER3 = *SSD_DATA
                MOV.B   #SSD_NUM,R0H            ; R0H = 桁数
 
SSD_DRAW_LOOP:  MOV.B   @ER1+,R2L               ; 1 文字取得
                ADD.B   #-'0',R2L               ; 文字 - '0'
                BLD.B   #0,R0H                  ; 反転している7セグ?
                BCS     SKIP_REVERS:8
                ADD.B   #10,R2L                 ; 文字 + 10
SKIP_REVERS:    MOV.B   @(SSD_DATA_TBL,ER2),R0L ; 7セグ点灯データに変換
 
                MOV.B   R0L,@ER3
                INC.L   #1,ER3
 
                DEC.B   R0H
                BNE     SSD_DRAW_LOOP:8
 
                MOV.B   @ER1+,R2L               ; 1 文字取得
                CMP.B   #'.',R2L                ; '.' じゃない?
                BEQ     SSD_DRAW_END:8
                                                ; ドットの描画
                MOV.L   #SSD_DOT_TBL,ER2        ; ER2 = *SSD_DOT_TBL
                MOV.L   #SSD_DATA,ER3           ; ER3 = *SSD_DATA
                MOV.B   #SSD_NUM/2,R0H          ; R0H = 桁数
SSD_DOT_LOOP:   MOV.W   @ER2+,E1
                MOV.W   @ER3+,R1
                AND.W   E1,R1
                MOV.W   R1,@(-2,ER3)
                DEC.B   R0H
                BNE     SSD_DOT_LOOP:8
 
SSD_DRAW_END:   RTS

割り込み処理も、前回と同じ。

;******************************************************************************
;       7セグの描画割り込み
;
;       INT_SSD_DRAW
;         2005/01/05 : 初期バージョン完成
;
;       [IN]    なし
;
;       [OUT]   なし
;
;       [DED]   なし
;******************************************************************************
                public  INT_SSD_DRAW
INT_SSD_DRAW:   PUSH.L  ER0
                PUSH.L  ER1
 
                MOV.B   #SSD_DATA_SP,R0L        ; 桁を切り替える前にデータクリア
                MOV.B   R0L,@SSD_DATA_PORT
 
                MOV.B   @SSD_DIGIT,R0L          ; 桁の切り替え
                MOV.B   R0L,@SSD_DIGIT_PORT
 
                EXTU.W  R0
                EXTU.L  ER0
                MOV.L   #SSD_DATA + (SSD_NUM - 1),ER1
                SUB.L   ER0,ER1
                MOV.B   @ER1,R0H
                MOV.B   R0H,@SSD_DATA_PORT
 
                INC.B   R0L                     ; 桁を進めておく
                CMP.B   #SSD_NUM,R0L
                BNE     INT_SSD_SKIP:8
                SUB.B   R0L,R0L
INT_SSD_SKIP:   MOV.B   R0L,@SSD_DIGIT
 
                POP.L   ER1
                POP.L   ER0
                BCLR.B  #0,@TSR2
                RTE

動作チェック用のサンプル。あくまでも表示チェック用なので精度は悪いです。
本来は500ms割り込みを使用しカウントすべきです。(1000msでないのはドットを点滅させるため)

extern void SsdInit(void) ;
extern void SsdDraw(char *str) ;
 
void main(void) {
    int     h = 12,m = 34,s = 0 ;
    char    d = '.' ;
 
    _di() ;
    SsdInit() ;
    _ei() ;
 
    while(1) {
        char str[8] ;
 
        sprintf(str,"%02d%02d%02d%c",h,m,s,d) ;
        SsdDraw(str) ;
        if(d ^= '.') {
            if(++ s >= 60) {
                s = 0 ;
                if(++ m >= 60) {
                    m = 0 ;
                    if(++ h >= 24) {
                        h = 0 ;
                    }
                }
            }
        }
        Wait1ms(500) ;
    }
}

実行結果

見た目は時計っぽいです。時刻設定やアラーム設定などを作れば使えそうです。

7seg21.jpg

h8/7セグで時計表示.txt · 最終更新: 2018/03/18 09:56 (外部編集)
 
特に明示されていない限り、本Wikiの内容は次のライセンスに従います: CC Attribution-Share Alike 4.0 International
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki