メインプログラム:N_TIMER.c
プロセッサーエキスパート(PE)で設定した結果、下図の様なソースファイルが生成されます。初期設定は全て完了していますのでMAIN関数の含まれているN_TIMER.cのみを記述します。PEが自動生成した物は除き、記述した部分に付いて説明します。
【宣言部】
#defineでコンパイラに対して”C”と”G”という文字に対して3822と2551という数値を宣言しています。以後プログラムに”C”と記述すれば3821という数値として扱われます。
ピアノの鍵盤で左から3オクターブ目のラの音が440Hzになります。2093Hzは7オクターブ目のソの音に相当します。この周波数の周期は477.8μSです。
タイマーのクロック周期は0.125μSですから477.8μS/0.125μS≒3822となります。カウンターの周期を3822クロックとすればカウンタ出力に接続した圧電スピーカからソの音が出ます。
/****************************************************
* *
* Filename : N_TIMER.c *
* Version : 01.00 *
* Compiler : CodeWarrior HCS08 C Compiler *
* Date/Time : 2009/12/15, 0:00 *
* *
* ラーメンタイマー制御プログラム *
* *
* Copyright : n.Tanaka *
* *
****************************************************/
/***** 宣言部 *****/
#define C 3822 // 2093Hz 7オクターブ目のド
#define G 2551 // 3136Hz 7オクターブ目のソ
int TIME = 60; // タイマーレジスタ初期値は60秒
int IND_TIME; // 表示値レジスタ
char flg; // タイマーカウントフラグ
char T_flg; // タイムアップフラグ
unsigned int j; // スリープタイマーレジスタ
unsigned int tmp; // テンポラリーレジスタ
【タイマー割込み処理】
PEで割込みベクタをSECに設定したので、モジュロタイマーが1秒をカウントするとこの関数に飛んできます。1秒経過したのでTIMEを-1します。割込みがあった事を示すflgをセットします。カウントダウン中を示すT_flgをクリアします。
/***** 関数群 *****/
/***** タイマー割込み処理 *****/
ISR(SEC)
{
MTIMSC_TOF = 0; // モジュロタイマリセット
TIME = TIME-1; // タイマーレジスタをデクリメント
flg = 1; // タイマーカウントフラグをセット
T_flg = 0; // タイムアップフラグクリア
}
【SW読込関数】
ポートA1に接続されたスイッチが押されているか判断する関数です。チャタリングと長押しもチェックし押された時はクリック音を鳴らします。
/****************
* SW読込関数 *
****************/
void GetSW(void)
{
if(PTAD_PTAD1 == 0) // SW ON
{
Cpu_Delay100US(10); // 1mS待機
if(PTAD_PTAD1 == 0) // チャタリングではない
{
int i;
for(i=0;i<100;i++) // 長押しチェックループ
{
flg =1; // フラグをセット
Cpu_Delay100US(100); // 10mS待機
if(PTAD_PTAD1 == 1) // SW OFFになった(長押しではない!)
{
i = 100; // カウンタをMAX
TIME = TIME+60; // タイマ設定値+1分
flg = 0; // フラグをクリア
}
}
}
TPMSC_CLKSA = 1; // クリック音スタート
Cpu_Delay100US(1000); // 100mS待ち
TPMSC_CLKSA = 0; // クリック音停止
while(PTAD_PTAD1 == 0); // SW OFF待ち
j = 0; // スリープタイマーリセット
}
}
【カウントダウン表示関数】
TIMEレジスタの値は秒単位なので分単位にしてswitch文でLED表示に変換して表示します。
/****************************
* カウントダウン表示関数 *
****************************/
void TimeInd(void)
{
if(TIME < 10)IND_TIME = TIME; // 10秒未満は秒を表示
if(TIME > 10)IND_TIME = 1; // 10秒以上は1分と表示
if(TIME > 60)IND_TIME = 2; // 60秒以上は2分と表示
if(TIME > 120)IND_TIME = 3; // 120秒以上は3分と表示
if(TIME > 180)IND_TIME = 4; // 180秒以上は4分と表示
if(TIME > 240)IND_TIME = 5; // 240秒以上は5分と表示
switch(IND_TIME) // ポート出力
{
case 0 :PTBD = 0xC0;break; // 7セグメントLEDの文字に変換
case 1 :PTBD = 0xF9;break;
case 2 :PTBD = 0xA4;break;
case 3 :PTBD = 0xB0;break;
case 4 :PTBD = 0x99;break;
case 5 :PTBD = 0x92;break;
case 6 :PTBD = 0x82;break;
case 7 :PTBD = 0xF8;break;
case 8 :PTBD = 0x80;break;
case 9 :PTBD = 0x98;break;
default:PTBD = 0x00;
}
}
【サウンド関数】
カウントダウン終了でスピーカを鳴らす音を15秒間再生します。ドからソまで音程を上げてピューンという音を繰り返します。スイッチが押されたら終了します。
/********************
* サウンド関数 *
********************/
void sound(void)
{
TIME = 15; // サウンド再生時間15秒
MTIMSC_TOIE = 1; // 割込み許可
MTIMSC_TSTP = 0; // タイマースタート
while(!TIME == 0)
{
TPMSC_CLKSA = 1; // サウンドスタート
for(tmp=C;tmp>G;tmp--) // ドからソまで音程変化繰り返し
{
TPMC0V = tmp;
TPMMOD = tmp;
Cpu_Delay100US(5); // 500μS待ち
}
if(PTAD_PTAD1 == 0) TIME = 0; // SW ONなら終了
}
flg = 0; // 再生時間終了
TPMSC_CLKSA = 0; // サウンド停止
MTIMSC_TOIE = 0; // 割込み禁止
MTIMSC_TSTP = 1; // タイマー停止
j = 0; // スリープタイマークリア
TPMC0V = G; // クリック音設定
TPMMOD = G;
while(PTAD_PTAD1 == 0); // SW OFF待ち
}
【タイムカウント関数】
カウントダウン時間計測を行う関数です。LEDの表示は消費電流を削減するため、6mS周期でデューティは1/6としています。時間計測と同期させるためT_flgをセットして待ちますのでモジュロタイマの1秒計測して割込みが発生するまで次の表示を行ないません。カウントダウンキャンセルが出来るようにスイッチをチェックします。
/************************
* タイムカウント関数 *
************************/
void TimeCount(void)
{
MTIMSC_TSTP = 0; // タイマースタート
MTIMSC_TOIE = 1; // 割込み許可
while(!TIME == 0)
{
int i;
for(i=0;i<80;i++) // 80回繰り返し
{
Cpu_Delay100US(50); // 5mS待機
TimeInd(); // 時間を表示
Cpu_Delay100US(10); // 1mS待機
PTBD = 0xFF; // 表示を消す
}
T_flg = 1; // タイムアップフラグをセット
while(T_flg); // タイムアップ待ち
if(PTAD_PTAD1 == 0)
{
MTIMSC_TOIE = 0; // 割込み禁止
MTIMSC_TSTP = 1; // タイマー停止
flg = 0;
TIME = 0;
TPMSC_CLKSA = 1; // クリック音スタート
Cpu_Delay100US(1000);
TPMSC_CLKSA = 0; // クリック音停止
j = 0;
}
}
MTIMSC_TOIE = 0; // 割込み禁止
MTIMSC_TSTP = 1; // タイマー停止
if(flg == 1) sound(); // サウンド再生
TIME = 60; // 初期設定時間セット
while(PTAD_PTAD1 == 0); // SW OFF待ち
}
【メイン関数】
1秒を計測するモジュロカウンタとスピーカ用16ビットタイマーは共に初期状態では停止とします。jはスリープタイマー用のレジスタで操作が行われないとカウントアップします。
現在のプログラムでは1分15秒程度操作が無いと表示を消してマイコンがウェイトモードとなります。復帰するには電源のOFF/ONが必要です。
/*************
* メイン関数 *
*************/
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. ***/
/* Write your code here */
/* For example: for(;;) { } */
/***********
* 初期設定 *
***********/
/***** TRIM設定 *****/
ICSTRM = 0xA4; // 内臓基準クロックのトリム設定
ICSSC_FTRIM = 1; // 内臓基準クロックのファイントリム設定
/***** モジュロタイマ設定 *****/
MTIMSC_TOIE = 0; // 割込み禁止
MTIMSC_TSTP = 1; // タイマー停止
/***** タイマー設定 *****/
TPMSC_CLKSA = 0; // タイマー停止
/***** メインループ *****/
for(;;)
{
j = j++; // スリープタイマーインクリメント
Cpu_Delay100US(10); // 1mS待機
TimeInd(); // 時間表示
Cpu_Delay100US(1); // 100μS待機
PTBD = 0xFF; // 表示消し
GetSW(); // スイッチ読込
if(TIME > 300) TIME = 60; // 設定値が300秒を超えたら60秒に戻す
if(flg ==1) TimeCount(); // タイマーカウントフラグが1ならタイマーカウント関数へ
if(j > 0xFFFA) // スリープタイマー判断
{
PTBD = 0xFF; // 表示消し
_asm(wait); // ウェイトモード移行
}
}
/*** 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!!! ***/