PIC16F628Aにプログラミングできない!
Windows 7へMPLABをインストールする の後、当然ターゲットボードのテストプログラムを書くことになる。LEDをユニゾンで(5個同時に)0.5秒間隔でオン・オフするプログラムをMPLABで早速作った。
プログラムは、Project/Build Allにてビルドすることができる。Outputウインドウに"BUILD SUCCEEDED"と出てくればとりあえずHEXコードは作成されている。MPLABを使い始めたどこかの時点でビルドするプログラムを"Absolute"とするか、"Relocatable"とするか聞いてくるので、"Absolute"を選択しておく。この設定は、"Project/Build Options/Project"ダイアログの"MPASM/C17/C18 Suite"タブで設定変更できるようだ。
ビルドが終わったら出来上がったコードを確認する。"View/Program Memmory"をクリックして"Program Memory"ウインドウを表示する。今作成したアセンブラのコードがそこにあるはずだ。
さて、ターゲットボードにこのプログラムを流し込む。ターゲットボードをICD 3に接続し、"Programmer/Select Prorammer/MPLAB ICD 3"を選択しICD 3へ接続する。次いで、"Programmer/Program"を選択してプログラムをターゲットボードのPICへ流し込む。
うまくいくと、Outputウインドウがこのようになるらしい。

"Programming/Verify complete"と出てくる。見た目はうまく言っているようだが、PICは、ICD 3書き込み後直ちにプログラムを実行するはずなのだが、LEDは光らない。
実際にPICに書き込まれたはずの内容を"Program Memory"ウインドウに読み出してみる。"Programmer/Read"をクリックすると、"Program Memory"ウインドウにPICのメモリが表示されるのだが・・・

Address=000のOpcode(オペコード)が0001となっており、Disassembly欄が空欄となっている。これは明らかに書き込み不良だ。"Program Memory"ウインドウをスクロールしてプログラムを書き込んでいない領域を見ると、Opcodeは0x3FFFとなっている。つまり0x3FFFが初期状態や消去された状態。ICD 3でメモリクリア(Programmer/Erase Flash Device)しても、書き込みしているアドレス領域は0x3FFFとならないんだよね。
プログラム書き込みが一見成功しているようでも、実際には書き込まれていない。何度も試しているうちに、"Programming failed"と、書き込みそのものを失敗とレポートしてくるようになった。

正常に書き込まれていないことが確定した。しかし、なぜだろう?
最初はターゲットボードの配線を疑った。RJ11モジュラージャックからPICの足(PGD/PGM)やVcc/GNDなどへいたる経路を10xルーペを使い接触不良と疑われる箇所にハンダを盛る。PICに供給されている電圧を測定し、3.3Vであることを確認する。
それでも正常に書き込みできない。
途方にくれてネットで調べていると、Programming the PIC16f628aというサイトを探し当てた。この記事の中ほどに、「ブラウンアウトリセットが有効な状態だと、4.5V以下でPICを動かすことができない。PIC16F628Aは3.0Vで稼動可能であるが、ブラウンアウトリセットをオフとしなければならない。」と書いてある。そのちょっと下にはコメントとして、「ブラウンアウトリセットは、有効となっているならば、Vdd如何を問わず、通常4.0V以下で起こる。」と書いてある。 そして、このブラウンアウトリセットは、PIC16F627A/628A/648A Data SheetのConfiguration Bits (p96)によれば、Bit6(BOREN, Brown Out Reset ENable)はデフォルトでONとなっている。つまり、僕のターゲットボード(Vdd=3.3V)では、PICは常にブラウンアウトリセット状態であり、どんなに頑張ってもPICは動作出来ないというわけだ。
よし分かった。物は試しで、ソースファイル中の__CONFIG行にコンフィギュレーションビットのオプションを指定してしまおう。
INCLUDE "P16F628A.INC"
__CONFIG _INTOSC_OSC_NOCLKOUT & _BOREN_OFF & _LVP_OFF
;
; Variables definition.
;
CNT1 EQU 020H
...
__CONFIGで指定できる定数は、インクルードファイル(C:\Program Files (x86)\Microchip\MPASM SuitePIC16F628A.INC)を見れば書いてあるよ。ここではついでにLVP(Low Voltage Programming)もオフとしておいた。
この状態でソースを再コンパイルしてPICへプログラムを流し込む。やはり正常に書き込みできない。とどのつまり、コンフィグレーションビットもデータメモリ(address=0x2007)であり、そもそも書き込みを行うことが出来ないということであろう。
3.3V駆動したPIC16F628Aに書き込みが出来ない件に関する記事を見つけた。3.3 V Target ICD programmingというやつだ。もうこれは3.3V駆動はあきらめるしかないね。
使っているICは皆5V駆動可能なので、3端子レギュレータを5V版に差し替えるしかない・・・と決意した。やれやれ。
PIC16F628Aは他にも制限がある。ICD 3でIn-Circuit Debuggingができないようだ。ターゲットボードをICD 3へ接続した状態で"Debugger/Select Tool/MPLAB ICD 3"を選択しても、エラーとなってしまう。

