PICプログラマのソフトウェア2 〜PICマイコンと通信する〜〜

PICプログラマのソフトウェア

 今回は、以前検討したハードウェアを使って、プログラムを書き込む(=ダウンロードする)ための制御プログラムを作ります。

 PIC16F627A/628A/648A EEPROM Memory Programming Specificationがバイブルです。これを読み解きながら、必要な制御は何かを見つけていきます。制御線はちょっと前に検討したとおりです。

低電圧書き込みモード

LVPモード

 今回とりあえず取り組んでみるのは、電源電圧5Vだけでどうにかなってしまう「Low Voltage Programming」つまり低電圧書き込みモードを使用します。これを使うとPICマイコンの端子のうち自由に使えるものがひとつ減ってしまうのですが、13Vへの昇圧はおいおい検討していくとして、まずは手軽にできるこの低電圧書き込みモードに着手することにします。

 このモードに入るためには、まず最も重要なこととして、コンフィギュレーションレジスタのLVPビットが1になっている必要があります。PICを買ってきて最初の状態では1になっています。なので、それをそのままいじらずにいれば、1になっているはずです。

 そして、先のPIC16F627A/628A/648A EEPROM Memory Programming SpecificationFIGURE 2-3に示された順番で信号を制御します。まず電源電圧VDDをONにし、続いてPGM、MCLR端子の順番でHIGHレベルにしていきます。この間、DATA、CLOCKはLOWレベルにしておきます。この辺は以前検討したとおりですね。

 現在の回路では、VDDはUSBに接続した時点で5Vがかかっています。そして、CR遅延回路で少し遅れてPGMが勝手にHIGHレベルになります。

 MCLRはTX信号を使うのですが、初期状態はHIGHレベルですので、LOWレベルに一旦落として再度HIGHレベルにします。TX信号をLOWレベルにするには、ブレーク信号を送ります。ブレーク解除の前に、DTR・CTS信号をLOWレベルにしておきます。

 MCLRをHIGHレベルに、つまりブレーク解除すると、そこで低電圧書き込みモードに入ります。

通信フォーマット

 PICマイコンとのデータのやりとりには、CLOCK(PGC)とDATA(PGD)の2線を使用します。2.4 Program/Verify Modeを読んでいくと、「クロックパルスの下りエッジでデータをラッチする」とあります。つまり、CLOCKがHIGHレベルからLOWレベルに落ちるときにDATAがHIGHレベルなら1、LOWレベルなら0、ということになります。そして、殆どのコマンドは、コマンド部6ビット、データ部16ビットの形式をとります。TABLE 2-3: COMMAND MAPPING FOR PIC16F627A/PIC16F628A/PIC16F648Aに、9つのコマンド形式が記入されています。データ部のデータは14ビットの場合は両端に0をはさんで送信、8ビットの場合は、上位に6ビットの0を足して14ビットにしたうえで、両端にさらに0をつけて送信します。そして、コマンド部・データ部ともにLSbファースト、つまり下位のビットを先に送るような形式になっています。

データ送信

 で、それらの実際の波形が2.4.1からずらずらずらっと書かれています。例としてFIGURE 2-4: LOAD DATA COMMAND FOR PROGRAM MEMORYを見てみましょう。

 LOAD DATA FOR PROGRAM MEMORYコマンドは、コマンド部が X X 0 0 1 0 の6ビットですので、まずこれを送信します。Xは何でもいいということですから、ここでは0を送ることにします。LSbファーストですから、0, 1, 0, 0, 0, 0 の順番で送ればいいわけですね。DATA・CLOCKともにLOWレベルが初期状態です。

 1ビット目の0を送信するには、まずCLOCKをHIGHレベルにします。DATAは0ですから、LOWレベルを維持します。そして、CLOCKをHIGHレベルからLOWレベルに落としたとき、DATAはLOWレベルですから0が確定します。続いて2ビット目はDATAは1です。CLOCKをHIGHレベルにしたあと、DATAをHIGHレベルにします。そしてCLOCKをLOWレベルに落とした瞬間に、DATAがHIGHレベルですから1が確定します。こういう風に、データを送っていけばいいわけですね。

 あと重要なのが、タイミングの規定です。DATAのレベルを確定してから、TSET1時間を置いてCLOCKをLOWレベルに落とします。このTSET1時間は、4.0 PROGRAM/VERIFY MODE ELECTRICAL CHARACTERISTICSにて規定されています。「Data in setup time before clock↓」CLOCKを下げる前のDATAのセットアップタイムってところを見ると、100nsとなっています。あまり急ぎすぎてもダメということですね。同様に、THOLD1も100ns。通信速度が早くなってきたら気をつけなければなりません。

