目次PIC回路集LEDフラッシャー


LEDフラッシャー ソフトデバッグ説明

ソフトウェアのデバッグ方法はいろいろあると思いますが、今回私が行った方法を以下に記載します。
今回のソフトデバッグではステップ動作による方法とブレークポイントによる方法で行いました。
準備
デバッグはMPLABを使って行います。画面には以下のウインドウを表示しておきます。
    アッセンブルリスト
      Window → Absolute Listing で表示することができます。

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

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

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


以下の説明ではプログラムの実行場所を表すのに
プログラムメモリのアドレス( PCカウンタの内容 )を使います。

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

    ステップ動作による確認
       ボタンをクリックしながら動作を確認します。
      PCチェックポイント
      0000:PC=0005にジャンプします。
      0005: SFRの Status Register が 1Ch から 3Ch に変化します。
      RP0が'1'になり、バンクが'1'に切り替わりました。
      0006:W Register にFFhを設定しますが、元々FFhになっているので変化はありません。
      0007: TRISA Register にFFhを設定します。ただ、Aポートは5本しかないので5ビットのみ有効です。
      TRISA は元々1Fhになっているのでここも変化はありません。
      0008: TRISB Register を0クリアします。
      これでBポートが全て出力ポートとして設定されました。
      0009: バンクを'0'に切り替えます。
      Status Register が 3Ch から 1Ch に変化します。
      000A:W Register にFFhを設定しますが、元々FFhになっているので変化はありません。
      000B:PORTB Register にFFhを設定します。ここも既にFFhなので変化はありません。

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


スイッチスキャンおよびLED点滅処理のデバッグ
    初期化処理の終了後、プログラムカウンタは000Chになります。PORTA Register はリセットした時点から内容はAll'0'なので、全てのスイッチが'ON'状態である条件でデバッグを進めます。

    ステップ動作による確認
       ボタンをクリックしながら動作を確認します。
      PCチェックポイント
      000C:PORTA は全て'0'なので、BTFSS命令は次の番地(000Dh)の命令を実行します。
      000D: PATTREN 0 のLED点滅処理サブルーチンの先頭(0017h)にジャンプします。
      サブルーチンへのジャンプなので、戻り番地がSTACKに格納されます。
      念のためにSTACKの内容を確認します。
      STACKウインドウは Window → Stack で表示させることができます。

      戻り番地としてサブルーチンを呼んだ番地(000Dh)の次の番地(000Eh)が格納されています。

      ここからはLED点滅処理になります。
      0017:W Register にFEhを設定します。SFRの w の項目がFFhからFEhに変化することを確認します。
      0018:PORTB Register にFEhを設定します。SFRの portb の項目がFFhからFEhに変化することを確認します。
      0019: LEDの点灯時間を確保するためにタイマーサブルーチンにジャンプします。
      Pattren 0 の場合、100ミリ秒タイマーを使いましたので、100ミリ秒タイマーの先頭の番地(00C0h)にジャンプします。
      STACKに戻り番地として001Aが書かれたことを確認します。

    スイッチスキャンおよびLED点滅処理は基本的に以上のような処理を各条件に合わせて実行しています。
    各点滅パターンをブレークポイントによる方法で確認することもできますが、時間がかかるので、各パターンの確認は実際のPICで行った方が良いと思います。


