LCD・液晶ディスプレイ使って四則の計算や数値の変換などのプログラムを少しやってみました。マイコン回路は「LCD表示テスト用回路」を使用します。
AVRマイコンで計算をして、答えを表示させるプログラムです。
プログラムファイル lcd3a.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | Config Lcdpin=Pin, Db4=Porta.4, Db5=Porta.5 | LCDのピン接続の設定。DB4=PA4, DB5=PA5。 | |
4 | Config Lcdpin=Pin, Db6=Porta.6, Db7=Porta.7 | LCDのピン接続の設定。DB6=PA6, DB7=PA7。 | |
5 | Config Lcdpin=Pin, E=Porta.3, Rs=Porta.2 | LCDのピン接続の設定。E=PA3, RST=PA2。 | |
6 | Config Lcd = 16 * 2 | 16文字×2行表示のLCDを使用する。。 | |
7 | Dim A As Byte | バイト型変数「A」を用いる。 | |
8 | Cursor Off | カーソルを表示しない。 | |
9 | Cls | LCDの表示を消去する。 | |
10 | A = 2 + 3 | 「2+3」の答えを変数「A」に代入する。 | |
11 | Lcd "2+3=" ; A | LCDに計算式と答えを表示する。 | |
12 | A = 7 - 6 | 「7−6」の答えを変数「A」に代入する。 | |
13 | Locate 1, 8 | 上の行の8文字目から、 | |
14 | Lcd "7-6=" ; A | LCDに計算式と答えを表示する。 | |
15 | A = 2 * 4 | 「2×4」の答えを変数「A」に代入する。 | |
16 | Locate 2, 1 | 下の行の1文字目から、 | |
17 | Lcd "2x4=" ; A | LCDに計算式と答えを表示する。 | |
18 | A = 9 ⁄ 3 | 「9÷3」の答えを変数「A」に代入する。 | |
19 | Locate 2, 8 | 下の行の8文字目から、 | |
20 | Lcd "9" ; Chr(&Hfd) ; "3=" ; A | LCDに計算式と答えを表示する。 | |
21 | End | 終わり。 |
10行目「A = 2 + 3」は右辺を計算してその答えを変数「A」に代入するプログラムです。11行目で計算式と答えをLCDに表示させます。「Lcd "A"」と書くと画面にはそのまま「A」と表示されますが、「Lcd A」と書くと、その時点での変数「A」の値(この場合は「5」)が画面に表示されます。
プログラム上での掛け算の記号は「 * 」(アスタリスク)、割り算の記号は「 ⁄ 」(スラッシュ)です。LCD画面での表示には、掛け算は小文字の「 x 」(エックス)を使いました。割り算の記号「÷」はLCDの文字コード表にありました。
計算の答えが整数にならない場合、どう表示されるでしょうか。「7÷4」の答え(1.75)を、バイト型変数とシングル型変数に代入してそれぞれLCD画面に表示させてみました。結果は下の図の通りです。バイト型変数は端数を切り捨てて表示するようです。
プログラムファイル lcd3b.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | Config Lcdpin=Pin, Db4=Porta.4, Db5=Porta.5 | LCDのピン接続の設定。DB4=PA4, DB5=PA5。 | |
4 | Config Lcdpin=Pin, Db6=Porta.6, Db7=Porta.7 | LCDのピン接続の設定。DB6=PA6, DB7=PA7。 | |
5 | Config Lcdpin=Pin, E=Porta.3, Rs=Porta.2 | LCDのピン接続の設定。E=PA3, RST=PA2。 | |
6 | Config Lcd = 16 * 2 | 16文字×2行表示のLCDを使用する。。 | |
7 | Dim A1 As Byte | バイト型変数「A1」を用いる。 | |
8 | Dim A2 As Single | シングル型変数「A2」を用いる。 | |
9 | Cursor Off | カーソルを表示しない。 | |
10 | Cls | LCDの表示を消去する。 | |
11 | A1 = 7 ⁄ 4 | 「7÷4」の答えを変数「A1」に代入する。 | |
12 | Lcd "Byte" | LCDに「Byte」と表示する。 | |
13 | Locate 1, 8 | 上の行の8文字目に、 | |
14 | Lcd "7" ; Chr(&Hfd) ; "4=" ; A1 | 計算式と答えを表示する。 | |
15 | Lowerline | 下の行の表示に移る。 | |
16 | A2 = 7 ⁄ 4 | 「7÷4」の答えを変数「A2」に代入する。 | |
17 | Lcd "Single" | LCDに「Single」と表示する。 | |
18 | Locate 2, 8 | 下の行の8文字目に、 | |
19 | Lcd "7" ; Chr(&Hfd) ; "4=" ; A2 | 計算式と答えを表示する。 | |
20 | End | 終わり。 |
BASCOM-AVRのマニュアルで「Round」という命令を見つけました。小数点以下を四捨五入する命令です。試しに上のプログラムの16行目の後に「A2 = Round (a2)」と書いてみたところ、「7÷4=2.0」と表示されました。
「7÷4」の答え(商)と余りを表示するプログラムです。商はバイト型変数を使って整数部分だけを表示しました。余りを求めるときは「Mod」を使います。
プログラムファイル lcd3c.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | Config Lcdpin=Pin, Db4=Porta.4, Db5=Porta.5 | LCDのピン接続の設定。DB4=PA4, DB5=PA5。 | |
4 | Config Lcdpin=Pin, Db6=Porta.6, Db7=Porta.7 | LCDのピン接続の設定。DB6=PA6, DB7=PA7。 | |
5 | Config Lcdpin=Pin, E=Porta.3, Rs=Porta.2 | LCDのピン接続の設定。E=PA3, RST=PA2。 | |
6 | Config Lcd = 16 * 2 | 16文字×2行表示のLCDを使用する。。 | |
7 | Dim A1 As Single | シングル型変数「A1」を用いる(答1)。 | |
8 | Dim A2 As Byte | バイト型変数「A2」を用いる(答2)。 | |
9 | Dim M As Byte | バイト型変数「M」を用いる(余り)。 | |
10 | Cursor Off | カーソルを表示しない。 | |
11 | Cls | LCDの表示を消去する。 | |
12 | A1 = 7 ⁄ 4 | 「7÷4」の答えを変数「A1」に代入する。 | |
13 | Lcd "7" ; Chr(&Hfd) ; "4=" | LCDに計算式を表示する。 | |
14 | Lcd A1 | LCDに変数「A1」の値を表示する。 | |
15 | A2 = 7 ⁄ 4 | 「7÷4」の答えを変数「A2」に代入する。 | |
16 | M = 7 Mod 4 | 7を4で割った余りを変数「M」に代入する。 | |
17 | Lowerline | LCDの下の行に、 | |
18 | Lcd "7" ; Chr(&Hfd) ; "4=" | 計算式を表示する。 | |
19 | Lcd A2 ; "..." ; M | 「A2」の値、「...」、「M」の値を表示する。 | |
20 | End | 終わり。 |
A2はバイト型変数なので、15行目「A2 = 7 ⁄ 4」の「A2」は「1」になります。16行目「M = 7 Mod 4」は「7÷4」の余り(この場合は「3」)を変数「M」に代入するプログラムです。
ところで、シングル型変数の整数部分あるいは小数部分だけを取り出す命令があります。「Int」および「Frac」という命令語です (こういうのは「命令」じゃなくて「関数」って言うのかな)。これらを使って上のプログラムを記述すると下記のようになります。主要部分だけ示します。このプログラムはマイコンICのメモリーの実に94%を消費してしまいます (上記のように書いた場合は57%です)。シングル型変数を2つも使ったからでしょう。表示は「7÷4=1...3.0」となります。
「ルート2」のような延々と続く少数を、キリのいいところで四捨五入して表示するプログラムです。LCDの表示用に文字変数を用います。
プログラムファイル lcd3d.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | Config Lcdpin=Pin, Db4=Porta.4, Db5=Porta.5 | LCDのピン接続の設定。DB4=PA4, DB5=PA5。 | |
4 | Config Lcdpin=Pin, Db6=Porta.6, Db7=Porta.7 | LCDのピン接続の設定。DB6=PA6, DB7=PA7。 | |
5 | Config Lcdpin=Pin, E=Porta.3, Rs=Porta.2 | LCDのピン接続の設定。E=PA3, RST=PA2。 | |
6 | Config Lcd = 16 * 2 | 16文字×2行表示のLCDを使用する。。 | |
7 | Dim A1 As Single | シングル型変数「A1」を用いる。 | |
8 | Dim A2 As String * 5 | 5文字の変数「A2」を用いる。 | |
9 | Cursor Off | カーソルを表示しない。 | |
10 | Cls | LCDの表示を消去する。 | |
11 | A1 = Sqr(2) | 「2」の平方根を変数「A1」に代入する。 | |
12 | Lcd "SQR(2)=" ; A1 | LCDに式と答えを表示する。 | |
13 | Lowerline | 下の行の表示に移る。 | |
14 | A2 = Fusing (a1, "#.###") | A1の値を「#.###」の形にしてA2に代入。 | |
15 | Lcd "SQR(2)=" ; A2 | LCDにA2の値を表示する。 | |
16 | End | 終わり。 |
8行目「Dim A2 As String * 5」は文字変数を定義するプログラムです。文字変数は「 * (数)」で文字数も定義する必要があります。シングル型の変数で普通に「ルート2」を計算すると小数点以下が長々と表示されます。14行目「A2 = Fusing (a1, "#.###")」で、変数「A1」の値を「#.###」の形、つまり小数点以下3桁までで四捨五入して表示することができます。文字変数の文字数はこのときの表示桁数に合わせます。
14行目のプログラムで得られた文字変数の値「1.414」は「文字」ですので、このまま別の計算に用いることはできません。この値で計算を続けるときは、「文字」から「数値」に変換します。BASCOM-AVRにはそのような命令(「Val」)もあります。
10進数の数を16進数や2進数に変換して表示します。表示される16進数や2進数は文字変数になります。
プログラムファイル lcd3e.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | Config Lcdpin=Pin, Db4=Porta.4, Db5=Porta.5 | LCDのピン接続の設定。DB4=PA4, DB5=PA5。 | |
4 | Config Lcdpin=Pin, Db6=Porta.6, Db7=Porta.7 | LCDのピン接続の設定。DB6=PA6, DB7=PA7。 | |
5 | Config Lcdpin=Pin, E=Porta.3, Rs=Porta.2 | LCDのピン接続の設定。E=PA3, RST=PA2。 | |
6 | Config Lcd = 16 * 2 | 16文字×2行表示のLCDを使用する。。 | |
7 | Dim N As Byte | バイト型変数「N」を用いる。 | |
8 | Dim H As String * 2 | 2文字の変数「H」を用いる(16進数の表示用)。 | |
9 | Dim B As String * 8 | 8文字の変数「B」を用いる(2進数の表示用)。 | |
10 | N = 100 | 変数「N」の値を「100」とする。 | |
11 | Cursor Off | カーソルを表示しない。 | |
12 | Cls | LCDの表示を消去する。 | |
13 | H = Hex(n) | 「N」の値を16進数に変換して「H」に代入。 | |
14 | Lcd "100=&H" ; H | 「100=&H」に続いて「H」の値を表示。 | |
15 | B = Bin(n) | 「N」の値を2進数に変換して「B」に代入。 | |
16 | Locate 2,4 | 下の行の4文字目に、 | |
17 | Lcd "=&B" ; B | 「=&B」に続いて「B」の値を表示。 | |
18 | End | 終わり。 |
10行目「N = 100」で変換する10進数を「100」にしたので、16進数では2桁、2進数では7桁になります。16進数表示用の文字変数「H」と2進数表示用の文字変数「B」の文字数は、それぞれの桁数に合わせます。といってもぴったりにする必要はなく、桁数が不足しなければ大丈夫です。
13行目「H = Hex(n)」は10進数の変数「N」の値を16進数に変換して文字変数「H」に代入するプログラムです。最初これを「H = Hex(100)」と書いたところエラーになりました。カッコ内は数値変数名でないとだめなようです。15行目「B = Bin(n)」は同様に「N」の値を2進数に変換して文字変数「B」に代入するプログラムです。
「60×4」および「60÷4」を計算するプログラムです。普通に「A = 60 * 4」「A = 60 ⁄ 4」と書いてもいいのですが、掛ける数・割る数が2の累乗の場合は「Shift」命令を使う方法があります。
プログラムファイル lcd3f.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | Config Lcdpin=Pin, Db4=Porta.4, Db5=Porta.5 | LCDのピン接続の設定。DB4=PA4, DB5=PA5。 | |
4 | Config Lcdpin=Pin, Db6=Porta.6, Db7=Porta.7 | LCDのピン接続の設定。DB6=PA6, DB7=PA7。 | |
5 | Config Lcdpin=Pin, E=Porta.3, Rs=Porta.2 | LCDのピン接続の設定。E=PA3, RST=PA2。 | |
6 | Config Lcd = 16 * 2 | 16文字×2行表示のLCDを使用する。。 | |
7 | Dim A As Byte | バイト型変数「A」を用いる。 | |
8 | Cursor Off | カーソルを表示しない。 | |
9 | Cls | LCDの表示を消去する。 | |
10 | A = 60 | 変数「A」の値を「60」(2進数で00111100)とする。 | |
11 | Shift A , Left , 2 | 変数「A」の値を2ビット分左にシフトする。 | |
12 | Lcd "60x4=" ; A | LCDに計算式と答えを表示する。 | |
13 | A = 60 | 変数「A」の値を「60」(2進数で00111100)とする。 | |
14 | Shift A , Right , 2 | 変数「A」の値を2ビット分右にシフトする。 | |
15 | Lowerline | LCDの下の行に、 | |
16 | Lcd "60" ; Chr(&Hfd) ; "4=" ; A | LCDに計算式と答えを表示する。 | |
17 | End | 終わり。 |
11行目「Shift A , Left , 2」は2進数の数字の並びを左へ2ビット(2桁)ずらす命令です。ひとつ前の行で「A = 60」としました。10進数で指定していますが、マイコンICは2進数で記憶しています。つまり「A = 00111100」です。これを左へ2ビット分シフトすると「A = 11110000」になります。これは10進数では「240」なので、LCD画面にはそのように表示されます。
今回は掛ける数が「4」、つまり「2^2」だったので、左へ2ビットシフトしました。もし掛ける数が8(=2^3)だったら左へ3ビット、16(=2^4)だったら左へ4ビットシフトさせます。要するに指数分だけ左へずらせばいいわけです。割り算の場合は考え方が逆で、4(=2^2)で割る場合は右へ2ビット、8(=2^3)で割る場合は右へ3ビットシフトさせます。
LEDの点灯プログラムのところで「Rotate」という命令が出てきました。「Rotate」の場合は、例えばバイト型変数(最大値が8ビット)で左へ1ビットシフトさせると最上位の桁の数値が最下位へ回り込みます。一方「Shift」で左へ1ビットシフトさせるとそのまま左へずれていって最下位には「0」が追加されるだけです。
今回の例「A = 00111100」を左へ3ビット「Rotate」したときと、同じく左へ3ビット「Shift」したときの違いを下に示します。
元の値 | 0011 1100 |
左へ3ビット「Rotate」する | 1110 0001 |
左へ3ビット「Shift」する | 1 1110 0000 |
「Shift」命令を使う場合、計算結果が8桁を超えるときは、変数をあらかじめ範囲の広い型(「Integer」など)で定義しておく必要があります。