硬件圖:
源程序:
; 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