メインプログラム:IR_RX.c
プロセッサーエキスパートで設定した結果、下図の様なソースが生成されます。初期設定は全て完了していますのでMAIN関数の含まれているEVR.cのみ記述すれば終わりです。
メインプログラムは以下の関数から構成されます。
宣言部について
赤外線コマンド信号の解析
赤外線コマンダーから発射された赤外線は赤外線受信モジュールによって下図のような信号となってマイコンに入力されます。PPM(パルス位置変調方式)ですから、パルスの周期の違いで”1”か”0”かを判断して解析します。ONはLow、OFFはHiになります。データーが”0”の時は1周期は1.125mS、データーが”1”の時は周期が2.25mSになります。信号の立下り(ONの始まり)でモジュロータイマーをリセットし、次の立ち下がりまでの時間を測定して判定します。
POART A割込み処理関数
ISR(IR_INT)
入力ポートがLowになるとポート割込みが発生。割込みベクターで設定されたこの関数に飛んでくる。
表示処理が終了するまで割込みは禁止し、受信フラグをセットする。モジュロタイマーをリセットして時間計測を開始して戻ります。
/************************
* POART A割込み処理関数 *
************************/
ISR(IR_INT)
{
PTASC_PTAIE = 0; // 割込み禁止
flag = 1; // Ir受信フラグセット
MTIMSC_TSTP = 0; // モジュロタイマーアクティブ
MTIMSC_TRST = 1; // カウンタリセット
PTASC_PTAACK = 1; // PTA割込みフラグPTAIFをクリア
}
リーダー受信関数
void RX_LEADER(void)
データ解析のはじめはリーダーコードです。リーダーコードだけはONの時間を判定します。
モジュロタイマーがスタートしていますので、ポートを監視してOFFになるまで待ちます。OFFになったらタイマーの値が8mS以上であるか比較し、NGならエラーフラグを立てます。OFFにならない場合は14.6mSでタイムアウトが発生してエラーフラグを立てます。
OKな時はそのままONになるまで待機します。ONになったらここからはカスタムコードの始まりです。モジュロタイマーをリセットして時間計測を開始して戻ります。
/*******************
* リーダー受信関数 *
*******************/
void RX_LEADER(void)
{
endf = 1; // 待機解除要求フラグ 1=待機、0=待機解除
ERR = 0; // リーダーコード判定レジスタクリア
while(endf) // ON終了まで待機
{
if(PTAD_PTAD0 == 1)endf = 0; // ON終了なら待機解除 ON→OFF
if(MTIMSC_TOF == 1) // タイムオーバーなら
{ //
ERR = 1; // エラーフラグをセット
endf = 0; // 待機解除
MTIMSC_TRST = 1; // モジュロカタイマーをクリア(TOF=0)
}
}
if(MTIMCNT < 125)ERR = 1; // リーダーコード判定(8mS以下は不良)
endf = 1;
while(endf) // OFF終了待ち
{
if(PTAD_PTAD0 == 0)endf = 0; // OFF終了なら待機解除 OFF→ON
if(MTIMSC_TOF == 1) // タイムオーバーなら
{
ERR = 1; // エラーフラグをセット
endf = 0; // 待機解除
}
}
MTIMSC_TRST = 1; // モジュロタイマーをクリア(TOF=0)
}
コード受信関数
void RX_CODE(void)
ここからは1.66mSを基準に1.125mS周期(0)と2.25mS周期(1)の2種類の違いを判定します。8ビット分繰り返してTEMPレジスタにLSBから1ビットづつ格納していきます。
途中で信号が途切れた時はモジュロタイマーのタイムアウトでエラーフラグを立てます。
/*****************
* コード受信関数 *
*****************/
void RX_CODE(void)
{
TEMP =0; // データ保留レジスタをクリア
for(i=0;i<8;i++) // 8ビットなので8回繰り返し
{
endf = 1;
while(endf) // ON終了待ち
{
if(PTAD_PTAD0 == 1)endf = 0; // ON終了なら待機解除 ON→OFF
if(MTIMSC_TOF == 1) // タイムオーバーなら
{
ERR = 1; // エラーフラグをセット
endf = 0; // 待機解除
MTIMSC_TRST = 1; // カウンタリセット(TOF=0)
}
}
endf = 1;
while(endf) // OFF終了待ち
{
if(PTAD_PTAD0 == 0)endf = 0; // OFF終了なら待機解除 OFF→ON
if(MTIMSC_TOF == 1) // タイムオーバーなら
{
ERR = 1; // エラーフラグをセット
endf = 0; // 待機解除
MTIMSC_TRST = 1; // カウンタリセット(TOF=0)
}
}
if(MTIMCNT < 26) // 周期判定 64uS×26=1.66mS("0"は1.125mS,"1"は2.25mS)
{
MTIMSC_TRST = 1; // モジュロタイマーリセット
TEMP = TEMP & ~BitMask[i]; // TEMPレジスタのiビット目をクリア
}
else
{
MTIMSC_TRST = 1; // モジュロタイマーリセット
TEMP = TEMP | BitMask[i]; // TEMPレジスタのiビット目をセット
}
}
}
メイン関数
void main(void)
初期設定
TRIM設定はOSBDMでデバックする場合、プログラムで設定します。工場設定値を読み取るか、内部基準クロックを31.25kHzになるように調整したトリム値設定します。
測定方法についてはHCS08QGのICSの項目をご覧ください。
モジュロタイマー設定
内部固定クロックの周波数は内部基準クロックの1/2になります。プリスケーラは1/128とし周期は64μSになります。
モジュロ値はリーダー部のタイムアウト13.5mSより長い、14.6mSに設定しています。
割込み設定
KBIに似た機能でPin Interruptを使用します。赤外線受信モジュールが接続されているポートA0のみを割込み要因とします。立下りエッジのみを対象に設定します。
メインループ
受信フラグがフラグが立たない時は永久ループです。
赤外線受信モジュールがコマンドを受信すると割込みが発生して受信フラグが立ちます。
リーダーコードを受信してエラーフラグが立っていなければ引き続きカスタムコードを受信します。カスタムコード受信にエラーが無ければコード判定をします。
上位バイトは0x00、下位バイトは0x78であれば赤外線コマンダーの信号なので引き続き、データコードを受信します。受信中にエラーが無ければSW_DATAレジスタに格納します。次は反転したデータコードを受信し、エラーが無ければ受信データを反転してSW_DATAレジスタの値と比較します。ここでも違っていればエラーフラグを立てます。
最後にエラーフラグが立っていなければデータに対応したポートをセットしてフラグやモジュロタイマーをリセットして割込みを許可。永久ループに戻ります。
/*************
* メイン関数 *
*************/
void main(void)
{
/* Write your local variable definition here */
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/
/***********
* 初期設定 *
***********/
/***** TRIM設定 *****/
ICSTRM = 0xA5; // 内臓基準クロックのトリム設定
ICSSC_FTRIM = 1; // 内臓基準クロックのファイントリム設定
/***** モジュロタイマー設定 *****/
MTIMSC = 0x10; // モジュロタイマー停止
MTIMCLK = 0x10; // 固定内部クロック15.625kHz
MTIMMOD = 228; // 9mS+4.5mS=13.5mS (タイムアウトは228*64uS=14.6mS)
/***** 割込み設定 *****/
PTAES = 0; // 立下りエッジ
PTAPS = 1; // PTA0のみ割込み対象
PTASC_PTAMOD = 0; // エッジのみ
PTASC_PTAIE = 1; // 割込み許可
/* Write your code here */
/* For example: for(;;) { } */
/***** メインループ *****/
for (;;)
{
if(flag == 1) // Ir受信したら
{
/***** Leader code *****/
RX_LEADER(); // リーダー受信
/***** Custom code H *****/
if(ERR == 0)RX_CODE(); // エラーが無ければカスタムコード上位バイト受信
if(TEMP != 0x00)ERR = 1; // カスタムコードH判定(カスタムコードは0x00)
/***** Custom code L *****/
if(ERR == 0)RX_CODE(); // エラーが無ければカスタムコード下位バイト受信
if(TEMP != 0x78)ERR = 1; // カスタムコードL判定(カスタムコードは0x78)
/***** Data code *****/
if(ERR == 0)RX_CODE(); // エラーが無ければデータ受信
SW_DATA = TEMP; // データレジスタに格納
/***** !Data code *****/
if(ERR == 0)RX_CODE(); // エラーが無ければ反転データ受信
if(ERR == 0)
{
TEMP = ~TEMP;
if(SW_DATA == (TEMP)) // データと反転データを比較
{
switch(SW_DATA) // ポート出力
{
case 0 :PTBD = 0x01;break;
case 1 :PTBD = 0x02;break;
case 2 :PTBD = 0x04;break;
case 3 :PTBD = 0x08;break;
case 4 :PTBD = 0x10;break;
case 5 :PTBD = 0x20;break;
case 6 :PTBD = 0x40;break;
case 7 :PTBD = 0x80;break;
default:PTBD = 0x00;
}
}
}
MTIMSC_TRST = 1; // カウンタリセット(TOF=0)
MTIMSC_TSTP = 1; // カウンタ停止
flag = 0; // フラグクリア
ERR = 0; // エラーフラグクリア
PTASC_PTAACK = 1; // 割込みフラグクリア
PTASC_PTAIE = 1; // 割込み許可
}
}
/*** Don't write any code pass this line, or it will be deleted during code generation. ***/
/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
for(;;){}
/*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/
/* END IR_RX */
/*
** ###################################################################
**
** This file was created by Processor Expert 3.06 [04.26]
** for the Freescale HCS08 series of microcontrollers.
**
** ###################################################################
*/