281/317
9 - A Carrier-current System for domestIc Remote Control
switches. To allow this, the voltage at both phases of the motor is reduced, then rectified and
the resulting voltage is the higher of the two. When the motor is steady, the voltage at its ter-
minals is the line voltage (e.g. 230 VAC); if running, one of the terminals is at a higher voltage,
due to the effect of the phase-shift capacitor. This difference in voltage tells us when the motor
is stopped.
To save power, the analog to digital converter is only powered when used. Thus, the following
function first sets the ADC control register with the channel number and also sets the ADON
bit to start the operation of the converter. A first loop waits until the first conversion is finished;
but, as specified in the data sheet, to produce accurate results, the converter needs time to
stabilize after being powered on. This first reading will be discarded, and a second loop will
wait until the second conversion is complete. The value read is then returned:
#pragma NO_OVERLAP
/* This function is also called from an interrupt
service routine */
Byte ReadADC ( Byte Channel )
{
TACR1 &= ~( 1 << ICIE ) ;
/* Disable timer A interrupts to avoid
re-entrancy. */
ADCCSR = Channel | ( 1 << ADON ) ;
while ( ! ( ADCCSR & ( 1 << COCO ) ) )
;
/* Perform one reading to stabilize. */
ADCCSR = Channel | ( 1 << ADON ) ;
while ( ! ( ADCCSR & ( 1 << COCO ) ) )
;
/* Perform good reading. */
ADCCSR = 0 ;
/* Turn off ADC. */
TACR1 |= ( 1 << ICIE ) ;
/* Re-enable timer A interrupts. */
return ADCDR ;
}
Here is a special remark about this function. It is called both from the main program and the
Timer A interrupt service routine, through the
ReceiveOneFrameElement
function. Since func-
tions are not re-entrant in Hiware C, we must take care that it cannot be called in a re-entrant
manner, that is, while it is being called by the main program. For this purpose, the interrupt en-
able bit of Timer A is reset on entry, and set again on exit.
Please pay attention to the
pragma
just before the function header. By default, the compiler
tries to locate the local variables (either explicit, those defined in the C source text, or implicit,
those used for the purpose of the C- to-assembler translation) in the
_OVERLAP
segment, to re-
duce the consumption of read-write memory. A n intelligent mechanism determines which
function calls which function, in order to avoid collisions. However, this mechanism does not
work if the function can be called by an interrupt service routine, since interrupts constitute a
distinct calling tree. Collisions are thus avoided by explicitly declaring that this function may
not share its storage with others, hence the
pragma
.