Measuring Duty Cycles With An Intel MCS-51 Microcontroller: Paul C. de Jong and Ferry N. Toth
Measuring Duty Cycles With An Intel MCS-51 Microcontroller: Paul C. de Jong and Ferry N. Toth
The fastest way of measuring duty cycles is with the aid of hardware. The MCS-51 type of
microcontrollers offers possibilities for that since they are equipped with two internal timer/
counters.
The two port-pins INT0 (P3.2) and INT1 (P3.3) can control these timer/ counters directly by
hardware. Therefore we consider them as “fast-inputs”. All other pins can control the timer/
counters only by software. The internal configuration of the hardware including the smart
sensor SMT 160 is shown in Fig. 1.
TR1 bit
TL0 TH0
TR0 bit
&
SMT160 INT0 pin
interrupt
IE0 bit
wake up from idle
This application note describes A) four assembly programs for the measurement of duty-cycles
by hardware and B) a program for the measurement by software. Finally, we will discuss the
conditions for which averaging can improve the resolution.
1
to run any background programs because that will cause errors in both the measuring and the
background program.
Both timer/ counters are selected to operate in the 16-bits timer mode. Therefore the “timer/
counter mode control” (TMOD) register is initialised with the value 19H. In this mode
TIMER0 only runs when P3.2 is logically “1”, while TIMER1 can only be controlled by
software. TIMER1 measures the total measurement time. After a measurement the duty-cycle
p is obtained by:
contents _ of _ TIMER0
p=
contents_ of _ TIMER1
Detection of an edge with a resolution of 1µs is obtained when the measurement is started and
stopped by using interrupts. An interrupt is generated on a falling edge of the input signal
(when the interrupt flags are enabled).
The measurement is explained with the aid of a flow diagram (fig. 2). Firstly, the contents of
both timers are set. The initialising part starts with the detection of a 0-1 transition. Then the
interrupt enable flag is set and the IDLE mode is invoked. Now the processor is waiting for an
interrupt. When it is generated, which occurs at the next 1-0 transition of the input signal, the
flags TR0 and TR1 in the “timer control” register (TCON) are set. Now TIMER0 only runs
when P3.2 is pulled high, so it measures the time that the input signal is logically 1. TIMER1
is continuously running during the whole measurement. Note that TIMER1 starts 3µs too late
because processing of an interrupt takes 3µs. However because the measurement will be
stopped in the same way this delay is eliminated in the final result.
With respect to the measurement time, there is the choice to fix either the number of periods
or the measurement time. Because the period duration can vary between 300µs and 800µs a
fixed number of periods is an inefficient option. For short periods the measurement time is also
short so the result will be troubled because of sampling noise. Therefore a fixed measurement
time is chosen corresponding to 16 bits of machine cycles. Now the measurement will be
finished after TIMER1 generates an overflow. In this case we have a 17 bits result which
would require complex software routines. This problem is solved when TIMER1 is initialised
(before the measurement) with an offset. This offset corresponds to the maximum length of
two periods of the sensor signal (about 1.6ms in time). The offset is subtracted from the 17
bits result and will results in a 16 bits word.
When TIMER1 generates an overflow the measurement has to be stopped (see the right-hand
branch in figure 2). After occurrence of the next 1-0 transition of the sensor signal the
interrupt-enable flag is set and once again the IDLE mode is invoked. After occurrence of the
interrupt the flags TR0 and TR1 in the TCON register are cleared.
After correction for the offset in TIMER1, the contents of both timers are used to calculate
the duty-cycle.
2
INITIALISING PART
TIMER1=offset
TIMER0=0
Input signal = 0
yes
Interrupt enable
Invoke IDLE
TIMER0 run
TIMER1 run
Disable interrupt
Input signal = 0
yes
no
TIMER1 overflow?
no yes
Interrupt enable
Input signal = 1
Invoke IDLE
1-0 transition of
interrupt
sensorsignal
Figure 2. Flow diagram of a duty-cycle measurement with a resolution of one machine cycle.
3
A2. Measurement via INT0 pin with serial communication
The method proposed in the previous section uses the 8051 IDLE mode to create a constant
delay (interrupt latency) between the moment of interrupt (on the falling edge of the input
signal) and the moment of sampling Timer0. This is necessary because when the processing of
an instruction is interrupted, the instruction is first completed and not all instructions have an
equal execution time.
During the IDLE mode no instructions are being processed because the execution unit of the
8051 is disabled. However, the interrupt timer and serial units are left running. In this mode
the power consumption is significantly reduced.
To realize a constant latency only one interrupt source may be enabled (as is the case in
Figure 1). However, in some cases we require simultaneous temperature measurement and
serial communication. The serial communication is likely to require and interrupt of its own as
well as a timer to generate the baud rate. Using a 33MHz 8051 it is possible to realize 1200
baud communication and duty-cycle measurement, without additional hardware, as shown in
Fig.3.
In this case Timer 1’s overflow rate is required to generate the baud rate. Using a 32.9856
MHz crystal Timer 1 needs to count 859 clocks to overflow. proposed that it is used in a 16
bit mode. The Timer 1 overflow bit generates an interrupt (TF1) to reload the divider value.
Since we are using a fast processor this same interrupt handler can increment a software
counter in a short time. This software counter combined with the actual value of Timer 1 is
used as a time base to determine the period of the SMT160 output signal. Timer 0 retains its
function for counting the high period of the signal.
Of course, since we are now using 3 interrupt handlers (INT0, TF1, Serial) the interrupt
latency is not constant anymore, so the resolution of the measurement will be degraded by a
factor of 3. However, this is compensated by the higher clock speed of the processor.
TL0 TH0
TR0 bit
&
SMT160 INT0 pin
4
A3. Duty-cycle measurement using Timer 2; capture register
Many 8051 derivatives, including 8052 and the 16 bit 8051XA, are equipped with an
additional timer, Timer 2 (Fig. 4). Timer 2 is an advanced 16 bit timer/counter with
capture/reload register. In our case, the function of the capture register is to instantaneously
load the value of Timer 2 (capture) and hold it until the interrupt handler reads it. This
eliminates the effect of the interrupt latency, provided that the latency is less then the interrupt
rate.
TL0 TH0
TR0 bit
&
SMT160 INT0 pin
OUT
pin
5
A4. Duty-cycle measurement using a programmable counter array
(PCA)
The 8051FX derivatives are equipped with an additional piece of hardware: the programmable
counter array. This consists of one timer and 5 capture registers.
The timer can be programmed to run at a frequency Osc/12 or Osc/4. As compared to the
ordinary 8051, the use of the FX types enables to perform the measurements with 3 times the
resolution in the same measurement time.
Osc. ÷4 CH CL CF bit
CR bit interrupt
6
} else {
PCACapture0 = FALSE;
if (!Ready) {
CaptureUp.Byte.Hi = CCAP0H; /* save PCA counter */
CaptureUp.Byte.Lo = CCAP0L;
if (First) {
First = FALSE; /* 1st time just caputure value */
HiTime = LoTime = 0;
SetPCA1NegEdge(); /* enable falling edges */
} else {
LoTime += (CaptureUp.Word - CaptureDo.Word);
if (--Count == 0) { /* when Count = 0 ready */
SetCaptureOff(); /* capture off */
PCACapture0 = FALSE; /* clear flags */
PCACapture1 = FALSE;
PCAOverFlow = FALSE;
Ready = TRUE; /* measurement ready */
};
}; /* determine high period */
};
};
if (!Ready) {
};
OverFlow = 0; /* we have a signal */
};
return;
}
We interface with the interrupt handler from the main program, using the following functions:
#include <pca.h>
#include <stdio.h>
#define PERIODS 25
struct DoubleByte {
unsigned char Hi, Lo;
};
union Word2Byte {
unsigned short Word;
struct DoubleByte Byte;
};
void StartCount(void) {
First = TRUE; /* Initializes all varialbes */
OverFlow = 0;
Count = Periods;
Ready = FALSE;
Error = FALSE;
SetPCA0PosEdge(); /* Enable capture */
}
bit IsReady(void) {
return(Ready);
}
bit IsError(void) {
7
return(Error);
}
float GetDutyCycle(void) {
return (float)HiTime / (HiTime + LoTime);
}
The main program needs to initialize the interrupt handler once, the repeatedly start a
measurement, wait till the measurement is finished, check for errors and display the result.
main() {
SetPeriods(51);
while(TRUE) {
StartCount();
while(!IsReady()); continue;
if(IsError()) printf("An error has occured\n");
else printf(“The termperature is %f\n”,
(GetDutycycle() - 0.32) / 0.0047));
}
}
B. Software-controlled Measurement
Only the I/ O ports P3.2 and P3.3 can be used to detect interrupts. Therefore, when sensors
are connected to the other I/ O ports only a software-controlled measurement can be used to
measure the duty-cycle. Again two counters are required. However, it is still possible to use a
hardware timer, although it is software controlled. This timer TIMER0 can count the
measurement time. A fast software routine is used to measure the “1” state of the sensor
signal. The results are stored in a counter called: HIGH_COUNTER.
The timer TIMER0 increments every machine cycle, which takes 1µs. The software sample
rate takes 3µs. Therefore, to obtain the duty-cycle p, HIGH_COUNTER is multiplied by 3,
according to the equation:
3 × HIGH _ COUNTER
p=
TIMER0
Normally HIGH_COUNTER should store more than 8 bits and therefore requires two 8-bits
registers. This would cause a decrease of the sampling rate, because two extra commands
would be needed to “glue” these registers (test on overflow of the low_byte and, depending
on the test result, incrementing of the high_byte). Therefore, an alternative solution has been
applied: When the input signal is low, HIGH_COUNTER is waiting until the signal goes high
again. This time can be used to “calculate” HIGH_COUNTER (figure 7). This figure shows
the use of a temporary-result register which is called : temporary_high_counter. This counter
contains the number of samples for which the input signal was high during one period. As
soon as the input signal goes low, the value of HIGH_COUNTER is calculated by adding the
temporary_high_counter to it During this calculation interval the sensor signal is not sampled.
This restricts the duty-cycle to a limit. However the calculations take only 15µs, so that even
when the duty-cycle equals 0.95 for a period of about 600 µs, there will not be a problem.
The counts for the measurement time are stored in the hardware timer/ counter TIMER0. It is
started and stopped by software at a 1-0 transition of the input signal. In that case
8
Input = 1
no yes
Increment temporary_high_counter
HIGH –COUNTER :=
HIGH-COUNTER + temporary_high_counter
Clear temporary_high_counter
Input = 0 yes
no
(a)
Input signals
samples
A B C A B C A
(b)
Figure 7 a) Flow diagram of a duty-cycle measurement by software (only the part to measure
the “high”-time).
b) Time diagram belonging to figure 7a. During interval C HIGH_COUNTER is
calculated followed by clearing of the temporary_high_counter.
Examples: The standard deviation σ of the sampling noise, of a duty-cycle modulated signal
can be calculated from the equation:
ts 1 ts
σ= = × ,
6Tm × Tp 6 N Tp
9
where: ts= the time interval between successive samples
TP = the period of the input signal
Tm = the measurement time (=N× Tp)
N = number of periods within 1 measurement
The period of the input signal is between 300µs (at 400C) and 800µs (at -400C or 1200C). The
measurement time is about 64ms (slightly smaller than 216 × 1µs because of the offset). When
the sampling rate is 1 µs, then the sampling noise is between ó≅ 5× 10-5 and 10-4. As a rule of
thumb we can say that 95% of all values are read in the range of ±2σ around the mean value
(Gaussian distribution).
When the sampling rate is 3µs the sampling noise is 3 times more:
10
10
Stdev [us]
0.1
100 1000 10000 100000
Period between start edge [us]
11