曜日表示プログラム
コンフィグレーションワード
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行づつ表示し、表示が終了した時点で入力データの読み込みを行い、表示の内容を一挙に更新をするという動作です。 |