目次PIC回路集大型表示電波時計


大型表示電波時計 ソフトウェア処理説明

時計本体プログラム

マクロの変更

16Fシリーズのプログラムメモリは最大8Kワードで、2Kワード単位のページに分けられています。ですから、最大4ページのメモリがあります。このページの指定はPCLATHレジスタのビット3、ビット4の値で指定されます。
他のページで紹介している電波時計ではPIC16F873を使用しています。873のプログラムメモリーは4Kワードですので、プログラムメモリは2ページしか使用していません。ですから、ページ切り替え用のマクロも2ページの制御しか作られていません。
今回使用したPIC16F877は最大の8Kワードを実装しています。そして、追加したプログラムはページ2に割り付けています。そのため、ページ切り替え用のマクロも4ページ切り替えるように変更しました。

picmac1.inc
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
setpch  macro
        if      ($ >= 0) && ($ < 0x800)
        bcf     PCLATH,3
        bcf     PCLATH,4
        else
        if      ($ >= 0x800) && ($ < 0x1000)
        bsf     PCLATH,3
        bcf     PCLATH,4
        else
        if      ($ >= 0x1000) && ($ < 0x1800)    
        bcf     PCLATH,3
        bsf     PCLATH,4
        else
        bsf     PCLATH,3
        bsf     PCLATH,4
        endif
        endif
        endif
        endm

マクロはアセンブルするとメモリに展開されます。今までのマクロはPCLATHのビット3のみを操作していたのですが、今回のマクロではビット3とビット4を操作します。ですから、メモリも今までより1ワード多く使います。マクロを20回使えば20ワード増えます。実際にアセンブルすると既存の処理がページ1をオーバーしてしまいました。そのため、初期化処理の一部をページ2に移動しています。


ページ2でマクロが展開されている例を以下に示します。赤字の部分の2ワードがメモリに割り付けられているのが分かります。

0E38   118A 160A 2000 03855         LCALL   LED_DISP        ;Display 7 seg LED
                      03856         SETPCH                  ;
                          M         IF      ($ >= 0) && ($ < 0X800)
                          M         BCF     PCLATH,3
                          M         BCF     PCLATH,4
                          M         ELSE
                          M         IF      ($ >= 0X800) && ($ < 0X1000)
0E3B   158A               M         BSF     PCLATH,3
0E3C   120A               M         BCF     PCLATH,4
                          M         ELSE
                          M         IF      ($ >= 0X1000) && ($ < 0X1800)
                          M         BCF     PCLATH,3
                          M         BSF     PCLATH,4
                          M         ELSE
                          M         BSF     PCLATH,3
                          M         BSF     PCLATH,4
                          M         ENDIF
                          M         ENDIF
                          M         ENDIF


汎用メモリ(GPR)の割付
PIC16F873とPIC16F877では汎用メモリの仕様が異なっています。

877では最後の16バイトは全バンク共通になっています。そこで、従来バンク0のみに割り付けられていた時計情報を後半の16バイトに割り付けることにより、どのバンクに切り替わっても読めるように変更しました。割付の位置を変えただけで、バンク0でも従来通り読み書きができるので既存の処理に影響はありません。以下の16バイトを共通エリアに割り付けました。
adr
070
071
072
073
074
075
076
077
078
079
07A
07B
07C
07D
07E
07F
 
dec_sts1                ;decode status1
tm_ndh                  ;Day counter (Upper)
tm_ndl                  ;Day counter (Lower)
tm_10y                  ;10th of years counter
tm_1y                   ;1st of year counter
tm_10mth                ;10th of mounths counter     
tm_1mth                 ;1st of mounth counter
tm_10d                  ;10th of days counter
tm_1d                   ;1st of day counter
tm_10h                  ;10th of hours counter
tm_1h                   ;1st of hour counter
tm_10m                  ;10th of minutes conuter
tm_1m                   ;1st of minute counter
tm_10s                  ;10th of seconds counter
tm_1s                   ;1st of second counter
tm_wd                   ;Week counter

この全バンク共通のエリア以外のメモリにアクセスする場合には、バンクを切り替えてから読み書きする必要があります。

