Design IdeasDecember 19, 1996 |
Converting a random-width pulse to
a signal with the same frequency but with a 50% duty cycle isn't easy,
especially when the specified frequency range is large. The circuit in
Figure 1a
and the program in Listing 1 use an inexpensive µC to do the
job. The circuit's frequency range is 0.025 Hz to 20 kHz. The input pulse width
must be at least 10 msec.
The PIC16C54 is one of the fastest small µCs on the market. RA1 detects the input signal, and RA0 outputs the 50% duty-cycle version. The program sets up two 24-bit software counters in the µC's RAM: counter A and counter B. Counter A comprises cnt1, cnt2, and cnt3 in low-byte to high-byte order. Cnt11, cnt12, and cnt13 form counter B.
These two counters work alternately (Figure 1b). For example, during one period, counter A increments from 0 at a certain rate and counter B decrements at twice that rate. During the next period, counter A decrements at the doubled rate and counter B increments at normal speed. If the input signal's frequency doesn't change, the count value that counter B accumulates in the previous cycle equals the count value that counter A accumulates in the current cycle. Therefore, decrementing counter B at double the rate of counter A means that counter B reaches zero exactly in the middle of the input signal's period.
The program sets RA0 to high when RA1 changes from low to high and resets RA0 when counter B reaches zero. You can download the listing from EDN's Web site: /. At the registered-user area, go into the "Software Center" to download the file from DI-SIG, #1968. (DI #1968)
| Listing 1 --Random-Width to 50%-Duty-Cycle Converter | |
|
LIST P=16C54 cnt1 equ 8 ; counter A cnt2 equ 9 cnt3 equ 10 cnt11 equ 15 ; counter B cnt12 equ 16 cnt13 equ 17 last_in equ 18 PORTA equ 5 PORTB equ 6 org 0x1ff goto main org 0x0 main movlw 0x00 movwf cnt1 movwf cnt11 ; clean counters movwf PORTA movlw 0x02 tris PORTA ; set port A direction movlw 0x01 movwf last_in movwf cnt2 movwf cnt3 movwf cnt12 movwf cnt13 ; clean counters first bsf PORTA,0 ; first loop. set output=1 movlw 0x00 movwf cnt1 movlw 0x01 movwf cnt2 movwf cnt3 ; reset counter A lp_1 decfsz cnt11 ; decrease counter B once goto lp_2 goto lp_3 lp_2 decfsz cnt11 ; decrease counter B twice goto lp_4 lp_3 decfsz cnt12 goto lp_4 decfsz cnt13 goto lp_4 bcf PORTA,0 ; if counter B=0, set output=0 incfsz cnt1 ; increase counter A goto test1 incfsz cnt2 goto test1 incfsz cnt3 goto test1 goto main ; if over flow, return to start point |
test1 btfss PORTA,1 ; test input goto lp_5 ; if input=0, set last_in=0 and back btfsc last_in,0 ; if input=1 and last_in=1, back goto lp_1 movlw 0x01 ; if input=1 and last_in=0, set movwf last_in ; last_in=1 and go to second loop goto second lp_5 movlw 0x00 movwf last_in goto lp_1 second bsf PORTA,0 ; second loop, set output=1 movlw 0x00 movwf cnt11 movlw 0x01 movwf cnt12 movwf cnt13 ; reset counter B lp_6 decfsz cnt1 ; decrease counter A once goto lp_7 goto lp_8 lp_7 decfsz cnt1 ; decrease counter A twice goto lp_9 lp_8 decfsz cnt2 goto lp_9 decfsz cnt3 goto lp_9 bcf PORTA,0 ; if counter A=0, set output=0 lp_9 incfsz cnt11 ; increase counter B goto test2 incfsz cnt12 goto test2 incfsz cnt13 goto test2 goto main ; if over flow, return to start point test2 btfss PORTA,1 ; test input goto lp_10; ; if input=0, set last_in=0 and back btfsc last_in,0 ; if input=1 and last_in=1, back goto lp_6 movlw 0x01 movwf last_in ; if input=1 and last_in=0, set goto first ; last_in=1 and go to first loop lp_10 movlw 0x00 movwf last_in goto lp_6 end |
| EDN Access | feedback | subscribe to EDN! |