16bit カウンタを用いるハードウェアタイマー(TIMER0 .. 4) を利用可能です。
このタイマーは、PWM 出力などのペリフェラルとして利用することもできますし、ソフトウェア処理を行うハードウェアタイマーとして利用することも可能です。
ポートの割り当て
TWELITE RED ではさらにPWM出力系統が増えていますが、TWELITE NET での標準的な対応は TIMER0..4 とします。
初期化と開始、終了
事前にペリフェラルマニュアルを参照の上、Timer で利用しないポートを宣言します。この宣言をしないと、Timer の初期化後、該当ポートは汎用のIOポートとして利用できなくなります。
以下の例では bit0,1,2 をセットします。これは TIMER0 で使用する PWM 用のピンを全て汎用IO向けに解放します。
vAHI_TimerFineGrainDIOControl(0x7);
tsTimerContext() のパラメータ
必要なタイマーの周波数に対して適切な PreScale を選択するようにします。
tsTimerContext sTimerApp; // global or static allocation
// set 64ticks/sec
memset(&sTimerApp, 0, sizeof(tsTimerContext));
sTimerApp.u8Device = E_AHI_DEVICE_TIMER0;
sTimerApp.u16Hz = 64;
sTimerApp.u8PreScale = 4; // 15625ct@2^4
最後に、Timer を開始します。
vTimerConfig(&sTimerApp); // initialize
vTimerStart(&sTimerApp); // start timer
Timer を一時的に停止させるには、vTimerStop() を呼び出します。完全に無効化するには vTimerDisable() を呼び出します。
// just stop the timer
vTimerStop(&sTimerApp);
...
// restart
vTimerStart(&sTimerApp);
...
// now, disable timer completely
vTimerStop(&sTimerApp);
vTimerDisable(&sTimerApp);
タイマー割り込み
ToCoNet_u8HwInt() ToCoNet_vHwEvent() の u8DeviceID パラメータが E_AHI_DEVICE_TIMER0 から E_AHI_DEVICE_TIMER4 をとります。
割り込み周波数が高くなるとハード割り込みやイベントの処理が無視できなくなります。
不要なタイマーの割り込みは無効にしておく
tsTimerContext の bDisableInt を TRUE に設定する
割り込み処理のみで対応し、ハードイベントは発生させない
割り込みハンドラを TRUE で return する
// hardware interrupt (return quickly!)
uint8 cbToCoNet_u8HwInt(
uint32 u32DeviceId,
uint32 u32ItemBitmap) {
uint8 u8handled = FALSE;
switch (u32DeviceId) {
case E_AHI_DEVICE_TIMER0:
_C {
static bool_t b;
b = !b;
vPortSet_TrueAsLo(PORT_DO1, b);
u8handled = FALSE; // if TRUE, no HwEvent follows.
}
break;
}
}
// hardware event (in the application loop)
// where we can make a bigger job, like RF transmit.
void cbToCoNet_vHwEvent(
uint32 u32DeviceId,
uint32 u32ItemBitmap) {
switch (u32DeviceId) {
case E_AHI_DEVICE_TIMER0:
vPutChar(&sSerStream, 'x'); // put x every tick
if (...) {
...
ToCoNet_bMacTxReq(...); // send a packt
}
break;
}
}
PWM 出力
Timerの出力として PWM 出力を設定することが可能です。
PWM出力を得るためには以下の設定が必要です。
vAHI_TimerFineGrainDIOControl() で出力を無効にしていない
tsTimerContext sTimerPWM; // global or static allocation
// initialize
memset(&sTimerPWM, 0, sizeof(tsTimerContext));
sTimerPWM.u8Device = E_AHI_DEVICE_TIMER1;
sTimerPWM.u16Hz = 1000; // 1Khz
sTimerPWM.u8PreScale = 0;
sTimerPWM.u16duty = 512; // 50%
sTimerPWM.bPWMout = TRUE; // PWM out
sTimerPWM.bDisableInt = TRUE; // no interrupt (for CPU save)
// start
vTimerConfig(&sTimerPWM);
vTimerStart(&sTimerPWM);
...
// change duty
sTimerPWM.u16Duty = 256; // set new duty ratio
vTimerStart(&sTimerPWM); // just start again to change duty