目次PIC回路集大型表示電波時計処理説明


大型表示電波時計 処理説明(曜日表示)

曜日表示プログラム

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

012
013
014
015
016
017
018
        __config        h'3F10' ;OSC is Int 4MHz
                                ;RA5,RA6,RA7,RB4 are I/O
                                ;Power-up timer ON
                                ;Code protection OFF
                                ;Data code protection OFF   
                                ;Brown-out detection OFF
                                ;Watchdog timer OFF
表示スキャンと同様、4Hzの内蔵発振器を使用しています。

汎用メモリ

021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
;****************  Label Definition  ********************   
        cblock  h'20'
disp1                           ;1st line data
disp2                           ;2nd line data
disp3                           ;3rd line data
disp4                           ;4th line data
disp5                           ;5th line data
disp6                           ;6th line data
disp7                           ;7th line data
disp8                           ;8th line data
line_indexr                     ;Index for display
line_indexw                     ;Index for set
input_data                      ;Input data save area
line_data                       ;Data save area
        endc
汎用メモリにはドットマトリクスLEDに表示するデータのワークエリア(disp1-disp8)を置いています。プログラムではこのエリアのデータをスキャンし、LEDの点灯制御を行います。
line_indexr はLEDマトリクスの表示制御行を指定するカウンタです。このカウンタの値を順次変えることによりLEDで文字を表示します。
line_indexw は文字パターンを書き換える際の行を指定するカウンタです。LEDへの表示とワークエリアの書き換えは同時には行われないため、line_indexrと同じでも問題は無かったと思いますが、分かりやすさのために分けています。
input_data は文字パターン書き換え処理で使用する入力情報待避用のエリアです。
line_data は文字パターン書き換え処理で読み出したデータを一次的に待避するエリアです。

表示文字パターン

045
046
047
048
049
050
051
052
053
054
;******************** Dispaly data **********************   
monday
        retlw   b'10000011'     ;1st line data
        retlw   b'10111011'     ;2nd line data
        retlw   b'10000011'     ;3rd line data
        retlw   b'10111011'     ;4th line data
        retlw   b'10000011'     ;5th line data
        retlw   b'10111011'     ;6th line data
        retlw   b'10111011'     ;7th line data
        retlw   b'10111101'     ;8th line data
今回の処理では表示する文字パターンをプログラムメモリに格納しています。汎用メモリでも文字パターンを格納できる容量はありますが、ここでは retlw によるデータ読み込みの方法を使いました。
月曜日から日曜日までの7種類と消灯用のパターンを作っています。
この処理方式については「表示データの読み込み処理」で述べます。
回路の構成によりますが、今回の場合はLEDの左側がビット0、右側がビット7になります。また、内容が"0"で点灯です。

各種レジスタの初期化処理

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
;******************* Initial Process ********************   
init
;*** Set Port mode
        bsf     status,rp0      ;Change to Bank1
        movlw   b'00111000'     ;RA2-0:OUT RA3-5:IN mode
        movwf   trisa           ;Set TRISA reg
        movlw   b'00000000'     ;RB7-0:OUT mode
        movwf   trisb           ;Set TRISB reg

;*** Set Option reg
        movlw   b'00000100'     ;PS=1:32
        movwf   option_reg      ;Set OPTION_REG

;*** Set PIE1 reg
        movlw   b'00000000'     ;TMR1IE=OFF
        movwf   pie1            ;Set PIE1 reg
        bcf     status,rp0      ;Change to Bank0

;*** Set CMCON reg
        movlw   b'00000111'     ;RA port to digital
        movwf   cmcon           ;Set CMCON reg

;*** Set TMR0 reg
        movlw   d'225'          ;256-1000us/32us=225
        movwf   tmr0            ;Set TMR0
PORTAのビット3からビット5の3ビットにはCPLDからの曜日情報がバイナリーで入力されます。そのほかのポートは全て出力モードに設定しています。
TMR0のプリスケーラは1:32に設定しているので、カウント周期は32μ秒にしています。TMR0による割り込みは表示スキャンと同様に1_秒なので、表示スキャンと同様でも良いのですが、設計当初の割り込み周期は5_秒にしていました。最終的には1_秒の割り込みにしたのですが、当初のプリスケーラ値をそのまま使っています。
プリスケーラの値が小さいほうが割り込み周期の精度は高くなりますが、今回の回路では精度はあまり問題にはならないのでそのままにしています。

ワークエリアの初期化処理

152
153
154
155
156
157
158
159
160
161
162
163
164
165
;*** Other registers and work area initialization
        clrf    porta           ;Clear PORTA
        clrf    portb           ;Clear PORTB
        clrf    line_indexr     ;Clear index for dip        
        clrf    line_indexw     ;Clear index for set
        movlw   b'11111111'     ;Set light out data
        movwf   disp1           ;Set 1st line
        movwf   disp2           ;Set 2nd line
        movwf   disp3           ;Set 3rd line
        movwf   disp4           ;Set 4th line
        movwf   disp5           ;Set 5th line
        movwf   disp6           ;Set 6th line
        movwf   disp7           ;Set 7th line
        movwf   disp8           ;Set 8th line
ポートレジスタおよびインデックスカウンタを初期化したあと、ドットマトリクスLEDに表示するデータのワークエリアに消灯"1"データを設定しています。電源投入直後だけの動作なので、この設定を行わなくても実質的には問題はありません。その場合、電源投入時にLEDがチラッと点灯するだけで、その後は文字情報が表示されます。

