プログラムの書き方 1
前回までのLEDチカチカ目標のブログでは、LEDチカチカに必要最低限のプログラムの書き方しかかきませんでした。
今回から、C言語でプログラムを書く、書き方を書きます。
上のプログラムは、コンフィギュレーションの設定と、main関数を書いたものです、ここまでは、説明しました。
しかし、本当は、説明していない所があるのです。
まず、上のプログラムの空白行(一行何も書いてない行)ですが、これは、無視されます、つまり、空白行はなく全部詰めて書いてあるのと同じです、空白行は、プログラムを書いたものが見やすいように存在するのです。
次に、int、main、(、void、)、{,},return、0、;の様な単語を、トークンと言います、プログラムは最小単位のトークンを組み合わせて作りますが、書き方の約束があります。
まず、トークンとトークンをくっ付けて書いてはいけない(意味が変わってしまう)、しかし、例外があり、記号はつなげてもよいのです。
例を挙げると、上のプログラムの int main(void) ですが、int main の間にはスペースがありますが(くっつけると意味が変わってしまう)、main(void) の記号と単語の間にスペースはありません、くっついていても意味が変わらないからです。
また、スペースには、絶対必要なもの(int main の間のスペース)と本来は要らないが見やすくするためのスペースがあります(こっちのスペースはいくつあっても無視されます)。
例を挙げると、上のプログラムの #praguma config FOSC = INTOSCIO //Osclllator ・・・ですが、praguma config FOSC の間のスペースは絶対必要なもので、FOSC = INTOSCIO //Oscllla の間のスペースは本来は要らないが見やすくするためのスペースです(FOSC=INTOSCIO//Oscllla でも意味は同じ)。
次に、praguma と Praguma は、別の単語として認識されますので(大文字と小文字を区別する)、praguma config FOSC を Praguma config FOSC と書いてしまうとエラーになります。
もう一つ非常に注意しなければならないのが、半角英数字のスペースと全角スペースです、プログラム命令自体には、半角英数字記号しか使えませんが//以降の注釈文には、全角文字(日本語文字)が使えます、しかし、全角スペースの罠にはまりやすいのです。
例を挙げると、#praguma config FOSC = INTOSCIO //Osclllator ・・・ですが、//以降は注釈行ですから、全角スペースがあっても問題はありません、ところが、#praguma config FOSC = INTOSCIO //Osclllator の INTOSCIO //Osc 間のスペースは、全角スペース1個か半角スペース2個か見た目では区別できません、半角スペース2個なら無視されますので問題は起きませんが、全角スペース1個だとエラーになります(全角スペースは命令文内、つまり//より左側には使えない)、このエラーが非常に発見しづらいのです、何せ見た目には正常な文に見えてしまうからです、対策は、すべて(注釈文も)半角英数字記号で記述するか、十分注意して注釈行に全角スペースを使うしかありません。
次に、int main(void) ですが、LEDチカチカの時は、解説が長くなるので、サラッと書きましたが、ここで、詳しく説明します。
int main(void)
{
ここに、命令文を書きます。
return 0;
}
上の int から } までを関数と言います、mainが関数名です。
関数は、他の一般のプログラムでいう、サブルーチンのようなもので、他のプログラムから呼び出され、処理をして、リターンする形をとっていますので、最後にreturn 0;命令があるわけです、PICはペリフェラルインターフェースコントローラの略で、本来メインのCPUの制御で周辺の機器をコントロールするのが仕事なのです。
しかし、私たちが趣味などで、単独でPICを使う場合は、どこからか呼び出されることはないので、void main(void) で始めて、return 0; なしでも動作します。
void main(void) や int main(void) の最初の void や int は、メイン関数を処理した結果を出力する変数の型を表しています(詳細は後記します)、(void)は、メイン関数を呼び出すときに引き渡す変数です。voidは、無しという意味です、したがって、void main(void) は、メイン関数から何も出力しないし、受け取る物もない関数です、int main(void) は、メイン関数からint型で結果を出力し、受け取る物はない関数です。
C言語プログラムでは、メイン関数が一つあり、そこの最初の命令から処理が始まり次々と命令が処理され、リターン命令で処理が終わります、関数は、メイン関数以外にも作ることができ、適当な名前を付けて作成し、メイン関数から呼び出して使います。
int main(void)
{
ここに、命令文を書きます。
sub(); //sub 関数の呼び出し、カッコ内は、sub(void)なので、何も書かない。
return 0;
}
void sub(void)
{
ここに、命令文を書きます。
出力が void の時はリターンは不要。
}
自作関数(サブの関数)は、別の機会に解説。
さて、メイン関数の内容(命令文等の)かきかたですが、PICもコンピュータですから、計算をします、計算するにあたり、計算すべきデータや計算した結果を保存しておく必要があります、保存しておく場所をレジスタといい、PICが動作するにあたり必要なデータなどを保存しておくSFR(スペシャルファンクションレジスタ、PICが特定の目的のために管理する)と汎用レジスタ(プログラマーが自由に使える)とがあります。
上の表はPIC16F627Aのデータメモリマップですが、上の方の名前のあるレジスタがSFRで、 General Purpose Register が汎用レジスタでプログラマが自由に使える部分です。
LEDチカチカでは、上の表の PORTA とか PORTB を使ってプログラムを組みましたが、SFRを操作してやれば、ピンを制御することができたわけです。
上の表を見てください、PIC16F627Aは、プログラムを書きこむ場所が1024✖14、汎用レジスタが224✖8、EEPROMが128✖8備わっています。
プログラムを書きこむ場所が1024✖14というのは、14ビット命令が1024個(機械語命令)書けますと言う事ですが、C言語で書いた命令は、1~数個の機械語命令に変換されるので、1024行書けるわけではない。
汎用レジスタが224✖8というのは、8ビットのデーターを224個保存できるということで、16ビットなら112個保存できるということ。
コンパイラが、適正にデータ管理をするので、8・16ビットのデータを混在で記憶できる。
MP LAB XC8 でプログラムを書いて、ビルドすると、上の図の Memory の項に、データメモリとプログラムメモリの使用量が、表示されます。
Data Used 5 (0x5) Free 219(0XBD) はデータレジスタを5つ使用していて、残りが219個です、()内は16進数表記。(使用率は2%)
Program Used 57 (0x39) Free 967(0xC7) はプログラムメモリを57個使用していて、残りが967個です、()内は16進数表記。(使用率は6%)
今回は、実際の命令記述までたどり着きませんでしたが、次回から、実際に命令を記述していきます。