;--------------------------------------------------------------------- ; スクロール時計 ; 2009.02.13 T.Nakamura ; ; (1). RC0〜7 [out] : 行(データポート) LEDアノード側 ; (2). RA0〜2,4,RB4〜7[out] : 列(スキャンポート) LEDカソード側 ; (3). RA3 [in] : タクトスイッチ ; (4). RA5 [out] : 圧電ブザー(未使用) ;--------------------------------------------------------------------- ; ;--------------------------------------------------------------------- ; デバイス定義 ;--------------------------------------------------------------------- LIST P=PIC16F689 INCLUDE "P16F689.INC" __CONFIG _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT ERRORLEVEL -302 ;アセンブル時のバンク警告メッセージ抑制 ;--------------------------------------------------------------------- ; 変数レジスタの定義(BANK0) ;--------------------------------------------------------------------- ;--------------------------------------------------------------------- ; 変数レジスタの定義(マトリックスLEDプラットフォーム) ;--------------------------------------------------------------------- DSPBUF EQU 020H ; 表示バッファ 8バイト(20H〜27H, 28H) ; ; 28HはLEDなし(スクロール時の次の列データ) ROWCNT EQU 029H ; マトリックスLEDのROWカウンタ FLAG EQU 02AH ; 各種フラグ 0ビット:SW-ON:1,OFF:0(押されている間ON) ; 1ビット:SW-ON:1(PGで解除するまでON) ; 2ビット:SWが離されてしばらくするとON BKUPW EQU 02BH ; Wレジ待避用 BKUPS EQU 02CH ; STATUSレジ待避用 BKUPFR EQU 02DH ; FSRレジ待避用 BKUPPCL EQU 02EH ; PCLHレジ待避用 BKPORTA EQU 02FH ; PORTA状態(ビープ音用) ; POSX EQU 030H ; LED座標X POSY EQU 031H ; LED座標Y BUFCNT1 EQU 032H ; 表示バッファ作業用 BUFCNT2 EQU 033H ; 表示バッファ作業用 CNT EQU 034H ; カウンタ WCNT1 EQU 035H ; ウェイトカウンタ WCNT2 EQU 036H ; ウェイトカウンタ WCNT3 EQU 037H ; ウェイトカウンタ BCNT1 EQU 038H ; ビープ用 BWCNT1 EQU 039H ; ビープ用 BWCNT2 EQU 03AH ; ビープ用 BWCNT3 EQU 03BH ; ビープ用 SMPLCNT EQU 03CH ; チャタリング回避用(割り込み10回:3.2ms) ; CHRCNT EQU 03DH ; メッセージカウンタ CHRPTR EQU 03EH ; メッセージポインタ SWCNT EQU 03FH ; スイッチ状態の監視カウンタ ;--------------------------------------------------------------------- ; 変数レジスタの定義(アプリ用) ;--------------------------------------------------------------------- H10PTN EQU 040H ; 040H-042H 10時数字パターン H01PTN EQU 044H ; 044H-046H 01時数字パターン COLPTN EQU 048H ; 048H : パターン M10PTN EQU 04AH ; 04AH-04CH 10分数字パターン M01PTN EQU 04EH ; 04EH-050H 01時数字パターン ; H10DGT EQU 052H ; 10時 H01DGT EQU 053H ; 01時 M10DGT EQU 054H ; 10分 M01DGT EQU 055H ; 01分 SECDIG EQU 056H ; 秒 TIMFLG EQU 057H ; 0 : 秒フラグ(1秒経過後にON) ; 1 : 時刻設定モード SECLOW EQU 058H ; 秒カウンタ(下位) SECHIGH EQU 059H ; 秒カウンタ(上位) ; DGTCNT EQU 05AH OFFSET EQU 05BH WKCNT EQU 05CH NUMBER EQU 05DH WAIT EQU 05EH SCCNT EQU 05FH ; スクロールタイミング ; ; 最後は 07FH ;--------------------------------------------------------------------- ; マクロ定義 ;--------------------------------------------------------------------- BANK0 MACRO BCF STATUS,RP0 ;BANK0に切り替える BCF STATUS,RP1 ; ENDM BANK1 MACRO BSF STATUS,RP0 ;BANK1に切り替える BCF STATUS,RP1 ; ENDM BANK2 MACRO BCF STATUS,RP0 ;BANK2に切り替える BSF STATUS,RP1 ; ENDM ;--------------------------------------------------------------------- ; リセットベクタ ;--------------------------------------------------------------------- ORG 00H ; リセット時の飛び込み先 RESET GOTO START ; メイン処理へ ; ORG 04H ; 割り込み時の飛び込み先 GOTO INTRUPT ;--------------------------------------------------------------------- ; メイン処理 ;--------------------------------------------------------------------- START CALL INIT ; 初期化 MAIN BTFSC FLAG,0 ; 時刻設定モード CALL SETTIME ; BTFSS TIMFLG,0 ; 秒フラグ確認 GOTO MAIN ; CALL COUNTUP GOTO MAIN ; ;--------------------------------------------------------------------- ; 初期化 ;--------------------------------------------------------------------- INIT BCF INTCON,GIE ;全割込み禁止 BANK2 CLRF ANSEL CLRF ANSELH BANK1 MOVLW B'11001000' MOVWF TRISA ; ポートAはBIT0,1,2,4,5を出力、3を入力端子 CLRF TRISB ; ポートBは全て出力端子 CLRF TRISC ; ポートCは全て出力端子 ;割り込みタイマーセット MOVLW H'82' ; プリスケーラを1:8にする MOVWF OPTION_REG ; 488.28125Hzで割り込みが入るはず ; clock4MHz -> 1Mcycle ; 1Mcycle/256/8 = 488.28125Hz MOVLW B'00000000' ; 内蔵発振のキャリブレーション MOVWF OSCTUNE ; 0000 0111 Max freq. BANK0 ; 0001 0000 Min freq. ; CLRF PORTA ; PORTクリア CLRF PORTB ; CLRF ROWCNT ; LED ROWカウンタクリア CLRF FLAG ; CLRF ROWCNT ; クリア CLRF FLAG CLRF ROWCNT ; 表示ラインカウンタクリア CLRF SECLOW ; 秒カウンタ(下位)クリア CLRF SECHIGH ; 秒カウンタ(上位)クリア CLRF TIMFLG ; 秒フラグクリア CLRF SECDIG CLRF M01DGT CLRF M10DGT CLRF H01DGT CLRF H10DGT CLRF DGTCNT MOVLW D'16' MOVWF SCCNT ; CALL CLRPTN CALL DSPCOL CALL CLRDPBUF CALL SET4DGT ; 初期値"0:00"への変換 MOVLW D'5' MOVWF SMPLCNT ; SW状態のサンプリング間隔(2ms*5=約10ms) ; BSF INTCON,T0IE ; タイマ0割り込みイネーブル BSF INTCON,GIE ; 割り込み許可 ; RETURN ;--------------------------------------------------------------------- ; 割り込み処理でダイナミック表示を行う。 ;--------------------------------------------------------------------- INTRUPT ;レジスタ待避 MOVWF BKUPW ;バックアップ(Wレジ) SWAPF STATUS,W ;バックアップ(STATUSレジ) MOVWF BKUPS MOVF FSR,W ;バックアップ(FSRレジ) MOVWF BKUPFR MOVF PCLATH,W ;バックアップ(PCLATHレジ) MOVWF BKUPPCL ; BCF INTCON,T0IF ;割り込みフラグリセット ; INCF SECLOW,F ; 1秒カウンタUP BTFSC STATUS,Z INCF SECHIGH,F ; 桁上げがあったらHIGHカウンタUP ; MOVLW H'01' ; 488になったら1秒とする SUBWF SECHIGH,W ; 正確には488.28125で1秒なので、 BTFSS STATUS,Z ; 0.0576%の誤差→10分で約0.346秒進むことになる GOTO CHK_SW ; しかし内蔵発振の誤差が±1%なので無視できる MOVLW H'E8' ; 256+232=488 SUBWF SECLOW,W BTFSS STATUS,Z GOTO CHK_SW CLRF SECLOW CLRF SECHIGH BSF TIMFLG,0 ; 1秒経ったのでFLAG=1 ; ; タクトスイッチの状態確認 ; CHK_SW DECFSZ SMPLCNT,F ; チャタリング回避のためのサンプル時間確認 GOTO DSPLED ; LED表示 ; MOVLW D'5' ; 次回のためにカウンタセット MOVWF SMPLCNT ; INCF SWCNT,F MOVLW D'100' SUBWF SWCNT,W BTFSC STATUS,Z BSF FLAG,2 ; 長時間押されなかった ; BCF FLAG,0 ; スイッチフラグクリア BTFSC PORTA,3 GOTO DSPTIM BSF FLAG,0 ; スイッチON BSF FLAG,1 ; スイッチON BCF FLAG,2 ; 長時間押されなかったフラグ CLRF SWCNT ; DSPTIM BTFSC TIMFLG,1 ; 時刻設定時はスクロール無し GOTO DSPLED DSPSCRL DECFSZ SCCNT,F ; スクロール確認 GOTO DSPLED CALL SCRTIM ; 時刻表示&スクロール MOVLW D'16' MOVWF SCCNT DSPLED ; ; 表示バッファの内容を1行分(1行)出力 ; ; 次の行データを出力する前に受け側portをHIGH(消灯になる) MOVLW B'11111111' ; MOVWF PORTB ; PORTB出力 BTFSS PORTA,5 ; PORTA(5) 確認 MOVLW B'11011111' ; PORTA(5) LOW MOVWF PORTA ; PORTA出力 ; MOVF ROWCNT,W ADDLW DSPBUF ; DSPバッファアドレス加算 MOVWF FSR MOVF INDF,W MOVWF PORTC ; PORTCに1行分のデータ出力 ; BTFSC ROWCNT,2 ; 4以上ならPORTBを設定 GOTO SETPRTB ; MOVF ROWCNT,W CALL DECPORTA BTFSS PORTA,5 ; PORTA(5) 確認 ANDLW B'11011111' ; PORTA(5) LOW MOVWF PORTA ; PORTA出力 MOVLW B'11111111' MOVWF PORTB ; PORTB出力 GOTO NXTROW ; 次の行にROWCNT設定 SETPRTB MOVLW D'4' SUBWF ROWCNT,W CALL DECPORTB MOVWF PORTB ; PORTB出力 MOVLW B'11111111' BTFSS PORTA,5 ; PORTA(5) 確認 ANDLW B'11011111' ; PORTA(5) LOW MOVWF PORTA ; PORTA出力 ; NXTROW INCF ROWCNT,W ANDLW H'07' ; ROWCNTは0〜7 MOVWF ROWCNT ; RSTREG ;レジスタ復元 MOVF BKUPPCL,W ;復元(PCLATHレジ) MOVWF PCLATH MOVF BKUPFR,W ;復元(FSRレジ) MOVWF FSR SWAPF BKUPS,W ;復元(STATUSレジ) MOVWF STATUS SWAPF BKUPW,F ;復元(Wレジ) SWAPF BKUPW,W ; RETFIE ;割り込みから復帰 ; DECPORTA CLRF PCLATH ; ADDWF PCL,F RETLW B'11111110' ; 0 RETLW B'11111101' ; 1 RETLW B'11111011' ; 2 RETLW B'11101111' ; 3 ; DECPORTB CLRF PCLATH ; ADDWF PCL,F RETLW B'11101111' ; 4 RETLW B'11011111' ; 5 RETLW B'10111111' ; 6 RETLW B'01111111' ; 7 ; ;--------------------------------------------------------------------- ; 時刻設定モード時の表示(時) ;--------------------------------------------------------------------- DSPHH MOVF H10PTN,W MOVWF DSPBUF ; 表示バッファに格納 MOVF H10PTN+1,W MOVWF DSPBUF+1 MOVF H10PTN+2,W MOVWF DSPBUF+2 MOVF H10PTN+3,W MOVWF DSPBUF+3 MOVF H10PTN+4,W MOVWF DSPBUF+4 MOVF H10PTN+5,W MOVWF DSPBUF+5 MOVF H10PTN+6,W MOVWF DSPBUF+6 MOVF H10PTN+7,W MOVWF DSPBUF+7 BSF DSPBUF,7 ; 「時」設定モードの表示(左下LED点灯) RETURN ; ;--------------------------------------------------------------------- ; 時刻設定モード時の表示(分) ;--------------------------------------------------------------------- DSPMM MOVF M10PTN,W MOVWF DSPBUF ; 表示バッファに格納 MOVF M10PTN+1,W MOVWF DSPBUF+1 MOVF M10PTN+2,W MOVWF DSPBUF+2 MOVF M10PTN+3,W MOVWF DSPBUF+3 MOVF M10PTN+4,W MOVWF DSPBUF+4 MOVF M10PTN+5,W MOVWF DSPBUF+5 MOVF M10PTN+6,W MOVWF DSPBUF+6 CLRF DSPBUF+7 BSF DSPBUF+7,7 ; 「分」設定モードの表示(右下LED点灯) RETURN ; ;--------------------------------------------------------------------- ; 時刻表示&スクロール ;--------------------------------------------------------------------- SCRTIM MOVF DGTCNT,F BTFSC STATUS,Z CALL CHKZSUP ; 0X時ならゼロサプレス分は表示しない MOVLW H10PTN ADDWF DGTCNT,W MOVWF FSR ; MOVF INDF,W MOVWF DSPBUF+8 ; 表示バッファに格納 ; INCF DGTCNT,F MOVLW D'18' SUBWF DGTCNT,W BTFSC STATUS,C CLRF DSPBUF+8 CALL DSPBUFST ; 表示バッファシフト ; MOVLW D'25' SUBWF DGTCNT,W BTFSS STATUS,Z RETURN ; CLRF DGTCNT CALL SET4DGT RETURN ; CHKZSUP MOVF H10DGT,F ; 0X時か? BTFSS STATUS,Z RETURN MOVLW D'4' ADDWF DGTCNT,F RETURN ;--------------------------------------------------------------------- ; 表示バッファシフト ;--------------------------------------------------------------------- DSPBUFST MOVLW DSPBUF MOVWF FSR ; FSRに表示バッファの先頭アドレスセット MOVLW D'8' MOVWF WKCNT DSPBUFS1 INCF FSR,F MOVF INDF,W ; Wレジに読み込み DECF FSR,F ; FSRをデクリメント MOVWF INDF ; 一行シフトして上書き INCF FSR,F DECFSZ WKCNT,F GOTO DSPBUFS1 CLRF INDF ; 最後の行をクリアして戻る RETURN ; ;--------------------------------------------------------------------- ; 表示用バッファクリア ;--------------------------------------------------------------------- CLRDPBUF MOVLW D'8' MOVWF CNT ; 8バイト分のクリア MOVLW DSPBUF ; W ← DSPBUFの先頭アドレス MOVWF FSR ; FSR にアドレスをセット CLRDPBUF2 CLRF INDF ;(FSR)クリア INCF FSR,F ; DECFSZ CNT,F ; GOTO CLRDPBUF2 RETURN ; ;--------------------------------------------------------------------- ; 時刻数字バッファクリア ;--------------------------------------------------------------------- CLRPTN MOVLW D'17' MOVWF CNT ; 17バイト分のクリア MOVLW H10PTN ; MOVWF FSR ; FSR にアドレスをセット CLRPTN2 CLRF INDF ;(FSR)クリア INCF FSR,F ; DECFSZ CNT,F ; GOTO CLRPTN2 RETURN ; ;--------------------------------------------------------------------- ; 時刻設定モード(時刻の2桁をカウントアップ) ;--------------------------------------------------------------------- SETTIME BSF TIMFLG,1 ; 時刻設定モード CLRF M01DGT ; SETHOUR CALL SET4DGT ; 表示パターンに変換 CALL DSPHH ; 「時」設定表示 BTFSC FLAG,0 ; SWが離されるまで待つ GOTO $-1 WAITSW1 BTFSC FLAG,2 ; 長い時間、押されなかった? GOTO SETMIN BTFSS FLAG,0 ; スイッチが押されなければ待つ GOTO WAITSW1 ; INCF H01DGT,F MOVLW D'3' SUBWF H01DGT,W BTFSS STATUS,Z GOTO CHK10H MOVLW D'1' SUBWF H10DGT,W BTFSS STATUS,Z GOTO CHK10H ; 01時にする MOVLW D'1' MOVWF H01DGT CLRF H10DGT GOTO SETHOUR CHK10H MOVLW D'10' SUBWF H01DGT,W ; 桁上げ確認 BTFSS STATUS,Z GOTO SETHOUR INCF H10DGT,F CLRF H01DGT GOTO SETHOUR ; SETMIN ; 5分刻みで設定 CALL SET4DGT ; 表示パターンに変換 CALL DSPMM ; 「分」設定表示 BCF FLAG,2 CLRF SWCNT BTFSC FLAG,0 ; SWが離されるまで待つ GOTO $-1 WAITSW2 BTFSC FLAG,2 ; 長い時間、押されなかった? GOTO SETEND BTFSS FLAG,0 ; スイッチが押されなければ待つ GOTO WAITSW2 ; MOVLW D'5' ADDWF M01DGT,F MOVLW D'10' SUBWF M01DGT,W ; 桁上げ確認 BTFSS STATUS,Z GOTO SETMIN CLRF M01DGT INCF M10DGT,F MOVLW D'6' SUBWF M10DGT,W BTFSS STATUS,Z GOTO SETMIN ; 00分にする CLRF M01DGT CLRF M10DGT GOTO SETMIN ; SETEND CLRF SECLOW ; 秒カウンタ(下位)クリア CLRF SECHIGH ; 秒カウンタ(上位)クリア CLRF SECDIG ; 秒をクリア BCF TIMFLG,0 ; 秒フラグクリア CALL SET4DGT ; 表示パターンに変換 CLRF DGTCNT CALL CLRDPBUF ; 表示バッファクリア BCF TIMFLG,1 ; 時刻設定モード終了 RETURN ; ;--------------------------------------------------------------------- ; 時刻カウントアップ ;--------------------------------------------------------------------- COUNTUP BCF TIMFLG,0 ; 秒フラグクリア ; INCF SECDIG,F ; 秒カウントアップ MOVLW D'60' SUBWF SECDIG,W BTFSS STATUS,Z RETURN CLRF SECDIG ; 秒クリア ; CNTUPMIN INCF M01DGT,F ; 分(1の位)カウントアップ MOVLW D'10' SUBWF M01DGT,W BTFSS STATUS,Z RETURN CLRF M01DGT ; INCF M10DGT,F ; 分(10の位)カウントアップ MOVLW D'6' SUBWF M10DGT,W BTFSS STATUS,Z RETURN CLRF M10DGT ; INCF H01DGT,F ; 時(1の位)カウントアップ MOVLW D'10' SUBWF H01DGT,W BTFSC STATUS,Z GOTO H10UP ; MOVLW D'3' ; 13時のチェック SUBWF H01DGT,W BTFSS STATUS,Z RETURN MOVLW D'1' SUBWF H10DGT,W BTFSS STATUS,Z RETURN MOVLW D'1' ; 12時の次は 1時にする MOVWF H01DGT CLRF H10DGT RETURN H10UP CLRF H01DGT INCF H10DGT,F ; 時(10の位)カウントアップ RETURN ; ;--------------------------------------------------------------------- ; :(コロン)の表示 ;--------------------------------------------------------------------- DSPCOL MOVLW B'00010100' ; :(コロン) MOVWF COLPTN RETURN ; ;--------------------------------------------------------------------- ; 4桁分の時刻を表示バッファに格納 ;--------------------------------------------------------------------- SET4DGT MOVF H10DGT,W BTFSC STATUS,Z GOTO CLRH10 ; ゼロサプレス MOVWF NUMBER MOVLW H10PTN ; 表示バッファ MOVWF FSR CALL DSPDGT ; 表示バッファに表示パターン格納 GOTO SETH01 CLRH10 CLRF H10PTN CLRF H10PTN+1 CLRF H10PTN+2 SETH01 MOVF H01DGT,W MOVWF NUMBER MOVLW H01PTN ; 表示バッファ MOVWF FSR CALL DSPDGT ; 表示バッファに表示パターン格納 ; MOVF M10DGT,W MOVWF NUMBER MOVLW M10PTN ; 表示バッファ MOVWF FSR CALL DSPDGT ; 表示バッファに表示パターン格納 SETM01 MOVF M01DGT,W MOVWF NUMBER MOVLW M01PTN ; 表示バッファ MOVWF FSR CALL DSPDGT ; 表示バッファに表示パターン格納 ; RETURN ;--------------------------------------------------------------------- ; 一桁分の数字(3x5ドット)を表示バッファに設定 ; NUMBER:数値(0〜9) ... 破壊される ; FSR :表示バッファアドレスの先頭を格納 ... 破壊される ;--------------------------------------------------------------------- DSPDGT CLRF OFFSET ; 列カウンタクリア MOVLW D'3' MOVWF WKCNT DSPDGTL CALL DIGITDT ; 数値の先頭1列分を取り出す MOVWF INDF ; 表示バッファに書き出す INCF OFFSET,F ; 1列進める INCF FSR,F ; 表示バッファを進める DECFSZ WKCNT,F GOTO DSPDGTL RETURN ; DIGITDT ;数字の1列分のデータを取り出し MOVF OFFSET,F ; offsetが0か判断 BTFSS STATUS,Z ; 0ならスキップ GOTO DIGITDT1 ; 0以外ならoffsetをインクリメント ; 0でない→その数字の最初の1列 ; 数値を4倍してoffsetへ BCF STATUS,C ;キャリークリア RLF NUMBER,F RLF NUMBER,W MOVWF OFFSET DIGITDT1 MOVLW H'01' MOVWF PCLATH MOVF OFFSET,W ADDWF PCL,F ; digit 0 RETLW B'00111110' RETLW B'00100010' RETLW B'00111110' RETLW B'00000000' ; digit 1 RETLW B'00100100' RETLW B'00111110' RETLW B'00100000' RETLW B'00000000' ; digit 2 RETLW B'00111010' RETLW B'00101010' RETLW B'00101110' RETLW B'00000000' ; digit 3 RETLW B'00101010' RETLW B'00101010' RETLW B'00111110' RETLW B'00000000' ; digit 4 RETLW B'00001110' RETLW B'00001000' RETLW B'00111110' RETLW B'00000000' ; digit 5 RETLW B'00101110' RETLW B'00101010' RETLW B'00111010' RETLW B'00000000' ; digit 6 RETLW B'00111110' RETLW B'00101010' RETLW B'00111010' RETLW B'00000000' ; digit 7 RETLW B'00000010' RETLW B'00111010' RETLW B'00000110' RETLW B'00000000' ; digit 8 RETLW B'00111110' RETLW B'00101010' RETLW B'00111110' RETLW B'00000000' ; digit 9 RETLW B'00101110' RETLW B'00101010' RETLW B'00111110' RETLW B'00000000' ; ;--------------------------------------------------------------------- END ;--------------------------------------------------------------------- ; 終わり ;---------------------------------------------------------------------