目次PIC回路集サインボード


サインボード ソフトデバッグ説明


ソフトウェアのデバッグ方法はいろいろあると思いますが、今回私が行った方法を以下に記載します。
今回のソフトデバッグではステップ動作による方法とブレークポイントによる方法で行いました。


準備
デバッグはMPLABを使って行います。画面には以下のウインドウを表示しておきます。

    アッセンブルリスト

Window → Absolute Listing で表示することができます。



    SFR ( Special Function Register )

Window → Special Function Registers または  で表示することができます。



    File Registers

Window → File Registers または  で表示することができます。



    EEPROM Window

Window → EEPROM Memory で表示することができます。

    EEPROMウインドウの内容にはアッセンブルした結果のデータ内容が表示されています。ソースコードで org h'2100' により指定した内容です。

    画面が広い場合は全てのウインドウを表示しておいても良いのですが、そうでない場合には必要な画面のみを表示します。各ウインドウの表示内容は閉じていても更新されています。特に内容が変化した部分は赤字で表示されますが、その内容はウインドウを閉じていても更新されているので、必要なときにウインドウを開けば更新内容を確認することができます。
    でも、最低限アッセンブルリストは常時表示しておいた方が良いです。


初期化処理のデバッグ

    リセット
      まず、 ボタンをクリックしてPICを電源投入直後の状態にします。
      アッセンブルリストのPC=0000の行に黒いバーが付きます。

    ステップ動作による確認
       ボタンをクリックしながら動作を確認します。

      PCチェックポイント
      0000:PC=0005にジャンプします。
      0005: SFRの Status Register が 1Ch から 3Ch に変化します。
      RP0が'1'になり、バンクが'1'に切り替わりました。
      0006: TRISA Register を0クリアします。
      これでAポートが全て出力ポートとして設定されました。
      0007: TRISB Register を0クリアします。
      これでBポートが全て出力ポートとして設定されました。
      0008:タイマー割り込みのためのデータを W Register に設定します。
      0009:OPTION_REG がFFhから07hに変化します。
      000A: バンクを'0'に切り替えます。
      Status Register が 3Ch から 1Ch に変化します。
      000B
      000C
      :割り込みタイマー値(00h)をTMR0に設定します。
      000D
      000E
      :タイマー割込回数の規定値を設定します。
      000F
      0010
      0011
      : EEPROM関係データの初期化を行います。
      各レジスタの設定内容を確認します。
      e_adr(21h) = 00h ( 元々00hなので変化はありません )
      e_check(22h) = 20h
      0012
      0013
      : タイマー割り込みを可能にします。
      INTCON Register の GIE および T0IEビットを'1'にします。

      以上で初期化処理のデバッグが終了しました。


