ハードの方はめどがたちましたが、さて問題はソフトです。全ての処理を1つのマイクロコントローラに任せるプログラムを書くのは相当高度なテクニックが必要そうですが、今回は豪華に2つ使うことにしました。まるで大名のような贅沢ですね。いや、ひょっとするとそれ以上かもしれません。放射線のカウント、表示の処理は「ちびでぃ~の2」にまかせて、もう一つはパルス発生だけに専念します。これなら初心者の私でも何とかなりそうです。
e-電子工房さんのサイトを見ると400Vの場合、1KHzの周期でパルス幅が大体62n秒であれば良いことがわかります。まったくもって貴重な情報を公開していただき本当にありがとうございます。今回はアッセンブラでプログラムを作り、秋月電子通商から仕入れた新品のATmega168Pへ書き込みます。
当然のことながらAVRのアッセンブラも初めて触る私です。Nの電子講座・AVRマイコン編やAVRマイコンで学ぶ コンピュータの仕組みのサイトに詳しく記述されていましたので勉強させていただきました。ありがとうございました。今回は特に小山さんが書かれた「AVRマイコンで学ぶ コンピュータの仕組み」から、ソフトウエアタイマー “blink.asm”の項を参考にプログラムを組ませていただきました。本当にお世話になりました。
フローを考えると次のようになります
スタート–>初期設定–>①–>1を出力する–>62μS待つ–>0を出力する–>938μS待つ–>①へジャンプ
前述のBlink.asmを参考にコードを書いていきます。特に変える必要もなさそうなので、出力ポートも同じPB3にさせていただきました。
GeigerClock.asm .include "m168Pdef.inc" .cseg LDI R16,0b00001000 OUT DDRB,R16 ;PB3は出力,他は入力 LDI R16,HIGH(RAMEND) ;RAM最終アドレス上位を取得 OUT SPH,R16 ;スタック ポインタ上位を初期化 LDI R16,LOW(RAMEND) ;RAM最終アドレス下位を取得 OUT SPL,R16 ;スタック ポインタ下位を初期化 LOOP: LDI R16,0b00001000 OUT PORTB,R16 ;PB3は1, 他は0 RCALL T62us ;62μ秒待つ LDI R16,0b00000000 OUT PORTB,R16 ;PB3は0, 他も0 RCALL T938uS ;938μ秒待つ RJMP LOOP ;LOOPの箇所にジャンプ
62μSと938μS待機するサブルーチンを作成します。ATMEGA168Pを8MHzのクロックで動作させて1クロックサイクル=0.125μSで計算します。62μSは50μs+12μSで、938μSは50μSを18回繰り返し、さらに+38μSとすれば大体良さそうです。コメントに書いてある数値、計算は参考にさせて頂いた「AVRマイコンで学ぶ コンピュータの仕組み」サイト中に丁寧な説明があります。
; timer subroutine T50US: ;((3)+1+5*78-1+4)*0.125=397*0.125=49.625μ秒 LDI R20,78 ;1 以下を78回繰り返す _TUS: NOP ;1 NOP ;1 DEC R20 ;1 R20から1を減じ BRNE _TUS ;1/2 結果が0でなければ_TUSへ RET ;4 T62us: ;((3)+397+1+8*12-1+4)*0.125=500*0.125=62.5μ秒 RCALL T50US ;397 LDI R21,12 ;1 以下を12回繰り返す _T12US: NOP ;1 NOP ;1 NOP ;1 NOP ;1 NOP ;1 DEC R21 ;1 R21から1を減じ BRNE _T12US ;1/2 結果が0でなければ_T12USへ RET ;4 T938us: ;((3)+1+400*18-1+1+8*38-1+4)*0.125=7510*0.125=938.875μ秒 LDI R21,18 ;1 以下を18回繰り返す _T900US: RCALL T50US ;397 DEC R21 ;1 BRNE _T900US ;1/2 結果が0でなければ_T900USへ LDI R21,38 ;1 以下を38回繰り返す _T38US: NOP ;1 NOP ;1 NOP ;1 NOP ;1 NOP ;1 DEC R21 ;1 R21から1を減じ BRNE _T38US ;1/2 結果が0でなければ_T38USへ RET ;4
うまく動くでしょうか????