Anda di halaman 1dari 19

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 Timer 0 Capabilities Mode 0: 13-bit counter/timer Mode 1: 16-bit counter/timer Mode 2: 8-bit auto-reload counter/timer Mode 3: two separate 8-bit counters Mode 0-2: identical to those in Timer 0 Mode 3: holds its contents

Timer 1

Timer 2, 3, 16-bit counter/timer with auto-reload 16-bit counter/timer with capture and 4 Toggle clock out Edge-triggered capture Software timer High-speed output Frequency output 8-bit PWM 16-bit PWM

PCA

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.

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 input Timer 1 external input Timer 2 external input Timer/counter 2 capture/reload trigger and direction control Timer 3 external input Timer/counter 3 capture/reload trigger and direction control Timer 4 external input Timer/counter 3 capture/reload trigger and direction control External count input to PCA0 External I/O for compare/capture module 0 External I/O for compare/capture module 1 External I/O for compare/capture module 2 External I/O for compare/capture module 3 External I/O for compare/capture module 4 External I/O for compare/capture module 5 External 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.
T0M C/T0 Prescaled clock SYSCLK
0 0 1 1

T0 Crossbar INT0 GATE0

TR 0

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.

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.
T0M C/T0 Prescaled clock SYSCLK
0 0 1 1

T0 Crossbar INT0 GATE0

TR0

TL0 (8 bits)

TF0 Reload

TH0 (8 bits)

Figure 8.2a Timer 0 mode 2 block diagram (C8051F040)

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.

0
Value after

TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 Reset: 00h rw rw rw rw rw rw rw rw 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)

7 GATE1 rw

6 C/T1 rw

5 T1M1 rw

4 T1M0 rw

3 GATE0 rw

2 C/T0 rw

1 T0M1 rw

0 T0M0 rw
Value after Reset: 00h

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 1 C/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 1 C/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)
7 -rw 6 -rw 5 -rw 4 T1M rw 3 T0M rw 2 -rw 1 SCA1 rw 0 SCA0 rw

Value after Reset: 00h

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 source T0M: 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 clock SCA1-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)

Figure 3.19. Clock control register (CKCON)

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 negativegoing 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 <C8051F040.h> 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

pw while(1);

= 65536*T1OvCnt + 256*(unsigned long)TH1 + (unsigned long)TL1;

} 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 <C8051F040.h> void sysinit(void); void t1_ISR (void); unsigned char t1ovCnt; void main (void) { char i; long int freq;

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. // --------------------------------------------------------------------------------------------------------

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 autoreload, 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.
7 TFn TF2 6 EXFn EXF2 5 -RCLK 4 -TCLK 3 EXENn EXEN2 2 TRn TR2 1 C/Tn C/T2 0 CP/RLn CP/RL2 TMRnCN
reset:00h

T2CON
reset: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

7 ---

6 ---

5 ---

4 TnM1 --

3 TnM0 --

2 TOGn --

1 TnOE T2OE

0 DCEN DCEN

TMRnCF
reset:00h

T2MOD
reset: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 autoreload) 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.

10

TnM1:TnM0 2

MUX

SYSCLK external clock Tn

2 8

TOGn 0xFF C/T 0 1 DCEN TCLK TMRnL TMRnH TFn 0xFF

toggle

Tn

crossbar TRn EXENn RCAPn H

Timer n interrupt

TnEX

crossbar

RCAPnL

EXFn

Figure 8.6 Timer 2, 3, or 4 in capture mode block diagram (C8051F040)

TnM1:TnM0 2

0xFF

0xFF

TOGn Toggle circuit to Tn

external clock (XTAL1) Tn

MUX

SYSCLK

2 8

DCEN C/T 0 1 TCLK TMRnL TMRnH


overflow

TFn

crossbar TRn EXENn

Timer n interrupt

TnEX

crossbar

RCAPnL

RCAPnH

EXFn

Figure 8.7c Timer 2, 3, or 4 in auto-reload mode updown counter diagram (C8051F040)

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.

11

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)

12

edge1 edge2

= the captured time of the first edge = 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 <c8051F040.h> // 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 }

13

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 <C8051F040.h> 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); }

14

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 3.3 F T2 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 <c8051F040.h> // compiled using SDCC void sysInit(void) {

15

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; }

16

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 #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define <c8051F040.h> G3H 0x0B // reload value of TMR2 for the G3 note G3L 0xDC // " B3H 0x3E // reload value of TMR2 for the B3 note B3L 0x39 // " C4H 0x49 // reload value of TMR2 for the C4 note C4L 0x1A // " C4SH 0x53 // reload value of TMR2 for the C4 sharp note C4SL 0x5D // " D4H 0x5D // reload value of TMR2 for the D4 note D4L 0x0D // " E4H 0x6E // reload value of TMR2 for the E4 note E4L 0xD5 // " F4H 0x76 // reload value of TMR2 for the F4 note F4L 0xFB // " F4SH 0x7E // reload value of TMR2 for the F4 sharp note F4SL 0xAB // " G4H 0x85 // reload value of TMR2 for the G4 note G4L 0xEE // " A4H 0x93 // reload value of TMR2 for the A4 note A4L 0x3F // " B4FH 0x99 // reload value of TMR2 for the B4 flat note B4FL 0x59 // " B4H 0x9F // reload value of TMR2 for the B4 note B4L 0x1C // " C5H 0xA4 // reload value of TMR2 for the C5 note C5L 0x8D // " D5H 0xAE // reload value of TMR2 for the D5 note D5L 0x87 // " E5H 0xB7 // reload value of TMR2 for the E5 note E5L 0x6B // " F5H 0xBB // reload value of TMR2 for the F5 note F5L 0x7D // " ZH 0xFF // stop sound (high frequency and inaudible note) ZL 0xF0 // notes 118

void sysInit(void); void delayby10ms(unsigned char kk);

17

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

18

OSCICN = 0x83; XBR0 = 0xF7; XBR1 = 0xFF; XBR2 = 0x5D; XBR3 = 0x8F; P2MDOUT |= 0x80; SFRPAGE = 0; SPI0CN = 0x01;

// " // assign port pins to all peripheral signals

// enable T2 output (must be done) // switch to SFR page 0 // 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 }

19

Anda mungkin juga menyukai