Hardware timers that use 16-bit counters (TIMER0 … 4) are available.
This timer can be used as a peripheral, such as a PWM output, or it can be used as a hardware timer for software processing.
| Timer Name | Primary pin assgin | Sub | Sub2 | explanation |
|---|---|---|---|---|
| TIMER0 | 8, 9, 10 | 2,3,4 | General-purpose timer function available | |
| TIMER1 | 11 | 5 | PWM output only | |
| TIMER2 | 12 | 6 | DO0* | PWM output only |
| TIMER3 | 13 | 7 | DO1* | PWM output only |
| TIMER4 | 17 | 8 | PWM output only |
It can be changed to a sub-allocation with the peripheral API vAHI_TimerSetLocation().
In TWELITE RED, there are more PWM output systems, but the standard response in TWELITE NET is TIMER0..4.
Declare the ports that will not be used by the Timer by referring to the peripheral manual in advance. If this declaration is not made, the corresponding port will not be available as a general-purpose IO port after the Timer is initialized.
In the following example, bit0, 1, and 2 are set. This releases all PWM pins used of TIMER0 for general-purpose IO.
the parameter of vAHI_TimerFineGrainDIOControl()
Bit |
Timer Input/Output |
|---|---|
| 0 | TIMER 0 gate/event input |
| 1 | TIMER 0 capture input |
| 2 | TIMER 0 PWM output |
| 3 | TIMER 1 PWM output |
| 4 | TIMER 2 PWM output |
| 5 | TIMER 3 PWM output |
| 6 | TIMER 4 PWM output |
| 7 | reserved |
Next, the initialization structure tsTimerContextfor the Timer library is statically allocated and configured.必要なタイマーの周波数に対して適切な PreScale を選択するようにします。
The prescale (u8PreScale) selects a smaller value in most cases for the required period (frequency).
The Timer prescales the counter value at 16Mhz, and the count value (Ct) for one cycle is given by the following equation
Ct = 16,000,000 / 2^p / hz
p : prescale value
hz : Timer cycle
Set this Ct value so that it does not exceed the maximum number of 16 bits (65535). For example, if you want a 64Hz timer, p=2 gives Ct = 62500, p=4 gives Ct = 15625. If you need a PWM output with a more accurate duty ratio, choose a slightly smaller p=2, but if you simply need a timer for software, p=4 makes no difference.
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^4Finally, start the Timer.
To stop the timer temporarily, call vTimerStop(). To disable it completely, call vTimerDisable().
// just stop the timer
vTimerStop(&sTimerApp);
...
// restart
vTimerStart(&sTimerApp);
...
// now, disable timer completely
vTimerStop(&sTimerApp);
vTimerDisable(&sTimerApp);The u8DeviceID parameter of ToCoNet_u8HwInt() and ToCoNet_vHwEvent() takes E_AHI_DEVICE_TIMER0 to E_AHI_DEVICE_TIMER4.
As the interrupt frequency increases, the overhead of processing hard interrupts and events becomes non-negligible.
bDisableInt of tsTimerContext to TRUE.return an interrupt handler with TRUE.// 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;
}
}The PWM output can be set as the output of the Timer.
In order to improve the accuracy of the Duty ratio, it is recommended that the prescale value described above be kept small enough.
The following settings are required to have PWM output.
bPWMOut of tsTimerContext to TRUE.u16duty of tsTimerContext to a value of 0..1024.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