外部割込みによるパルス周期測定プログラムを実験をしました。マイコン回路は「パルス周期の測定(その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」という命令を見つけました。面白そうだけど使い方がわかりません。