(2002/8/9)
【入出力ピン制御の考え方】
CCS C Compiler での入出力ピンの制御方法は、いわゆる変数レジスタと
して扱う方法と、ピン単位で直接制御する方法の2通りがあります。
さらに各ピンの入出力モードの設定についても、通常は入出力関数の実行
の都度コンパイラが自動的に設定命令を追加しますが、下記プリプロセッサ
を使うことで、追加を無くしたり、あらかじめ固定しておくことも出来ます。
《入出力ピン制御用プリプロセッサ関数一覧》
プリプロセッサ関数
機能・その他
#USE STANDARD_IO(port) portの入出力命令の時はその都度入出力モード設定用アセンブラ命令を追加する。 #USE FAST_IO(port) portの入出力命令に入出力モード設定用の命令を追加せず、直前のモード設定に従う。 #USE FIXED_IO
(port_OUTPUTS=pin,pin....)指定した入出力ピンのモードを固定とし、入出力命令にはモード制御を付加しない。
【例題の対象回路】
本ページで例題として説明するプログラムは、下記の回路図による
PIC16F84を使った、最もシンプルなものです。
PICのRB0の入出力ピンに発光ダイオードが接続してあり、ピンがLow
になると点灯するようになっています。
実際の試作品は写真に示した
ように、汎用の穴明き基板で
組み立てました。
【変数レジスタとして制御する方法】
まず、入出力ピンを変数レジスタと見なして制御する方法での
プログラミング例です。
たった10行程度の非常に短いプログラムですが、これで0.5秒間隔
で発光ダイオードを点灯/消灯を繰り返す機能を実現しています。
《プログラム例》 漢字を含むのでこのままでは使えません
////////////////////////////////////////////
// This is an example of led control.
// Led controled by pararell output.
// The interval is about 0.5sec.
////////////////////////////////////////////
#device PIC16F84
#use delay(clock=10000000)
#byte port_b=6
main() {
set_tris_b(0); //set all output
while(1){ //endless
port_b=0; //all led on
delay_ms(500); //wait 0.5sec
port_b=0xff; //all led off
delay_ms(500);
}
}
/////////////////////////////////////////////
《解説》
#DEVICE CHIP
PICの種別を指定しています。これによりコンパイラに以下の
関数をどう扱えば良いかを教えていることになります。
同時にメモリ構造も決まることになります。
#USE DELAY(CLOCK=speed)
PICの動作速度を指定しています。speedにはクロックをHz単位で
入れます。この速度を決めると、連動してDELAY_MSとDELAY_MS
の各関数の時間が決定されます。
#BYTE ID=X
1バイトの変数領域をレジスタファイル内のX番地に指定します。
上記例ではPORT Bは6番地と決まっているので対応づけて指定し
ています。
main()
必ず一つだけ必須の関数で。実行はここから開始されます。
SET_TRIS_B(value)
Bレジスタの各ピンの動作モードを設定します。valueには00から
oxffを指定します。
while(expr) stmt;
exprが真の間stmtを実行します。
PICの場合には、do stmt while(expr) の構文の方が効率の良い
関数となるようです。
port_b=0 port_b=0xff
変数レジスタport_bに0を書き込みます。これによりポートBの
出力モードとなっている入出力ピンは全てLow(High)となります。
DELAY_MS(time)
msec単位の待ち時間を指定します。timeは定数の時は0-65535
の値を指定できますが、変数にする時は0-255の範囲しか使えま
せん。
【ビット制御関数による制御方法】
変数として扱うのには特別な関数は必要ありませんでしたが、ビット制御を
行うには専用の関数が用意されています。これには下表のような種類が
あります。
ビット制御関数の方が一般的に効率の良いプログラムを生成するようです。
また、ビット制御関数の時には、ピンのモード設定もそのピンだけについて
その都度直前に設定されます。
但し、 #USE FAST_IO(port) 関数で指定されたポートの時はモード設定
が省略されます。
Ver3以降で下記表の2つが追加されました。
これにより、変数レジスタとして扱わなくても、直接8ビット同時に並列での
入出力が可能となりました。
《入出力ピン制御関数一覧》
関数形式
機 能 ・ その他
OUTPUT_BIT(pin,value) 指定されたピンに0か1の値を出力する。
ピンのモードは#USE*_IOで設定しておく。OUTPUT_FLOAT(pin) 指定されたピンを入力モードにする。
またはハイインピーダンスにする。OUTPUT_HIGH(pin) 指定されたピンに1を出力する。 OUTPUT_LOW(pin) 指定されたピンに0を出力する。 PORT_B_PULLUPS(flag) ポートBのプルアップを制御します。
flag=TRUEの時on、FALSEの時off。b=INPUT(pin) 指定したピンの状態を変数bに入力する。
bはSHORT INT型。モードは事前設定するSET_TRIS_X(value) Xポートの入出力モードを設定する。
valueは0が出力、1が入力で8ビットまとめての設定となる。 X=A,B,C,D,Eのどれかoutput_a()
output_b()
output_c()
output_d()
output_e()output_x(value)
valueは8ビットのint
output_b(0xF0);
指定ポートに指定データを出力する
8ビットの同時出力が可能input_a()
input_b()
input_c()
input_d()
input_e()value = input_x()
valueはint型
data = input_b();
指定ポートから8ビットを同時に読み込み
int型で返す
下記も同じ様に前記回路で発光ダイオードを0.5秒間隔で点灯/消灯を
繰り返すプログラム例です、わずか10行しかありません。
《プログラム例》 漢字を含むのでこのままでは使えません
//////////////////////////////////////////
// This is an ezample of led control.
// Led is controled by bit output.
// The interval time is about 0.5sec.
// Include the standard header file.
/////////////////////////////////////////
#include <16f84.h>
#use delay(clock=10000000)
main() {
while(1){ //endless loop
output_low(PIN_B0); //led on
delay_ms(500);
output_high(PIN_B0); //led off
delay_ms(500);
}
}
///////////////////////////////////////////
《解説》
#INCLUDE <FILENAME>
#INCLUDE "FILENAME"
コンパイルの時指定したファイルを接続して実行する。<>の時は
systemディレクトリを探し、" "の時はカレントディレクトリを探します。
この標準のインクルードファイルはあらかじめコンパイラをインストール
した時に用意されており、指定するだけで標準的なラベルを使うこと
が可能になります。(上例では、PIN_B0 など)
#OUTPUT_LOW(pin)
指定したピン(ここではPIN_B0でポートBの0ビット目ということになる)
に0を出力します。
PIN_B0というラベルはインクルードファイルの16f84.hというファイル内
で定義されています。
入出力ピンから実際にデータを入力する方法にも、上記出力と
同じ様に。変数レジスタとして8ビット同時に入力する方法と、
ピン制御関数でピン毎に行う方法との2種類の方法があります。
【変数レジスタとして入力する方法】
テスト用に使用した回路は上記と全く同じです。ここではスイッチ
の状態を入力し、それと同じデータを発光ダイオードに出力する
という機能を実現しています。
《プログラム例》 漢字を含むのでこのままでは使えません
////////////////////////////////////////////
// This is an example of input output test.
// First input portA, next control led
// by pararell output.
////////////////////////////////////////////
#device PIC16F84
#byte port_a=5
#byte port_b=6
main() {
set_tris_a(0xff); //set all input
set_tris_b(0); //set all output
while(1){ //endless
port_b=port_a;
}
}
/////////////////////////////////////////////
《解説》
#byte
ポートA,B両方ともレジスタへの割付をしています。
set_tris_a set_tris_b
各々入力と出力にモードを指定します。
port_b=port_a
それぞれ変数として扱うことができますから、代入すれば
良いことになります。
【ビット制御関数により入力する方法】
これも出力例と同様、ビット制御の関数を使って実現した例です。
この例では、毎回の入出力関数の度に追加される入出力モード
設定命令が追加されないように、#USE FAST_IO 関数を使用して
います。
《プログラム例》 漢字を含むのでこのままでは使えません
////////////////////////////////////////////
// This is an example of input output test.
// First input portA, next control led
// by bit oriented output.
////////////////////////////////////////////
#include <16f84.h>
main() {
set_tris_a(0xff);
set_tris_b(0);
#use fast_io(a)
#use fast_io(b)
while(1){ //endless
output_bit(PIN_B0,input(PIN_A0));
}
}
/////////////////////////////////////////////
《解説》
#use fast_io
これ以降で使われる入出力関数には、モード設定用のアセン
ブラ命令が自動追加されないようになります。
output_bit(pin,value)
この関数のvalueには0か1が使われますが、そこにinputで
読み込んだデータを利用します。