第32回 PICマイコンのプログラムデバッグ(1)

前回作成したプログラムをMPLABX IDEのデバッグ機能を使用して動作させます。

目次

デバッグ機能とは?

今までの記事で、いくつかチャレンジ課題に挑戦していただきましたが、一発でプログラムが動作せずに困った経験はないでしょうか。自分の場合、チャレンジ課題のプログラムもそうですが、記事に載せている大半のプログラムは、一発でうまく動くことはほとんどない、という現状です。

PICマイコンにプログラムを書き込んで、意図した通りに動かない場合、なんだかPICマイコンの中でプログラムがどう動いているのか実際に確認したくなりますよね。

デバッグ機能は、このような時のために用意されています。PICマイコンの中でプログラムがどのように動いているか確認しながら動作させることができる機能です。

と説明されても、いまいちどうやって確認できるのか具体的にわからないですよね。そこで、習うより慣れろということで、前回作成した動作確認用プログラムを使ってデバッグ機能を動かしてみます。

動作確認プログラムのデバッグで行うこと

前回作成した動作確認プログラムは、main関数内では温湿度・気圧センサモジュールのチップIDを取得するだけの動作でした。

void main(void) {

    // 動作周波数設定
    OSCCON1bits.NDIV = 0b0000;  // 分周1:1
    OSCFRQbits.HFFRQ = 0b010;   // 4MHz

    // ピン属性設定
    ANSELC = 0b00000000;
    TRISC  = 0b01000000;

    // SPI信号線初期設定
    SPI_SCK  = 0;  // クロックを0
    SPI_MOSI = 0;  // マスタ→スレーブを0
    SPI_CSB  = 1;  // チップセレクトを1(=無効)

    // 0xD0に格納されているチップIDを読み取る
    uint8_t chipid = 0;

    chipid = spiRead1ByteData(0xD0);
    
    // ここで動作停止
    while(1){
    }

}

このように、PICマイコンの動作設定を行なったあと、取得したチップIDの値はただ変数(chipid)に入れるだけで、LCDモジュールに表示することはありませんので、人間が外から確認することができません。このプログラムを書き込んで動作させても、外から見ると動いているのか動いていないのかすらわかりません。

そこで、デバッグ機能を使って、実際にPICマイコンを動作させてchipidの中身をみてみることにします。これから、PICマイコンを実際に動作させて、spiRead1ByteData関数を実行した後にchipidに入っている値を確認します。

なお、プログラムのデバッグはMPLABX IDEとPICマイコンが通信しながら行いますので、デバッグ動作中はPICKIT3を接続したまま使用することになります。

PICKIT3を接続すると物理的に安定しませんので、今まではプログラム書き込み時に片手で押さえていたかもしれません。デバッグ機能を使用する場合、デバッグ中PICKIT3を接続したままにしますので、両手が空くようにPICKIT3をうまく固定できるようにしておきましょう。

それでは、PICKIT3をブレッドボードのピンヘッダに接続したら、MPLABX IDEでプロジェクトを開き、電池ボックスの電源を入れましょう。

デバッグ手順その1

今回の「プログラムの特定の行の変数の値を確認する」などのように、プログラムの特定の行の実行結果の状態を確認したい場合、PICマイコンにはその前の行までは普通に処理を行なってもらい、指定した行で処理をストップしてもらうことができます。

このように処理をストップする特定する行のことを「ブレークポイント」と呼びます。日本語では「止める地点」という意味合いでしょうか。

chipidの変数の値を確認するには、確認する次の行にブレークポイントを設定します。具体的には

chipid = spiRead1ByteData(0xD0);

の次の行、

