サブルーチン内で変数を使用するプログラムを試してみました。プログラムの動作は「サブルーチン(その1)」と同じです。
| 時間 | LED7 | LED6 | LED5 | LED4 | LED3 | LED2 | LED1 | LED0 |
| 0 | ||||||||
| 1 | ||||||||
| 2 | ||||||||
| 3 | ||||||||
| 4 | ||||||||
| 5 | ||||||||
| 6 | ||||||||
| 7 | ||||||||
| 8 | ||||||||
| 9 | ||||||||
| 10 | ||||||||
| 11 | ||||||||
| 12 | ||||||||
| 13 | ||||||||
| 14 | ||||||||
| 15 |
サブルーチンで変数を使う前に、「(その1)」に出てきた「sub1b.bas」のメインプログラム部分を変数を使って書いてみます。ループを回すためのパラメーターは「2」の指数を用いました。「LEDの点灯・消灯(その5)」の「on_off5c.bas」と同じやり方です。LEDの点灯個数を1個ずつ増やす動作をメインプログラム内で、一方、0.5秒間のポーズとLEDの消灯をサブルーチン内でやっています。
プログラムファイル sub2a.bas
| 1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
| 2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
| 3 | Config Porta = Output | ポートAを出力に設定する。 | |
| 4 | Dim N1 As Byte | バイト型変数「N1」を用いる。 | |
| 5 | Dim N2 As Byte | バイト型変数「N2」を用いる。 | |
| 6 | Declare Sub Routine | サブルーチン「Routine」を使用する。 | |
| 7 | For N1 = 1 to 8 | Forループの範囲ここから。 | |
| 変数N1に1から8を順に代入する。 | |||
| 8 | N2 = 2 ^ N1 | 2のN1乗をN2とする。 | |
| 9 | Porta = N2 - 1 | ポートAの出力を「N2−1」にする。 | |
| 10 | Call Routine | サブルーチン「Routine」を呼び出す。 | |
| 11 | Next N1 | Forループの範囲ここまで。 | |
| 7行目へ戻り、N1に1を加えて繰り返し。 | |||
| 12 | Porta = 0 | ポートAを「0」にする。すべてのLEDが消灯する。 | |
| 13 | End | メインプログラム終わり。 | |
| 14 | Sub Routine | 「Routine」という名前のサブルーチンここから。 | |
| 15 | Waitms 500 | 0.5秒間そのまま。 | |
| 16 | Porta = 0 | ポートAの出力を「0」にする。すべてのLEDが消灯。 | |
| 17 | Waitms 500 | 0.5秒間そのまま。 | |
| 18 | End Sub | サブルーチン終わり。呼ばれた場所へ戻る。 |
上記とは逆に、LEDの点灯個数を増やすプログラムをサブルーチンに入れ、Wait命令と消灯命令をメインプログラムに入れてみます。サブルーチン内で変数を使うときは、サブルーチンのラベルのあとに、サブルーチン内で用いる変数の名前と型を記述する必要があります。
プログラムファイル sub2b.bas
| 1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
| 2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
| 3 | Config Porta = Output | ポートAを出力に設定する。 | |
| 4 | Dim N1 As Byte | バイト型変数「N1」を用いる。 | |
| 5 | Dim N2 As Byte | バイト型変数「N2」を用いる。 | |
| 6 | Declare Sub Routine (n1 As Byte, N2 As Byte) | サブルーチン「Routine」を用いる。 | |
| サブルーチン内で変数「N1」と「N2」を用いる。 | |||
| 7 | For N1 = 1 to 8 | Forループの範囲ここから。 | |
| 変数N1に1から8を順に代入する。 | |||
| 8 | Call Routine (n1, N2) | サブルーチン「Routine」を呼び出す。 | |
| 9 | Waitms 500 | 0.5秒間そのまま。 | |
| 10 | Porta = 0 | ポートAの出力を「0」にする。すべてのLEDが消灯。 | |
| 11 | Waitms 500 | 0.5秒間そのまま。 | |
| 12 | Next N1 | Forループの範囲ここまで。 | |
| 7行目へ戻り、N1に1を加えて繰り返し。 | |||
| 13 | Porta = 0 | ポートAを「0」にする。すべてのLEDが消灯する。 | |
| 14 | End | メインプログラム終わり。 | |
| 15 | Sub Routine (n1 As Byte, N2 As Byte) | 「Routine」という名前のサブルーチンここから。 | |
| サブルーチン内で変数「N1」と「N2」を用いる。 | |||
| 16 | N2 = 2 ^ N1 | 2のN1乗をN2とする。 | |
| 17 | Porta = N2 - 1 | ポートAの出力を「N2−1」にする。 | |
| 18 | End Sub | サブルーチン終わり。呼ばれた場所へ戻る。 |
6行目と15行目は、サブルーチン名のあとに使用する変数名と型を記述します。「n1」は「N1」と同じです。BASCOM-AVRの仕様でこのように変換されます。6行目はスペースの関係で2行に分けて書きましたが、実際は改行せずに1行で書いてください。8行目「Call Routine」のところは変数の名前だけでかまわないようです。
前にも書きましたが、この程度のプログラムでこんなややこしいことをする必要はまったくありません。あくまでサブルーチンの書き方の練習のためにやっています。
2つの変数のうちN2はサブルーチンの中でしか使われません。こういう場合はN2をサブルーチン内で定義することができます。「Local N2 As Byte」と書きます。
プログラムファイル sub2c.bas
| 1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
| 2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
| 3 | Config Porta = Output | ポートAを出力に設定する。 | |
| 4 | Dim N1 As Byte | バイト型変数「N1」を定義する。 | |
| 5 | Declare Sub Routine (n1 As Byte) | サブルーチン「Routine」を使用する。 | |
| 6 | For N1 = 1 to 8 | Forループの範囲ここから。 | |
| 変数N1に1から8を順に代入する。 | |||
| 7 | Call Routine (n1) | サブルーチン「Routine」を呼び出す。 | |
| 8 | Waitms 500 | 0.5秒間そのまま。 | |
| 9 | Porta = 0 | ポートAの出力を「0」にする。すべてのLEDが消灯。 | |
| 10 | Waitms 500 | 0.5秒間そのまま。 | |
| 11 | Next N1 | Forループの範囲ここまで。 | |
| 6行目へ戻り、N1に1を加えて繰り返し。 | |||
| 12 | Porta = 0 | ポートAを「0」にする。すべてのLEDが消灯する。 | |
| 13 | End | メインプログラム終わり。 | |
| 14 | Sub Routine (n1 As Byte) | 「Routine」という名前のサブルーチンここから。 | |
| 15 | Local N2 As Byte | サブルーチン内で用いる変数「N2」を定義する。 | |
| 16 | N2 = 2 ^ N1 | 2のN1乗をN2とする。 | |
| 17 | Porta = N2 - 1 | ポートAの出力を「N2−1」にする。 | |
| 18 | End Sub | サブルーチン終わり。呼ばれた場所へ戻る。 |
4行目では変数N1のみ定義しています。5, 7, 14行目もN1(n1)だけを書きます。変数N2はサブルーチン内で定義します(15行目)。