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


大型表示電波時計 トラブルシューティング

装置製作の過程でいくつかのトラブルが発生しました。参考に掲載します。

スキップ処理の最後でメロディーが鳴ってしまう

原因 : 最後のスキップ処理をした直後にサイレント解除をしたため。
対処 : 最後のスキップ処理のあと、1秒後にサイレント解除をするようにした。

チャイムを鳴らしたあと、メロディーの曲位置合わせのため1秒毎に7回スキップ処理をしますが、7回目のスキップ処理でメロディーが鳴ってしまいました。カウンターが0になったらスキップ処理終了と勘違いしました。

jjy_cont.asm
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
led_sig05
        decf    led_1m,w        ;1st of minute - 1
        btfss   status,z        ;1/1 00:01 ?
        goto    led_cont        ;No.
        rbank2
        movfw   led_ff          ;Read fast forward
        btfsc   status,z        ;Fast forward ended ?
        goto    led_sig06       ;Yes.
        rbank0
        bcf     portc,2         ;Set melody
        bsf     portc,4         ;Set silent
        bsf     portc,3         ;Fast forward
        rbank2
        decf    led_ff,f        ;Fast forward counter - 1
        goto    led_cont        ;Jump to LED control
led_sig06
        rbank0
        bcf     portc,4         ;Cancel silent
        goto    led_cony        ;Jump to LED control
<
<
<
<
<
<
<
< カウンタ 0 の場合、サイレント解除へ
<
<
<
<
<
< 単に減算するだけで 0 の判定はしない。
<
<
<
< サイレント解除
<



バンク1およびバンク2の汎用メモリを先頭から使うと正常に動作しない

原因 : 汎用メモリの上位5バイトは各種レジスタのセーブエリアとして使っているため。
対処 : バンク1およびバンク2のメモリ割付を6バイト目からにした。

PIC16F877の場合、バンク1の汎用メモリは0xA0番地から、バンク2は0x110番地から使えます。でも、オリジナルのソフトウェアではバンク1を0xA5番地から使っています。ただ、ラベルを調べても0xA0から0xA4までを使用している形跡がありません。メモリの節約のためバンク1は0xA0番地から、バンク2は0x120番地からメモリを割り付けました。バンク2は0x110番地から使えるのですが、位置をそろえるために0x120番地からにしました。0x110番地から使っていたら今回の現象は分からなかったかもしれません。バンク2の0x120番地には時刻取り込み中にLEDにハイフンを表示するフラッグエリアを割り付けました。このフラッグは1秒毎にハイフンの表示/非表示を制御するためのものです。でも、電源を入れると最初に1回だけハイフンが点灯し、その後は点滅しません。どこかでフラッグが消されているのです。
MPLABのデバッグモードを使い、ステップを順番に追ってみました。フラッグが正常に設定されていることを確認してさらに先へ行くと、割り込み処理の先頭にあるtmp_w (Wレジスタセーブエリア) への書き込みでフラッグが消されています。 tmp_w はバンク0に割り付けられているのですが、バンク切り替え処理を行っていません。そのため、バンク2の状態で割り込みが入るとバンク2のメモリに書いてしまうのです。バンク0の上位5バイトは各種レジスタのセーブエリアとして使っています。全バンク共通にしようと考えたのでしょうか。でも、Wレジスタのリカバリはバンク0に切り替えているので、バグのように思えます。Wレジスタ以外はバンク0に切り替えてからセーブしています。設計思想がよく分からないので、そのままにすることにしてバンク1を0xA5番地から、バンク2を0x125番地から割り当てました。これにより、ハイフンの点滅制御も正常に動作するようになりました。


タイマーを設定するとLED表示が異常になる

原因 : FSRレジスタ競合のため。
対処 : LED表示処理でFSRレジスタを使うとき、前の値をセーブして処理後に戻す。

元々のソフトには4種類のタイマー機能があります。今回もそのまま使っています。ところが、タイマーの時刻を設定するとLEDのディスプレーの時刻表示が異常になります。また、タイマーの時刻設定も正常に行えません。
試しに、今回追加した処理を外してみるとタイマーは正常に設定できます。そこで、どの処理を行ったら異常になるのか、return命令の位置を変えながらチェックしました。すると、led_writeサブルーチンで使っている間接メモリ処理(FSR/INDF)を実行すると異常になることが分かりました。
タイマー設定処理ではFSRレジスタを使ってメモリの読み書きをしていますが、FSRレジスタの内容は他の処理で変えられないことを前提としているようです。今回私が追加した処理は1秒毎に実行されます。タイマー設定の操作は1秒では終わりません。ですから、操作の途中でLED表示処理が行われるとFSRレジスタの内容が変わってしまい、タイマー設定ができなかったのです。LED表示がなぜ異常になったのかは分かりません。FSRレジスタの内容が変わったため、全体の処理が異常になったのだと思います。とにかく、FSRレジスタをセーブすることによりタイマー設定もLED表示も正常になりました。