while(1) {

という行にブレークポイントを設定します。ブレークポイントを設定すると、設定した行を実行しない状態で処理をストップします。

それではこの行にブレークポイントを設定しましょう。設定は、以下のようにストップさせたい行の行番号を1回クリックします。

Pic practice 32 breakpoint setting

行番号をクリックすると、行番号が四角の記号に変わり、行が赤色でハイライトされます。これがブレークポイントが設定されている表現になります。

次に、PICマイコンにデバッグ実行してもらいます。今までは書き込みボタンをクリックしていましたが、デバッグの場合は以下のデバッグ実行のボタンをクリックします。もしクリックしてメニューが表示されてしまったら「Debug Main Project」を選択してください。

Pic practice 32 debug button

デバッグボタンをクリックすると、最初に以下のようなダイアログが表示されることがあります。

Pic practice 32 debug message

このダイアログの内容ですが、「現在のプログラムで設定されているPICマイコンのコンフィグレーション設定は、デバッグ実行する場合は無効になるため、デバッグ時にはそのコンフィグレーションを変更して実行しますよ、いいですか」という意味です。

具体的には、上のダイアログでは「現在のプログラム設定では、PWRTはenable、MCLRはdisableになっていますが、これらはデバッグ時には、PWRT=disable、MCLR=enalbeにする必要があるので、変更して実行しますがいいですか。

でもこの変更はデバッグ実行時のみMPLABX IDEが変更し、あなたが作ったプログラムは変えないですし、デバッグ実行が終われば元に戻します」という内容です。

デバッグをする場合、このダイアログでOKボタンを押さないとデバッグ実行できないですし、そもそもデバッグ実行時のみMPLABX IDEが勝手に変更してくれるので、いちいち聞かなくてもいいような気もします。でもこのダイアログが表示されると、いつもと違った感じで「デバッグだ!」という雰囲気になりますので、一応このダイアログを確認したふりをしてOKボタンをクリックすることにします。

OKボタンをクリックしてしばらくすると、PICマイコンはプログラムの先頭から処理を実行して、ブレークポイントの行にくると処理を止めてくれます。ブレークポイントで処理が止まると、以下のようにPICマイコンは待機状態になります。

Pic practice 32 stopped at breakpoint

これで、chipidを取得した後、while行の実行手前で処理が止まりました…

止まってのはいいですが、結局chipidに何が入っているんでしょうか…

chipid変数の中身の確認方法は3通りありますので、それぞれ確認して見ましょう。

一つ目の方法は、カーソルをchipidという文字列に合わせます。カーソルを合わせてちょっと待つと、chipidの内容がツールチップして以下のように表示されます。

Pic practice 32 variable content

ツールチップには、「Address」の値と「chipid」変数の値が表示されています。Addressとは、chipidの値を格納するためのメモリ上のアドレスです。次のchipidが変数の値で、0x60であることがわかります。チップIDは0x60になるはずですのでうまく取得できていることが確認できました。

二つ目の方法は、Variablesウインドウを確認する方法です。MPLABX IDEの下の方にウインドウがいくつか並んであると思いますが、その中に「Variables」というウインドウがあるはずですので探してみてください。もし見つからない場合は、MPLABX IDEメニューの「Window」→「Debugging」→「Variables」を選択してください。

Pic practice 32 variables window

このウインドウを選択して表示すると、以下の画像は見づらいですが変数の値が表示されています。内容は先ほどと同様、chipidのアドレスと値が表示されているはずです。

Pic practice 32 variables window content

3つ目の方法は、Watchesウインドウを確認する方法です。先ほどのVariablesウインドウの並びに「Watches」ウインドウがありますので探してみてください。もし見つからない場合は、MPLABX IDEメニューの「Window」→「Debugging」→「Watches」を選択してください。

Pic practic 32 watch window

先ほどの2つの方法とは違って、何も表示されていません。このウインドウは、自分で確認したい(Watchしたい)変数などを登録しておくところになります。

それでは変数chipidを登録してみましょう。

以下の部分をダブルクリックします。

Pic practice 32 watch window register

ダブルクリックすると、以下のようなダイアログが表示されますので、以下のようにchipidと入力してクリックするとchipidが登録され、中身の確認ができるようになります。

Pic practice 32 watcih windows dialog

なお、ダブルクリックの間隔が長い場合(=2回のクリックの場合)、以下のように変数名の欄に直接変数名を入力するモードになりますので、以下のようにchipidと入力すると、chipidが登録され中身の確認ができるようになります。

Pic practice 32 watch dialog direct

これでデバッグ機能を使用してchipidの確認ができました。

PICマイコンはこの行で処理を停止しています。

この後にさらにプログラムがあり処理を継続させたい場合は、以下のContinueボタン(処理継続ボタン)をクリックします。

Pic practice 32 continue button

なお、今回のプログラムはこの後「while(1){}」ですので、実行は続けますが何も変化はありません。

また、デバッグを終了する場合は、以下のFinishボタン(デバッグ終了ボタン)をクリックします。

Pic practice 32 finishボタン

以上が典型的なデバッグの手順ですが、デバッグ機能は他にも色々な機能があります。次回の記事で、このプログラムを使用して他のデバッグ機能の確認を行います。

更新履歴

日付 内容
2018.5.6 新規投稿
通知の設定
通知タイミング
guest
13 コメント
新しい準
古い順 一番投票が多い
本文中にフィードバック
全てのコメントを見る
しゅう☆
しゅう☆
2 月 前

有用な情報をいつもありがとうございます。
紹介されている部品をなるべく揃えて記事を参考に1つずつ進めているところです。
私も3年前のteruさんと同じように赤い■が破れた柄になりRunningのままになりました。

■開発環境
 Windows10
 MPLAB X IDE 6.15
 XC8 v2.46
 PicKit5

1) Break Pointで止まらない件
 → while(1){
 で止めようとすると止まらずに、
 2行に渡っているwhile文を下記のように1行に書き換えると止まりました。
 → while(1){ }
 複数行行に渡っている文の1行目だけをBreak Pointに出来ないような気がします。

試しにwhile文の直前に適当に
 → __delay_ms(100);
 を追記してBreake Pointに設定すると止まったので、
 上記の1文1行にすることを思いつきました。

2) chipidの中身を見ようとすると”Not Recognized”になる件
 1)で止まるようになったけど、変数が読めない件は
 管理者殿の解説通りなのかな?と思いました。
 main関数の外に、chipidをグローバル変数としてvolatile無しで
 ”uint8_t chipid = 0;”
 と定義しても、記事の通りに変数の中身が読めるようになりました。

