2019年09月03日 | 公開。 |
この章では、FASTIOライブラリを使うスケッチの作り方について説明します。
FASTIOライブラリを使うスケッチは、冒頭部分で必ずfastio.hというヘッダファイルをインクルードする必要があります。つまり、スケッチの先頭行に、リスト9に示すインクルード指令を書く必要があります。
#include <fastio.h>
注:リスト9のインクルード指令の前に、コメント行や別のインクルード指令を記述する事は許されます。この場合、リスト9のインクルード指令は先頭行にはなりません。
この節では、GPIO(Arduino本体のI/Oピン)をFASTIOライブラリで制御する方法について説明します。
GPIOを制御する方法には、I/Oピンをピン番号で指定する方法と、I/Oピンに名前(名称)を付ける方法の、2通りの方法があります。それぞれについて、順に説明します。
I/Oピンをピン番号で指定する方法には、FASTIOライブラリを使わずにGPIOを制御する方法に、記述方法が近いという特徴があります。そのため、FASTIOライブラリを使わずに作ったスケッチをFASTIOライブラリを使って高速化するのに向いています。
FASTIOライブラリを使わないスケッチでは、出力ピン(pinMode関数で出力モードにしたI/Oピン)に電圧を出力するには、digitalWrite関数を次の書式で呼び出します。
ピン番号には、I/Oピンを番号で指定します。
電圧値には、出力する電圧を指定します。電圧値に0を指定するとLを出力し、1を指定するとHを出力します。
参考:電圧値の指定のために、LOWという定数が0と定義されており、HIGHという定数が1と定義されていますので、電圧値にはしばしば、0や1の代わりにLOWやHIGHを指定します。
FASTIOライブラリを使うスケッチでは、やはりdigitalWrite関数を使ってI/Oピンに電圧を出力しますが、書式が次の様に変わります。
FASTIOライブラリを使わない場合は、ピン番号と電圧値の両方を1つの丸括弧でくくり、かつピン番号と電圧値の間にカンマ(,)を入れるのに対し、FASTIOライブラリを使う場合は、ピン番号を山括弧でくくり、電圧値を丸括弧でくくります。
例えば
digitalWrite(5,LOW);
は、
digitalWrite<5>(LOW);
に書き換えます。
FASTIOライブラリを使う場合は、2ページで説明した様に、digitalWrite関数の実行速度が向上する代わりに、ピン番号に変数(を含む式)が使えなくなるという制限があります。ピン番号は定数式(定数のみからなる式でコンパイル時に評価される物)である必要があります。
ただし、通常のスケッチでは、ピン番号は定数式にするため、この制限は問題にならない事がほとんどだと思われます。
FASTIOライブラリでは、digitalWrite関数以外でも、引数を山括弧でくくる場合がありますが、山括弧でくくった引数は必ず定数式である必要があります。
リスト10に、ピン番号の制限の説明のためのスケッチを示します。
#include <fastio.h> // FASTIOライブラリを使う場合はfastio.hをインクルード
#define LED 13 // LEDが付いている13番ピンのピン番号をLEDという定数にする
int pin; // ピン番号を指定するint型の変数を宣言
void setup()
{
pinMode(12,OUTPUT); // 12番ピンを出力モードに設定
pinMode(13,OUTPUT); // 13番ピンを出力モードに設定
pin=13; // 変数pinに13を代入
}
void loop()
{
digitalWrite<LED>(HIGH); // LEDは定数なのでOK
digitalWrite<LED-1>(HIGH); // LED-1は定数式なのでOK
digitalWrite<pin>(HIGH); // pinが変数なのでコンパイル時にエラーになる
digitalWrite(LED,HIGH); // fastio.hをインクルードしていても、この書式でdigitalWrite関数を呼び出すと、FASTIOライブラリを使わない。この行はエラーにならない。
digitalWrite(LED-1,HIGH); // この行もOK
digitalWrite(pin,HIGH); // pinは変数で、定数式ではないが、FASTIOライブラリを使っていないのでOK
}
注:リスト10のスケッチには、コンパイル時エラーになる行が含まれていますが、コンパイル時エラーになる1行を削除またはコメントアウトすれば、正常にコンパイルおよび実行ができます。
I/Oピンに入力された電圧を読み出す場合は、digitalRead関数を使います。
FASTIOライブラリを使わない場合には、次の書式でdigitalRead関数を呼び出します。
ピン番号に電圧を読みたいI/Oピンの番号を渡すと、digitalRead関数は、入力された電圧をLOW(0)またはHIGH(1)で返します。
FASTIOライブラリを使う場合には、次の書式でdigitalRead関数を呼び出します。
ピン番号を山括弧でくくった上で、中に何もない丸括弧を後に付けなければならない事に注意してください。
例えば
digitalRead(3)
は、
digitalRead<3>()
に書き換えます。
FASTIOライブラリを使ってdigitalRead関数を呼び出す場合には、ピン番号は定数式である必要があります。(リスト11参照)
#include <fastio.h> // FASTIOライブラリを使う場合はfastio.hをインクルード
#define IN_PIN 2 // 入力電圧を読みたいI/Oピンの番号(2)をIN_PINと定数宣言
int pin; // ピン番号を指定するint型の変数を宣言
void setup()
{
pinMode(2,INPUT); // 2番ピンを入力モードに設定
pinMode(3,INPUT); // 3番ピンを入力モードに設定
pin=2; // 変数pinに2を代入
}
void loop()
{
int val; // ピンから読み取った入力電圧を代入するための変数の宣言
val=digitalRead<IN_PIN>(); // IN_PINは定数なのでOK
val=digitalRead<IN_PIN+1>(); // IN_PIN+1は定数式なのでOK
val=digitalRead<pin>(); // pinが変数なのでコンパイル時にエラーになる
val=digitalRead(IN_PIN); // fastio.hをインクルードしていても、この書式でdigitalRead関数を呼び出すと、FASTIOライブラリを使わない。この行はエラーにならない。
val=digitalRead(IN_PIN+1); // この行もOK
val=digitalRead(pin); // pinは変数で、定数式ではないが、FASTIOライブラリを使っていないのでOK
}
注:リスト11のスケッチには、コンパイル時エラーになる行が含まれていますが、コンパイル時エラーになる1行を削除またはコメントアウトすれば、正常にコンパイルおよび実行ができます。
FASTIOライブラリを使わずに作ったスケッチをFASTIOライブラリに対応させて、高速化するには、次の2つの手順でスケッチのソースファイルを書き換えます。
スケッチの先頭にリスト9で示したインクルード指令を追加します。
ピン番号が定数式で指定されている全てのdigitalWrite関数とdigitalRead関数を、ピン番号を山括弧でくくるFASTIOライブラリに対応した書式に書き換えます。
リスト12は、FASTIOライブラリを使わずに作ったGPIOを制御するスケッチの例です。このスケッチでは、ピン番号は全て定数で指定しています。
// 2番ピンに入力された電圧をそのまま3番ピンに出力するスケッチ(FASTIOライブラリ不使用)
void setup()
{
pinMode(2,INPUT); // 2番ピンを入力モードに設定
pinMode(3,OUTPUT); // 3番ピンを出力モードに設定
}
void loop()
{
digitalWrite(3,digitalRead(2)); // 2番ピンから読んだ電圧を3番ピンに出力
}
リスト12をFASTIOライブラリに対応させると、リスト13の様になります。
// 2番ピンに入力された電圧をそのまま3番ピンに出力するスケッチ(FASTIOライブラリ使用)
#include <fastio.h> // FASTIOライブラリを使う場合はfastio.hをインクルード
void setup()
{
pinMode(2,INPUT); // 2番ピンを入力モードに設定
pinMode(3,OUTPUT); // 3番ピンを出力モードに設定
}
void loop()
{
digitalWrite<3>(digitalRead<2>()); // 2番ピンから読んだ電圧を3番ピンに出力
}
リスト13のスケッチは、リスト12のスケッチよりもloop関数が高速に実行されるので、2番ピンに入力された電圧が変化すると、より速くその変化が3番ピンに反映されます。
まれなケースですが、場合によっては、ピン番号が定数式にならないスケッチをFASTIOライブラリに対応させる必要があります。
リスト14は、ピン番号が変数を含む式で指定されている部分を含むスケッチの例です。
// このスケッチは、2番ピンに入力された電圧の論理否定(NOT)を3番ピンに出力し、4~7番ピン(4番ピンがLSBで7番ピンがMSB)
// に入力された4ビットの信号に1を足して、8~11番ピン(8番ピンがLSBで11番ピンがMSB)に出力する。
#define INPUT_BUS_LSB 4 // 入力用4ビットバスのLSBのピン番号
#define OUTPUT_BUS_LSB 8 // 出力用4ビットバスのLSBのピン番号
void setup()
{
pinMode(2,INPUT); // 2番ピンを入力モードに設定
pinMode(3,OUTPUT); // 3番ピンを出力モードに設定
// 入力用4ビットバスのピンを入力モードに設定
for(int i=INPUT_BUS_LSB; i<INPUT_BUS_LSB+4; i++) pinMode(i,INPUT); // 4~7番ピンを入力モードに設定
// 出力用4ビットバスのピンを出力モードに設定
for(int i=OUTPUT_BUS_LSB; i<OUTPUT_BUS_LSB+4; i++) pinMode(i,OUTPUT); // 8~11番ピンを出力モードに設定
}
void loop()
{
digitalWrite(3,!digitalRead(2)); // 2番ピンの電圧の論理否定を3番ピンに出力
writeBus(readBus()+1); // 入力用4ビットバスから読んだ値に1を足した値を出力用4ビットバスに出力(足し算時の繰上りは無視)
}
// 入力用4ビットバスから値を読み込む関数
int readBus()
{
int val=0; // 読み込んだ値を格納する変数の宣言
for(int i=0; i<4; i++) { // iはビット番号(0がLSBで3がMSB)
val+=digitalRead(INPUT_BUS_LSB+i)<<i; // iビット目をINPUT_BUS_LSB+i番ピンから読みこむ
}
return val;
}
// 出力用4ビットバスに引数の下位4ビットを出力する関数
void writeBus(int val)
{
for(int i=0; i<4; i++) { // iはビット番号(0がLSBで3がMSB)
digitalWrite(OUTPUT_BUS_LSB+i,((val>>i) & 1)); // 引数のiビット目をOUTPUT_BUS_LSB+i番ピンに出力
}
}
リスト14を、先に示した2つの手順に従って、FASTIOライブラリに対応させたスケッチを、リスト15に示します。
// このスケッチは、2番ピンに入力された電圧の論理否定(NOT)を3番ピンに出力し、4~7番ピン(4番ピンがLSBで7番ピンがMSB)
// に入力された4ビットの信号に1を足して、8~11番ピン(8番ピンがLSBで11番ピンがMSB)に出力する。
#include <fastio.h> // FASTIOライブラリを使う場合はfastio.hをインクルード
#define INPUT_BUS_LSB 4 // 入力用4ビットバスのLSBのピン番号
#define OUTPUT_BUS_LSB 8 // 出力用4ビットバスのLSBのピン番号
void setup()
{
pinMode(2,INPUT); // 2番ピンを入力モードに設定
pinMode(3,OUTPUT); // 3番ピンを出力モードに設定
// 入力用4ビットバスのピンを入力モードに設定
for(int i=INPUT_BUS_LSB; i<INPUT_BUS_LSB+4; i++) pinMode(i,INPUT); // 4~7番ピンを入力モードに設定
// 出力用4ビットバスのピンを出力モードに設定
for(int i=OUTPUT_BUS_LSB; i<OUTPUT_BUS_LSB+4; i++) pinMode(i,OUTPUT); // 8~11番ピンを出力モードに設定
}
void loop()
{
digitalWrite<3>(!digitalRead<2>()); // 2番ピンの電圧の論理否定を3番ピンに出力(FASTIOライブラリ使用)
writeBus(readBus()+1); // 入力用4ビットバスから読んだ値に1を足した値を出力用4ビットバスに出力(足し算時の繰上りは無視)
}
// 入力用4ビットバスから値を読み込む関数
int readBus()
{
int val=0; // 読み込んだ値を格納する変数の宣言
for(int i=0; i<4; i++) { // iはビット番号(0がLSBで3がMSB)
val+=digitalRead(INPUT_BUS_LSB+i)<<i; // iビット目をINPUT_BUS_LSB+i番ピンから読みこむ(ピン番号が定数式ではないのでFASTIOライブラリ不使用)
}
return val;
}
// 出力用4ビットバスに引数の下位4ビットを出力する関数
void writeBus(int val)
{
for(int i=0; i<4; i++) { // iはビット番号(0がLSBで3がMSB)
digitalWrite(OUTPUT_BUS_LSB+i,((val>>i) & 1)); // 引数のiビット目をOUTPUT_BUS_LSB+i番ピンに出力(ピン番号が定数式ではないのでFASTIOライブラリ不使用)
}
}
このスケッチでは、readBus関数内のdigitalRead関数の呼び出し時と、writeBus関数内のdigitalWrite関数の呼び出し時に、ピン番号が変数を含む数式で指定されているために、FASTIOライブラリを使っていません。そのため、readBus関数やwriteBus関数の高速化はできていません。
readBus関数やwriteBus関数を、FASTIOライブラリを使って高速化するには、forループを開いて、digitalWrite関数やdigitalRead関数におけるピン番号の指定を定数式にする必要があります。
readBus関数やwriteBus関数もFASTIOライブラリを使って高速化したスケッチを、リスト16に示します。
// このスケッチは、2番ピンに入力された電圧の論理否定(NOT)を3番ピンに出力し、4~7番ピン(4番ピンがLSBで7番ピンがMSB)
// に入力された4ビットの信号に1を足して、8~11番ピン(8番ピンがLSBで11番ピンがMSB)に出力する。
#include <fastio.h> // FASTIOライブラリを使う場合はfastio.hをインクルード
#define INPUT_BUS_LSB 4 // 入力用4ビットバスのLSBのピン番号
#define OUTPUT_BUS_LSB 8 // 出力用4ビットバスのLSBのピン番号
void setup()
{
pinMode(2,INPUT); // 2番ピンを入力モードに設定
pinMode(3,OUTPUT); // 3番ピンを出力モードに設定
// 入力用4ビットバスのピンを入力モードに設定
for(int i=INPUT_BUS_LSB; i<INPUT_BUS_LSB+4; i++) pinMode(i,INPUT); // 4~7番ピンを入力モードに設定
// 出力用4ビットバスのピンを出力モードに設定
for(int i=OUTPUT_BUS_LSB; i<OUTPUT_BUS_LSB+4; i++) pinMode(i,OUTPUT); // 8~11番ピンを出力モードに設定
}
void loop()
{
digitalWrite<3>(!digitalRead<2>()); // 2番ピンの電圧の論理否定を3番ピンに出力(FASTIOライブラリ使用)
writeBus(readBus()+1); // 入力用4ビットバスから読んだ値に1を足した値を出力用4ビットバスに出力(足し算時の繰上りは無視)
}
// 入力用4ビットバスから値を読み込む関数(forループを開いて高速化)
int readBus()
{
int val=0; // 読み込んだ値を格納する変数の宣言
val+=(digitalRead<INPUT_BUS_LSB+0>() << 0); // 0ビット目をINPUT_BUS_LSB+0番ピン(4番ピン)から読み込む
val+=(digitalRead<INPUT_BUS_LSB+1>() << 1); // 1ビット目をINPUT_BUS_LSB+1番ピン(5番ピン)から読み込む
val+=(digitalRead<INPUT_BUS_LSB+2>() << 2); // 2ビット目をINPUT_BUS_LSB+2番ピン(6番ピン)から読み込む
val+=(digitalRead<INPUT_BUS_LSB+3>() << 3); // 3ビット目をINPUT_BUS_LSB+3番ピン(7番ピン)から読み込む
return val;
}
// 出力用4ビットバスに引数の下位4ビットを出力する関数(forループを開いて高速化)
void writeBus(int val)
{
digitalWrite<OUTPUT_BUS_LSB+0>((val>>0) & 1); // 0ビット目をOUTPUT_BUS_LSB+0番ピン(8番ピン)に出力する
digitalWrite<OUTPUT_BUS_LSB+1>((val>>1) & 1); // 1ビット目をOUTPUT_BUS_LSB+1番ピン(9番ピン)に出力する
digitalWrite<OUTPUT_BUS_LSB+2>((val>>2) & 1); // 2ビット目をOUTPUT_BUS_LSB+2番ピン(10番ピン)に出力する
digitalWrite<OUTPUT_BUS_LSB+3>((val>>3) & 1); // 3ビット目をOUTPUT_BUS_LSB+3番ピン(11番ピン)に出力する
}
この様に、ピン番号が定数式でない場合にスケッチを高速化する場合は、ループを開くなどの工夫をして、ピン番号の指定を定数式にする必要があります。
次のページでは、I/Oピンに名前を付けて、GPIOを制御する方法について説明します。