左のリストの左側はメモリ番地を示しています。他のリストではソースコードの行数を示していますが、ここではメモリ上に位置を説明するためにメモリ番地を書いています。

バンク2は110h番地から割付が可能です。しかし、バンク0およびバンク1と位置を合わせるため、120hから割り付けました。あまり意味はありません。バンク3のGPRは使用していません。
バンク1およびバンク2の割付開始は0A5h番地および125h番地から行っています。これについてはトラブルシュートの「バンク1およびバンク2の汎用メモリを先頭から使うと正常に動作しない」を参照してください。

既存ソフトウェアの変更

コンフィグレーションワード変更

0016
0017
0018
0019
0020
0021
0022
        __config        h'3F32' ;OSC is HS
                                ;RB3,RB6,RB7 are I/O
                                ;Brown-out detection OFF
                                ;Power-up timer ON
                                ;Code protection OFF
                                ;Data code protection OFF   
                                ;Watchdog timer OFF
従来の電波時計に対して電源電圧低下検出機能を停止しました。
この変更については「バッテリー駆動にするとCPUが止まる」をご覧ください。


PORTCのビット割付変更
PORTCの各ビットの用途を変更しました。
緑色のビットが変更したビットです。

この関係で以下のソースコードを変更しています。

0117
0118
0119
0120

0128

1095

1136

1151

1219

3436

3963

3986

4077
;#define minute_out     portc_buf,2     ;True minute output                  @@(Delete)
;#define hour_out       portc_buf,3     ;True hour output                    @@(Delete)
;#define day_out        portc_buf,4     ;True day output                     @@(Delete)
;#define month_out      portc_buf,5     ;True month output                   @@(Delete)
-----------------------------------------------------------
;#define tco_out        portc,0         ;Time code output                    @@(Delete)
-----------------------------------------------------------
;       bsf     minute_out      ;Yes. Set true minute LED bit                @@(Delete)
-----------------------------------------------------------
;       bsf     hour_out        ;Yes. Set true hour LED bit                  @@(Delete)
-----------------------------------------------------------
;       bsf     day_out         ;Set true day LED bit                        @@(Delete)
-----------------------------------------------------------
;       bsf     month_out       ; Set true month LED bit                     @@(Delete)
-----------------------------------------------------------
        movlw   b'11000001'     ;RC6(TX),RC7(RX),RC0(PW) input mode          @@(Change)
-----------------------------------------------------------
        movlw   b'00110101'     ;Set clear pattern                           @@(Change)
-----------------------------------------------------------
;       bsf     tco_out         ;Set TCO LED ON (RC0)                        @@(Delete)
-----------------------------------------------------------
;       bcf     tco_out         ;Set TCO LED OFF (RC0)                       @@(Delete)

不要処理の削除
ページ1のメモリが不足したため、不要な処理の削除、および変更を行いました。

3885
3886
3887
3888

4202
4203
4204
4205
4206
4207

4219
4220
4221
4222
4223
4224

4239
4240
4241
4242
4243
4244
4245
;       movf    tm_1s,f         ;No. Read 1st of second                      @@(Delete)
;       jpnz    clock_main3     ;If 1st of second != 0, jump to clock_main3  @@(Delete)
;       movf    tm_10s,f        ;Read 10th of second                         @@(Delete)
;       jpnz    clock_main3     ;If 10th of second != 0, jump to clock_main3 @@(Delete)
-----------------------------------------------------------
;       clrf    rep_cnt             ;Clear key repeate counter               @@(Delete)
;       movf    ikey_dat,w          ;Read key number                         @@(Delete)
;       rbank0                      ;                                        @@(Delete)
;       movwf   key_dat             ;Save key number                         @@(Delete)
;       bsf     key_sts,0           ;Set key status                          @@(Delete)
;       goto    int_vec1            ;Jump to return                          @@(Delete)
-----------------------------------------------------------
;       clrf    rep_cnt             ;Clear key repeate counter               @@(Delete)
;       movf    ikey_dat,w          ;Read key number                         @@(Delete)
;       rbank0                      ;                                        @@(Delete)
;       movwf   key_dat             ;Save key number                         @@(Delete)
;       bsf     key_sts,0           ;Set key status                          @@(Delete)
;       goto    int_vec1            ;Jump to return                          @@(Delete)
-----------------------------------------------------------
        goto    kswchk5             ;                                        @@(Add)