割り込み設定および割り込み待ち処理

167
168
169
170
171
;*** Set interrupt condition
        movlw   b'10100000'     ;GIE,TOIE=1
        movwf   intcon          ;Interruption enable        

        goto    $               ;Wait interruption
全ての初期化を終え、割り込みを可能にします。
その後は割り込み処理で表示制御が実行されます。

割り込み処理

割り込み初期化
173
174
175
176
177
int
;***** TMR0 Interruption ( 1 millisecond interval) ******   
        bcf     intcon,t0if     ;Clear timer int flag
        movlw   d'225'          ;Set 1 millisecond
        movwf   tmr0            ;Set TMR0
割り込み処理の最初では割り込みフラッグのクリアおよびタイマー値の初期化を行います。


LED表示処理
179
180
181
182
183
184
185
186
187
188
189
190
191
192
        movfw   line_indexr     ;Read index
        movwf   porta           ;Set display index
        
        movlw   disp            ;Read disp table head adr   
        addwf   line_indexr,w   ;RA table head + index
        movwf   fsr             ;Set table address
        movfw   indf            ;Read display data
        movwf   portb           ;Set data to PORTB
        incf    line_indexr,f   ;Index + 1
        movfw   line_indexr     ;Read index
        sublw   d'7'            ;Check upper limit
        btfsc   status,c        ;Over ?
        goto    int_end         ;No. Jump to end
        clrf    line_indexr     ;Yes. Clear index
PORTAに表示行の情報を設定します。この情報はデコーダーへの入力になります。PORTAのビット3からビット5の3ビットは入力ポートですが、PORTAの全ビットを書き換えても入力情報が変わることはありません。
次に汎用メモリに設定したドットマトリクスLED表示用ワークエリアの先頭番地にインデックス値を加え、表示するデータを読み出します。その値をPORTBに設定することにより該当する行のLEDが点灯します。一番上の行から1_秒ごとに順番に点灯させます。同時には1行しか点灯していませんが、高速なので同時に点灯しているように見えます。


入力データ読み込み処理
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
        movlw   b'00111000'     ;Set input data mask        
        andwf   porta,w         ;Read input data
        movwf   input_data      ;Save input data
        rrf     input_data,f    ;Rotate Right
        rrf     input_data,f    ;Rotate Right
        rrf     input_data,f    ;Rotate Right
        movlw   b'00000111'     ;Set pick up mask
        andwf   input_data,f    ;Pick up input data

        movfw   input_data      ;Read input data
        btfss   status,z        ;Input data = 0 ?
        goto    p002            ;No. Next

;*** Light out
p001
        movlw   light_out       ;Read data address
        call    data_set        ;Data set
        btfsc   status,c        ;Over ?
        goto    p001            ;Next line
        goto    p_end           ;Jump to end
LEDの1行目から8行目までの表示が終了した時点で入力情報の読み取り処理を行います。入力情報はPORTAのビット3からビット5に入ります。
この入力情報を取り出し、内容をチェックします。
0: 消灯、1:日曜日、2: 月曜日、3: 火曜日、4: 水曜日、5: 木曜日、6: 金曜日、7: 土曜日です。
入力情報の内容によりプログラムメモリ上にあるデータの先頭番地をWレジスタに格納し data_set サブルーチンにジャンプします。


表示データの読み込み処理

310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
data_set
        call    data_read       ;Read data
        movwf   line_data       ;Save data
        movlw   disp            ;Read display table HA      
        addwf   line_indexw,w   ;Table HA + index
        movwf   fsr             ;Set table address
        movfw   line_data       ;Read data
        movwf   indf            ;Write data
        incf    line_indexw,f   ;Index + 1
        movfw   line_indexw     ;Read index
        sublw   d'7'            ;Check upper limit
        return

data_read
        addwf   line_indexw,w   ;DATA HA + Index
        movwf   pcl             ;Read data
deta_set サブルーチンでは最初に data_read サブルーチンを呼び出しています。
data_read サブルーチンではWレジスタに格納されているデータ先頭番地にデータ書き込み用のインデックス値を加え、表示するデータが書かれているプログラムメモリ番地を算出します。その値をPCLレジスタに書き込むと該当する番地に処理が移ります。そこには表示データが書かれた retlw 命令があります。ですから、retlw が実行されると data_read を呼び出した番地の次の番地に戻ります。左のリストでいうと、312行目に移ります。このときWレジスタには retlw に書かれている値が入ります。それはLEDに表示するデータになっています。
ただ、この方法を使うときには注意が必要です。PCLは8ビットのレジスタなので、255までしか管理できません。すなわち、0番地から255番地までしか指定できません。それ以降の番地にジャンプさせる場合にはPCLATHレジスタを操作する必要があります。加算した結果がオーバーフローした場合にはPCLATHに1を加算する必要があります。今回のデータテーブルは255番地以内にあるので、その処理は行っていません。
data_set サブルーチンではこれを表示用のワークエリアに書き込みます。
1回の周期で8行分のデータをワークエリアに書き込みます。

全体の動きとしては1_秒毎にLEDの上の行から下に向かって1行づつ表示し、表示が終了した時点で入力データの読み込みを行い、表示の内容を一挙に更新をするという動作です。