外部割込みによるパルス周期測定プログラムを実験をしました。マイコン回路は「パルス周期の測定(その1)」と同じですが、IC2の入力端子が違うので、一部接続を変更する必要があります。
下の図のように、IC1の出力(周期1000mSの信号)をIC2のINT0入力(6番ピン)に入力します。IC2では外部割込みINT0によって入力パルスの立上りを検出してTimer1をスタートさせます。入力信号の次の立上りで再びINT0割込みが起こると、この時点のカウント数をLCD画面に表示し、Timer1のカウントをクリアします。プログラム的にはCapture1割込みとほとんど同じです。IC1に書き込む入力信号用のプログラムは「1000ms.bas」です。

プログラムファイル pwidth2a.bas
| 1 | $regfile = "attiny2313.dat" | ATtiny2313を使用する。 | |
| 2 | $crystal = 1024000 | クロック周波数を1.024MHzに設定。 | |
| 3 | |||
| 4 | Config Lcdpin=Pin, Db7=Portb.0, Db6=Portb.1 | LCDの接続設定。DB7=PB0, DB6=PB1。 | |
| 5 | Config Lcdpin=Pin, Db5=Portb.2, Db4=Portb.3 | LCDの接続設定。DB5=PB2, DB4=PB3。 | |
| 6 | Config Lcdpin=Pin, E=Portb.4, Rs=Portb.5 | LCDの接続設定。E=PB4, RST=PB5。 | |
| 7 | Config Lcd = 16 * 2 | 16文字×2行表示のLCDを使用する。 | |
| 8 | Cls : Cursor Off | LCDの表示を消去。カーソルを消去。 | |
| 9 | |||
| 10 | Config Timer1 = Timer, Prescale = 1024 | Timer1はタイマー。分周比1024。 | |
| 11 | Config Int0 = Rising | 立上りエッジでINT0割込み発生。 | |
| 12 | Dim T As Word | ワード型変数「T」を使用する。 | |
| 13 | On Int0 Int0_int | INT0割込みが発生したら「Int0_int」へ。 | |
| 14 | Enable Interrupts | 割込み全般を許可する。 | |
| 15 | Enable Int0 | INT0割込みを許可する。 | |
| 16 | |||
| 17 | Do | Doループの範囲ここから。 | |
| 18 | Cls | LCDの表示を消去する。 | |
| 19 | Lcd "T " ; T ; "mS" | LCDに変数「T」の値を表示する。 | |
| 20 | Wait 1 | 1秒間そのまま。 | |
| 21 | Loop | Doループの範囲ここまで。 | |
| 22 | |||
| 23 | End | メインプログラム終わり。 | |
| 24 | |||
| 25 | Int0_int: | 割込みプログラム「Int0_int」ここから。 | |
| 26 | T = Timer1 | Timer1のカウント数を「T」とする。 | |
| 27 | Timer1 = 0 | Timer1のカウントを「0」にする。 | |
| 28 | Return | 割込みプログラム「Int0_int」ここまで。 |
外部割込みはINT0とINT1の2つが使えるので、デューティ比が50%でない信号の「1」の時間と「0」の時間をそれぞれ測定できるプログラムを作りました。
その前にテスト用の入力信号を作らなければなりません。下記のプログラムは「1」の時間が600mS、「0」の時間が400mS、すなわち周期が1000mSでデューティ比が60%の信号を出力するプログラムです。これをIC1・ATtiny26Lに書き込みます。
プログラムファイル duty60.bas
| 1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
| 2 | $crystal = 1024000 | クロック周波数を1.024MHzに設定。 | |
| 3 | |||
| 4 | Config Porta = Output | ポートAを出力に設定する。 | |
| 5 | |||
| 6 | Do | Doループの範囲ここから。 | |
| 7 | Porta.0 = 1 | PA0出力を「1」にする。 | |
| 8 | Waitms 597 | 597mSそのまま。 | |
| 9 | Waitus 60 | 60μSそのまま。 | |
| 10 | Porta.0 = 0 | PA0出力を「0」にする。 | |
| 11 | Waitms 398 | 398mSそのまま。 | |
| 12 | Waitus 32 | 32μSそのまま。 | |
| 13 | Loop | Doループの範囲ここまで。 | |
| 14 | |||
| 15 | End | 終わり。 |
IC1へのプログラム書込みが終わったら、IC2にパルス幅測定用のプログラムを書き込むため、ライターをつなぎ換えておきます。IC1の出力は、下の図のようにIC2のINT0(6番ピン)とINT1(7番ピン)の両方につなぎます。IC2では、入力信号の立上りでINT0割込み、立下りでINT1割込みを発生させます。それぞれの割込みが起きる間の時間をTimer1で計測してLCDに表示します。

