Hello:
I have problems with the timer in aw60, i need to use two different time interruption ,I use ch2 and ch3 of the timer1 , when I use only one channel it works fine ,so I tried this with two channel.
//channel 2 init an enable interrupt
void timer_ch2() //1mseg
{
TPM1SC=0x00;
TPM1C2SC=0x50;
TPM1C2V=TPM1MOD=0x9C4;
TPM1SC= 0x0B; //Preescaler 8
}
//channel 2 init an enable interrupt
void timer_ch3() //2mseg
{
TPM1SC=0x00;
TPM1C3SC=0x50;
TPM1C3V=TPM1MOD=0x1388;
TPM1SC= 0x0B; //Preescaler 8
}
void main(){
timer_ch2();
timer ch3();
}
but with this ch2 change to 2mseg
interrupt 7 void timer(void)
{
clrReg8(TPM1C2SC,0x80);
PTAD_PTAD0 = ~PTAD_PTAD0; //to verify
}
interrupt 8 void timer3(void)
{
clrReg8(TPM1C3SC,0x80);
PTAD_PTAD1 = ~PTAD_PTAD1;
}
//channel 2 init an enable interrupt
void timer_ch2() //1mseg
{
TPM1SC=0x00;
TPM1C2SC=0x50;TPM1C2V=TPM1MOD=0x9C4;
TPM1SC= 0x0B; //Preescaler 8
}
//channel 2 init an enable interrupt
void timer_ch3() //2mseg{
TPM1SC=0x00;
TPM1C3SC=0x50;TPM1C3V=TPM1MOD=0x1388;
TPM1SC= 0x0B; //Preescaler 8
}
void main(){
timer_ch2();
timer ch3();
}
but with this ch2 change to 2mseg
channels can work independently?
Thanks for you soon reply, but I'm a litle confused, if channels can work independently and shared settings are the same,(timer1_Init) and I need two interruption of 1mseg and 2mseg I did this but it doesn't work ,how can i configure this ? can you post some code for do this ?
thanks for you help.
void Timer1_Init()
{
TPM1SC=0x00;
TPM1SC= 0x0B; //Preescaler 8
TPM1MOD=0x9C4;
}
void timer1_ch2() //1mseg
{
TPM1C2SC=0x50;
TPM1C2V=0x9C4;
}
void timer1_ch3() //2mseg
{
TPM1C3SC=0x50;
TPM1C3V=0x1388;
}
Hello Mayu,
Further to Kef's reply, leaving TPM1MOD register set to its default value, for free-running operation, will certainly simplify the coding. The only requirement is that the TPM overflow period be greater than the longest interrupt period. This would seem to be the case for a pre-scale division of 8. The following code might then apply for each ISR.
interrupt 7 void timer(void)
{
TPM1C2SC_CH2F = 0; // Clear flag
TPM1C2V += 2500; // Next output compare value 1ms
PTAD_PTAD0 = ~PTAD_PTAD0; //to verify
}
interrupt 8 void timer3(void)
{
TPM1C3SC_CH3F = 0; // Clear flag
TPM1C3V += 5000; // Next output compare value 2ms
PTAD_PTAD1 = ~PTAD_PTAD1;
}
You might also consider the initialisation of the TPM1C2V and TPM1C3V registers, so that the two interrupts never become concurrent, causing additional periodic latency. Perhaps the following initialisation code -
TPM1SC= 0x0B; // Preescaler 8
TPM1C2SC=0x50; // Interrupt only
TPM1C2V = TPM1CNT + 50;
TPM1C2SC=0x50; // Interrupt only
TPM1C3V = TPM1CNT + 1300;
Regards,
Mac
You can't use modulus setting to define channel frequency since modulus setting is shared among channels. Instead of changing modulus, on channel interrupt you can calculate and change TPMxCyV setting to match next pulse edge.
For example you want next interrupt to occur 1000 timer ticks past current interrupt. To do so you write in channel interrupt handler:
{
unsigned short t;
// current output compare
t = TPM1C3V;
// calculate next timer tick
t = (t + 1000) % MODULUS; // where MODULUS is current TPM1MOD setting
TPM1C3V = t; // next timer compare
}
Please note that it makes sense to leave default modulus setting (0x10000) since
short t % 0x10000 is t and slow division operation will be optimized out
Changing channel compare value and maybe ELSnA:ELSnB bits from set output pin on compare to clear and vice versa, it is possible to generate almost any pulse width and pulse frequency.
I don't have working example but idea should be clear.