LEDスクリーン処理のデバッグ

    初期化処理の終了後、プログラムカウンタは0014hになります。ここからLEDへの表示制御処理になります。

    ステップ動作による確認
       ボタンをクリックしながら動作を確認します。

      PCチェックポイント
      0014:割り込みを可能にします。INTCON RegisterのGIEビットが'1'になります。
      0015
      0016
      0017
      0018
      : ループカウント値および、データ読み込み用のインデックス値の初期化を行います。
      lpcnt(0Ch) = 10h
      scrnidx(0Dh) = 0Fh
      0019:割り込みを禁止します。INTCON RegisterのGIEビットが'0'になります。
      001A
      001B
      : LEDを消灯状態にします。
      PORTBに'FFh'が設定されることを確認します。
      001C
      001D
      : LEDの列情報をPORTAに出力します。
      列情報としてはテーブルインデックス値を使っているので、最初は0Fhがportaに書かれます。
      001E:データテーブルの先頭番地(10h)を W Register に設定します。
      001F: データテーブルの先頭番地とインデックス値の加算を行います。
      この結果が読み出すデータメモリのアドレスになります。
      0020:W Register の内容(データメモリアドレス)をFSR Register に設定します。
      0021: FSR Register にアドレスを設定すると INDF Register に該当するデータメモリの内容が書き込まれます。
      その内容を W Register に移します。
      0022: データメモリの内容をPORTBに出力します。
      PORTB Register の内容は元々00h なので変化は分かりません。
      この処理が正常に行われていることを確認する方法としてModify機能を使うことができます。

      Modify機能
      この機能はRegisterの内容を変更する機能です。以下の操作で使えます。
      (1) SFR Window のportb項目部分をダブルクリックすると、Modify Windowが表示されます。

        このWindowは Window → Modify でも表示することができます。
        その場合にはAddress の項目でportbを選択します。

      (2) Data/Opcodeをクリックしてカーソル移動し、設定する値を入力します。
      (3) Writeボタンをクリックします。この操作で設定した値がPORTBに入ります。
      (4) Closeボタンをクリックして、Modify window を閉じます。
      以上の操作後、001Eの命令を実行するとPORTBの内容が00hに変化することが確認できます。
      0023: テーブルインデックスを減算します。
      アドレス0Dhの内容が 0Fh から 0Eh に変化します。
      0024
      0025
      : データテーブルが一巡したかどうかを判定します。
      -1した結果が 00h になると一巡したことになります。
      一巡していない場合、プログラムの実行は0025hに移り、001Ahにジャンプします。
      以降、データテーブルを一巡するまで、インデックスを減算しながら処理が行われます。
      0026: 処理が一巡するとこのアドレスに処理が移ります。
      ここにブレークポイントを設定して確認しても良いですし、ステップ動作で処理を確認しても良いです。データテーブルのサイズは16なので、ステップで確認してもそれほど大変ではありません。

    以上でLEDスクリーン処理の動作が確認できました。この処理はタイマー割り込み処理が行われていないとき、常に実行されています。
    通常は上記の確認の最中にタイマー割り込みが発生することはないと思いますが、処理が長いと途中で割り込みが発生するかもしれません。
    その場合、プログラムの実行番地が0004hになります。


タイマー割り込み処理のデバッグ
    割り込みが発生するまでステップ動作をさせても良いのですが、面倒なので、割り込み処理の先頭にブレークポイントを設定して確認します。

    ブレークポイントの設定
      ブレークポイントは以下のような手順で設定します。
      (1)処理を停止させたいステップをクリックしてカーソルを移動します。今回の場合は0027hです。
      (2)
      マウスの右ボタンをクリックします。

      表示されたメニューの中のBreak Point(s)を選択してマウスの左ボタンをクリックします。

      ブレークポイントが設定された行が赤い色に変わります。

      以上の操作でブレークポイントが設定されました。
      ブレークポイントまで処理進めるのには ボタンをクリックします。 Debug → Run → Run でもできます。

    中断プログラムの戻り番地確認
      割り込みが発生した時点で、念のため、中断プログラムの戻り番地がスタックに書かれているかを確認します。この確認は今後は一々行う必要はありません。
      表示される戻り番地は割り込みが発生するタイミングで変わります。ですから、同じ番地になるとは限りません。
      通常は毎回違う番地になります。

      STACKウインドウは Window → Stack で表示させることができます。

    ステップ動作による確認
       ボタンをクリックしながら動作を確認します。
      PCチェックポイント
      0027: W Register の待避を行います。
      待避先はRAMレジスタファイルの0Ehです。
      W Register の内容が0Ehに書かれることを確認します。
      0028
      0029
      : STATUS Register の内容を待避します。
      待避先(0Fh)にSTATUS Register の内容が書かれることを確認します。
      002A
      002B
      002C
      : タイマー割り込みであるかどうかを確認します。
      タイマー割り込みであれば002Bhに、その他の割り込みの場合には002Chに処理が移ります。
      今回の場合、タイマー割り込み以外の割り込みは使用してません。
      通常は002Bhでタイマー処理にジャンプします。
      0032: タイマー割り込みのフラッグ(表示)をクリアします。
      INTCON Register のT0IFビットが0になることを確認します。
      0033
      0034
      : タイマー値を設定します。
      TMR0が 00h になることを確認します。
      0035: タイマー割り込みの回数が規定回数かどうかをチェックします。
      規定回数以下の場合には回数を減算して割り込み終了処理に移ります。

      割り込み終了処理のデバッグ
      1回目の割り込みでは規定回数以下ですから、割り込み終了処理を引き続き確認します。
      002D: STATUS Register の内容を待避エリアから元に戻します。
      W Register に メモリアドレス0Fhの内容が書かれることを確認します。
      002E: W Register の内容がSTATUS Register に書かれることを確認します。
      STATUS Register の内容をModify機能で変えておくと確認し易いです。
      002F: W Register を元に戻すためにswapf命令を使用しています。
      待避エリアの内容の上下4ビットが反転することを確認します。
      例. 0D → D0
      0030: W Register に元の値が書かれることを確認します。
      前に実行したswapf命令で反転した内容をさらに反転させるので、元に戻ります。
      0031: RETFIE命令で割り込み処理から中断した処理に戻ります。
      INTCON Register のGIEビットに'1'が設定されることを確認します。
      また、プログラムカウンター(PC)が中断したプログラムに移動することを確認します。