PIC16F628A problemを見る限り、PIC16F628Aの仕様上の制限らしいのでどうしようもない。デバッグをするときには、"Debugger/Select Tool/MPLAB SIM"を選んで、シミュレータを使うしかないだろうね。
しかし、PIC16F628Aを使う利点は、内蔵クロックを使用するならば、スリープモードに切り替えなくても、動作周波数を切り替えて低周波(48KHz)で動作させることにより、消費電力をぐっと抑えることができることだ。割り込み処理時は4MHzで稼動させ、割り込み処理が終わったら48KHzに切り替えるといった使い方ができる。4MHzはワンサイクルが1マイクロ秒なので、処理時間の計算もしやすいし。
すぐに5Vの三端子レギュレータや若干の抵抗・コンデンサを発注した。今回は、若松通商の通販を利用した。抵抗等の能動素子も手に入る。3端子レギュレータは何種類もあるけれども、冬季は-20℃まで気温が低下することがある軽井沢でも使えるように、低温サイドの動作温度範囲の広い(-20℃~85℃)μPC78L05を使用することにした。
若松通商から送られてきた商品、例えば0.33μFの電解コンデンサ10個の梱包の中に0.1μFや0.2μFが少し混じっているんですけど・・・まぁ、調達数は余裕を持たせてあるし、何かに使うかもしれないし、まぁいいか。
3.3Vの三端子レギュレータ周りをハンダ吸い取り線とハンダゴテを使ってハンダを吸い取りつつ部品を引っこ抜いていく。開いたスペースに今度は5Vの三端子レギュレータとコンデンサを仕込んであっさりとVcc=5V化は完了。念のため、VccとGNDの間の電圧が5Vであることをテスターで確認しよう。よくある間違いは、三端子レギュレータのINとOUTを取り違えることだ。僕はまだそんなヘマをしたこと無いので、何が起こるかは知らないよ~。 μPC78L05のデータシートをalldatasheet.comより入手し、端子の機能をきちんと確認しておくように。
この状態でICD 3とMPLABを使ってプログラムの書き込みを再び行う。MPLABのメニューからProgrammer/Select Programmer/MPLAB ICD 3を選択してICD 3へ接続する。接続できたらProgrammer/Programを選択してPICにICSP経由でプログラムを書き込む。Programmer/Readを選択してPICのプログラムメモリを読み込み、View/Program Memoryを選択して内容を確認する。僕の場合、一度ではうまくいかなかったので、二度同じ動作を実施した結果、正しく書き込めた結果を確認できた。

PICに目をやると、なにやら全LEDが煌々と光っている。しかし、点滅はしていない。。。