プログラムファイル pwidth2b.bas
| 1 | $regfile = "attiny2313.dat" | ATtiny2313を使用する。 | |
| 2 | $crystal = 1024000 | クロック周波数を1.024MHzに設定。 | |
| 3 | |||
| 4 | Config Lcdpin=Pin, Db7=Portb.0, Db6=Portb.1 | LCDの接続設定。DB7=PB0, DB6=PB1。 | |
| 5 | Config Lcdpin=Pin, Db5=Portb.2, Db4=Portb.3 | LCDの接続設定。DB5=PB2, DB4=PB3。 | |
| 6 | Config Lcdpin=Pin, E=Portb.4, Rs=Portb.5 | LCDの接続設定。E=PB4, RST=PB5。 | |
| 7 | Config Lcd = 16 * 2 | 16文字×2行表示のLCDを使用する。 | |
| 8 | Cls : Cursor Off | LCDの表示を消去。カーソルを消去。 | |
| 9 | |||
| 10 | Config Timer1 = Timer, Prescale = 1024 | Timer1はタイマー。分周比1024。 | |
| 11 | Config Int0 = Rising | 立上りエッジでINT0割込み発生。 | |
| 11 | Config Int1 = Falling | 立下りエッジでINT1割込み発生。 | |
| 13 | Dim T0 As Word | ワード型変数「T0」を使用する。 | |
| 14 | Dim T1 As Word | ワード型変数「T1」を使用する。 | |
| 15 | |||
| 16 | On Int0 Int0_int | INT0割込みが発生したら「Int0_int」へ。 | |
| 17 | On Int1 Int1_int | INT1割込みが発生したら「Int1_int」へ。 | |
| 18 | Enable Interrupts | 割込み全般を許可する。 | |
| 19 | Enable Int0 | INT0割込みを許可する。 | |
| 20 | Enable Int1 | INT1割込みを許可する。 | |
| 21 | |||
| 22 | Do | Doループの範囲ここから。 | |
| 23 | Cls | LCDの表示を消去する。 | |
| 24 | Lcd "T1 " ; T1 ; "mS" | LCDに変数「T1」の値を表示する。 | |
| 25 | Lowerline | LCDの下の行に、 | |
| 26 | Lcd "T0 " ; T0 ; "mS" | 変数「T0」の値を表示する。 | |
| 27 | Wait 1 | 1秒間そのまま。 | |
| 28 | Loop | Doループの範囲ここまで。 | |
| 29 | |||
| 30 | End | メインプログラム終わり。 | |
| 31 | |||
| 32 | Int0_int: | 割込みプログラム「Int0_int」ここから。 | |
| 33 | T0 = Timer1 | Timer1のカウント数を「T0」とする。 | |
| 34 | Timer1 = 0 | Timer1のカウントを「0」にする。 | |
| 35 | Return | 割込みプログラム「Int0_int」ここまで。 | |
| 36 | |||
| 37 | Int1_int: | 割込みプログラム「Int1_int」ここから。 | |
| 38 | T1 = Timer1 | Timer1のカウント数を「T1」とする。 | |
| 39 | Timer1 = 0 | Timer1のカウントを「0」にする。 | |
| 40 | Return | 割込みプログラム「Int1_int」ここまで。 |
入力信号のレベルが「1」になっている時間が「T1」、「0」になっている時間が「T0」です。入力信号の立上りでINT0割込みが発生し、Timer1がスタートします。600mS後に信号は「0」レベルになり、ここでINT1割込みが起きます。この時点でのTimer1のカウントが変数「T1」の値になります。ここでTimer1をクリアして再び0からカウントを始めます。入力信号の次の立上りでまたINT0割込みが起きます。ここまでのカウントが変数「T0」の値になります。上記のプログラムではTimer1のスタート・ストップのタイミングには無頓着ですが、プログラムの1サイクルの時間と比較してTimer1の1カウントの時間が長いので、これでも大丈夫です。
上記の「T1」の時間を周期で割り算して、デューティ比も表示できるようにしました。最初、デューティ比の計算にシングル型の変数を使ったらICのメモリー容量をオーバーしてしまったので、「T1」値を100倍し、すべて整数どうしの計算にしています。LCD画面では「T1」は「H」、「T0」は「L」で表わしてみましたが、それでもちょっと窮屈ですね。なお、32行目「Chr(&H25)」は「%」の文字コードです。

