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