Chapter 08
Chapter 08
Han-Way Huang
Introduction
Timer0
- Can
C bbe configured
fi d as an 8-bit
8 bi or 16-bit
16 bi timer
i or counter.
- Can select the internal instruction cycle clock or the T0CKI signal as the clock signal.
- The user can choose to divide the clock signal by a prescaler before connecting it to
the clock input to Timer0.
- The
Th T0CON registeri controls
l the
h operation
i off Ti
Timer0.0
Set interrupt
flag bit TMR0IF
on overflow
FOSC/4 0
1 Sync with TMR0
1 internal TMR0L
Programmable high byte
T0CKI ppin 0 clocks
Prescaler 8
T0CS (2 Tcy delay) Read TMR0L
T0SE 3
PSA 8 8
Write TMR0L
T0PS2,T0PS1,T0PS0
TMR0H
8
Data bus <7:0>
Figure 8.1b Timer0 block diagram in 16-bit mode (redraw with permission of Microchip)
7 6 5 4 3 2 1 0
value after TMR0ON T08BIT T0CS T0SE PSA T0PS2 T0PS1 T0PS0
reset 1 1 1 1 1 1 1 1
TMR0ON: Timer0 on/off control bit
0 = stops Timer0
1 = Enables
E bl Timer0
Ti 0
T08BIT: Timer0 8-bit/16-bit control bit
0 = Timer0 is configured as a 16-bit timer
1 = Timer0 is configured as an 8-bit timer
T0CS: Timer0 clock source select
0 = Instruction cycle
y clock
1 = Transition on T0CKI pin
T0SE: Timer0 source edge select bit
0 = Increment on falling edge transition on T0CKI pin
1 = Increment on rising edge transition on T0CKI pin
PSA: Timer0 prescaler assignment bit
0 = Timer0 prescaler is assigned . Timer0 clock input comes from prescaler output
output.
1 = Timer0 prescaler is not assigned. Timer0 clock input bypasses prescaler.
T0PS2:T0PS0: Timer0 prescaler select bits
000 = 1:2 prescaler value
001 = 1:4 prescaler value
010 = 1:8 prescaler value
011 = 1:16
1 16 prescaler
l value
l
100 = 1:32 prescaler value
101 = 1:64 prescaler value
110 = 1:128 prescaler value
111 = 1:256 prescaler value
Example 8.2 Write a subroutine to create a time delay that is equal to 100 ms times the
contents of the PRODL register assuming that the crystal oscillator is running at 32
MHz.
Solution: The 100 ms delay can be created as follows:
1. Place the value 15535 into the TMR0 high byte and the TMR0L register so that
Timer0 will overflow in 50000 clock cycles
cycles.
2. Choose instruction cycle clock as the clock source and set the prescaler to 16
so that Timer0 will roll over in 100 ms.
3. Enable Timer0.
4 Wait until Timer0 to overflow.
4. overflow
In C language,
Timer1
Data bus
<7:0>
8
TMR1H p
CCP Special
event trigger
Write TMR1L
8 8
Read TMR1L
8 Synchronized
0 clock input
TMR1
TMR1L
high byte 1
TMR1ON T1SYNC
on/off
T1OSC
T13CKI/T1OSC 1 Synchronize
Prescaler
T1OSCEN FOSC/4 de
Enable
1, 2, 4, 8
internal 0 t
T1OSI Oscillator
clock
2 SLEEP input
TMR1CS
T1CKPS1:T1CKPS0
Figure 8.3 Timer1 block diagram: 16-bit mode (redraw with permission of Microchip)
7 6 5 4 3 2 1 0
value after RD16 -- T 1CKP S1 T 1CKP S0 T 1OSCEN T 1SYNC T MR1CS T MR1ON
reset 0 0 0 0 0 0 0 0
RD16: 16-bit read/write mode enable bit
0 = Enables read/write of T imer1 in two 8-bit operations
1 = Enable read/write of T imer1 in 16-bit
16 bit operation
T 1CKP S1:T 1CKP S0: T imer1 input clock prescale select bits
00 = 1:1 prescale value
01 = 1:2 prescale value
10 = 1:4 prescale value
11 = 1:8 prescale value
T 1OSCEN: T imer1 oscillator enable bit
0 = T imer1 oscillator is shut off
1 = T imer1 oscillator is enabled
T 1SYNC: T imer1 external clock input synchronization select bit
When T MR1CS = 1
0 = Synchronize external clock input
1 = Do not synchronize external clock input
When T MR1CS = 0
T his bit is ignored.
T MR1CS: T imer1 clock source select bit
0 = Instruction cycle
y clock ((FOSC/4))
1 = External clock from pin RC0/T 1OSO/T 13CKI
T MR1ON: T imer1 on bit
0 = Stop T imer1
1 = Enables T imer1
Figure 8.4. T 1CON contents (redraw with permission of Microchip)
• 16-bit mode
• prescaler value set to 1
• disable oscillator
• do not synchronize external clock input
• select external T1CKI pin signal as the clock source
#include <p18F8680.inc>
t1ov_cnt set 0x00 ; Timer1 rollover interrupt count
freq set 0x01 ; to save the contents of Timer1 at the end
org 0x00
goto start
; high priority interrupt service routine
org 0x08
btfss PIR1,TMR1IF,A ; skip if Timer1 roll-over interrupt
retfie ; return if not Timer1 interrupt
bcf PIR1,TMR1IF,A ; clear the interrupt flag
incf t1ov_cnt,F,A ; increment Timer1 roll-over count
retfie
; dummy low priority interrupt service routine
org 0x18
retfie
start clrf t1ov_cnt,A ; initialize Timer1 overflow cnt to 0
clrf freq,A ; initialize frequency to 0
clrf freq+1,A ; "
clrf TMR1H ; initialize Timer1 to 0
clrf TMR1L ; "
clrf PIR1 ; clear all interrupt flags
bsf RCON,IPEN,A ; enable priority interrupt
#include <p18F8680.h>
p
unsigned int t1ov_cnt;
unsigned short long freq;
void high_ISR(void);
void low_ISR(void);
( );
#pragma code high_vector = 0x08 // force the following statement to
void high_interrupt (void) // start at 0x08
{
_asm
goto high_ISR
_endasm
}
#pragma code //return to the default code section
#pragma interrupt high_ISR
void high_ISR (void)
{
if(PIR1bits TMR1IF){
if(PIR1bits.TMR1IF){
PIR1bits.TMR1IF = 0;
t1ov_cnt ++;
}
}
Timer2
- 8-bit timer TMR2 and 8-bit period register PR2.
Prescaler Reset
FOSC/4 TMR2
1:1, 1:4, 1:16
2 Postcaler
Comparator
T2CKPS1:T2CKPS0 EQ 1:1 to 1:16
4
PR2
T2OUTPS3:T2OUTPS0
7 6 5 4 3 2 1 0
value after -- TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0 TMR2ON T2CKPS1 T2CKPS0
reset 0 0 0 0 0 0 0 0
TOUTPS3:TOUTPS0: Timer2 output postscale select bits
0000 = 1:1 postscale
0001 = 1:2 postscale
.
.
.
1111 = 1:16 postscale
TMR2ON: Timer2 on bit
0 = Timer2 is off
1 = Timer2 is on
T2CKPS1: T2CKPS0: Timer2 clock prescale select bits
00 = prescaler is 1
01 = prescaler is 4
1 = prescaler
1x l isi 16
Examplep 8.4 Assume that the PIC18F8680 is runningg with a 32 MHz crystal
y oscillator.
Write an instruction sequence to generate periodic interrupts every 8 ms with high
priority using Timer2.
Solution: By setting the prescaler and postscaler to 16 and loading 249 into the PR2
register,
g Timer2 will generate
g periodic
p interrupt
p everyy 8 ms:
Timer3
- Timer3 consists of two 8-bit registers TMR2H and TMR2L.
- Timer3 can choose to use either the internal (instruction cycle clock) or external
signal as the clock source.
- The block diagram of Timer3 is quite similar to that of Timer1.
- Reading TMR3L will load the high byte of Timer3 into the TMR3H register.
- Timer3 operation is controlled by the T3CON register.
8 T3CCPx
Write TMR3L 8
Read TMR3L
8 Synchronized
0 clock input
Set TMR3IF flag Timer3 CLR
on overflow high byte TMR3L 1
TMR1ON T3SYNC
on/off
T1OSC
T13CKI/T1OSC 1 S h i
Synchronize
Prescaler
T1OSCEN FOSC/4
Enable 1, 2, 4, 8 det
internal 0
T1OSI Oscillator
clock
2 SLEEP input
When the T1OSCEN bit is TMR3CS
cleared, the inverter and T3CKPS1:T3CKPS0
feedback resistor are turned off
Figure 8.7 Timer3 block diagram: 16-bit mode (redraw with permission of Microchip)
7 6 5 4 3 2 1 0
value after RD16 T3CCP2 T3CKPS1 T3CKPS0 T3CCP1 T3SYNC TMR3CS TMR3ON
reset 0 0 0 0 0 0 0 0
RD16: 16-bit read/write mode enable bit
0 = Enables read/write of Timer3 in two 8-bit operations
1 = Enables read/write of Timer3 in 16-bit operation
T3CCP2:T3CCP1: Timer3 and Timer1 to CCPx enable bits
00 = Timer1 and Timer2 are the clock sources for CCP1 through CCP5
01 = Timer3 and Timer4 are the clock sources for CCP2 through CCP5;
Timer1 and Timer2 are the clock sources for CCP1
10 = Timer3 and Timer4 are the clock sources for CCP3 through CCP5;
Timer1 and Timer2 are the clock sources for CCP1 and CCP2
11 = Timer3 and Timer4 are the clock sources for CCP1 through CCP5
T3CKPS1:T3CKPS0: Timer3 input clock prescale select bits
00 = 1:1 prescale value
01 = 1:2 prescale value
10 = 1:4 prescale value
11 = 1:8 prescale value
T3SYNC: Timer3 external clock input synchronization select bit
When TMR3CS = 1
0 = Synchronizes external clock input
1 = Do not synchronize external clock input
When TMR3CS = 0
This bit is ignored.
TMR3CS: Timer3 clock source select bit
0 = Instruction cycle clock (FOSC/4)
1 = External clock from pin RC0/T1OSO/T13CKI
TMR3ON: Timer3 on bit
0 = Stops Timer3
1 = Enables Timer3
Figure 8.8. T3CON contents (redraw with permission of Microchip)
Timer4
- Only available to the PIC18F8X2X and PIC6X2X devices.
- The block diagram of Timer4 is shown in Figure 8.9.
- The value of TMR4 is compared to PR4 in each clock cycle.
- When the value of TMR4 equals that of PR4, TMR4 is reset to 0.
- The contents of T4CON are identical to those of T2CON.
Prescaler Reset
FOSC/4 TMR4
1:1, 1:4, 1:16
2 Postcaler
Comparator
T4CKPS1:T4CKPS0 EQ 1:1 to 1:16
4
PR4
T4OUTPS3:T4OUTPS0
void OpenTimer0
p ((unsigned
g char config);
g);
void OpenTimer1 (unsigned char config);
void OpenTimer2 (unsigned char config);
void OpenTimer3 (unsigned char config);
void OpenTimer4
p ((unsigned
g char config);
g);
The arguments to these functions are a bit mask that is created by ANDing the values
from each category.
Example
writeTimer0 (15535);
Capture/Compare/PWM
p p ((CCP)) Modules
DCxB1:DCxB0: PWM duty cycle bit 1 and bit 0 for CCP module x
capture mode:
unused
compare mode:
unused
PWM mode:
These two bits are the lsbs (bit 1 and bit 0) of the 10-bit PWM duty cycle.
CCPxM3:CCPxM0: CCP module x mode select bits
0000 = capture/compare/PWM disabled (resets CCPx module)
0001 = reserved
0010 = compare mode, toggle output on match (CCPxIF bit is set)
0100 = capture mode, every falling edge
0101 = capture mode, every rising edge
0110 = capture mode, every 4th rising edge
0111 = capture mode
mode, every 16th rising edge
1000 = compare mode, initialize CCP pin low, on compare match force CCP pin high
(CCPxIF bit is set)
1001 = compare mode, initialize CCP pin high, on compare match force CCP pin low
(CCPxIF bit is set)
1010 = compare
p mode,, g
generate software interrupt p on compare
p match ((CCP p
pin
unaffected, CCPxIF bit is set).
1011 = compare mode, trigger special event (CCPxIF bit is set)
For CCP1 and CCP2: Timer1 or Timer3 is reset on event
For all other modules: CCPx pin is unaffected and is configured as an I/O port.
11xx = PWM mode
Figure 8.10 CCPxCON register (x = 1,..,5) (redraw with permission of Microchip)
- Each module is associated with a control register (CCPxCON) and a data register
(CCPRx).
- The data register
g in turn consists of two 8-bit register:
g CCPRxL and CCPRxH.
- The CCP modules utilize Timers 1, 2, 3, or 4, depending on the module selected.
- Timer1 and Timer3 are available to modules in capture or compare mode.
- Timer2 and Timer4 are available to modules in PWM mode.
- The assignment
g of a particular
p timer to a module is determined byy the bit 6 and bit 3
of the T3CON register as shown in Figure 8.11.
Figure 8.11 CCP and Timer interconnect configurations (redraw with permission of Microchip)
andd TMR1
edge detect T3CCP2 enable
TMR1H TMR1L
Q's CCPxCON<3:0>
Figure 8.13 Capture mode operation block diagram (redraw with permission of Microchip)
Capture
p Operation
p
void OpenCapture1
p p ((unsigned
g char config);
g);
void OpenCapture2 (unsigned char config);
void OpenCapture3 (unsigned char config);
void OpenCapture4 (unsigned char config);
void OpenCapture5
p p ((unsigned
g char config);
g);
There are two values for the parameter config: interrupt enabling and the edge to
capture.
Interrupt enabling
Edge to capture
C _EVERY
Cx V _FALL_EDGE
G : capture
captu e on
o every
eve y falling
a g edge
Cx_EVERY_RISE_EDGE : capture on every rising edge
Cx_EVERY_4_RISE_EDGE : capture on every 4th rising edge
Cx_EVERY_16_RISE_EDGE : capture on every 16th rising edge
Applications
pp of Capture
p Mode
Example 8.5 Period measurement. Use the CCP channel 1 in capture mode to
measure the period of an unknown signal assuming that the PIC18 MCU is running
with a 16 MHz crystal oscillator. Use the number of clock cycles as the unit of period.
The period of the unknown signal is shorter than 65536 clock cycles.
Solution:
Either two consecutive rising edges or two falling edges must be captured.
The difference of these two edges becomes the period of the signal.
The required timers settings are
#include <p18F8720.inc>
p
org 0x00
goto start
org 0x08
retfie
org 0x18
retfie
start bsf TRISC,CCP1,A ; configure CCP1 pin for input
movlw 0x81 ; use Timer1 as the time base
movwf T3CON,A ; of CCP1 capture
bcf PIE1,CCP1IE,A ; disable CCP1 capture interrupt
movlw 0x81 ; enable Timer1, prescaler set to 1,
movwf T1CON,A, ; 16-bit,, use instruction cycle
y clock
movlw 0x05 ; set CCP1 to capture on every rising edge
movwf CCP1CON,A ; "
bcf PIR1,CCP1IF,A ; clear the CCP1IF flag
edge1
g btfss PIR1,CCP1IF,A
, , ; wait for the first edge
g to arrive
bra edge1 ; "
movff CCPR1H,PRODH ; save the first edge
movff CCPR1L,PRODL ; "
#include <p18F8720.h>
void main (void)
{
unsigned
g int pperiod;
Let
ovcnt = timer overflow count
diff = the difference of two edges
edge1 = the captured time of the first edge
edge2
g = the captured
p time of the second edgeg
- The Timer1 overflow interruptp should be enabled after the first signal
g edge
g is
captured.
- Timer1 interrupt service routine simply increments ovcnt by 1 and returns.
Example 8.6
8 6 Write a program to measure the period of a signal connected to the CCP1
pin assuming that the instruction clock is running at 5 MHz. Make the program more
general so that it can also measure the period of a signal with very low frequency.
Solution:
#include <p18F8720.inc>
ov_cnt set 0x00 ; timer overflow count
per_hi
p set 0x01 ; high
g byte
y of edgeg difference
per_lo set 0x02 ; low byte of edge difference
org 0x00
goto start
orgg 0x08
goto hi_pri_ISR ; go to the high-priority service routine
org 0x18
retfie
#include <p18F8720.h>
p
#include <timers.h>
#include <capture.h>
unsigned int ov_cnt, temp;
unsigned
g short long
g pperiod;; /* 24-bit pperiod value */
void high_ISR(void);
void low_ISR(void);
#pragma code high_vector = 0x08 // force the following statement to
void high
g _interrupt
p (void)
( ) // start at 0x08
{
_asm
goto high_ISR
_endasm
}
#pragma interrupt high_ISR
void high_ISR (void)
{
if (PIR1bits.TMR1IF) {
PIRbits.TMR1IF = 0;
ov_cnt ++;
}
tempp = ReadCapture1(
p ( ); /* save the first captured
p edge
g */
PIR1bits.CCP1IF = 0;
PIR1bits.TMR1IF = 0;
INTCON |= 0xC0; /* enable global interrupts */
PIE1bits.TMR1IE = 1;; /* enable Timer1 rollover interrupt
p */
while(!(PIR1bits.CCP1IF));
CloseCapture1(); /* disable CCP1 capture */
temp1 = ReadCapture1( );
if ((temp1
p < temp)p)
ov_cnt--;
period = ov_cnt * 65536 + temp1 - temp;
}
- The 16-bit CCPRx register is compared against the TMR1 (or TMR3).
- When they match, one of the following actions may occur on the associated CCPx pin:
1. driven high
2. driven low
3. toggle output
4. remains unchanged
- The CCP1 and CCP2 modules can also generate this event to reset TMR1 or TMR3
depending on which timer is the base timer.
special event
trigger
CCPRxH CCPRxL
set flag bit
CCPxIF
Q S Output
Logic comparator
CCPx pin R match
output
enable
CCPxCON<3:0> T3CCP2 0 1
mode select
Figure 8.19 Circuit for CCP in compare mode (redraw with permission of Microchip)
- The CCP compare mode can be used to generate waveforms and create delays.
Example
p 8.7 Use CCP1 to ggenerate a pperiodic waveform with 40% duty y cycle
y and 1
KHz frequency assuming that the instruction cycle clock frequency is 4 MHz.
Solution: The waveform of 1 KHz waveform is shown in Figure 8.20.
400 s
600 s
no
CCP1IF = 1?
yes
set CCP1 pin low initially and then
pull high on match
no
CCP1IF = 1?
yes
set CCP1 pin high initially and then
pull low on match
Figure 8.21b Logic flow for generating a 1-KHz waveform with 40% duty cycle
#include <p18F8720.inc>
<p18F8720 inc>
hi_hi equ 0x06 ; number (1600) of clock cycles that signal
hi_lo equ 0x40 ; is high
lo_hi equ 0x09 ; number (2400) of clock cycles that signal
lo lo
lo_lo equ 0x60 ; is low
org 0x00
goto start
…
start bcf TRISC CCP1
TRISC,CCP1 ; configure CCP1 pin for output
movlw 0xC9 ; enable 16-bit Timer3, prescaler 1:1
movwf T3CON ; “
bcf PIR1,CCP1IF
movlw 0x09 ; CCP1 pin set high initially and
movwf CCP1CON ; pull low on match
; CCPR1 TMR3 + 1600 ; start a new compare operation
movlw hi_lo ; “
addwf TMR3L W
TMR3L,W ; “
movwf CCPR1L ; “
movlw hi_hi ; “
addwfc TMR3H,W ; “
addwfc TMR3H W
TMR3H,W ; “
bcf PIR1,CCP1IF
,
hi_time btfss PIR1,CCP1IF ; wait until CCPR1 matches TMR3
bra hi_time ; “
bcf PIR1,CCP1IF
movlw 0x08 ; CCP1 pin
p set low initiallyy and
movwf CCP1CON ; pull high on match
; CCPR1 CCPR1 + 2400 ; start another compare operation
movlw lo_lo ; “
addwf CCPR1L,F, ; “
movlw lo_hi ; “
addwfc CCPR1H,F ; “
lo_time btfss PIR1,CCP1IF ; wait until CCPR1 matches TMR3
bra lo_time ; “
bcf PIR1,CCP1IF
movlw 0x09 ; CCP1 pin set high initially and
movwf CCP1CON ; pull low on match
movlw hi_lo ; start another new compare
p operation
p
addwf CCPR1L,F ; “
movlw hi_hi ; “
addwfc CCPR1H,F ; “
bra hi_time
end
#include <p18F8720.h>
void main (void)
{
TRISCbits.TRISC2 = 0; /* configure CCP1 pin for output */
T3CON = 0xC9; /* turn on TMR3 in 16-bit mode, TMR3 & TMR4 as
base timer for all CCP modules */
CCP1CON = 0x09; /* configure CCP1 pin set high initially and pull low
on match */
CCPR1 = TMR3 + 1600; /* start CCP1 compare operation with 1600 cycles
delay */
PIR1bits.CCP1IF = 0;
while (1) {
while (!(PIR1bits.CCP1IF));
PIR1bits.CCP1IF = 0;
CCP1CON = 0x08; /* set CCP1 pin low initially, pull high on match */
CCPR1 += 2400; /* start CCP1 compare with 2400 as delay */
while (!(PIR1bits.CCP1IF));
PIR1bits.CCP1IF = 0;
CCP1CON = 0x09; /* change CCP1 setting */
CCPR1 += 1600;
}
}
Example
p 8.8 Use interrupt-driven
p approach
pp to generate
g the waveform specified
p in
Example 8.7.
Solution: This program uses a flag to select either 1600 (=0) or 2400 (=1) as the delay
count for the compare operation.
#include <p18F8720.inc>
hi_hi equ 0x06 ; number (1600) of clock cycles that signal
hi_lo equ 0x40 ; is high
lo_hi equ
q 0x09 ; number (2400)
( ) of clock cycles
y that signal
g
lo_lo equ 0x60 ; is low
flag equ 0x00 ; select 1600 (=0) or 2400 (=1) as delay
org 0x00
ggoto start
org 0x08
goto hi_ISR
org 0x18
retfie
start bcf TRISC,CCP1 ; configure CCP1 pin for output
movlw 0xC9 ; choose TMR3 as the base timer for
movwf T3CON ; CCP1
movlw 0x09 ; configure
g CCP1 pin
p to set high
g initiallyy
bsf PIE1,CCP1IE ; “
forever nop ; wait for interrupt to occur
bra forever
Example 8.9 Assume that there is a PIC18 demo board (e.g., SSE8720) running with a
16-MHz crystal oscillator. Write a function that uses CCP1 in compare mode to create
a time delay that is equal to 10 ms multiplied by the contents of PRODL.
Solution:
- Set the Timer3 prescaler to 1
- Use 40000 as the delay count of the compare operation
5V
10
8
PIC18F452
74HC04
1K
CCP1 2N2222
Example
p 8.10 Use the circuit in Figure
g 8.22 to ggenerate a siren that oscillates between
440 Hz and 880 Hz assuming the PIC18 is running with a 4 MHz crystal oscillator.
Solution: The procedure is as follows:
Step 1. Configure the CCP channel to operate in the compare mode and toggle output on
match.
Step 2. Start a compare operation and enable its interrupt with a delay equals to half of
the period of the sound of the siren.
Step 3. Wait for certain amount of time (say half of a second). During the waiting period,
interrupts will be requested by the CCP compare match many times. The interrupt
service routine simply clears the CCP flag and starts the next compare operation and
then return.
Step 4. At the end of the delay choose different delay time for the compare operation so
the siren sound with different frequency can be generated.
Step 5. Wait for the same amount of time as in Step 3. Again, interrupt caused by CCP
compare match will be requested many times.
Step 6. Go to Step 2.
#include <p18F452.inc>
hi_hi equ 0x02 ; delay count to create 880 Hz sound
hi_lo equ 0x38 ; "
lo_hi equ 0x04 ; delay count to create 440 Hz sound
lo_lo equ 0x70 ; "
org 0x00
goto start
org 0x08
goto hi_ISR
org 0x18
retfie
start bcf TRISC,CCP1,A ; configure CCP1 pin for output
movlw 0x81 ; Enable Timer3 for 16-bit mode, use
movwf T3CON,A ; Timer1 as the base timer of CCP1
movwf T1CON,A ; enables Timer1 for 16-bit, prescaler set to 1:1
movlw 0x02 ; CCP1 pin toggle on match
movwf CCP1CON,A ; "
bsf RCON,IPEN ; enable priority interrupt
bsf IPR1,CCP1IP ; configure CCP1 interrupt to high priority
movlw hi_hi ; load delay count for compare operation
#include <p18F452.h>
#define base 3125 /* counter count to create 0.1 s delay */
#define NOTES 38 /* total notes in the song to be played */
#define C4 0x777
#define F4 0x598
#define G4 0x4FC
#define A4 0x470
#define B4 0x3F4
#define C5 0x3BC
#define D5 0x353
#define F5 0x2CC
}
/* ----------------------------------------------------------------------------------------------------*/
/* The following function runs on a PIC18 demo board running with a 4 MHz crystal */
/* oscillator. The parameter xc specifies the amount of delay to be created */
/* ----------------------------------------------------------------------------------------------------*/
void delay (unsigned char xc)
{
switch (xc){
case 1: /* create 0.1 second delay (sixteenth note) */
T0CON = 0x84; /* enable TMR0 with prescaler set to 32 */
TMR0 = 0xFFFF - base; /* set TMR0 to this value so it overflows in
0.1 second */
INTCONbits.TMR0IF = 0;
while (!INTCONbits.TMR0IF);
break;
INTCONbits.TMR0IF = 0;
while
hil (!INTCONbi
(!INTCONbits.TMR0IF);
TMR0IF)
break;
case 6: /* create 1.2 second delay (3 quarter note) */
T0CON = 0x84; /* set prescaler to Timer0 to 32 */
TMR0 = 00xFFFF
FFFF - 12*base;
12*b /* set TMR0 to this
hi value
l so it
i overflows
fl
in 1.2 second */
INTCONbits.TMR0IF = 0;
while (!INTCONbits.TMR0IF);
b k
break;
case 7: /* create 1.6 second delay (full note) */
T0CON = 0x84; /* set prescaler to Timer0 to 32 */
TMR0 = 0xFFFF - 16*base; /* set TMR0 to this value so it overflows
i 1.6
in 1 6 secondd */
INTCONbits.TMR0IF = 0;
while (!INTCONbits.TMR0IF);
break;
default:
break;
}
}
CCPRxH (slave)
Comparator R Q
CCPx
TRISz<k>
TMRy (y
( = 2 or 4)) z = C or B or G
S
Comparator
Clear timer,
CCPx pin and
latch D.C
PRy (y=2 or 4)
Figure 8.24 Simplified PWM block diagram (redraw with permission of Microchip)
Step 1
Set the PWM period by writing to the PRy (y = 2 or 4) register.
Step 2
Set the PWM duty cycle by writing to the CCPRxL register and CCPxCON<5:4> bits.
Step 3
Configure the CCPx pin for output
Step 4
Set the TMRy prescale value and enable Timery by writing to TyCON register
Step 5
Configure CCPx module for PWM operation
Example 8.12 Configure CCP1 in PWM mode to generate a digital waveform with
40% duty cycle and 10 KHz frequency assuming that the PIC18 MCU is running with
a 32 MHz crystal oscillator.
Solution:
Timer setting
1. Use Timer2 as the base timer of CCP1 through CCP5 for PWM mode
2. Enable Timer3 in 1616-bit
bit mode with 1:1 prescaler
3. Set Prescaler to Timer2 to 1:4
I t ti sequence to
Instruction t achieve
hi the
th previous
i setting:
tti
Example 8.14 Write a program to dim the lamp in Figure 8.25 to 10% of its brightness
in 5 seconds assuming that the PIC18 is running with a 32 MHz crystal oscillator.
Solution:
- Set duty cycle to 100% initially. Load 99 and 400 as the initial period and duty
cycle register values.
- Dim the lamp by 10% in the first second by reducing the brightness in 10 steps.
- Dim the lamp down to 10% brightness in the next 4 seconds in 40 steps.
#include <p18F452.inc>
org 0x00
goto start
org 0x08
retfie
org 0x18
retfie
start bcf TRISC,CCP1,A ; configure CCP1 pin for output
movlw 0x81 ; Use Timer2 as the base timer for PWM1
movwf T3CON ; and enable Timer3 in 16-bit
16 bit mode
movlw 0x63 ; set 100 as the period of the digital
movwf PR2,A ; waveform
#include <p18F452.h>
#include <pwm.h>
#include <timers.h>
void delayy (void);
( );
void main (void)
{
int i;
TRISCbits.TRISC2 = 0;; /* configure
g CCP1 pinp for output
p */
T3CON = 0x81; /* use Timer2 as base timer for CCP1 */
OpenTimer2 (TIMER_INT_OFF & T2_PS_1_4 & T2_POST_1_1);
SetDCPWM1 (400); /* set duty cycle to 100% */
OpenPWM1
p ((99);
); /* enable PWM1 with pperiod equals
q 100 */
for(i = 0; i < 10; i++) {
delay();
CCPR1L --; /* decrement duty cycle value by 1 */
}
for(i = 0; i < 40; i++) {
delay();
CCPR1L -= 2; /* decrement duty cycle value by 2 */
}
}
DC Motor Control
- DC motor speed is regulated by controlling its average driving voltage. The higher
the voltage, the faster the motor rotates.
- Changing motor direction can be achieved by reversing the driving voltage.
- Motor braking can be performed by reversing the driving voltage for certain length
of time.
- Most PIC18 devices have PWM functions that can be used to drive DC motors.
- Many DC motors operate with 5 V supply.
- DC motors require large amount of current to operate. Special driver circuits are
needed for this purpose.
- A simplified DC motor control circuit is shown in Figure 8.26.
PIC18 MCU
direction
RB4
speed
CCP1 on/off Driver DC motor
feedback
CCP2
VSS
1 1 L293
0 16
CE1 1 L293 16 VSS 2 1
1 15
0 0 M
IN1 2 15 IN4
3 1 3
OUT1 3 14 OUT4 14
13
GND 4 13 GND 4
M 12
5
GND 5 12 GND
11
OUT2 6 11 OUT3
6 4
IN2 7 10 IN3 1 2 10 1
7 0 M
VS 8 9 CE2 0 9
8 1
0
Figure 8.27 Motor driver L293 pin assignment and motor connection
FeedBack
- DC motor needs the speed information to adjust the voltage output to the motor
driver circuit.
- A sensing device such as Hall-effect transistor can be used to measure the motor
speed.
- The Hall
Hall-effect
effect transistor can be mounted on the shaft (rotor) of a DC motor and
magnets are mounted on the armature (stator).
- The attachment of the Hall-effect transistors is shown in Figure 8.28.
- Each time the magnet passes by the Hall-effect transistor, a pulse is generated.
- CCP capture mode can be used to measure the motor speed.
- The schematic of a motor-control system is illustrated in Figure 8.29.
Magnets
Hall-effect
transistor
T/2
T is the time for one revolution
Figure 8.28 The output waveform of the Hall-effect transistor
VCC VCC
PIC18F452
1 16
8 3
15
CCP1 2 6.8F
13
RB4 7
12
0.33 F
4 L293
5
9 M
10 6
NC
11 14 VCC
VCC 6.8F
CCP2 1
30137
10K 3 2
All diodes are the same and could be any one of the 1N4000 series Hall-effect
switch
Figure 8.29 Schematic of a PIC18-based motor-control system
L293
PWM (CCP1)
A When A = B, torque
applied to motor = 0
A
Electrical Braking
- Once a DC motor is running, it picks up speed.
- Turning off the voltage to the motor does not stop the motor immediately.
- The momentum of the DC motor will keep the motor running after the voltage it
turned
u ed off.
o .
- An abrupt stop may be achieved by reversing the voltage applied to the motor .
- The duration of braking needs to be precisely measured.
Example 8.15
8 15 For the circuit shown in Figure 8.29,
8 29 write a function in C language to
measure the motor speed (in RPM) assuming that the PIC18 MCU is running with a 20
MHz crystal oscillator.
Solution:
- Motor speed can be measured by capturing two consecutive rising or falling edges.
edges
- Let diff and f are the difference of two captured edges and the Timer1 frequency.
Speed = 60 f ( 2 diff)
T3CON = 0x81; /* enables Timer3 in 16-bit mode and use Timer1 and Timer2 for
CCP1 thru CCP2 operations */
OpenTimer1(TIMER_INT_OFF & T1_16BIT_RW & T1_SOURCE_INT &
T1_PS_1_4);); /* set Timer1 prescaler
p to 1:4 */
PIR2bits.CCP2IF = 0;
OpenCapture2(CAPTURE_INT_OFF & C2_EVERY_RISE_EDGE);
while (!PIR2bits.CCP2IF);
edge1
g = CCPR2;; /* save the first risingg edge
g */
PIR2bits.CCP2IF = 0;
while (!PIR2bits.CCP2IF);
CloseCapture2();
diff = CCPR2 - edge1;
g ; /* compute
p the difference of two risingg consecutive edges
g */
temp = 1250000ul/(2 * diff);
rpm = temp * 60;
return rpm;
}