時計本体プログラム
マクロの変更
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 |
|