;       clrf    rep_cnt             ;Clear key repeate counter               @@(Delete)
;       movf    ikey_dat,w          ;Read key number                         @@(Delete)
;       rbank0                      ;                                        @@(Delete)
;       movwf   key_dat             ;Save key number                         @@(Delete)
;       bsf     key_sts,0           ;Set key status                          @@(Delete)
;       goto    int_vec1            ;Jump to return                          @@(Delete)

初期化処理サブルーチン
初期化処理では各種のレジスタ設定および汎用メモリの初期化を行います。初期化処理はプログラムメモリのページ1にありますが、今回追加したエリアの初期化を行うとページ1の容量をオーバーしてしまいます。そこで、初期化処理の一部をサブルーチンにしてページ2に移動しています。最初は汎用メモリはバンク1だけでしたが、あとでバンク2にも割付を行いました。そのため、名称はバンク1の初期化になっていますが、バンク2の初期化も行っています。
ページを超えたサブルーチンなので、戻ったときにsetpchマクロでPCLATHの値を自分のページに書き換えます。

3477
3478

4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4849
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
        lcall   bank1_init      ;Bank1 data initialization                   @@(Add)
        setpch                  ;                                            @@(Add)
-----------------------------------------------------------
;@@@@@@@@@@@@@ Bank1 data initialization Subroutine @@@@@@@@@@@@@@@@@
bank1_init
        rbank1                  ;Set bank 1
        clrf    int_cnt         ;Clear 100uS interval counter
        clrf    int_cnt10m      ;Clear 10mS interval counter
        clrf    int_cnt100m     ;Clear 100mS interval counter
        clrf    tco_cnt         ;Clear TCO counter
        clrf    tco_hicnt       ;Clear TCO high counter
        clrf    tco_period      ;Clear TCO period counter
        clrf    tco_sts         ;Clear TCO status
        clrf    sync_cnt        ;Clear Sync valid counter
        clrf    ikey_dat        ;Clear Key number
        clrf    ikey_dat0       ;Clear Key scan position
        clrf    ikey_dat1       ;Clear Key input data
        clrf    key_phs         ;Clear Key phase
        clrf    rep_cnt         ;Clear key repeate counter
        clrf    led_10y         ;Clear LED 10th of year
        clrf    led_1y          ;Clear LED 1st of year
        clrf    led_10mth       ;Clear LED 10th of month
        clrf    led_1mth        ;Clear LED 1st of month
        clrf    led_10d         ;Clear LED 10th of day
        clrf    led_1d          ;Clear LED 1st of day
        clrf    led_10h         ;Clear LED 10th of hour
        clrf    led_1h          ;Clear LED 1st of hour
        clrf    led_10m         ;Clear LED 10th of minute
        clrf    led_1m          ;Clear LED 1st of minute
        clrf    led_10s         ;Clear LED 10th of second
        clrf    led_1s          ;Clear LED 1st of second
        clrf    led_wd          ;Clear LED week of the day
        movlw   seg7_ha         ;Set pattern table head address
        movwf   led_ha          ;Save pattern table head address
        movlw   seg7_0          ;Set pattern 0
        movwf   led_0           ;Save pattern 0
        movlw   seg7_1          ;Set pattern 1
        movwf   led_1           ;Save pattern 1
        movlw   seg7_2          ;Set pattern 2
        movwf   led_2           ;Save pattern 2
        movlw   seg7_3          ;Set pattern 3
        movwf   led_3           ;Save pattern 3
        movlw   seg7_4          ;Set pattern 4
        movwf   led_4           ;Save pattern 4
        movlw   seg7_5          ;Set pattern 5
        movwf   led_5           ;Save pattern 5
        movlw   seg7_6          ;Set pattern 6
        movwf   led_6           ;Save pattern 6
        movlw   seg7_7          ;Set pattern 7
        movwf   led_7           ;Save pattern 7
        movlw   seg7_8          ;Set pattern 8
        movwf   led_8           ;Save pattern 8
        movlw   seg7_9          ;Set pattern 9
        movwf   led_9           ;Save pattern 9
        movlw   seg7_a          ;Set hyphen pattern
        movwf   led_a           ;Save hyphen pattern
        movlw   seg7_b          ;Set OFF pattern
        movwf   led_b           ;Save OFF pattern

        rbank2
        clrf    led_hyphen      ;Clear LED hyphen
        clrf    led_cnt100u     ;Clear LED 100us counter
        clrf    led_wkdata      ;Clear LED work data
        rbank0                  ;Set bank 0
        return 