プログラムファイル pwidth2c.bas
| 1 | $regfile = "attiny2313.dat" | ATtiny2313を使用する。 | |
| 2 | $crystal = 1024000 | クロック周波数を1.024MHzに設定。 | |
| 3 | |||
| 4 | Config Lcdpin=Pin, Db7=Portb.0, Db6=Portb.1 | LCDの接続設定。DB7=PB0, DB6=PB1。 | |
| 5 | Config Lcdpin=Pin, Db5=Portb.2, Db4=Portb.3 | LCDの接続設定。DB5=PB2, DB4=PB3。 | |
| 6 | Config Lcdpin=Pin, E=Portb.4, Rs=Portb.5 | LCDの接続設定。E=PB4, RST=PB5。 | |
| 7 | Config Lcd = 16 * 2 | 16文字×2行表示のLCDを使用する。 | |
| 8 | Cls : Cursor Off | LCDの表示を消去。カーソルを消去。 | |
| 9 | |||
| 10 | Config Timer1 = Timer, Prescale = 1024 | Timer1はタイマー。分周比1024。 | |
| 11 | Config Int0 = Rising | 立上りエッジでINT0割込み発生。 | |
| 11 | Config Int1 = Falling | 立下りエッジでINT1割込み発生。 | |
| 13 | Dim T0 As Word | ワード型変数「T0」を使用する。 | |
| 14 | Dim T1 As Word | ワード型変数「T1」を使用する。 | |
| 15 | Dim D As Word | ワード型変数「D」を使用する。 | |
| 16 | Dim T100 As Long | ロング型変数「T100」を使用する。 | |
| 17 | |||
| 18 | On Int0 Int0_int | INT0割込みが発生したら「Int0_int」へ。 | |
| 19 | On Int1 Int1_int | INT1割込みが発生したら「Int1_int」へ。 | |
| 20 | Enable Interrupts | 割込み全般を許可する。 | |
| 21 | Enable Int0 | INT0割込みを許可する。 | |
| 22 | Enable Int1 | INT1割込みを許可する。 | |
| 24 | Do | Doループの範囲ここから。 | |
| 25 | T100 = T1 * 100 | 「T1×100」を変数「T100」とする。 | |
| 26 | D = T1 + T0 | 「T1+T0」を変数「D」とする。 | |
| 27 | D = T100 ⁄ D | 「T100÷D」を新たな「D」とする。 | |
| 28 | Cls | LCDの表示を消去する。 | |
| 29 | Lcd "H " ; T1 ; "mS" | LCDに変数「T1」の値を表示する。 | |
| 30 | Lcd "L " ; T0 ; "mS" | LCDに変数「T0」の値を表示する。 | |
| 31 | Lowerline | LCDの下の行に、 | |
| 32 | Lcd "DUTY " ; D ; Chr(&H25) | 変数「D」の値を表示する。 | |
| 33 | Wait 1 | 1秒間そのまま。 | |
| 34 | Loop | Doループの範囲ここまで。 | |
| 35 | |||
| 36 | End | メインプログラム終わり。 | |
| 37 | |||
| 38 | Int0_int: | 割込みプログラム「Int0_int」ここから。 | |
| 39 | T0 = Timer1 | Timer1のカウント数を「T0」とする。 | |
| 40 | Timer1 = 0 | Timer1のカウントを「0」にする。 | |
| 41 | Return | 割込みプログラム「Int0_int」ここまで。 | |
| 42 | |||
| 43 | Int1_int: | 割込みプログラム「Int1_int」ここから。 | |
| 44 | T1 = Timer1 | Timer1のカウント数を「T1」とする。 | |
| 45 | Timer1 = 0 | Timer1のカウントを「0」にする。 | |
| 46 | Return | 割込みプログラム「Int1_int」ここまで。 |
ところで、BASCOM-AVRのマニュアルで「Pulsein」という命令を見つけました。面白そうだけど使い方がわかりません。