他のスレッドで「H8/36094:IRQ0の処理が起動しないことがある」というのを見かけましたが
SH7670で下記のようなソースで自作関数を作成しています
ソースここから→
/////////////////////////////////////////////////////////////////////////タイマを設定するTIME_PROC tproc[]={{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},};BOOL bWaitTimer=FALSE;BOOL WaitTimer(int msec,void (*pc)()){ int i; CMT.CMSTR.BIT.STR1=0;//タイマ停止 for(i=0; i<10; i++){ if(tproc[i].msec ==0){ tproc[i].msec =msec; tproc[i].pc =pc; //1m Sec タイマ開始 if(!bWaitTimer){ bWaitTimer=TRUE; cpu_ms1_start //タイマを開始させるマクロ } CMT.CMSTR.BIT.STR1=1;//タイマ開始 return TRUE; } } //登録できない return FALSE;}/////////////////////////////////////////////////////////////////////////////////////1mSインターバルタイマvoid cmi1_(void){ BOOL flg; int i; void (*pc)(); CMT.CMCSR1.BIT.CMF &= 0; CMT.CMSTR.BIT.STR1=0; flg=FALSE; for(i=0; i<10; i++){ if(tproc[i].msec > 0){ tproc[i].msec--; if(tproc[i].msec == 0){ pc = tproc[i].pc; tproc[i].pc=0; pc(); } } if(tproc[i].msec > 0)flg=TRUE; } if(!flg){ bWaitTimer=FALSE; return; } CMT.CMCSR1.WORD=0; CMT.CMCNT1.WORD=0; CMT.CMCOR1.WORD=1000; CMT.CMCSR1.BIT.CKS=1;//11:Pφ/512 CMT.CMCSR1.BIT.CMIE=1; CMT.CMSTR.BIT.STR1=1; cpu_ms1 ++;}/////////////////////////////////////////////////////////////////////////タイマ関数 end///////////////////////////////////////////////////////////////////////
→ソースここまで、これを使用するには
void test(void)
{
}
に飛ばしたい場合に
WaitTimer(100, &test );
等とすると、100ミリ秒後にtest()が実行されるという仕組みですが
どうやらたまに実行されない場合があるということで、なにが原因なのか思案しています
アドバイスお願いできませんでしょうか?
LEONです。 私も以下例のように、超々シンプルなルーチンを使っています。 分周やインタバルを変えたり、uint型にしたりで、実用用途に合わせます。 typedef unsigned short int ushort; // 符号無し2Byte #define PCLOCK 50000000 // PCLOCK=50MHz #define TM10 10 // 10ms インタバルタイマ周期時間 #define TM_CMCOR (((PCLOCK/8)/1000)*TM10)-1 // =62499 CMT0.CMCORの設定値 #define TM_1000MS (1000/TM10) // 1000ms #define TMC_100US (((TM_CMCOR+1)*100)/10000) // 100us volatile static ushort Tm1; // TMカウンタ 10ms精度. ushort型 //-- 10ms精度のタイマ監視用 --// void Int_CMT0(void) // CMT0 インタバルタイマ割込み { Tm1++; // TMカウンタ更新(ushort型) // 0x0000~0xFFFFを永遠に繰り返し } void Tm1_Start(ushort *ptm1) // 時間計測開始 { *ptm1 = Tm1; // 開始時のTm1値 } ushort Tm1_Check(ushort tm1) // 時間経過チェック { return((ushort)(Tm1 - tm1)); // 経過時間演算 } <使用例> static ushort TmChk; Tm1_Start(&TmChk); // 時間計測開始 : if(Tm1_Check(TmChk) < TM_1000MS){ // 1000ms未経過? return 等 // 未経過時の処理.他タスク実施等 } 経過の処理 ・CMT0は10msインタバルの設定で初期化時に開始。以降、動作しっぱなし。 ・メインループ中で、時間計測開始と経過時間チェックを行う。 ・ushort型なので最大655350ms(約655秒) ・開始時のTm1値が 0xFFFE、チェック時のTm1値が 0x0001 の場合、 0x0001 - 0xFFFE = 0x0003 => 30ms経過 ・±10ms誤差。1msインタバルなら±1ms誤差。 実用上、用途によっては上記で十分ではないでしょうか。 更に精度を上げたい時、以下を追加。10ms未満限定でμsレベルの精度 が得られます。(メインループが追いつかないけどね) //-- 10ms未満の計測用 --// void TmC_Start(ushort *ptmC) { *ptmC = CMT0.CMCNT; // タイマ開始時の CMT0.CMCNT値 } ushort TmC_Check(ushort tmC) { ushort tmCnt = CMT0.CMCNT; if(tmCnt < tmC) tmCnt += TM_CMCOR+1; return((ushort)(tmCnt - tmC)); // 経過時間演算 } <使用例> static ushort TmC_Chk; TmC_Start(&TmC_Chk); // 時間計測開始 : if(TmC_Check(TmC_Chk) < TMC_100US) // 100μs未経過?