generates a bit stream of a specified duty cycle for digital-to-analog conversion.
Many designers think "hardware" when they need to convert a digital value to an analog voltage. For many applications, a firmware DAC like the PBASIC command Pwm (pulse-width modulation), can do the job with just an external resistor and capacitor.
The principle is simple. If the RC circuit shown here is connected to a square wave source that is high 50% of the time, the voltage across the capacitor will be 2.5 volts (assuming high = 5 volts and low = 0 volts). If the waveform is high 10% of the time, the voltage will be 0.5 volts.
The Pwm command generates variable duty-cycle waveforms from 0% to 100% in steps of 0.392% (1/255). Each time it is called, it outputs 256 pwm cycles with the specified proportion of highs to lows.
Pwm's output is not a high pulse of x duration followed by a low of y duration. It is a jumbled series of highs and lows whose overall proportion is x/y. That's because Pwm relies on the repeated addition of the duty value into an accumulator to generate carries. After each addition, it copies the carry bit to the output. This looks like a mess when viewed on an oscilloscope.
To use Pwm, set the desired pin to output, put the port number (0 to 2 for RA through RC) into w, put the pin number into the variable pin, and the duty cycle into the variable duty. Then call Pwm. Pwm emits 256 pulses at the specified duty cycle and then returns. At this time, your program should change the pin from output to input. This disconnects the pin from the RC integrator and prevents the steady state of the pin from altering the charge on the capacitor. The example program uses the duty cycle to vary the brightness of an LED. No RC integrator required.
Pwm, like the other routines that accept pin and port arguments, requires the short table Pinz. Remember that tables must be located in the first 256 words of a 512-word program memory page. One hint on using Pwm: always assign the port number to w immediately before calling the routine. If you don't, some other instruction that uses w may change its contents, causing an error.
To see Pwm in operation, connect the circuit below to an erasable PIC or PIC emulator, such as the Parallax downloader. Assemble and run PWM.SRC. The LED, initially off, will gradually glow brighter until it reaches full brightness. It will abruptly turn off, then repeat the process.
; ; *************************************************************************** ; *** Bubble Software Parallax to PIC Source Converter. Copyright 1999. *** ; *** http://www.bubblesoftonline.com email: sales@picnpoke.com *** ; *************************************************************************** ; ; PWM port (in w), pin, duty ; Generates a bit stream of 256 1s and 0s with the specified ; duty cycle. If this bit stream is run through a simple RC ; integrator, the result is an analog voltage output of ; (duty/255) * (PIC supply voltage). For example, if duty is ; 100 and the supply is 5 volts, then the integrated output of ; pwm would be (100/255) * 5 = 1.96 volts. In many applications, ; pwm output should be buffered with a unity-gain op-amp ; circuit. In those cases, the pwm output pin should be set up ; as an output when Pwm is called, then immediately switched to ; input when Pwm is done. This prevents the steady-state output ; of the pin from affecting the voltage set by Pwm. P = pic16c55 #include <16c55.inc> ; processor assembler definitions _CONFIG _xt_osc & _wdt_off & _protect_off reset start org 8 duty Res d'1' ; Pwm duty cycle. acc Res d'1' ; Pwm accumulator. index Res d'1' ; Temporary counter for pwm. pin Res d'1' ; Pin number to pulse (0-7). ; Device data and reset vector org 0 ; Table to convert pin number (0-7) into bit mask (00000001b to 10000000b). Pinz ADDWF pcl RETLW d'1' RETLW d'2' RETLW d'4' RETLW d'8' RETLW d'16' RETLW d'32' RETLW d'64' RETLW d'128' start MOVLW d'0' ; All outputs. TRIS 5h CLRF 5h ; Start with LED off. CLRF duty ; Initial brightness = 0. CLRF index ; Clear loop counter for pwm. start_loop MOVLW d'2' ; Pin 2. MOVWF pin MOVLW d'0' ; of port ra. CALL pwm ; Send pwm to LED. INCF duty ; Turn up brightness. GOTO start_loop ; Endless loop ; Upon entry, the desired pin must already be set up as an output. ; Variable "pin" contains the pin number (0-7). The w register contains a ; number representing the output port (0-2) for RA through RC. The variable ; duty contains the desired duty cycle from 0 to 255. Pwm MOVWF fsr ; Point to the port number. MOVLW 5h ; Add offset for port RA. ADDWF fsr MOVF pin,w CALL Pinz ; Get bit mask from the table. MOVWF pin ; Put the mask into pin. Pwm_loop MOVF duty,w ; Let acc = acc + duty ADDWF acc MOVF pin,w BTFSC status,c ; IF carry THEN pin = 1 IORWF indirect ; ELSE pin = 0. COMF pin,w BTFSS status,c ANDWF indirect DECFSZ index ; Repeat 256 times. GOTO Pwm_loop RETLW 0h end
; PWM port (in w), pin, duty ; Generates a bit stream of 256 1s and 0s with the specified ; duty cycle. If this bit stream is run through a simple RC ; integrator, the result is an analog voltage output of ; (duty/255) * (PIC supply voltage). For example, if duty is ; 100 and the supply is 5 volts, then the integrated output of ; pwm would be (100/255) * 5 = 1.96 volts. In many applications, ; pwm output should be buffered with a unity-gain op-amp ; circuit. In those cases, the pwm output pin should be set up ; as an output when Pwm is called, then immediately switched to ; input when Pwm is done. This prevents the steady-state output ; of the pin from affecting the voltage set by Pwm. device pic16c55,xt_osc,wdt_off,protect_off reset start org 8 duty ds 1 ; Pwm duty cycle. acc ds 1 ; Pwm accumulator. index ds 1 ; Temporary counter for pwm. pin ds 1 ; Pin number to pulse (0-7). ; Device data and reset vector org 0 ; Table to convert pin number (0-7) into bit mask (00000001b to 10000000b). Pinz jmp pc+w retw 1,2,4,8,16,32,64,128 start mov !ra, #0 ; All outputs. clr ra ; Start with LED off. clr duty ; Initial brightness = 0. clr index ; Clear loop counter for pwm. :loop mov pin,#2 ; Pin 2. mov w,#0 ; of port ra. call pwm ; Send pwm to LED. inc duty ; Turn up brightness. jmp :loop ; Endless loop ; Upon entry, the desired pin must already be set up as an output. ; Variable "pin" contains the pin number (0-7). The w register contains a ; number representing the output port (0-2) for RA through RC. The variable ; duty contains the desired duty cycle from 0 to 255. Pwm mov fsr,w ; Point to the port number. add fsr,#RA ; Add offset for port RA. mov w,pin call Pinz ; Get bit mask from the table. mov pin,w ; Put the mask into pin. :loop add acc,duty ; Let acc = acc + duty mov w,pin snc ; IF carry THEN pin = 1 OR indirect,w ; ELSE pin = 0. mov w,/pin sc AND indirect,w djnz index,:loop ; Repeat 256 times. ret
See also:
Interested:
Philippe Paternotte Says:
Unfortunately this routine has a problem. It is linear with a first slope until Duty=128. At this point the slope changes and it is linear again with this new slope until Duty=255. I've not managed to find what is the problem here.+
file: /Techref/microchip/seepicsrc/psbpix/pwm.htm, 9KB, , updated: 2013/6/5 08:13, local time: 2024/11/1 03:40,
18.116.85.12:LOG IN ©2024 PLEASE DON'T RIP! THIS SITE CLOSES OCT 28, 2024 SO LONG AND THANKS FOR ALL THE FISH!
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/techref/microchip/seepicsrc/psbpix/pwm.htm"> The PIC Source Book: PWM</A> |
Did you find what you needed? |