-
1
EET484 Microcontroller Lecture 8
(Adapted from Prof. Huangs lecture notes)
8. Timer Functions
1. The Timer System of the C8051F040 The C8051F040 implements
Timer 0, 1, and 2 of the original 8051 and adds two
timers (Timer 3 and 4) that are identical to Timer 2.
The 8051F040 provides three popular timer functions, i.e., o
Capture: edge-triggered; requires capture register; can measure the
pulse
width, period or duty cycle of a signal.
o Compare: implemented by comparing the timer value in every
clock cycle with the value stored in the compare register; when
equal, sets pin.
o PWM: to generate periodic square waveforms with a given
frequency and duty cycle; can change the average DC voltage by
adjusting duty cycle.
The 8051F040 also adds a six-channel programmable counter array
(PCA). The capabilities of the C8051F040 timers and PCA are
illustrated in Table 8.1.
Table 8.1 Capability of the C8051F040 timer system
Timer subsystem
Capabilities
Timer 0
Mode 0: 13-bit counter/timerMode 1: 16-bit counter/timerMode 2:
8-bit auto-reload counter/timerMode 3: two separate 8-bit
counters
Timer 1 Mode 0-2: identical to those in Timer 0Mode 3: holds its
contents
Timer 2, 3, and 4
16-bit counter/timer with auto-reload16-bit counter/timer with
captureToggle clock out
PCA
Edge-triggered captureSoftware timerHigh-speed outputFrequency
output8-bit PWM16-bit PWM
Signal pins related to timer functions are listed in Table 8.2.
These signal pins are assigned to port pins by programming the
crossbar decoder.
-
2
Table 8.2 The functions of timer pins of the C8051F040
Pin name
T0
T1
T2
T2EX
T3
T3EX
T4
T4EX
ECI
CEX0
CEX1
CEX2
CEX3
CEX4
CEX5
ECI1
Description
Timer 0 external inputTimer 1 external inputTimer 2 external
inputTimer/counter 2 capture/reload trigger and direction
controlTimer 3 external inputTimer/counter 3 capture/reload trigger
and direction controlTimer 4 external inputTimer/counter 3
capture/reload trigger and direction controlExternal count input to
PCA0External I/O for compare/capture module 0External I/O for
compare/capture module 1External I/O for compare/capture module
2External I/O for compare/capture module 3External I/O for
compare/capture module 4External I/O for compare/capture module
5External count input to PCA1
2. Timer 0 and Timer 1
Each timer is implemented as a 16-bit register accessed as two
separate bytes (TH0:TL0 and TH1:TL1).
TCON enables/disables these two timers and indicates their
status. The TMOD register selects the operation mode of Timer 0 and
Timer 1. The CKCON register selects the clock source of Timer 0 and
Timer 1. The Timer 0 and Timer 1 should be stopped when changing
the operation mode or
reload a new value to the timer.
Mode 0: 13-bit timer or counter (use T0 as clock source)
Setting the GATE0 bit allows the INT0 pin to control the running
of Timer 0.
Setting TR0 enables but does not reset the timer.
0
1
0
1
Crossbar
Prescaled clock
SYSCLK
C/T0
T0M
T0
INT0
TR
0GATE0
TL0
5 bits)
TH0
(8 bits)TF0
Figure 8.1a Timer 0 mode 0 block diagram (C8051F040)
Mode 1: 16-bit timer or counter
The counters/timers are enabled and configured in the same
manner as in Mode 0. The block diagrams of Mode 1 for Timers 0 and
1 are identical to Figure 8.1a
except TL0 is 8 bits.
-
3
Mode 2: 8-bit timer or counter with auto-reload
The TLx is the counter whereas THx holds the reload value.
Whenever TLx overflows (from 0xFF to 0x00), the TFx flag is set and
the value
in THx is loaded into the TLx register.
0
1
0
1
Crossbar
Prescaled clock
SYSCLK
C/T0
T0M
T0
INT0
TR0GATE0
TL0(8 bits)
TH0(8 bits)
TF0
Figure 8.2a Timer 0 mode 2 block diagram (C8051F040)
Reload
Mode 3: two 8-bit timers or counters
Only available in Timer 0 Configured as two separate 8-bit
counters/timers held in TL0 and TH0 TL0 can use either the system
clock or an external input signal as its clock source. TL0 is
controlled using the Timer 0 control/status bits in TCON and
TMOD.
TH0 is restricted to timer function clocked by system clock or
prescaled clock. TH0 is enabled using TR1 of Timer 1 and sets the
TF1 flag on overflow.
-
4
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
7 6 5 4 3 2 1 0
TF1: Timer 1 overflow flag
0 = No Timer 1 overflow
1 = Timer 1 has overflowed
This flag is automatically cleared when the CPU vectors to Timer
1
interrupt service routine.
TR1: Timer 1 run control
0 = Timer 1 disabled
1 = Timer 1 enabled
TF0: Timer 0 overflow flag
0 = No Timer 0 overflow
1 = Timer 0 has overflowed
This flag is automatically cleared when the CPU vectors to Timer
0
interrupt service routine.
TR0: Timer 0 run control
0 = Timer 0 disabled
1 = Timer 0 enabled
IE1: External interrupt 1 flag
This flag is set when an edge/level of type defined by IT1
is
detected. It is automatically cleared when the CPU is vectored
to
the external interrupt 1 service routine. It can also be cleared
by
software.
IT1: Interrupt 1 type select
0 = /INT1 is level triggered, active low
1 = /INT1 is falling-edge triggered
IE0: External interrupt 0 flag
This flag is set when an edge/level of type defined by IT0
is
detected. It is automatically cleared when the CPU is vectored
to
the external interrupt 1 service routine. It can also be cleared
by
software.
IT0: Interrupt 0 type select
0 = /INT0 is level triggered, active low
1 = /INT0 is falling-edge triggered
Figure 3.17 Timer control register (TCON)
Value after Reset: 00h
rw rw rw rw rw rw rw rw
-
5
GATE1 C/T1 T1M1 T1M0 GATE0 C/T0 T0M1 T0M0
7 6 5 4 3 2 1 0
GATE1: Timer 1 gate control 0 = Timer 1 is enabled when TR1 = 1
irrespective of /INT1 logic level 1 = Timer 1 is enabled only when
TR1 = 1 and /INT1 = logic 1C/T1: Counter/Timer 1 select 0 = Timer
function: Timer 1 is incremented by clock defined by T1M bit 1 =
Counter function: Timer 1 is incremented by high-to-low transitions
on external input pin (T1)T1M1-T1M0: Timer 1 mode select 00 = Mode
0: 13-bit counter/timer 01 = Mode 1: 16-bit counter/timer 10 = Mode
2: 8-bit counter/timer with auto-reload 11 = Mode 3: Timer 1
inactive.GATE0: Timer 0 gate control 0 = Timer 0 is enabled when
TR0 = 1 irrespective of /INT0 logic level 1 = Timer 0 is enabled
only when TR0 = 1 and /INT0 = logic 1C/T0: Counter/Timer select 0 =
Timer function: Timer 0 is incremented by clock defined by T0M bit
1 = Counter function: Timer 0 is incremented by high-to-low
transitions on external input pin (T0)T0M1-T0M0: Timer 0 mode
select 00 = Mode 0: 13-bit counter/timer 01 = Mode 1: 16-bit
counter/timer 10 = Mode 2: 8-bit counter/timer with auto-reload 11
= Mode 3: Two 8-bit counter/timers.
Figure 3.18 Timer mode register (TMOD)
Value afterReset: 00h
rw rw rw rw rw rw rw rw
-- -- -- T1M T0M -- SCA1 SCA0
7 6 5 4 3 2 1 0
T1M: Timer 1 clock select (this bit is ignored when C/T1 is set
to 1) 0 = Timer 1 uses the clock defined by the prescale bits
SCA1-SCA0 1 = Timer 1 uses the system clock as clock sourceT0M:
Timer 0 clock select (this bit is ignored when C/T0 is set to 1) 0
= Timer 0 uses the clock defined by the prescale bits SCA1-SCA0 1 =
Timer 0 uses system clockSCA1-SCA0: Timer 0/1 prescale bits 00 =
system clock divided by 12 01 = system clock divided by 4 10 =
system clock divided by 48 11 = external clock divided by 8
Figure 3.19 Timer mode register (CKCON)
Value afterReset: 00h
rw rw rw rw rw rw rw rw
Figure 3.19. Clock control register (CKCON)
-
6
3. Applications of Timer 0 and Timer 1 3.1 Pulse Width
Measurement
Connect the unknown signal to INT0 (or INT1) Enable INT0 (or
INT1) pin falling edge interrupt Clear TF0 (or TF1) flag
The procedure is as follows:
1. Connect the unknown signal to the INT1 pin. Invert the signal
if it is a negative-
going pulse.
2. Configure Timer 1 to operate in mode 1 and select SYSCLK 12
as the clock input to the timer.
3. Initialize the Timer 1 overflow count to 0, and also
initialize the INT1 interrupt
count to 1.
4. Write a Timer 1 overflow interrupt service routine that
increments the overflow count by 1 and returns.
5. Write an INT1 interrupt service routine, which decrements its
interrupt count by 1.
6. Select falling edge interrupt from INT1 pin. Enable Timer 1
overflow interrupt.
7. Clear the TF1 flag to 0 and also enable Timer 1 to run.
8. Wait until the INT1 interrupt count is decremented to 0. Then
the pulse width of the
unknown signal is given by the following expression:
Pulse Width = (timer overflow count 216 + timer count) machine
cycles
Example1. Write a program to measure the pulse width of the
signal connected to the
INT1 pin, assuming that the C8051F040 is controlled by an
oscillator running at 24 MHz. include
void int1ISR(void);
void T1ISR(void);
char intCnt; // variable to wait for INT1 falling edge
interrupt
unsigned long pw;
unsigned long int T1OvCnt;
void sysinit(void);
void main(void) {
sysinit();
SFRPAGE = TIMER01_PAGE;
TL1 = 0; // count up from 0
TH1 = 0; // T1OvCnt = 0;
intCnt = 1; // there is only one falling edge in a pulse
width
TMOD = 0x90; // gated, timer mode, mode 1 operation
CKCON = 0; // Timer clock source is SYSCLK / 12
IT1 = 1; // choose falling edge interrupt for INT1
IE |= 0x8C; // enable INT1 and Timer 1 overflow interrupts
TF1 = 0;
TR1 = 1; // start Timer 1
while (intCnt); // wait until the falling edge of INT1
arrives
TR1 = 0; // stop the timer
-
7
pw = 65536*T1OvCnt + 256*(unsigned long)TH1 + (unsigned
long)TL1;
while(1);
}
void sysinit(void)
{
int n;
SFRPAGE = CONFIG_PAGE;
WDTCN = 0xDE; // disable watchdog timer
WDTCN = 0xAD; // "
OSCXCN = 0x67; // start external oscillator; 24 MHz Crystal
// system clock is 24 MHz
for (n = 0; n < 255; n++); // delay about 1 ms
while ((OSCXCN & 0x80) == 0); // wait for oscillator to
stabilize
CLKSEL |= 0x01; // switch to external oscillator
XBR2 = 0x5D; // enable crossbar and assign I/O pins to all
XBR0 = 0xF7; // peripheral signals,
XBR1 = 0xFF; // "
XBR3 = 0x8F; // "
SFRPAGE = SPI0_PAGE;
SPI0CN = 0x01; // enable 3-wire SPI (make sure SPI uses 3
pins
}
void int1ISR(void) interrupt 2
{
intCnt--;
}
void T1ISR(void) interrupt 3
{
T1OvCnt++;
}
3.2 Frequency Measurement
The frequency of an unknown signal can be measured by using
Timer 0 (or 1) to create a
delay of one second and use Timer 1 (or 0) to count the number
of rising (or falling)
edges arrived during this interval.
Connect unknown signal to T1 pin Use Timer 0 to create
one-second delay At the end of one second, the count value in Timer
0 is the frequency of the signal.
Example2. Write a program to measure the frequency of a signal
by using Timer 0 or
Timer 1 to create a delay of one second and use Timer 1 to count
the number of rising or
falling edges arrived at during this interval. #include
void sysinit(void);
void t1_ISR (void);
unsigned char t1ovCnt;
void main (void)
{
char i;
long int freq;
-
8
sysinit();
SFRPAGE = TIMER01_PAGE;
TMOD = 0x51; // configure Timer 1, Timer 0 to counter and timer
mode 1
CKCON = 0x02; // use SYSCLK/48 as the clock source of Timer
0
TH1 = 0x00; // Timer 1 count up from 0
TL1 = 0x00;
IE = 0x88; // enable Timer 1 interrupt
ET0 = 0; // disable Timer 0 interrupt
for (i = 0; i < 10; i++){
TF0 = 0;
TR0 = 0; // stop Timer 0
TH0 = 0x3C; // let Timer 0 count up from 15536 so it overflows
in 100 ms
TL0 = 0xB0; // *
TR0 = 1; // start Timer 0
while(!TF0); // wait for 100 ms
}
freq = (long)t1ovCnt * 65536 + 256 * (long)TH1 + (long)TL1;
}
void t1_ISR (void) interrupt 3
{
TF1 = 0;
t1ovCnt++;
}
//
---------------------------------------------------------------------------------------------------------
// include the sysinit() function here.
//
--------------------------------------------------------------------------------------------------------
-
9
4. Timer 2, Timer 3, and Timer 4 These Timers have identical
capabilities. These timers can operate as a timer or an event
counter. They also provide auto-
reload, capture, and toggle output modes with the capability of
counting up or
counting down.
The operation modes of these timers are configured by
programming the TMRnCN and TMRnCF registers.
The contents of TMRnCN and TMRnCF are shown in Figure 8.3 and
8.4.
TFn EXFn EXENn TRn C/Tn CP/RLn-- --
7 6 5 4 3 2 1 0TMRnCNreset:00h
TF2 EXF2 EXEN2 TR2 C/T2 CP/RL2RCLK TCLKT2CONreset:00h
TFn (n = 2, 3, or 4): Timer n overflow/underflow flag
0 = no overflow or underflow occurred.
1 = Timer n overflow or underflow (timer/counter count from
0x0000 to 0xFFFF) ocurred
EXFn (n = 2, 3, or 4): Timer 2, 3, or 4 external flag
This flag is set when either a capture or reload is caused by a
high-to-low transition on
the TnEX pin and EXENn is logic one. This flag must be cleared
by software.
RCLK: Receive clock bit
0 = use Timer 1 overflow as receive clock for serial port in
mode 1 or 3
1 = use Timer 2 overflow as receive clock for serial port in
mode 1 or 3
TCLK: Transmit clock bit
0 = use Timer 1 overflow as transmit clock for serial port in
mode 1 or 3
1 = use Timer 2 overflow as transmit clock for serial port in
mode 1 or 3
EXENn (n = 2, 3, or 4): Timer n external enable
0 = transitions on the TnEX pin are ignored
1 = transitions on the TnEX pin cause capture, reload, or
control the direction of timer
count (up or down) as follows:
Capture mode: 1-to-0 transition on TnEX pin causes RCAPnH:RCAPnL
to capture
count value.
Auto-reload mode:
DCEN = 0: 1-to-0 transition of TnEX pin causes reload of timer
and sets ExFn flag.
DCEN = 1: TnEX logic level controls direction of timer (up or
down)
TRn (n = 2, 3, or 4): Timer n run control
0 = timer n disabled
1 = timer n enabled
C/Tn (n = 2, 3, or 4): Counter/timer select
0 = timer function
1 = counter function: timer incremented by the falling edge of
Tn pin
CP/RLn (n = 2, 3, or 4): Capture/reload select
0 = timer is in reload mode
1 = timer is in capture mode
Figure 8.3 Contents of the TMRnCN and T2CON register
-
10
-- -- TnM0 TOGn TnOE DCEN-- TnM1
7 6 5 4 3 2 1 0TMRnCFreset:00h
-- -- -- -- T2OE DCEN-- --T2MODreset:00h
TnM1-TnM0 (n = 2, 3, or 4): Timer clock mode select bits
00: select SYSCLK/12 as the Timer n clock source
01: select SYSCLK as the Timer n clock source
10: select External Clock/8 as the Timer n clock source
11: select SYSCLK/2 as Timer n clock source
TOGn (n = 2, 3, or 4): Toggle output state bit
When timer is used to toggle a port pin, this bit can be used to
read the state of the output,
or can be written to in order to force the state of the
output
TnOE (n = 2, 3, or 4): Timer output enable bit
0 = output of toggle mode not available at timer's assigned port
pin
1 = output of toggle mode available at timer's assigned port
pin
DCEN: Decrement enable bit
0 = Timer will count up, regardless of the state of TnEX
1 = Timer will count up or down depending on the state of TnEX
as follows:
if TnEX = 0, the timer counts down
if TnEX = 1, the timer counts up
Figure 8.4 Contents of the TMRnCF and T2MOD register
4.1 Configuring Timer 2, 3, and 4 to Count Down
Set the DCEN bit of the TMRnCF register, and set the EXENn bit
of the TMRnCN register.
The count direction is determined by the logic level of the TnEX
(n = 2, 3, or 4) pin. The TnEX pin must be assigned to the I/O
pin.
When TnEX = 1, the timer counts up. Otherwise, timer counts
down. When DCEN bit is set, other functions of the TnEX input
(capture and auto-
reload) are not available
Thus, to count down: EXENn = 1, DCEN = 1 and TnEx = 0,
4.2 Timer 2, 3, and 4 Capture Mode
This mode is entered when the CP/RLn, TRn, and EXENn bits of the
TMRnCN register are set to 1.
The falling edge of the TnEX pin causes the 16-bit timer value
TMRnH:TMRnL to be copied into the capture register
RCAPnH:RCAPnL.
When a capture occurs, the EXFn flag will be set and may cause
an interrupt to the MCU.
Thus, to enable Capture mode, CP/RLn = 1, TRn = 1, EXENn = 1,
DCEN=0. When
a capture occurs, the EXFn flag is set.
-
11
2
2
8
SYSCLK
MU
X
external clock
crossbarTn
01
TRn
crossbar
EXENn
TnEX
TnM1:TnM0
TCLK TMRnL TMRnH
DCEN
RCAPnLRCAPn
H
TFn
EXFn
Timer ninterrupt
Figure 8.6 Timer 2, 3, or 4 in capture mode block diagram
(C8051F040)
C/T
0xFF 0xFFtoggleTOGn Tn
2
2
8
SYSCLK
MU
X
external clock
(XTAL1)
crossbarTn
01
TRn
crossbar
EXENn
TnEX
TnM1:TnM0
TCLK TMRnL TMRnH
DCEN
RCAPnL RCAPnH
TFn
EXFn
Timer ninterrupt
Figure 8.7c Timer 2, 3, or 4 in auto-reload mode updown counter
diagram (C8051F040)
0xFF 0xFF
C/T
overflow
Togglecircuit
TOGn
to Tn
4.3 Timer 2, 3, or 4 Auto Reload Mode
This mode is selected when the CP/RLn of the TMRnCN register is
0. Case A:
The DCEN bit is set to 1 to allow the user to select count up or
count down mode by pulling the TnEX pin to high or low.
When counting up and the timer overflows, the values in the
reload/capture register pair (RCAPnH:RCAPnL) will be reload into
the timer and counting
resumes.
-
12
When counting down and the time value matches that in
RCAPnH:RCAPnL, the timer will be loaded with 0xFFFF and counting
continues.
In auto-reload mode, the EXFn flag toggles upon every overflow
and underflow and does not cause an interrupt.
Case B:
When the DCEN bit is 0 and EXENn is set to 1, a falling edge of
the TnEX pin cause a timer reload (in addition to the auto-reload
caused by timer overflow).
Thus, there are three cases:
Auto reload at counting up mode:
CP/RLn=0, EXENn=1, DCEN = 1, TnEX = 1. Or
CP/RLn=0, EXENn=0, DCEN = 0, TnEX = dont care. Auto reload at
counting down mode: CP/RLn=0, EXENn=1, DCEN = 1, TnEX = 0.
Auto reload at a falling edge of TnEX pin: CP/RLn=0, EXENn=1,
DCEN = 0, TnEX
transit from 1 to 0
4.4 Toggle Clock Out Mode
Timer 2, 3, or 4 has the capability to toggle the state of their
associated output port pins (T2, T3, or T4) to produce a 50% duty
cycle waveform output.
This mode is entered by clearing the C/Tn bit and CP/RLn bits,
setting the TnOE bit, and loading a value into the RCAPnH:RCAPnL
register pair..
The timer pin toggles whenever the timer overflows (count up
mode) or underflows (count down mode)
When counting up, the auto-reload value comes from
RCAPnH:RCAPnL, the overflow occurs when the timer register reaches
0xFFFF.
When counting down, the auto-reload value is 0xFFFF, the
underflow occurs when the value in the timer matches the value in
RCAPnH:RCAPnL.
The circuit is the same as that in Figure 8.7c. Thus, Need to
set C/Tn = 0, CP/RLn=0, TnOE = 1,
The frequency of the clock output fSQ is determined by the clock
source fTCLK and value loaded into register pairs RCAPnH:RCAPnL,
which is
fSQ = fTCLK (2 (216
RCAPnH:RCAPnL)) --- (8.3)
Thus, given fSQ, the value to be loaded into the RCAPnH:RCAPnL
is
RCAPnH:RCAPnL = 216
fTCLK (2 fSQ) --- (8.4)
Using Timer 2 to Measure Signal Period
Capture two falling edges Need to take Timer 2 overflow into
account
Let
tovcnt = the Timer 2 overflow count
diff = edge2 edge1 (because 2s complement addition is used to
perform a subtract operation, this will give the correct magnitude
if edge1
is larger than edge 2)
= edge2 + (216
- edge1)
-
13
edge1 = the captured time of the first edge
edge2 = the captured time of the second edge
Then
Case 1: edge2 edge1
Period = tovcnt 216 + diff -- (8.5)
Case 2: edge2 < edge1
Period = (tovcnt 1) 216 + diff -- (8.6)
Example 8.3 Write a C program to measure the period of a signal
connected to T2EX
pin assuming the internal oscillator is used as SYSLK (24.5
MHz). Solution:
#include // compiled using the SDCC compiler
unsigned char tov2Cnt; // timer 2 overflow count
unsigned char periodH, periodL;
unsigned long period;
void t2ISR (void) interrupt 5
{
if (TF2) {
tov2Cnt++;
TF2 = 0;
}
}
void sysInit (void)
{
SFRPAGE = 0x0F;
WDTCN = 0xDE; // disable watchdog timer
WDTCN = 0xAD;
CLKSEL = 0; // select internal oscillator as SYSCLK
OSCICN = 0x83; // XBR0 = 0xF7; // assign all peripheral function
signals to port pins
XBR1 = 0xFF; // "
XBR2 = 0x5D; // "
XBR3 = 0x8F; // "
SFRPAGE = 0; // switch to SFR page 0
SPI0CN = 0x01; // enable and configure SPI to 3-wire mode
}
-
14
void main (void)
{
unsigned int t1, t2;
sysInit();
tov2Cnt = 0; // initialize timer 2 overflow count to 0
TMR2CN = 0x0D; // enable T2EN, capture mode, timer mode
IE = 0; // disable all interrupt
while(!EXF2); // wait for the first falling edge on T2EX pin
periodL = RCAP2L; // save the first edge
periodH = RCAP2H; // "
EXF2 = 0;
TF2 = 0;
IE = 0xA0; // enable Timer 2 interrupt
while(!EXF2); // wait for the second falling edge on T2EX
pin
t1 = 256 * (unsigned int)periodH + (unsigned int)periodL;
t2 = 256 * (unsigned int) RCAP2H + (unsigned int) RCAP2L;
if (t2 < t1)
tov2Cnt--;
period = (unsigned long) tov2Cnt * 65536 + (unsigned long)t2 -
(unsigned long)t1;
while(1);
}
4.5 Waveform Generation using Timer 2
Example 8.5 Write an instruction sequence to generate a 2 KHz
(period=0.5ms - High
time = Low time = 0.25ms, i.e., toggle frequency is 4KHz) square
waveform using the
Timer 2 of the C8051F040, which runs with the internal 24.5 MHz
internal oscillator
clock source.
Solution: The reload value is 216
24.5 106 (2 2000) = 65536 6125 = 0xE813.
#include
void sysinit (void);
void main (void)
{
sysinit();
TMR2H = 0xE8;
TMR2L = 0x13;
RCAP2H = 0xE8;
RCAP2L = 0x13;
TMR2CF = 0x0A; // select SYSCLK as timer clock, prescalar = 1,
TnM1-TnM0=01
// enable the output of toggle mode, T2OE = 1
TMR2CN = 0x04; // enable Timer 2, TR2 = 1, all other 0
while(1);
}
-
15
void sysinit (void)
{
SFRPAGE = 0x0F;
WDTCN = 0xDE;
WDTCN = 0xAD;
CLKSEL = 0;
OSCICN = 0x83;
XBR0 = 0xF7;
XBR1 = 0xFF;
XBR2 = 0x5D;
XBR3 = 0x8F;
P2MDOUT |= 0x80; // enable P2.8 output
SFRPAGE = SPI0_PAGE;
SPI0CN = 0x01; // enable 3-wire SPI mode
}
Generating Siren
C8051F040
T2
3.3 F
Speaker
Figure 8.10 Circuit connection for a speaker
Example 8.6 Use the circuit in Figure 8.10 to generate a
two-tone siren.
Solution: The procedure is as follows:
Step 1 Connect an 8- speaker to the T2 pin. Step 2 Configure
Timer 2 to operate in toggle output mode.
Step 3 Stop Timer 2 and load the value 37695 (= 65536
(24,500,000 (440 2))) to RCAP2H:RCAP2L and TMR2H:TMR2L register
pairs to generate the 440 Hz waveform.
Step 4 Enable Timer 2 and wait for half of a second.
Step 5 Load the value 51616 (= 65536 (24,500,000 (880 2))) to
RCAP2H:RCAP2L and TMR2H:TMR2L register pairs to generate the 880 Hz
waveform.
Step 6
Reenable Timer 2 and wait for half of a second.
Step 7 Stop Timer 2 and go to Step 3.
#include // compiled using SDCC
void sysInit(void)
{
-
16
SFRPAGE = 0x0F; // switch to SFR page 0
WDTCN = 0xDE; // disable watchdog timer
WDTCN = 0xAD;
CLKSEL = 0; // select internal oscillator as SYSCLK
OSCICN = 0x83; // "
XBR0 = 0xF7; // assign all peripheral signals to port pins
XBR1 = 0xFF; // XBR2 = 0x5D; // XBR3 = 0x8F; // P2MDOUT = 0x80;
// enable T2 pin output
SFRPAGE = 0; // switch to SFR page 0
SPI0CN = 0x01; // enable SPI in 3-wire mode
}
void delayby100ms(unsigned char k)
{
unsigned char i,tempage;
tempage = SFRPAGE;
SFRPAGE = 0;
TMOD = 0x11; // configure Timer 0 and 1 to mode 1
CKCON = 0x02; // Timer 0 use system clock divided by 48 as clock
source
for (i = 0; i < k; i++){
TH0 = 0x38; // place 14494 in TH0:TL0 so it overflows in 100
ms
TL0 = 0x9E;
TF0 = 0;
TR0 = 1; // enable Timer 0
while(!TF0); // wait for 100 ms
TR0 = 0; // stop Timer 0
}
SFRPAGE = tempage; // restore original SFRPAGE
}
void main (void)
{
sysInit(); // configure SYSCLK and all peripheral pin
assignments
TMR2CF = 0x0A; // select SYSCLK as timer 2 clock, enable T2
output
TMR2CN = 0; // stop TMR2 but select auto-reload timer mode
while (1) {
TMR2H = 0x93; // generate 440Hz tone
TMR2L = 0x3F; // RCAP2H = 0x93; // RCAP2L = 0x3F; // TR2 = 1; //
enable Timer 2 in auto reload mode
delayby100ms(5); // wait for 0.5 seconds
TR2 = 0;
TMR2H = 0xC9; // generate 880 Hz tone
TMR2L = 0xA0; // RCAP2H = 0xC9; // RCAP2L = 0xA0;
TR2 = 1; delayby100ms(5);
TR2 = 0;
}
-
17
}
Using Timer 2 to Play a Song
A note in the score consists of two components: pitch
(frequency) and tempo (duration).
The duration of a quarter note is 400 ms. Place the frequencies
and durations of all the notes of a music score in a table. For
every note, the user program uses the toggle output mode of Timer 2
to
generate the digital waveform with the specified frequency and
duration.
#include
#define G3H 0x0B // reload value of TMR2 for the G3 note
#define G3L 0xDC // "
#define B3H 0x3E // reload value of TMR2 for the B3 note
#define B3L 0x39 // "
#define C4H 0x49 // reload value of TMR2 for the C4 note
#define C4L 0x1A // "
#define C4SH 0x53 // reload value of TMR2 for the C4 sharp
note
#define C4SL 0x5D // "
#define D4H 0x5D // reload value of TMR2 for the D4 note
#define D4L 0x0D // "
#define E4H 0x6E // reload value of TMR2 for the E4 note
#define E4L 0xD5 // "
#define F4H 0x76 // reload value of TMR2 for the F4 note
#define F4L 0xFB // "
#define F4SH 0x7E // reload value of TMR2 for the F4 sharp
note
#define F4SL 0xAB // "
#define G4H 0x85 // reload value of TMR2 for the G4 note
#define G4L 0xEE // "
#define A4H 0x93 // reload value of TMR2 for the A4 note
#define A4L 0x3F // "
#define B4FH 0x99 // reload value of TMR2 for the B4 flat
note
#define B4FL 0x59 // "
#define B4H 0x9F // reload value of TMR2 for the B4 note
#define B4L 0x1C // "
#define C5H 0xA4 // reload value of TMR2 for the C5 note
#define C5L 0x8D // "
#define D5H 0xAE // reload value of TMR2 for the D5 note
#define D5L 0x87 // "
#define E5H 0xB7 // reload value of TMR2 for the E5 note
#define E5L 0x6B // "
#define F5H 0xBB // reload value of TMR2 for the F5 note
#define F5L 0x7D // "
#define ZH 0xFF // stop sound (high frequency and inaudible
note)
#define ZL 0xF0 // #define notes 118
void sysInit(void);
void delayby10ms(unsigned char kk);
-
18
code unsigned char scoreH[118] =
{D4H,B3H,G3H,B3H,D4H,G4H,B4H,A4H,G4H,B3H,C4SH,
D4H,ZH,D4H,ZH,D4H,B4H,A4H,G4H,F4SH,E4H,F4SH,G4H,ZH,G4H,D4H,B3H,G3H,
D4H,B3H,G3H,B3H,D4H,G4H,B4H,A4H,G4H,B3H,C4SH,D4H,ZH,D4H,ZH,D4H,
B4H,A4H,G4H,F4SH,E4H,F4SH,G4H,ZH,G4H,D4H,B3H,G3H,B4H,ZH,B4H,
B4H,C5H,D5H,ZH,D5H,C5H,B4H,A4H,B4H,C5H,ZH,C5H,ZH,C5H,B4H,A4H,G4H,
F4SH,E4H,F4SH,G4H,B3H,C4SH,D4H,ZH,D4H,G4H,ZH,G4H,ZH,G4H,F4SH,
E4H,ZH,E4H,ZH,E4H,A4H,C5H,B4H,A4H,G4H,ZH,G4H,F4SH,D4H,ZH,D4H,
G4H,A4H,B4H,C5H,D5H,G4H,A4H,B4H,C5H,A4H,G4H};
code unsigned char scoreL[118] =
{D4L,B3L,G3L,B3L,D4L,G4L,B4L,A4L,G4L,B3L,C4SL,
D4L,ZL,D4L,ZL,D4L,B4L,A4L,G4L,F4SL,E4L,F4SL,G4L,ZL,G4L,D4L,B3L,G3L,
D4L,B3L,G3L,B3L,D4L,G4L,B4L,A4L,G4L,B3L,C4SL,D4L,ZL,D4L,ZL,D4L,
B4L,A4L,G4L,F4SL,E4L,F4SL,G4L,ZL,G4L,D4L,B3L,G3L,B4L,ZL,B4L,
B4L,C5L,D5L,ZL,D5L,C5L,B4L,A4L,B4L,C5L,ZL,C5L,ZL,C5L,B4L,A4L,G4L,
F4SL,E4L,F4SL,G4L,B3L,C4SL,D4L,ZL,D4L,G4L,ZL,G4L,ZL,G4L,F4SL,
E4L,ZL,E4L,ZL,E4L,A4L,C5L,B4L,A4L,G4L,ZL,G4L,F4SL,D4L,ZL,D4L,
G4L,A4L,B4L,C5L,D5L,G4L,A4L,B4L,C5L,A4L,G4L};
code unsigned char dur[118] =
{30,10,40,40,40,80,30,10,40,40,40,
80,3, 20,3, 20,60,20,40,80,20,20,40,3, 40,40,40,40,
30,10,40,40,40,80,30,10,40,40,40,80,3, 20,3, 20,
60,20,40,80,20,20,40,3, 40,40,40,40,20,3, 20,
40,40,40,3, 80,20,20,40,40,40,3, 80,3, 40,60,20,40,
80,20,20,40,40,40,80,3, 40,40,3, 40,3, 20,20,
40,3, 40,3, 40,40,20,20,20,20,3, 40,40,20,3, 20,
60,20,20,20,80,20,20,60,20,40,80};
void main (void)
{
int j;
sysInit(); // configure SYSCLK and assign peripheral functions
to port pins
TMR2CF = 0x0A; // select SYSCLK as timer 2 clock, enable T2
output
TMR2CN = 0; // disable Timer 2
j = 0;
while (j < notes) {
TMR2H = scoreH[j]; // play the jth note
RCAP2H = scoreH[j];
TMR2L = scoreL[j];
RCAP2L = scoreL[j];
TR2 = 1; // enable Timer 2
delayby10ms(dur[j]);
TR2 = 0; // disable Timer 2 to change reload value
j++;
}
while(1); // stay here
}
void sysInit(void)
{
SFRPAGE = 0x0F;
WDTCN = 0xDE; // disable watchdog timer
WDTCN = 0xAD;
CLKSEL = 0; // select internal oscillator as SYSCLK
-
19
OSCICN = 0x83; // "
XBR0 = 0xF7; // assign port pins to all peripheral signals
XBR1 = 0xFF;
XBR2 = 0x5D;
XBR3 = 0x8F;
P2MDOUT |= 0x80; // enable T2 output (must be done)
SFRPAGE = 0; // switch to SFR page 0
SPI0CN = 0x01; // enable 3-wire SPI
}
void delayby10ms(unsigned char k)
{
unsigned char i, tempage;
tempage = SFRPAGE;
SFRPAGE = 0;
TMOD = 0x11; // configure Timer 0 and 1 to mode 1
CKCON = 0x00; // Timer 0 use system clock divided by 12 as clock
source
for (i = 0; i < k; i++){
TR0 = 0; // stop Timer 0
TH0 = 0xB0; // place 45119 in TH0:TL0 so it overflows in 10
ms
TL0 = 0x3F;
TF0 = 0;
TR0 = 1; // enable Timer 0
while(!TF0); // wait for 10 ms
}
SFRPAGE = tempage; // restore original SFRPAGE
}