ページを超えてサブルーチンを呼び出す場合には lcall を使用します。 lcall は擬似命令でPIC自体の命令形式ではありません。アッセンブルすると以下の3ステップに展開されます。call を実行する前にPCLATHの値をページ2に設定する処理が行われます。
        bcf     pclath,3
        bsf     pclath,4
        call    bank1_init
LED表示プログラムサブルーチンコールを追加
1秒毎に実行される処理にLED表示処理を追加しました。追加した処理はサブルーチン形式にしています。こちらもサブルーチンから戻ったとき、setpchマクロでPCLATHの値を自分のページに書き換えます。

3855
3856
        lcall   led_disp        ;Display 7 seg LED                           @@(Add)
        setpch                  ;                                            @@(Add)

追加プログラム
ここからが今回のプロジェクトのメインソフトウェアです。

PORTDおよびPORTE
PIC16F877で使用できるPORTDとPORTEの設定を追加します。このポートを使うために877を使うことにしたのです。

3422
3423

3438
3439
        clrf    PORTD           ;Clear PORTD                                 @@(Add)
        clrf    PORTE           ;Clear PORTE                                 @@(Add)
-----------------------------------------------------------
        clrf    TRISD           ;RD7-0:output mode                           @@(Add)
        clrf    TRISE           ;RE2-0:output mode                           @@(Add)

7セグメントデータ
数字に対応した7セグメントデータの定義をします。

0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
;@@@ 7 segment LED data
seg7_0  equ     b'00111111'     ;-gfedcba Pattern 0                          @@(Add)
seg7_1  equ     b'00000110'     ;         Pattern 1                          @@(Add)
seg7_2  equ     b'01011011'     ;         Pattern 2                          @@(Add)
seg7_3  equ     b'01001111'     ;         Pattern 3                          @@(Add)
seg7_4  equ     b'01100110'     ;         Pattern 4                          @@(Add)
seg7_5  equ     b'01101101'     ;         Pattern 5                          @@(Add)
seg7_6  equ     b'01111101'     ;         Pattern 6                          @@(Add)
seg7_7  equ     b'00000111'     ;         Pattern 7                          @@(Add)
seg7_8  equ     b'01111111'     ;         Pattern 8                          @@(Add)
seg7_9  equ     b'01101111'     ;         Pattern 9                          @@(Add)
seg7_a  equ     b'01000000'     ;         Hyphen                             @@(Add)
seg7_b  equ     b'00000000'     ;         OFF                                @@(Add)

汎用メモリ
汎用メモリに今回使用するメモリ定義を追加します。
led_ha は led_0 のアドレスを格納するエリアです。間接アドレス処理(FSR/INDF)を使用してメモリの読み書きを行う場合、テーブルの先頭番地を使います。テーブルの先頭番地を記録しておいたほうが処理が簡単になります。
led_0 から led_b はLEDの7セグメントデータを記録するエリアです。これも間接アドレス処理を使うために設けてあります。
led_10y から led_wd までは時計情報を格納するエリアです。既存のソフトウェアでは tm_XXX というラベルで時刻情報が格納されています。元々の処理では時間は24時間で管理されています。今回の処理では12時間表示をし、午前0時は 0:00 、正午の12時は 12:00 と表示させるため、時間情報を変えています。そのため、 tm の情報を led_10y から led_wd までにコピーしています。ここまでがバンク1に割り付けられる限界です。バンク1固有に割り付けられるのは80バイト、すなわち、 0EFhまでです。 led_wd のアドレスは 0EEh 。あと1バイト余裕がありますが、残りはバンク2に割り付けています。
今回の時計では最初の電源ONで時刻情報が不確定のときにLEDにハイフン(gセグメント)を1秒毎に点滅させています。led_hyphen は点灯中か、消灯中かの状態を管理するエリアです。
led_cnt100 は 100μ秒を作るためのカウンタエリアです。
led_wkdata は CPLD にデータを書き込むサブルーチンで入力情報を待避しておくためのエリアです。
led_ff は1月1日0:00にチャイムを鳴らしたあとの曲スキップ回数をカウントするエリアです。
led_fsr は CPLD 書き込み処理で FSR を待避するエリアです。