プログラムにバグがあるのか、PICのクロックがおかしいのか。とりあえず、ICSP(In-Circuit Serial Programming)でPICプログラムを流し込めるようになった次第だが・・・
現象を見ていると、PIC内蔵クロック(4MHz/48kHz切り替え式)を使うとLEDが光る。水晶振動子を使うと光らない。改めてPIC16F628Aのデータシート(PIC16F627A/628A/648A Data Sheet)を見てみると、p97にXT発振(4MHz)で使用するコンデンサは15-30pFと書いてある。僕がターゲットボードに実装したコンデンサはなぜか47pF。なぜ47pFにしたんだっけ・・・こりゃ確かにクリスタルのクロック発振は無理っぽい。そこで、水晶振動子に通じるPICの15ピンと16ピンを水晶振動子から切り離してオープン状態とし、PIC内蔵クロックを使用することにした。 更に、作成したテストプログラムをMPLAB内で(シミュレータを使って)デバッグしていると、メインループ最初のLED点灯処理直後に、おそらくトラブルシューティング中に挿入してしまった無条件ジャンプ命令が、なぜかメインループに書き込まれており、確かにこれはLEDが点灯しっぱなしになるはず。当該行を削除したら、きちんと約0.5秒おきにLEDが点滅するようになった。いやぁ、よかったよかった。 そういう次第で、テストプログラムも公開しちゃう。これが動けば、ICSPによるPICプログラミングとLED周りは正常だよ。回路図は、軽井沢別荘の温湿度自動測定【マイコン部設計編】 にあるよ。組立の様子は、軽井沢別荘の温湿度自動測定【マイコン組立編】 にて。RJ11のピン割り当ては、後閑哲也氏の「電子工作のためのPIC16F活用ガイドブック」の「ICSPの回路構成」の章(p140)に準拠しているから。そうそう、Vcc(電源電圧)は5Vに変更しておいてね。それと、水晶振動子は使わなくなったから。
; Thermo-hygrometer LED flickering test program.
;
; Copyright(c) 2012 Ryuichi Kurishima, All rights reserved.
;
; This program is GPLv3 licenced.
;
; PIC operates at 4MHz clock. 1 cycle = 1 microsecond (4 clocks)
;
LIST P=PIC16F628A
INCLUDE "P16F628A.INC"
__CONFIG _INTOSC_OSC_NOCLKOUT & _BOREN_OFF & _LVP_OFF & _WDT_OFF
;
; Variables definition.
;
CNT1 EQU 020H
CNT2 EQU 021H
CNT3 EQU 022H
;
; Reset and interrupt vectors
;
ORG 0
; GOTO START
; ORG 4
; GOTO INTPRC
;
; MAIN BODY
;
START
BSF STATUS,RP0
BCF STATUS,RP1 ; Select Bank 1.
BSF PCON,OSCF ; 4MHz internal clock.
BCF STATUS,RP0 ; Select Bank 0.
MOVLW 07H ; Turn off Analog comparators.
MOVWF CMCON
BSF STATUS,RP0 ; Select Bank 1.
MOVLW 020H ; Only RA5/Vpp as input.
MOVWF TRISA
MOVLW 0F2H ;PORTB setting.
MOVWF TRISB
BCF STATUS,RP0 ; Go back to Bank 0.
MOVLW 01FH
MOVWF PORTA ; LED's are all off.
CLRF PORTB ; Initialize PORTB.
MAINLP
CLRF PORTA ; LED on.
CALL TIM05S ; Wait for 0.5 seconds.
MOVLW 01FH ; LED off
MOVWF PORTA
CALL TIM05S ; Wait for another 0.5 seconds.
GOTO MAINLP
;
; The idea of this approximate timer routine originates from Tetsuya Gokan's
; PIC hobby electronics book.
;
; 1ms timer.
TIM1MS MOVLW 0F9H ; = 249(decimal)
MOVWF CNT1 ; 1 + 1 = 2
TIMLP1 NOP
DECFSZ CNT1,F ; 2(above) + (1 + 1 + 2) * (249 - 1) + 1 + 2 = 997
GOTO TIMLP1
RETURN ; 997(above) + 2 = 999, 999 * 1usec = 0.999msec
; 100ms timer.
TIM100 MOVLW 063H ; 1msec * 99
MOVWF CNT2 ; 1 + 1 = 2
TIMLP2 CALL TIM1MS ; 2 + 999 = 1001
DECFSZ CNT2,F ; 2(above) + (1001 + 1 + 2) * (99 - 1) + 1001(above) + 2 = 99397
GOTO TIMLP2
RETURN ; 99397(above) + 2 = 99399 * 1usec = 99.399msec
; 0.5sec timer.
TIM05S MOVLW 05H ; 100ms * 5
MOVWF CNT3 ; 1 + 1 = 2
TIMLP3 CALL TIM100 ; 2 + 99399 = 99401
DECFSZ CNT3,F ; 2(above) + (99401 + 1 + 2) * (5 - 1) + 99401 + 2 = 497021
GOTO TIMLP3
RETURN ; 497021(above) + 2 = 497023 * 1usec = 497.023 msec.
;INTPRC
; RETFIE
END ; EOF
コメントする