Here is how I would re-arrange your code. I did not check for bugs and so it is nowhere near running condition. I understand what you are trying to achieve and below are some more comments.
Code:
list p=16F877
;************************************************* *****************
;* *
;* Filename: 16F877 PWM.asm *
;* Author: hetal *
;* Date: 10-Jun-06 *
;* *
;* PWM program for voltage regulation of buck converter *
;* *
;* Using a 16F877 with 20-MHz clock *
;* *
;* *
;* MPLab: 7.31 *
;* *
;* *
;************************************************* *****************
; Setting the constants
#include<P16f877.inc>
COUNT equ d'25'
;
;
;**************** Program Start ***********************
org 0 ;Reset Vector
goto init
org 4 ;Interrupt Vector
; goto int
;Interruption wait
;*************** Interruption Process *****************
;PWM control
int:
SAVE_CONTEXT
clrf pir1 ;Clear interruption flag
btfsc ADCON0,GO;wait until conversion is done
goto Wait
;Write the 8 most significant bits located in ADRESH (since we setup the
;registers to be left justified) to port C as an output.
movf ADRESH,W
movwf ccpr1l ;Set Duty cycle of PWM
;Start the A/D conversion by setting ADCON0<2>
bsf ADCON0,GO;start the A/D conversion
;************ END of Interruption Process **************
Wait:
LOAD_CONTEXT
retfie
;Setup for PWM operation
;**************** Initial Process *********************
init:
;***Port Initilisation
bsf STATUS,RP0 ;change to bank 1
movlw b'00000001' ; RA0 and RB0 are inputs
movwf TRISA
movwf TRISB
movwf 00h
movlw TRISC ; all are otuputs
bcf STATUS,RP0
;*** A/D converter initialization
movlw b'10000001' ;ADCS=10 CHS=AN0 ADON=ON
movwf ADCON0
bsf STATUS,RP0 ;move to bank 1
movlw b'00001110' ;ADFM=0 PCFG=1110
movwf ADCON1 ;set adcon1 register
; clrf ADCON1 ;left justified, all input A/D
bcf STATUS, RP0 ;return to bank 0
; movlw 0x41 ;fosc/32 [7-6],A/D on ch0[5-3]
;*** PWM initialization
; Set the PWM period by writing to the PR2 register
; the period chosen is 78.12 khz which is closer to 100khz that was chosen for my buck converter
;configuring the CCP1 module for PWM operation
movlw 0fh ; 00001111
movwf CCP1CON
clrf TMR2
bsf STATUS,RP0
movlw 3Fh ; value of pr2 calculated came upto be 63
movwf PR2
bcf STATUS,RP0
;Set the PWM duty cycle by writing to the CCPR1L register and CCP1CON<5:4> bits
movlw 26h ; 60 percent duty cycle as the ooutput voltage required is 6 volts and the input is a solar input in the range of
; 7-10 volts. the value of the pwm duty cycle on calculation came to be 153.6 which in 8 bit binary was 26h
movwf CCPR1L
bsf CCP1CON,CCP1Y
bcf CCP1CON,CCP1X
;Make the CCP1 pin an output by clearing the TRISC<2> bit.
bsf STATUS,RP0
movlw fbh
andwf TRISC,f
bcf STATUS,RP0
;set the TMR2 prescale value ad enable Timer2 by writing to T2CON
movlw b'0000100'; the prescaler is 1:1 and setting the tm2on
movwf T2CON
;*** Interruption control
bsf status,rp0 ;Change to Bank1
movlw b'01000000' ; ADIE=Enable
movwf pie1 ;Set ADIE and CCP1IE bit register
bcf status,rp0 ;Change to Bank0
movlw b'11000000' ;GIE=ON PEIE=ON
movwf intcon ;Set INTCON register
; Setting up the ports
bsf STATUS,5
movlw 00h
movwf TRISA
bcf STATUS,5
bsf ADCON0,GO;start the A/D conversion
;****************************************************
Start:
; Turning the LED on
movlw 02h ; red on
movwf PORTA
; Calling a delay
call Delay
call Delay
call Delay
call Delay
; Turning the Led off after the delay
movlw 04h; yellow on
movwf PORTA
call Delay
movlw 08h; green on
movwf PORTA
call Delay
call Delay
call Delay
call Delay
; Again calling a delay before switching so that it becomes
; visible the switchign on and off of the Led
goto Start
end
1. Although, this PIC can only have one interrupt routine, it can handle more than one interrupt source by checking the PIR1 for the source of interrupt.
2. I don't think CCP1IE and CCP1IF works with the CCP PWM mode. The PIC16F877 documentation is silent on this. However, you can use TMR2IE and TMR2IF with PWM. This interrupt occurs at 78.12Khz rate which may be too fast. You can postscale it from 1:2 to 1:4 (39.06Khz, 26.04Khz and 19.53Khz respectively). If you use timer2 as interrupt source, you can periodically (once every 38.4usec @ 26Khz) start an A/D conversion inside the ISR. The conversion will be finished in 19.2usec,allowing 19.2usec remaining time for data acquisition.
3. Alternatively, you can use the speed of the A/D converter to determine how fast you update the duty cycle registers. If you use ADIF to trigger an interrupt, you have to insert a short 10-20usec acquisition time delay before starting a new conversion. I would recommend using timer2 triggered interrupts instead.
4. You have to save/restore context in the ISR. See the datasheet.