====== 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}}