データ受信

 データを送信するだけではなく、書き込んだ値を確認したりする必要があるので、受信もしなければなりません。今度は、FIGURE 2-9: READ DATA FROM PROGRAM MEMORYを例にデータ受信してみましょう。

 コマンド部は先ほどと同様に送信します。そうすると、次のデータ部でPICマイコンが読みたいデータを送信してくれるようになるわけです。ただしCLOCKはホストから制御します。そのCLOCKに合わせて、PICがデータをくれるというわけです。

 まず1ビット目。先ほどと同様にCLOCKをHIGHレベルにします。そしてLOWレベルに落とします。最初は必ず0が返ってきます。そして2ビット目。CLOCKをHIGHレベルにします。TDLY3時間は待つと、PICがデータに合わせてHIGHレベルかLOWレベルにしてくれています。CLOCKをLOWレベルに落とすときにそのDATA線の状態を読み取り、LOWレベルだったら0、HIGHだったら1とします。そしてそれを全部で16ビット続けます。1ビット目と16ビット目は必ず0になるはずですね。

メモリマップ

 今使っているPIC16F628Aのメモリマップを見てみます。FIGURE 2-1: PROGRAM MEMORY MAPPINGに書いてあります。628Aは2キロワードのプログラム領域を持ちます。0番地から0x7FF番地までがプログラムの格納される領域です。そして、ユーザが自由に使えるUser ID部やDevice ID部、そしてConfiguration Word部が0x2000番地から0x2007番地まで入っています。前回チェックしたhexファイルの仕様に従って、このエリアにデータを書き込んでいくわけです。あと、EEPROM領域があるのですが、これは面倒なので後々に先延ばしします。とりあえず動作させるのには必要ありませんから。

PC

 データを書き込むアドレスは、PC(プログラムカウンタ)によって管理されます。このPCは特定の場所を指定して移動させることができないようです。移動させる方法は3種類あるようです。

 先の方法によって低電圧書き込みモードにセットすると、PCは0にセットされます。そのままプログラムを書き込めば0番地に書き込まれ、読み込めば0番地の値が読めるわけです。そのままですと永遠に0番地にしかアクセスできないので、Increment AddresコマンドでPCを進めます。すると、次はアドレス1番地にアクセスできるというわけです。

 Configurationデータを書き込みたいときは、Load Configurationコマンドを送信します。これ自体は書き込むためのコマンドではないようですが、このコマンドによってPCが0x2000番地にジャンプします。0x2007番地にアクセスしたい場合は、Increment Addressコマンドを7回使ってPCを0x2007にする必要があります。そこからプログラム領域へ戻すにはリセットするしかありません。リセットコマンドはありませんので、MCLR信号を一旦LOWレベルに落とすことによって行います。すると、PCが0に戻ります。

 現在PCが何番地にあるかを読み出すことはできないようですので、いくつインクリメントしたのか管理しておく必要がありますね。

プログラム手順

 では実際に書き込んでいくわけですが、その手順は、プログラム領域であればFIGURE 3-3: PROGRAM FLOW CHART - PIC16F627A/PIC16F628A/PIC16F648Aに書かれてあります。これを順に追っていきましょう。

 まずは書き込みモードに設定します。2種類ありましたね。今回は低電圧書き込みモードを使いますので、Start Low Voltage Programmingを見てみます。まずVDDVDD電圧、ここでは5Vに設定します。4.0 PROGRAM/VERIFY MODE ELECTRICAL CHARACTERISTICSによると、プログラム領域・データ領域はVDD電圧は2.0Vから5.5Vで制御可能のようですから、乾電池2個でも十分書き込みできるようです。ただし、バルクイレースコマンドを使うなら4.5Vから5.5Vが要求されていますから5Vが安心ですね。USB給電なら全く問題ないというわけです。

 そして、続いてPGMVDD電圧に、MCLRVDD電圧に順番に入れていきます。それでやっと低電圧書き込みモードに設定できました。

 最初の分岐点、Address=StartAddress?とあります。たいてい0番地からなのでYesなのですが、違うアドレスから書き始めるときは、PCがそこに到達するまでIncrement Addressを繰り返します。PCが目的のアドレスになっていたら、Program Cycleを実行します。横のフローにやってきて、Load Data for Program Memory Commandで書き込むプログラムデータをセットします。そのデータを実際にプログラムメモリに書き込むために、Begin Programming Commandを実行します。TPROG時間かかりますのでその時間は待ちます。

 そのままですとPCは今書き込んだアドレスにあります。そのまま、Read Data from Program Memoryコマンドを実行すると、今書いたプログラムデータが読み込めます。書いたはずのデータと読んだデータが正しくなければエラーを報告します。実際にはもう一度くらい書いてみてもいいかもしれません。書き込みが正常に行われたらIncrement Addressコマンドで次のアドレスへPCを進め、書き込み・確認を繰り返します。全ての領域が書き込み終わったらPCを一旦0に戻し(=リセットし)、全領域の確認をします。書いたときに読んで確認しているからよさそうなものですが、もしIncrement Addressコマンドが正常に機能しない場合があったら、そこでアドレスがずれてしまうことになります。そのエラーを検出することができないので、全ての領域をチェックする方がいいでしょう。このフローチャートではVDDNOMで確認するようなニュアンスで書いてあるのですが、このVDDNOMの意味が見つかりません。どこかに書いてあるのでしょうか。5Vで問題ないと思うのですが・・・。違うかもしれません。

 こうして、プログラム領域の書き込みが可能になりました。

PIC PICの一年生