しゅう☆
しゅう☆
返信  しゅう☆
2 月 前

追記

プログラムの中で作っている3つのユーザー関数は
1バイトの返値を期待していると思うのですが、
モニターしてみると2バイトで戻ってきているようです。
追加情報でした。

teru
teru
3 年 前

いつもツールラボ様のサイトで勉強させていただいてます。
見よう見まねでここまできました。

以前、他の方と同じ内容の相談になるのですが、私のほうでもデバックができなくて困っています。
通常であればデバックすれば、赤色四角のアイコンで止まりchipidのアドレスがわかるはずなのですが、私のほうではツールラボ様と同じアイコンではなく、赤色四角が破れたような形のアイコンになっており、pick3の動作コメント欄にはrunningのままになっています。

現状は、1の方法ではchipidにカーソルを合わせるとchipidとだけ表示され、2・3の方法でも何も進展がない状況です。
なにかわかりましたらお返事いただけると助かります。

なお私のパソコンで使っているMPLABはv5.40で、xc8はv2.20となっております。
あと、第21回のブレッドボード回路の動作確認はできています。

私のほうで疑問に感じる事があるのですが、デバックを始めるとuint8_tなどに赤色の波線がつくのですが、これは何か関係があるのか気になっています。

よろしくお願いします。

管理者
管理者
返信  teru
3 年 前

ご質問どうもありがとうございます。

こちらでMPLABX IDE v5.40 + XC8 v2.20で確認したところ、chipidはunrecognized(認識できない)という状態でした。

この原因ですが、chipid変数は値を代入するだけでその後何もしないので、コンパイラによっては「この変数はあってもなくても動作に関係ないだろう」という判断がされてしまい、PICマイコンに書き込むコードから削除されてしまいます。

この状態になると、人間が見るソースコードとPICマイコンで動作しているプログラムに差が出てしまい、結果としてデバッグ時に変数がない状態になってしまいます。

解決方法としてはいくつかあります。一つはコンパイラの設定で最適化をしない、を選択する方法です。もう一つは、プログラム上に最適化しないでくれ、と明示的に書く方法です。

そこで、以下のようにプログラムを変更して試していただけませんでしょうか。

1) chipidの宣言をmain関数の中ではなく、先頭の方に以下のようにグローバル変数で定義する

volatile uint8_t chipid = 0;

2) main関数で宣言しているuint8_t chipid = 0;を削除、またはコメントアウトする

変数宣言時に「volatile」をつけると、メモリ上に変数を確保してくれます。

teru
teru
返信  管理者
3 年 前

お世話になっております。
長い間別の作業をしており、お返事遅れまして申し訳ございません。
ようやくデバック作業を開始できましたので確認したのですが、やはり失敗してしまいます・・。
お返事いただきました通り
volatile uint8_t chipid = 0;をグローバル変数で定義し、uint8_t chipid = 0;はコメントアウトはしています。
念のため配線間違いがあるのか、第21回のブレッドボード回路の動作確認をしており、配線は間違いないようなのですが。
電源の確保は、PICKKIT3はパソコンのUSBから(5V)、ブレッドボードには3.3Vを直接流しています。
PICKKIT3からの配線はオスメスジャンパー線でブレッドボードに繋げています。
なお、デバックした後のエラーは下記のようにでています。
Device Erased…
Programming…
The following memory area(s) will be programmed:
program memory: start address = 0x0, end address = 0x7ff
configuration memory
program memory
Address: 0 Expected Value: 3180 Received Value: 0
Failed to program device
お手数をおかけしますが、よろしくお願いします。

管理者
管理者
返信  teru
3 年 前

情報どうもありがとうございました。

いただいたエラーログをみると、PICマイコンへの書き込みに失敗しています。そこで大変お手数なのですが、LEDを点滅させるような簡単なプログラムの書き込み、動作ができるかご確認いただければと思います。

エラーログの最後の行は「3180を書き込んだはずなのに、読みだすと0になっている」という内容で、プログラムがうまく書き込めていないというエラーになっています。

