ブレッドボードラジオAVRマイコン入門

BASCOM-AVR パルス周期の測定(その2)

 外部割込みによるパルス周期測定プログラムを実験をしました。マイコン回路は「パルス周期の測定(その1)」と同じですが、IC2の入力端子が違うので、一部接続を変更する必要があります。

1. 外部割込みを使った周期の測定

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

 図1

 プログラムファイル 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」ここまで。

2. パルス幅の測定

 外部割込みは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に表示します。

 図2

 プログラムファイル 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カウントの時間が長いので、これでも大丈夫です。

3. デューティ比を表示する

 上記の「T1」の時間を周期で割り算して、デューティ比も表示できるようにしました。最初、デューティ比の計算にシングル型の変数を使ったらICのメモリー容量をオーバーしてしまったので、「T1」値を100倍し、すべて整数どうしの計算にしています。LCD画面では「T1」は「H」、「T0」は「L」で表わしてみましたが、それでもちょっと窮屈ですね。なお、32行目「Chr(&H25)」は「%」の文字コードです。

 図3

 プログラムファイル 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」という命令を見つけました。面白そうだけど使い方がわかりません。