たまりば

  パソコン・インターネット パソコン・インターネット  三鷹市 三鷹市

PICライタ製作_1
2012年05月28日 01:20

(ブログには書いていないが)今までPICで色々作ってきたが、ライタ(書き込み機)にはずっと自作したRCDライタを使っていた。
RCDライタというのは、詳しくは作者のページ(http://feng3.nobody.jp/rcd/)を見るとよいが、部品代数百円で作れる非常に財布に優しい物である。
しかしこれには欠点があって、最近のPICには書き込めない。
PICのプログラミング(書き込み)時には、プログラミングモードに移行させる指令として高電圧を掛けるのだが、この電圧が昔のものは12V前後なのだが最近の石では9Vになっている。
RCDライタではこの電圧が固定なのでそのまま使うと過電圧で石を壊してしまう。
また、少し前から大抵の石はLVP(Low Voltage Programming; 低電圧書き込み)モードがあるのだが、これもRCDライタは対応していない。
まあ新しい石を使わなければいい話なのでさほど気にせずやってきたのだが、この前衝動買いしたPIC10F322という石が9Vタイプであった。
折角買ったのに使えないのは癪なので、最近の9Vタイプにも書き込めるような書き込み機の情報を探そうかと思ったのだが、どうせなら自分で作った方が楽しいという結論に達した。

というわけで、PICライタを設計してみようかと思う。
作るにあたって、まずは書き込み方法の資料を入手する。
これはデバイスのファミリーごとに「PIC10(L)F320/322 Flash Memory Programming Specification」のような名前で公開されている。
なおデバイスごとに微妙に受け付けるコマンドが違ったりもするが書き込み手順自体は基本的にはみな同じである。
まずプログラミングモードに移行させて(このやり方は数種ある)から、クロックとデータの2本の線でシリアル通信をするという仕組みで、意外と簡単そうである。

今回まずは書き込みの実証程度のプログラムを作ってみた。
使った石は(書き込み側も書き込まれ側も)PIC16F628A。PICを始めるときに18ピンで安いものを選んで買った物だが、無難に色々機能があって使いやすいので以来ずっと愛用している。先日1番ピンが折れたがまだ使える。
何気にLVP(旧式)対応なので今回のテストに最適だ。
LVPなら面倒な高電圧を用意する必要が無いのと、新式のLVPはプログラミングモードに移行させるためにコマンド入力が必要なのだが旧式はピンを1本余計に使う代わりにこの面倒が無い。
事前にRCDライタでLVPをオンに設定して、ついでにプログラムメモリは全消去しておく。
書き込む内容はプログラム中にハードコーディングしておき、プログラムでは書き込みのみを行う。
プログラミングモードに入る手順を勘違い(※)してちょっとはまったりもしたが、まあそれなりにスムーズに成功した。
※手順は、「電源を印加」→「PGMピンをH」→「リセットを解除」なのだが、最後リセットをONにするのだと勘違いしていた。

書き込み風景はこんな感じ。
PIC書き込み実証
右が書き込み側、左が書き込まれ側。
上の抵抗2本がPGMと/MCLR、下の赤い線2本がPGD(データ)とPDC(クロック)に繋がっている。
LEDは書き込み信号が出力されているか確かめるために付けたのだが、外さなくても書き込めたのでそのままになっている。

書き込み用のコードはこんな感じ。
あまり人に見せるコードではないが、書き込めて嬉しいので勢いで公開してしまう。
 list p=16f628a
 #include p16f628a.inc
 variable env

; RA2+-v-+RA1
; RA3|  |RA0
; RA4|  |RA7
; RA5|  |RA6
; Vss|  |Vdd
; RB0|  |RB7
; RB1|  |RB6
; RB2|  |RB5
; RB3+---+RB4

env = _BOREN_OFF
env &= _CP_OFF
env &= _DATA_CP_OFF
env &= _PWRTE_OFF
env &= _WDT_OFF
env &= _LVP_OFF
env &= _MCLRE_OFF
env &= _INTOSC_OSC_NOCLKOUT
 __config env

RAMSTART equ 0x20
clk equ 0
dat equ 1

LOAD_CONF equ b'00000000'
LOAD_PROG equ b'00001000'
LOAD_DATA equ b'00001100'
INC_ADDR equ b'00011000'
READ_PROG equ b'00010000'
READ_DATA equ b'00010100'
BEGIN_PROG equ b'00100000'
ERASE_PROG equ b'00100100'
ERASE_DATA equ b'00101100'

 cblock RAMSTART
  count
  count2
  pgmcount
  iobuf
  clkbuf
  datbuf
  ptr
  temp
  
  freeram
 endc
;

 org 0x00
init

 clrf PORTB

 bsf STATUS,RP0
 
 clrf TRISB ; PORTB : all output
 clrf TRISA ; PORTA : all output

 clrf STATUS
 decf CMCON,F ; Comparator Off

 movlw 0x10
 movwf pgmcount

 clrf count2

waitloop1 ;なんとなく待つ
 call wait500us
 call wait500us
 call wait500us
 call wait500us
 decfsz count2
 goto waitloop1

 clrf iobuf ;PGMピンをHに
 bsf iobuf,7
 movf iobuf,W
 movwf PORTB
 nop ;5usでいいがなんとなく余計に待つ
 nop
 nop
 nop
 bsf iobuf,6 ;/MCLRピンをHに
 movf iobuf,W
 movwf PORTB

 clrf ptr

pgmloop
;ロード
 movlw freeram
 movwf FSR
 ;load for program memoryコマンドをセット
 movlw LOAD_PROG
 movwf INDF
 incf FSR,F
 movlw 0xFC
 movwf INDF
 incf FSR,F

 ;プログラムデータをセット
 call setdata
 incf ptr

 movlw freeram-1
 movwf FSR
 movlw d'24'
 call transmit

;プログラム
 movlw freeram
 movwf FSR
 ;begin programコマンドをセット
 movlw BEGIN_PROG
 movwf INDF
 incf FSR,F
 movlw 0xFC
 movwf INDF
 incf FSR,F
 movlw freeram-1
 movwf FSR
 movlw d'8'
 call transmit

;待ち。ループ書くのめんどくさい。
 call wait500us
 call wait500us
 call wait500us
 call wait500us
 call wait500us
 call wait500us
 call wait500us
 call wait500us
 call wait500us
 call wait500us
 call wait500us
 call wait500us

;アドレス++
 movlw freeram
 movwf FSR
 ;inc addressコマンドをセット
 movlw INC_ADDR
 movwf INDF
 incf FSR,F
 movlw 0xFC
 movwf INDF
 incf FSR,F
 movlw freeram-1
 movwf FSR
 movlw d'8'
 call transmit

 decfsz pgmcount
 goto pgmloop
 
 goto $

transmit
 movwf count
transmitloop
 movlw 0x07
 andwf count,W
 btfss STATUS,Z

 goto noadvance

 incf FSR
 movf INDF,W
 movwf datbuf
 incf FSR
 movf INDF,W
 movwf clkbuf

noadvance

 ;clkをLに
 bcf iobuf,clk
 movf iobuf,W
 movwf PORTB

 ;データ準備
 rrf datbuf,F
 bcf iobuf,dat
 btfsc STATUS,C
 bsf iobuf,dat
 rrf clkbuf,F
 btfsc STATUS,C
 bsf iobuf,clk

 ;出力
 movf iobuf,W
 movwf PORTB

 decfsz count,F
 goto transmitloop

 ;clkをLに
 bcf iobuf,clk
 movf iobuf,W
 movwf PORTB

 return

;;;;

setdata
;プログラムデータをセット
 movf ptr,W
 call readtable
 movwf INDF
 rlf INDF,F
 rlf temp,F ;Cを保存
 incf FSR,F
 movlw 0xFF
 movwf INDF
 incf FSR,F
 incf ptr
 movf ptr,W
 call readtable
 movwf INDF
 rrf temp,F ;Cを取り出し
 rlf INDF,F
 incf FSR,F
 movlw 0xFF
 movwf INDF

 return
 
;;;;

;0.5ms待つ
wait500us
 movlw d'165'
 movwf count
loop500us
 decfsz count,F
 goto loop500us
 return


readtable
 addwf PCL
programtable
 dt 0x83, 0x16, 0x86, 0x01, 0x85, 0x01, 0x83, 0x01, 0x9F, 0x03, 0x55, 0x30, 0xFF, 0x3A, 0x85, 0x00
 dt 0x86, 0x00, 0xA0, 0x01, 0xA1, 0x01, 0xA1, 0x0B, 0x0B, 0x28, 0xA0, 0x0B, 0x0A, 0x28, 0x06, 0x28
 dt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;何か間違ったときのために少し余計にデータを置いておく
 dt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

 end
最後の32バイトのデータが書き込んだプログラム。
このソースも一応書いておく。全てのI/Oピンから交互にH/Lを出力する。適当なピンとピンの間にLEDを挿してチェックできる。
なんとなく短さに挑戦してみた。同じ条件でこれ以上縮められる気はあまりしない。
(宣言とか略)
 org 0x00
init

 bsf STATUS,RP0
 
 clrf TRISB ; PORTB : all output
 clrf TRISA ; PORTA : all output

 clrf STATUS
 decf CMCON,F ; Comparator Off

 movlw 0x55
loop
 xorlw 0xFF
 movwf PORTA
 movwf PORTB

 clrf count1
wait1
 clrf count2
wait2
 decfsz count2
 goto wait2
 
 decfsz count1
 goto wait1

 goto loop

これからの予定:
・PCのシリアルポートからデータを受け取って書く
・書き込み用高電圧を昇圧回路で作る
・USBに対応
・既存のライタとインターフェースを合わせる

タグ :マイコン

  • Post time : 2012年05月28日 01:20│Comments(0)
    URL欄を実験的に消してる間に廃止されてしまいました。まあいいか。
     
    <ご注意>
    書き込まれた内容は公開され、ブログの持ち主だけが削除できます。
    削除
    PICライタ製作_1
      コメント(0)