teru
teru
返信  管理者
3 年 前

返信が遅くなり申し訳ございません。
いろいろと手こずっており遅くなりました(・・;)
ようやく無事にデバック出来ましたことをご報告させていただきます。
出来なかった原因といたしまして、PICKKITの配線に問題がありました。
アドバイスいただいた通り、まず簡単なプログラムを書き込もうとしたのですが、なぜか出来ずエラーも同じものが出てましたので、これは配線ミスか・・と疑いやり直したところ無事にできました。
初歩的なミスでお手間をとらせてしまい申し訳ありませんでした。
ただプログラムを書き込める状態になっているのもかかわらず、何故かうまくいかなかった原因が今もわかりません。
と言いますのも、デバック停止位置が
while(1)では、ずっとrunnig状態でデバックできず
chipid = spiRead1ByteData(0xD0);のところで停止すると出来たことです。今回~chipidをグローバル変数で定義していることと関係があるのでしょうか。謎のままです。
結果的にアドレスに0X60が表示されましたので、私は大満足しております。
本当にありがとうございました。

橋口 昭次
橋口 昭次
4 年 前

はじめてご連絡させて頂きます。
32回のBME280の動作確認プログラムにて確認作業をしているのですが
どうも上手くIDの読み込み確認が出来ません。
57歳おっさんの冷や水なのですが、ご指導頂けると助かります。
PCのOSはWindows7にてMPLAB X IDE v5.25 です。
どうか宜しくお願い致します。
因みにFBでも全く同じ内容で投稿させて頂きました。

管理者
管理者
返信  橋口 昭次
4 年 前

ご回答が遅くなり申し訳ございませんでした。

「IDの読み込みができない」というのは、この記事のデバッグ手順で、変数chipidの中身が0x60にならない(0x00になっている)という状況でしょうか。

chipidが正しく取得できない場合、SPI通信がうまくできていない可能性がありますので、まずは完成プログラムを書き込んで気象データが正しく液晶ディスプレイに表示されるかご確認いただければと思います。

完成プログラムが動作しているのに、chipidが正しく取得できない場合はプログラムやデバッグの問題の可能性があります。また完成プログラム自体が動かないのであれば、回路の問題も考えられます。

お手数ですが、まずは問題の切り分けをしていただければと思います。

ネモ
ネモ
4 年 前

ご回答ありがとうございます。
私も通知が来ず、分かりませんでした。。
PICはAliexpressで購入したもので、16F628Aとなっているしプログラムもその設定で書き込んでいますが、中華製なので中身がA無しを使われている可能性もありますね。
表の見方が分かりましたので、今後はそこで確認したいと思います。

ネモ
ネモ
4 年 前

いつも連載で勉強させて頂いています。
PICによってMPLABでのデバッグができるものとできないものがあるようなのですが
それをどこで調べればよいか教えて下さい。
PIC16F628Aが安めに売っていたので購入しプログラムして、いざデバッグしようとすると
「A debug header is required to debug this device」と表示されデバッグできません。
検索してみると、デバッグヘッダーという器具を使わないといけないということでした。
参考ページ:http://yak-shaver.blogspot.com/2013/09/pickit3-debug-header.html
ところが、ここに書かれている文書「Processor Extension Pak and Header Specification」が
メーカーのページにも無くて参照することができません。
それで「Device Support」の一覧表を見てみるとICDデバッグが「サポート」となっていて
記述が合わないのです。
comment image
実際デバッグできないので、記述が間違っているのではないかとおもうのですが、そうすると
次に買おうとするPICがデバッグできるのかどうか、どうやって調べればいいでしょうか?
各PICのデータシートを見ても書き方がそれぞれバラバラでよく分からないときがあります。
それでもやはりデータシートの記述で確認するしかないでしょうか?

管理者
管理者
返信  ネモ
4 年 前

回答が遅くなり申し訳ございませんでした(コメントの通知がきておらず、今気づきました…)

デバッグができるかどうかの情報は添付いただいた画像のファイルになります。このファイルは、MPLABX IDEをインストールすると、ドキュメントフォルダにインストールされますので、ご自身のPCでも確認できます。

なお、添付いただいたファイルの赤枠部分は、Microchip社の「MPLAB ICD」という製品でデバッグできるか、という情報です。

一番上の欄の名前がわかりづらいですが、以下のようになっています。

ICDP: ICDを使ったプログラム書き込み
ICDD: ICDを使ったデバッグ

PK3P: PICkit3を使ったプログラム書き込み
PK3D: PICkit3を使ったデバッグ

16F628Aは、PICkit3/4であればデバッグもできますが、16F628はデバッグができない、ということになります。

デバッグヘッダが要求される、ということは16F268Aではなく628と認識されてしまっている可能性があります。

目次