jjy_cont.asm
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
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
<
<
<
<
< FSRセーブ
<
<
<
<
<
<
<
<
<
<
< FSRリカバー
<
<
<
<
<
<
<
<
<
<
<
<
<



曜日のカウントがずれる

原因 : 曜日の始まりが日曜日からだった。
対処 : 0:ブランク、1:日曜日、2:月曜日、3:火曜日、4:水曜日、5:木曜日、6:金曜日、7:土曜日に変更した。

土曜日なのに表示は日曜日。曜日の始まりは月曜日と思いこんでいたのがミスのもとでした。


バッテリー駆動にするとCPUが止まる

原因 : CPUが電源電圧降下を検出してリセットしたため。
対処 : コンフィグレーションビットの低電圧リセット( BODEN )を無効にした。

PIC16F877は電源電圧の低下を検出してリセットする機能が備わっています。今回の回路では定電圧レギュレータで電源電圧を安定させているため検出はしないと思っていました。しかし、バッテリーに切り替えた時の微妙な電圧変動を検出し、リセットが働いてしまうようです。

jjy_cont.asm
11
12
13
14
15
16
17
18
19
20
21
22
23
24
        processor       16F877
        list            f=INHX32
        include         p16f877.inc
        include         picmac1.inc
        radix           dec
        __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
        errorlevel      -302    ;Eliminate bank warning
        errorlevel      -307    ;Eliminate Setting page bits warning
<
<
<
<
<
<
<
< 第6ビット目のBODENを'0'
<
<
<
<
<
<



バッテリー駆動のとき、曜日のLEDが薄く点灯する

原因 : CPLDを通して電源が回り込んでいた。
対処 : +12Vの電源電圧を監視し、OFFのときにCPLDの駆動を停止するようにした。

LED表示制御回路およびLEDそのものへの電源はAC電源が止まると、停止するはずでした。ですから、曜日のLEDが点くわけはないんです。CPUはバックアップバッテリーにより継続動作しています。バッテリー駆動時に電源装置の+12Vおよび+5Vを調べると+3Vほどの電圧があります。CPUユニットに流れる電流を調べると、AC電源がONの時には約20mA、でもAC電源をOFFにすると120mAくらいに増えます。CPUを外すとほとんど流れない。最初はCPLDを疑いませんでした。でも、考えられるのはCPLDしかありません。そこでCPLDを外すとCPUユニットには想定通りの20mAしか流れません。どうもPICのポートに出ている+5VがCPLDの入力端子を通してCPLDの電源に回り込んでいるようです。ちょっと考えられないことでした。最初はCPLDの電源回路に逆流防止用のダイオードを入れようかとも思ったのですが、配線が終わったあとだし、ダイオードによる電圧降下もいやだったし、その状態で長時間経つとCPLDにも悪影響が出そうだったので止めました。その代わりにAC電源のOFFを検出してCPLDへのポートを全て0Vにすることにしました。でも、この時点でPICのポートは全て使っていて空きがありません。しかたなく、TCOの表示LED用のポート(PORTC,0)を外し、+12V電源の監視用ポートに変更しました。+12Vを直接PICにかけられないので、抵抗器で分圧し+4.8Vにしています。PORTC,0をLED表示処理の先頭で監視し、0VであったらCPLDへのポートを全て 0 にして抜けるようにしました。
LED表示サブルーチンは1秒毎に起動されます。ですから、最大1秒間はCPUユニットに120mAの電流が流れます。元々はそれほど大きな電流が流れることは想定していなかったので、定電圧レギュレータも100mAタイプを使用していました。最大1秒ですが100mAを超えるため、レギュレータも1Aタイプに変更しました。電子回路での1秒は非常に長い時間です。

jjy_cont.asm
4312
4313
4314
4315
4316
4317
4318

4656
4657
4658
4659
4660
led_disp
        rbank0
        btfss   portc,0         ;AC Power ON ?
        goto    led_off         ;No. Jump to LED contro; OFF
        rbank1
        btfsc   det_mark_1st    ;1st marker detected ?
        goto    led_dsp03       ;Yes. Jump to time decode check
---------------------------------------------------------------
led_off
        clrf    portd           ;Clear PORTD
        clrf    porte           ;Clear PORTE
        bcf     portc,5         ;Clear CK bit
        return
<
<
< +12V電圧チェック
<
<
<
<

<
< CPLDへのポートを全て'0'にする
<
<
<



表示制御していないLEDのセグメントが一瞬点灯する

原因 : 不明。
対処 : 何もせず。

7セグメントLEDの点灯制御していないセグメントがときどきチラッと点灯します。点灯間隔は不規則です。1秒間点灯していれば、ラッチレジスタに書かれた内容の異常が考えられますが、一瞬だけなので、ラッチレジスタの書き込み異常ではないはずです。瞬間的なので点灯スキャン制御の関係と思います。配線を束ねているので、他の信号が雑音として乗るのかもしれません。でも、それほど高速でスキャンしているわけでもないし、ハイインピーダンスの回路でもないので、これもちょっと考えづらく原因は不明です。頻度もそれほど多くなく、実用上問題も無いので対処はしていません。