On Thu, Apr 21, 2005 at 12:49:10PM -0700, Dave Hylands wrote:
>
> Hi David,
>
> > Then when the interrupt is serviced it is cleared by the CPU back to
> > zero. BTW, the docs do not say precisely WHEN during the interrupt
> > service routine.... Anyway, the docs say repeatedly that the flag
> > can be cleared by the user BY WRITING A 1 TO THE FLAG REGISTER. I
> > have not tried this in real life, but I would have expected that the
> > SW should write a zero to the register. But apparently writing a 1
> > to the register that already has a 1 will reset the 1.....
>
> The reason that writing a 1 to it clears it is because if you write a
> 1 to some other bit in the same register, you're writing a zero to all
> of the other bits.
Believe it was Tony who wrote the >> quoted section above.
As for myself we're talking too much in generalities and no enough
specifics. So here is real code:
SIGNAL( SIG_INPUT_CAPTURE3 )
{
// Toggle edge sensitivity in preparation for next IRQ.
// Manual states this should be done early in this routine.
// Note toggling it here inverts the meaning of relay_dir.
TCCR3B ^= (1<<ICES3);
if( relay_cnt && ((TCCR3B & (1<<ICES3)) == relay_dir) ) {
RELAY_DRIVE_P |= RELAY_DRIVE_B; // drive triac gate
ETIFR |= (1<<OCF3B); // clear pending, just in case
ETIMSK |= (1<<OCIE3B); // enable OC3B
TCNT3 = 0; // unstick timer
relay_cnt--;
} else {
RELAY_DRIVE_P &= ~RELAY_DRIVE_B; // make sure its off
ETIMSK &= ~(1<<OCIE3B);
}
}
SIGNAL( SIG_OUTPUT_COMPARE3B )
{
RELAY_DRIVE_P &= ~RELAY_DRIVE_B; // clear triac gate
ETIMSK &= ~(1<<OCIE3B); // disable myself (OC3B)
}
void
t3_init(void)
{
RELAY_DRIVE_DDR |= RELAY_DRIVE_B; // enable output
TCCR3A = 0; // no OC's connected
// mode 4, div by 64
TCCR3B = (1<<WGM32) | (1<<CS31) | (1<<CS30);
OCR3B = XTAL/64/1000; // 1/1000th of 1 second
ETIFR |= (1<<ICF3); // clear any pending IRQ
ETIMSK |= (1<<TICIE3); // enable input capture IRQ
AC_XC_UTIL_DDR &= ~AC_XC_UTIL_B; // make sure its an input
}
void
engage_relay(uint8_t onoff)
{
// relay direction must be set first, else lockout IRQ when setting
if( onoff ) {
relay_dir = 0; // rising edge ???
ac_relay_state = 0; // need to verify value
} else {
relay_dir = (1<<ICES3); // falling edge ???
ac_relay_state = 1; // need to verify value
}
relay_cnt = 3; // 60 Hz, 3 cycles = 50 mS
}
The above isn't complete enough to compile, some external references and
defines are missing. But I think its complete enough to read. If the
"unstick timer" line is removed then SIG_OUTPUT_COMPARE3B is never
called. I don't know how to let TCNT3 free run. Its apparently stopped
in SIG_INPUT_CAPTURE3 as its contents are zero. But writing a zero
starts it counting so that SIG_OUTPUT_COMPARE3B is called when TCNT3
equals OCR3B. Notice I'm writing to a counter, not a control register.
--
David Kelly N4HHE, dkelly@HiWAAY.net
========================================================================
Whom computers would destroy, they must first drive mad.Message
Re: [AVR-Chat] Re: documentation of timer interrupts vs bugs
2005-04-21 by David Kelly
Attachments
- No local attachments were found for this message.