タイマー処理のデバッグ
    タイマー処理は基本タイマー処理として1ミリ秒タイマー処理があります。これは1ミリ秒間処理を繰り返しているものです。
    10MHzの発振器を使用している場合には2500サイクルの命令を実行すると1ミリ秒になります。

    プログラムカウンターの変更
      ブレークポイントを使用して1ミリ秒タイマーの先頭にプログラムカウンターを持っていく方法もありますが、ここではプログラムカウンターを直に変更する方法で行います。
      Debug → Run → Change Program Counter... または  によりプログラムカウンター変更のダイアログが表示されます。

      PCの項目に16進で変更したいプログラムカウンタ値を入力し、Changeボタンをクリックすると、プログラムカウンターが変わります。
      今回の場合は、PCに 00B5 と入力します。プログラムカウンターの表示バーが00B5に移動したことを確認します。

    ステップ動作による確認
       ボタンをクリックしながら動作を確認します。
      PCチェックポイント
      00B5: 1段目のループカウント値(2)を W Register に設定します。
      SFRの w が2になることを確認します。
      00B6: カウンター値をRAMレジスタファイルに格納します。格納場所はRAMレジスタのDh番地です。
      Dhが'2'になることを確認します。
      00B7: 2段目のループカウント値(249)を W Register に設定します。
      SFRの w がF9hになることを確認します。
      00B8: カウンター値をRAMレジスタファイルに格納します。格納場所はRAMレジスタのCh番地です。
      Chが'F9h'になることを確認します。
      00B9
      00BA
      : タイマーの処理時間を作るためのダミーステップです。
      処理は何もしませんが、命令サイクルは使われます。
      00BB: ループカウンターのカウントダウンとカウンターが'0'になったかどうかの判断をします。
      実行するとRAMファイルレジスタの0Chの値がF9hからF8hへと減算されます。
      減算した結果はまだ'0'ではないので、プログラムカウンターは次の番地(00BC)に移ります。
      00BC:ループ処理のために00B9にジャンプします。

      以後、カウンター減算の処理が行われます。
      これ以上ステップ動作で確認しても意味がないので、ブレークポイントによる確認を行います。

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

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

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

      以上の操作でブレークポイントが設定されました。

      次に ボタンをクリックします。 Debug → Run → Run でもできます。

      少し時間が経ってから、プログラムカウンターの表示バーが00BFhになって、止まります。
      MPLABがプログラムを実行(シミュレーション)している間は、画面の下にある、ステータスバーが黄色になっています。

      MPLABでのシミュレーション動作は実際のPICの動作に比べ、非常に遅いです。おおよそPICで1ミリ秒の処理に1秒位かかります。(約1000倍) 使用するパソコンによっても違うと思います。ですから、1秒タイマーを処理するのに約15〜20分位かかります。

      1ミリ秒タイマーの場合、数秒で止まると思います。これが、数十分かかっても止まらない場合は、作成したプログラムに誤りがあるか、ブレークポイントの設定が正しくないか確認する必要があります。

    ストップウォッチ機能による動作時間の確認
      MPLABにはストップウォッチ機能があります。これは実行ステップのサイクル数をカウントしてPICでの処理時間を表示する機能です。ですから、実際に使用するPICの発振器周波数を正しく設定していないと時間が正しく表示されません。
      MPLABでの発振器周波数の設定は Options → Development Mode... で表示されるダイアログのなかの CLOCK で設定できます。

      また、スチップウォッチのウインドウは Window → Stopwatch で表示することができます。

      実際に1ミリ秒タイマーの時間を測定してみます。
      (1) 1ミリ秒タイマーサブルーチンを呼び出している100ミリ秒タイマーから起動します。
      プログラムカウンターを 00C2 に設定します。
      (2)00C3にブレークポイントを設定します。
      (3) ストップウォッチウインドウを表示します。
      表示した時点でサイクル数が 0 でない場合は、Zeroボタンをクリックして表示を 0 にします。
      (4) ボタンをクリックします。
      (5)
      結果が以下のように表示されます。

      スタートしてからストップするまでに2503サイクル要したことを示しています。10MHzの発振器周波数で換算すると1.00ミリ秒になります。
      今回の方法の場合、100ミリ秒タイマーのサブルーチンコール命令(CALL)も実行ステップに含まれているので、1ミリ秒タイマー自体は2501サイクル要していることになります。

      ソフトウェアによるタイマーの場合、処理ステップにより待ち時間を作っているので、正確ではありません。と言うのは、1秒タイマーでは1ミリ秒タイマーを1000回使っているので、1ミリタイマーでは1サイクルの誤差でも、1秒タイマーでは1000サイクルの誤差になります。また、サブルーチンを呼び出す処理、ループカウンターの設定処理なども加わります。ただ、発振器自体の誤差もあるし、1秒の時間で数ミリ秒誤差が出ても実際には影響は少ないと思います。正確な時間を望むなら、ハードタイマーを使用した方が良いです。

      ちなみに1秒タイマーをストップウォッチ機能で計測してみました。私のパソコンではこの計測に18分かかりました。

6101サイクルの誤差は時間に換算すると2.44ミリ秒です。
LED点滅制御には全く問題ない誤差です。
もっとシビアな回路で使う場合は影響が出るかも知れません。