LEDスクリーンデータ変更処理のデバッグ
    LEDスクリーンデータの変更はタイマー割り込みで実行されます。まず、LEDスクリーンデータ変更処理の先頭にブレークポイントを設定します。
    他にブレークポイントを設定してある場合には、それらを解除しておきます。そうしないと、あちこちで処理が止まり、チェックしづらいです。
    今回の場合にはブレークポイントは0037hです。以下、プログラムカウンターが0037hになった条件です。

    ステップ動作による確認
       ボタンをクリックしながら動作を確認します。
      PCチェックポイント
      0037
      0038
      : タイマー割り込みの規定数を再設定します。
      TM_CNT(20h) が 00h から 0ch に変わることを確認します。
      0039
      003A
      : LEDの点灯情報を移動するためのループ処理カウンターの設定を行います。
      S_LOOP(23h) に 0Fh が設定されることを確認します。
      003B
      003C
      : LEDスクリーンテーブルの先頭を読み出しインデックスとして設定します。
      S_INDEX(24h) に 10h が設定されることを確認します。
      003D: インデックス値を加算します。
      この処理は、最初に移動元のデータを読み出すためです。
      W Register に 11h が設定されることを確認します。
      003E
      003F
      : 読み出すインデックス(データアドレス)をFSR Register に書き込みます。
      FSR が11hになったことを確認します。
      0040
      0041
      : 読み出したデータをワークエリアに格納します。
      これは、この後で書き込み先のメモリをアクセスしたときにINDF Register の内容が変わってしまうためです。
      S_WORK(25h) にINDF Register の内容が書かれることを確認します。
      ただ、元々 00h なので変化の確認は出来ないと思います。W Register にModify機能は使えません。
      0042
      0043
      : データ書込先のアドレスをFSRに設定します。
      003Dhで加算する前の値です。
      FSR が一つ少ない値に変わることを確認します。
      0044: S_WORKの内容を読み出し、INDFに設定します。
      INDFは他のResuterのようにINDF自体の内容を確認することはできません。INDFの内容はFSRで示しているアドレスの内容です。
      最初の段階ではメモリの内容が00hなので実際のメモリの変化は後で全体の確認で行います。
      0045: インデックスを加算します。
      S_INDEX(24h)が加算されることを確認します。
      0046: 15個分のデータ移動が終了したかどうかをチェックします。
      終了していない場合には、003Dhにジャンプして、データ移動を繰り返します。
      終了した場合には16個目としてEEPROMから新たなデータの読み込みを行う処理に移ります。(0048h)


    ブレークポイントの設定
      既に設定されているブレークポイントを全て解除して、0048hにブレークポイントを設定します。
      ブレークポイントまで処理進めるのには ボタンをクリックします。 Debug → Run → Run でもできます。

    ステップ動作による確認
       ボタンをクリックしながら動作を確認します。
      PCチェックポイント
      0048
      0049
      : データを書き込む先のアドレスをFSR Register に設定します。
      後で行うEEPROMからの読み出しにもW Register を使用するので、この処理で予め書き込み先アドレスをFSRに設定します。
      そうしないと、EEPROMからのデータを他のエリアに待避させなくてはいけなくなります。
      FSRにLEDスクリーンテーブルの最終アドレス(1Fh)が設定されることを確認します。
      004A
      004B
      : EEPROMの読み出しアドレスをEEADR register に設定します。
      初期化した状態ではEEPROMの先頭アドレス 00h が設定されます。
      EEADRの変化を確認するためにはModify機能を使えばできます。
      004C: EEPROMの読み出しを指示するためのEECON1 Register はBank1にあります。
      ですから、まず、バンクの切り替えを行います。
      STATUS Register のRP0ビットが'1'になることを確認します。
      004D:EECON1 Rgister のRDビットを'1'にして読み込み指示をします。
      004E: バンクを0に戻します。
      STATUS Register のRP0ビットが'0'になることを確認します。
      EECON1 のRDビットはEEPROMの読み込みが完了するとハードウェアで自動的に'0'になります。
      このステップを実行した時点で'0'になります。このステップの実行の結果ではありません。
      004F
      0050
      : 読み出したEEPROMの内容はEEDATA Register に格納されています。
      これをW Register にコピーし、INDF Register に書き込みます。
      LEDスクリーンテーブルの最終(1Fh)の内容がEEPROMから読み出した内容に書き変わることを確認します。
      0051: EEPROMの読み出しアドレスを更新します。これは次の周期での処理のためです。
      E_ADR(21h)が1つ加算されることを確認します。
      0052
      0053
      : EEPROMに書かれたデータが最終かどうかをチェックします。
      最終でない場合には0053hが実行され、割り込み処理の終了処理に移ります。


    以上でLEDスクリーンテーブルの基本動作の確認がされました。
    EEPROMデータの終了確認を行う前に、LEDスクリーンテーブルが割り込み周期毎に変化するかどうかを確認します。

    ブレークポイントの設定
      既に設定されているブレークポイントを全て解除して、0052hにブレークポイントを設定します。

      ファイルレジスタの 10h から 1Fh の変化を確認します。

      ボタンをクリックする度に内容が 1Fh側から 10h側へと変化することを確認します。

        10 11 12 13 14 15 16 17  18 19 1A 1B 1C 1D 1E 1F
        00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
        00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 FF
        00 00 00 00 00 00 00 00  00 00 00 00 00 00 FF FF
        00 00 00 00 00 00 00 00  00 00 00 00 00 FF FF E7
        00 00 00 00 00 00 00 00  00 00 00 00 FF FF E7 C3
        00 00 00 00 00 00 00 00  00 00 00 FF FF E7 C3 81
        00 00 00 00 00 00 00 00  00 00 FF FF E7 C3 81 81
        00 00 00 00 00 00 00 00  00 FF FF E7 C3 81 81 C3
        00 00 00 00 00 00 00 00  FF FF E7 C3 81 81 C3 E7
        00 00 00 00 00 00 00 FF  FF E7 C3 81 81 C3 E7 FF
        00 00 00 00 00 00 FF FF  E7 C3 81 81 C3 E7 FF FF
        00 00 00 00 00 FF FF E7  C3 81 81 C3 E7 FF FF 7E
        00 00 00 00 FF FF E7 C3  81 81 C3 E7 FF FF 7E 00
        00 00 00 FF FF E7 C3 81  81 C3 E7 FF FF 7E 00 7E
        00 00 FF FF E7 C3 81 81  C3 E7 FF FF 7E 00 7E FF
        00 FF FF E7 C3 81 81 C3  E7 FF FF 7E 00 7E FF F7
        FF FF E7 C3 81 81 C3 E7  FF FF 7E 00 7E FF F7 07
        FF E7 C3 81 81 C3 E7 FF  FF 7E 00 7E FF F7 07 F7





最後にEEPROMのデータが末尾になったときの動作を確認します。

    ブレークポイントの設定
      既に設定されているブレークポイントを全て解除して、0054hにブレークポイントを設定します。
      ブレークポイントまで処理進めるのには ボタンをクリックします。 Debug → Run → Run でもできます。
      EEPROMに書き込まれているデータが多い場合にはブレークポイントに達するまで多少時間がかかります。

    ステップ動作による確認
       ボタンをクリックしながら動作を確認します。
      PCチェックポイント
      0054: EEPROMからの読み出しアドレスを初期化します。
      E_ADR(21h)が0クリアされることを確認します。
      0055
      0056
      : EEPROMの末尾を確認するためのチェックカウンタを初期化します。
      E_CHECK(22h)にデータサイズが設定されることを確認します。
      0057:割り込み終了処理にジャンプします。


以上でデバッグが終了しました。