0169



0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
;*** Register area definition (bank 0)

途中省略

;@@@ Register area for 7 seg LED
        led_ha                  ;Table head address                          @@(Add)
        led_0                   ;7seg pattern 0                              @@(Add)
        led_1                   ;7seg pattern 1                              @@(Add)
        led_2                   ;7seg pattern 2                              @@(Add)
        led_3                   ;7seg pattern 3                              @@(Add)
        led_4                   ;7seg pattern 4                              @@(Add)
        led_5                   ;7seg pattern 5                              @@(Add)
        led_6                   ;7seg pattern 6                              @@(Add)
        led_7                   ;7seg pattern 7                              @@(Add)
        led_8                   ;7seg pattern 8                              @@(Add)

        led_9                   ;7seg pattern 9                              @@(Add)
        led_a                   ;7seg hyphen                                 @@(Add)
        led_b                   ;7seg OFF                                    @@(Add)
        led_10y                 ;10th of year                                @@(Add)
        led_1y                  ;1st of year                                 @@(Add)
        led_10mth               ;10th of month                               @@(Add)
        led_1mth                ;1st of month                                @@(Add)
        led_10d                 ;10th of day                                 @@(Add)
        led_1d                  ;1st of day                                  @@(Add)
        led_10h                 ;10th of hour                                @@(Add)

        led_1h                  ;1st of hour                                 @@(Add)
        led_10m                 ;10th of minute                              @@(Add)
        led_1m                  ;1st of minute                               @@(Add)
        led_10s                 ;10th of second                              @@(Add)
        led_1s                  ;1st of second                               @@(Add)
        led_wd                  ;Week of the day                             @@(Add)
        endc

;*** Register area definition (bank 2) 80 bytes can be used
        cblock  ram_base2
        led_hyphen              ;0:Hyphen OFF, 1:Hyphen ON                   @@(Add)
        led_cnt100u             ;100us counter                               @@(Add)
        led_wkdata              ;LED work data                               @@(Add)
        led_ff                  ;Fast forward data                           @@(Add)
        led_fsr                 ;FSR save area                               @@(Add)
        endc

seg7_ha equ     led_0           ;LED pattern table head address              @@(Add)

汎用メモリのバンク切り替え
汎用メモリはバンク0からバンク2まで使用しています。全バンク共通の 070h から 07Fh までの16バイトの読み書きであればバンク切り替えを意識する必要はありませんが、その他のメモリの読み書きを行う場合には現在のバンク状態を意識し、必要に応じてバンクを切り替えなければいけません。バンク切り替えはマクロとして作ってあるので、1行書くだけでバンクを切り替えることができます。
        rbank0     ;バンク0に切り替えるマクロ
        rbank1     ;バンク1に切り替えるマクロ
        rbank2     ;バンク2に切り替えるマクロ
picmac1.inc
54
55
56
57
58
59
60
61
62
63
64
65
66
67
rbank0  macro                   ;register bank 0 select     
        bcf     STATUS,5
        bcf     STATUS,6
        endm
;
rbank1  macro                   ;register bank 1 select
        bsf     STATUS,5
        bcf     STATUS,6
        endm
;
rbank2  macro                   ;register bank 2 select
        bcf     STATUS,5
        bsf     STATUS,6
        endm
バンク切り替え用マクロは左のリストのようになっています。
STATUSレジスタのビット5とビット6がバンク指定です。
マクロにはバンク3用も作られていますが、今回の処理では使用していないのでここには掲載していません。


追加プログラムの割付
追加プログラムはプログラムメモリのページ2から割り付けています。 org で 1000h から割り付ける指定をしています。

