please dont rip this site


The PIC Source Book: Pwm

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.

Demonstrating Pwm.

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,
TOP NEW HELP FIND: 
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?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://linistepper.com/techref/microchip/seepicsrc/psbpix/pwm.htm"> The PIC Source Book: PWM</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?