/****************************************************************************/ /* プロジェクト名: sensortest */ /* ファイル名: sensortest.c */ /* 内容: センサーラボ実習サンプルプログラム */ /* センサから10cm以内に障害物を検知したときにCPUボード */ /* 上のLED(Port0の0)を点灯、障害物がなくなれば消灯。 */ /* 日付: 2005.1.9 */ /* コンパイラ: NC30WA (Ver.5.10 Release 1) */ /* note: OAKS16対応(OAKS16-SENSOR LABO) */ /* 作成者: Kazuhiko Araki */ /****************************************************************************/ /* インクルードファイル */ #include "sfr62a.h" /* プロトタイプ宣言 */ void _main( void ); /* メインプログラム */ void initPort( void ); /* ポート初期化関数 */ void initTimer( void ); /* タイマ初期化関数 */ void initSensor( void ); /* AD入力初期化関数 */ unsigned int readSensor( unsigned char sens_num ); /* センサ出力読み込み関数 */ void ta1int( void ); /* タイマ割込み関数 */ /* 割込み処理の宣言 */ #pragma INTERRUPT ta1int /* ta1intが割込み処理であることを宣言する。 */ /* 指定した関数の入口と出口において、通常の関数 */ /* の手続き以外にM16C/60 シリーズ、M16C/20 シリ */ /* ーズの全レジスタの退避・復帰とreit 命令を生 */ /* 成します。割り込み処理関数の型は、引数/戻り */ /* 値ともにvoid 型のみ有効です。 */ /* マクロ定義 */ #define PORTOUT 0xff /* ポート方向レジスタを出力に設定する為のデータ */ #define OFF 0x00 /* フラグのOFFを示すデータ */ #define ON 0x01 /* フラグのONを示すデータ */ #define CNT_TA0 (2500-1) /* タイマA0カウンタ値 fck=f1/32→2μs */ #define CNT_TA1 (1250-1) /* タイマA1カウンタ値 fck=f1/8→500ns */ /* 外部変数宣言 */ unsigned char p0outbuf; /* ポート0出力バッファ */ unsigned int ledoutbuf; /* LED出力バッファ */ /*--------------------------------------------------------------------------*/ /* 関数名 :main() */ /* 機能 :光距離センサで障害物までの距離を計測し、接近を確認したとき */ /* CPUボード上のLEDを点灯させる。 */ /*--------------------------------------------------------------------------*/ void main( void ) { unsigned int right_sensor; /* 右センサAD変換値格納変数 */ unsigned int center_sensor; /* 中央センサAD変換値格納変数 */ unsigned int left_sensor; /* 左センサAD変換値格納変数 */ /* ポート初期化 */ initPort(); /* ポート初期化関数呼出 */ /* タイマ機能の初期化 */ initTimer(); /* タイマ初期化関数呼出 */ /* AD入力機能の初期化 */ initSensor(); /* AD入力初期化関数呼出 */ /* タイマの起動 */ tabsr = 0x03; /* カウント開始:タイマA0、A1 */ _asm("\tFSET I"); /* 割り込み許可 */ /* メインループ */ for( ; ; ) { /* メインループ */ if( ir_ta0ic == 1 ) { /* 5ms経過? */ ir_ta0ic = 0; /* AD変換処理 */ right_sensor = readSensor( 0 ); /* 右センサの読み込み */ center_sensor = readSensor( 1 ); /* 中央センサの読み込み */ left_sensor = readSensor( 2 ); /* 左センサの読み込み */ /* AD変換値の判定 */ if( right_sensor > 50 /* 右、中央、左のいずれかの */ || center_sensor > 50 /* センサに接近していれば */ || left_sensor > 50 /* LEDを点灯する。 */ ) { ledoutbuf = 0x00; /* 接近しているのでP00のLEDを点灯するデータをセット */ } else { ledoutbuf = 0x01; /* P00に"H"出力してLEDを消灯するデータをセット */ } } } } /*----------------------------------------------------------------------*/ /* 関数名 :InitPort() */ /* 機能 :ポートの初期設定を行う。 */ /* :ポートの初期設定はスタートアップの出来るだけ早い段階で行う */ /* :事が必要だが、ここでも初期化を行う(念のため)。 */ /* :アプリケーションによっては、この処理を簡略化する。 */ /*----------------------------------------------------------------------*/ void initPort( void ) { ledoutbuf = 0x01; /* LED出力バッファ=LED消灯 */ p0outbuf = 0x01; /* ポート0レジスタの初期化 */ p0 = p0outbuf; /* ポート0レジスタの初期化 */ pd0 = 0x11; /* Port0方向レジスタの設定初期化 */ } /*----------------------------------------------------------------------*/ /* 関数名 :initTimer() */ /* 機能 :使用するタイマーの初期設定を行う。 */ /* 用途 :TA0 :メインループの処理を10msに一回行う為に用いる。 */ /* :TA1 :800Hzパルス出力の為に割込みを用いる。 */ /*----------------------------------------------------------------------*/ void initTimer( void ) { /* タイマ関連共通レジスタ設定 */ udf = 0x00; /* アップダウンフラグ設定 */ /* bit0: 0: タイマA0ダウンカウント(10ms計測に使用) */ /* bit1: 0: タイマA1ダウンカウント(625μs割込に使用) */ /* bit2: 0: タイマA2ダウンカウント(未使用) */ /* bit3: 0: タイマA3ダウンカウント(未使用) */ /* bit4: 0: タイマA4ダウンカウント(未使用) */ /* bit5: 0: タイマA2 2相パルス信号処理機能禁止(未使用) */ /* bit6: 0: タイマA3 2相パルス信号処理機能禁止(未使用) */ /* bit7: 0: タイマA4 2相パルス信号処理機能禁止(未使用) */ /* timerA0設定 割り込みは使用せず要求ビットのみを監視する。10msに設定 */ ta0ic = 0x00; /* タイマA0割り込みレベルの設定 */ /* bit2,1,0: 000: 割り込みレベル1(割込み禁止) */ /* bit3: 0: 割り込み要求ビット←クリア */ ta0mr = 0x80; /* タイマA0タイマモードの設定 */ /* bit1,0: 00: タイマモード */ /* bit2: 0: パルス出力無し */ /* bit4,3: 0X: ゲート機能無し(TAiIN端子は通常のポ−ト端子) */ /* bit5: 0: タイマモードでは必ず"0" */ /* bit7,6: 10: カウントソース=f32 */ ta0 = CNT_TA0; /* タイマ値の設定 */ /* f32=周期2μsecの時 */ /* (5000-1)を設定すると、5000×2us=10ms */ /* →10ms毎にir_ta0icが”1”になる。 */ } /*----------------------------------------------------------------------*/ /* 関数名 :initSensor() */ /* 機能 :使用するAD入力の初期設定を行う。 */ /* :ADコンバータの設定 */ /* : 10ビット・サンプル&ホールド有り */ /* : ΦAD=1/6MHz(10MHz以下の条件がある。) */ /* : 単発モード使用、ソフトウエアトリガ使用 */ /* : 使用ch=0〜2 */ /* :AD変換時間の計算 */ /* : ΦAD=166.7ns(1/6MHz) */ /* : 10ビット・サンプル&ホールド有り時 33ΦAD */ /* : 変換時間=33×166.7e−9=5.5μsec */ /*----------------------------------------------------------------------*/ void initSensor( void ) /* AD入力初期化関数 */ { pd10 = 0x00; /* AD入力ポート方向レジスタ初期化 */ /* bit0: 0: 右センサAD入力ポート =入力設定 */ /* bit1: 0: 中央センサAD入力ポート=入力設定 */ /* bit2: 0: 左センサAD入力ポート =入力設定 */ /* bit3: 0: 未使用(入力にしておく) */ /* bit4: 0: 未使用(入力にしておく) */ /* bit5: 0: 未使用(入力にしておく) */ /* bit6: 0: 未使用(入力にしておく) */ /* bit7: 0: 未使用(入力にしておく) */ /* AD入力設定 */ adst = 0; /* AD変換停止 */ adic = 0x00; /* AD 割り込みレベルの設定 */ /* bit2,1,0: 000: 割り込みレベル0(最低:割り込み禁止) */ /* bit3: 0: 割り込み要求ビット←クリア */ adcon2 = 0x01; /* AD制御レジスタ2の設定 */ /* bit0: 1: サンプル&ホールド有り */ adcon0 = 0x80; /* AD制御レジスタ0の設定 */ /* bit2,1,0: 000: アナログ入力端子AN0を選択 */ /* bit4,3: 00: アナログ入力モード=単発モード */ /* bit5: 0: ソフトウエアトリガ選択 */ /* bit6: 0: AD変換停止 */ /* bit7: 1: AD変換動作周波数fAD/2を選択 */ adcon1 = 0x28; /* AD制御レジスタ1の設定 */ /* bit1,0: 00: A-D掃引端子AN0,AN1を選択(単発モード:無効) */ /* bit2: 0: A-D動作モード選択繰り返し掃引モード1以外 */ /* bit3: 1: 分解能選択10ビット選択 */ /* bit4: 0: AD変換動作周波数fAD/2またはfAD/4を選択 */ /* bit5: 1: Vref接続:接続 */ /* bit7,6: 00: ANEX0,ANEX1は使用しない */ /* AD変換の開始はAD入力処理中で行うので初期化処理では停止 */ /* timerA1設定 AD変換用の800Hzパルス出力のために割り込みを使用する 設定625μs */ ta1ic = 0x04; /* タイマA1割り込みレベルの設定 */ /* bit2,1,0: 100: 割り込みレベル4 */ /* bit3: 0: 割り込み要求ビット←クリア */ ta1mr = 0x40; /* タイマA1タイマモードの設定 */ /* bit1,0: 00: タイマモード */ /* bit2: 0: パルス出力無し */ /* bit4,3: 0X: ゲート機能無し(TAiIN端子は通常のポ−ト端子) */ /* bit5: 0: タイマモードでは必ず"0" */ /* bit7,6: 01: カウントソース=f8 */ ta1 = CNT_TA1; /* タイマ値の設定 */ /* f8=周期500nsecの時 */ /* (1250-1)を設定すると、1250×500ns=625μs */ /* →625μs毎にir_ta1icが”1”になり、ta1int()が呼出される。 */ } /*----------------------------------------------------------------------*/ /* 関数名 :readSensor() */ /* 引数 :sens_num :入力するセンサ番号 */ /*  0:右センサの読み込み */ /*  1:中央センサの読み込み */ /*  2:左センサの読み込み */ /* other:エラー="0"を返す */ /* 戻り値 :AD変換値センサ出力の電圧をAD変換した値 */ /* センサ番号が誤りの時は"0"を返す。 */ /* 機能 :指定されたセンサの電圧値AD変換し計測する。 */ /* AD変換完了してから復帰する。 */ /*----------------------------------------------------------------------*/ unsigned int readSensor( unsigned char sens_num ) /* センサ出力読み込み関数 */ { unsigned int result; /* 戻り値を格納する変数。 */ if( sens_num > 2 ) { result = 0; /* センサ指定が誤りなので"0"を返す */ } else { adcon0 = 0x80 | sens_num; /* AD制御レジスタ0で変換するADチャネルを指定 */ adst = 1; /* AD変換開始 */ for( ; ; ) { if( ir_adic == 1 ) /* AD変換完了? */ { /* yes */ ir_adic = 0; /* AD変換完了割り込み要求ビットクリア */ adst = 0; /* AD変換停止 */ switch( sens_num ) { case 0: result = ad0; /* 右センサAD変換データ読み込み */ break; case 1: result = ad1; /* 中央センサAD変換データ読み込み */ break; case 2: result = ad2; /* 左センサAD変換データ読み込み */ break; default: break; } break; /* forループを脱出する。 */ } } } return result; } /*--------------------------------------------------------------*/ /* 関数名 :ta1int() */ /* 機能 :ta1割り込み関数 */ /*  :割り込みのたびに距離センサ用800Hzのパルス出力 */ /* :0.625ミリ秒計時(タイマA1) */ /* : タイマA1のカウントソースをf8とする */ /* : 1カウントは1/(16MHz/8)=0.5μS */ /* : 625μsを計時するには625μs/0.5μs=1250カウント */ /*--------------------------------------------------------------*/ void ta1int( void ) { /* 800Hzパルス出力 */ p0outbuf = p0outbuf ^ 0x10; /* ポ−ト0のbit4: パルス出力ポートビット位置 */ p0outbuf = p0outbuf & 0xfe; p0outbuf = p0outbuf | ledoutbuf; p0 = p0outbuf; }