4307
4308
4309
4310
4311
4312
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
;                   7 seg LED Display subroutine
;                                             Author : Seiichi Inoue
;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
        org     0x1000
led_disp

電源状態の確認

4313
4314
4315

4655
4656
4657
4658
4659
4660
        rbank0
        btfss   portc,0         ;AC Power ON ?
        goto    led_off         ;No. Jump to LED contro; OFF   
-----------------------------------------------------------
;*** Display control OFF
led_off
        clrf    portd           ;Clear PORTD
        clrf    porte           ;Clear PORTE
        bcf     portc,5         ;Clear CK bit
        return
AC電源が停止してもCPUと受信機はバッテリーでバックアップして連続動作をします。もっとも、電波時計なので、バックアップしなくても復電してから数分後には再び時刻が表示されます。短時間の停電にはバッテリーバックアップしてあれば、復電後すぐに時刻が表示されます。AC電源の確認は電源ユニットの+12Vの電圧の有無を確認しています。+12Vは抵抗器で分電圧され、+5VがPORTCのビット0に入力されています。このビットが"1"であればAC電源は正常であり、LED表示処理が実行されます。ビットが"0"の場合にはAC電源が停止している状態なので、LED表示処理はせず、CPLDへの出力を停止する処理だけをしてサブルーチンを終了します。この理由については「バッテリー駆動のとき、曜日のLEDが薄く点灯する」をご覧ください。


時刻情報未取得時のハイフン表示

4316
4317
4318
4319
4320
4321
4322
4323
4324
4325

 
        rbank1
        btfsc   det_mark_1st    ;1st marker detected ?
        goto    led_dsp03       ;Yes. Jump to time decode check
led_dsp01
        rbank2
        btfsc   led_hyphen,0    ;LED hyphen ON ?
        goto    led_dsp02       ;Yes.
        rbank1
        movlw   d'10'           ;Read LED hyphen data
        movwf   led_10y         ;Set 10th of year

以下省略
電源投入時には時刻情報は取得できていないので、表示できません。 tm の情報をそのまま表示するとマーカ検出までの時間。マーカ検出後には時刻情報のデコード時間が表示されます。これらの表示はあまり意味がないので、ハイフン(7セグメントのGセグメント)を点滅させています。
マーカ検出が完了すると det_mark_1st(dec_sts1のビット1) が"1"になります。また、時刻のデコードが完了すると dec_time_1st(dec_sts1のビット4) が"1"になります。この2つのビットのいずれかが"0"の場合はハイフンを点滅させます。両方とも"1"になった場合には tm に時刻情報が入ったことになるので、LED表示処理を実行します。LEDにハイフンを表示するためにはハイフン用のパターンコード(10番)を使います。


時刻情報のコピー

4366
4367
4368
4369
4370
4371
4372
4373
4374

 
led_time_read:
        movfw   tm_10y          ;Read 10th of year
        movwf   led_10y         ;Save 10th of year
        movfw   tm_1y           ;Read 1st of year
        movwf   led_1y          ;Save 1st of year
        movfw   tm_10mth        ;Read 10th of month
        btfsc   status,z        ;10th of month = 0 ?
        movlw   d'11'           ;Yes. Set LED OFF data         
        movwf   led_10mth       ;Save 10th of month

以下省略
tm に入っている時刻情報をLED表示処理用のメモリにコピーします。このとき、時間情報の変換を行います。 tm の情報は24時間になっているので、13:00 は 1:00、23;00 は 11;00 というように変換します。10位と1位が別々なので単純ではありません。また、月の10位、日の10位、時間の10位が"0"の場合にはLEDを消灯させています。このほうが見やすいからです。LEDを消灯するためには消灯用のパターンコード(11番)を使います。


時報制御

4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469

 
;*** Time signal control
        movlw   d'6'            ;Set 6 o'clock
        subwf   led_1h,w        ;Check hour
        btfss   status,z        ;6 o'clock ?
        goto    led_sig01       ;No.
        goto    led_sig07       ;Jump to True time check       
led_sig01
        movlw   d'7'            ;Set 7 o'clock
        subwf   led_1h,w        ;Check hour
        btfss   status,z        ;7 o'clock ?
        goto    led_sig02       ;No.
        goto    led_sig07       ;Jump to True time check

以下省略
6:00、7:00、8:00、9:00にメロディーによる時報を鳴らします。午前、午後の区別はしていないので、一日に8回の時報が鳴ります。今回使用しているメロディーICには8曲が入っているので、一日で一巡し、毎日決まった時間に決まったメロディーが流れることになります。それと、1月1日の0:00にはチャイムを鳴らし、新年を知らせます。だた、チャイムを鳴らした場合でも曲選択のカウンターが更新されます。ですから、1年ごとに曲目が1時間ずれてしまいます。そのため、1月1日の0:01から1秒ごとに7回メロディーICを起動して曲選択カウンターの更新をし、時刻とメロディーを同期させています。このときメロディーが鳴るとうるさいので、メロディーICを消音モードにして更新しています。


時刻情報出力制御
年、月、時、分、秒、曜日の情報をCPLDのラッチレジスタに書き込みます。ラッチレジスタの位置はPORTEの3ビットとPORTDのビット7の合計4ビットで指定します。PORTDの下位7ビットは時刻情報の出力に使っています。出力処理は led_writeサブルーチンで行います。このサブルーチンのなかで、数字情報を7セグメントの制御情報に変換してCPLDに書き込みます。書き込みの制御はPORTCのビット5で行います。PORTDとPORTEに全ての情報を設定したあと、PORTCのビット5を"1"にします。この状態では、まだCPLDには書き込まれません。100μ秒後にPORTCのビット5を"0"にします。これによりPORTDに設定されている7セグメント情報がCPLDのラッチレジスタに書き込まれます。次の情報を書くまで100μ秒を置いています。これはCPLDの動作時間を確保するためです。
年10位、年1位、月10位、月1位、日10位、日1位、時10位、時1位、分10位、分1位、曜日、秒10位、秒1位の順番で13種類の情報をCPLDに書き込みます。1つの情報を書くのに約200μ秒かかるので、全てを書くのに要する時間は約3_秒弱になります。処理全体から見れば、大きな値ではありません。

4558
4559
4560
4561
4562
4563
4564
4565
4566



4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
;*** Display control
led_cont
        rbank0
        movlw   b'00000011'     ;Set 10th of year selector
        movwf   porte           ;Set selector data
        rbank1
        movlw   b'10000000'     ;Set 10th of year selector
        iorwf   led_10y,w       ;Set data
        call    led_write       ;Write data

途中省略

;@@@@@@@@@@@@@@@@@@@@ Data write Subroutine @@@@@@@@@@@@@@@@@@@@@@@@@
led_write
        rbank2
        movwf   led_wkdata      ;Save input data
        movfw   fsr             ;Read FSR
        movwf   led_fsr         ;Save FSR
        movlw   b'00001111'     ;Set mask
        andwf   led_wkdata,w    ;Pickup LED data
        rbank1
        addwf   led_ha,w        ;LED pattern table HA + LED data
        movwf   fsr             ;Set table address
        movfw   indf            ;Read 7seg data
        rbank0
        movwf   portd           ;Set 7seg data
        rbank2
        movfw   led_fsr         ;Read saved FSR
        movwf   fsr             ;Recover FSR
        movlw   b'10000000'     ;Set mask
        andwf   led_wkdata,w    ;Pick up selector data
        rbank0
        iorwf   portd,f         ;Set selector data
        bsf     portc,5         ;Start clock pulse
        rbank2
        call    led_t100u       ;100usec wait
        rbank0
        bcf     portc,5         ;Stop clock pulse (Data latch)
        rbank2
        call    led_t100u       ;100usec wait
        rbank0
        return

;@@@@@@@@@@@@@@@@@@@ 100usec Timer Subroutine @@@@@@@@@@@@@@@@@@@@@@@
led_t100u
        movlw   d'63'           ;Set loop cnt
        movwf   led_cnt100u     ;Save loop cnt
led_t100ulp
        nop                     ;Time adjust
        nop                     ;Time adjust
        decfsz  led_cnt100u,f   ;cnt100u - 1 = 0 ?
        goto    led_t100ulp     ;No, continue
        return