Hetal said:hii
i am new to programming and i would like to ask one ques how to code when i want two processes runnign simultaneously. Like i want the pwm to work and the leds to work simultaneously. and it has to loop forever for both of them.
the microchip i am using is pic16f877 and i want the help for the code in assembly language
btfsc PIEx,StatusFlag (say adc int: )
goto adc_isr_routine
btfsc <some other checking ,say INT>
goto int_handler_routine
goto isr_end
..
..
..
adc_isr_routine
..
..
..
goto isr_end
int_handler_routine
..
..
..
goto isr_end
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
Nigel Goodwin said:I would suggest you re-evaluate your 'need' for interrupts, I think you're just confusing your self! - as 'akg' mentioned you're not even using them correctly.
It's often possible to do it all in a software loop, then, perhaps later, use interrupts for one or two of the functions.
If you tell us what you're wanting to do, we can make suggestions as to what might be best?, but you do need to give all the details!.
motion said: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.
Hetal said:hi sorry for not including the details
my project overall involves..solar powere traffic light control.
so in my proj. we are stepping down the voltage by buck converter and then usng the microchip to regulate a 6v output and use the mocrochip for switching on the leds in a traffic light manner .
so the microchips basic function is
pwm and analog to digital conversion to get an output of 6v
leds to work from red to yellow to green
Nigel Goodwin said:For a start I would get the buck converter running, no need to worry about the traffic light part which is pretty trivial.
So setup the PWM module, details are in my PWM tutorial, then have a simple loop, reading the analogue input, and adjusting the PWM value accordingly - you will probably need a time delay before you loop back and read the analogue input again. You might also try taking multiple analogue readings and averaging them?.
Once that's working OK, and you've tested it under various loads, you could start adding the traffic light section. You could do it all in a single software loop, along with the buck converter, a PIC is more than capable of everything you want without using interrupts. However, I would suggest using a timer interrupt (personally I'd use timer2), and control the traffic lights within the interrupt routine.
The thing to remember is that the PWM is done entirely by the hardware, you tell it what mark/space ratio you want and it will continue doing that entirely independently while you go and do something else - this is a true 'simultaneous' process, as it's seperate hardware (although inside the PIC).
Hetal said:thanks for the info. i am looking into how to use timer interrupts now. moreover for the converter write now we are fixing the duty cycle to be 60 percent , so i dont need to worry about that. however my question arises onn that pwm is enough? i dont need to bother about analog to digital conversion.????i checked your code on pwm and i am making some modifications accordingly.
Nigel Goodwin said:If you just want a fixed 60% PWM, then you don't need the analogue to digital conversion.
For a timer interrupt example, check my seven segment tutorial, where I use timer2 interrupts to multiplex the display.
Hetal said:..oh sorry nigel i was trying to mix codes. now i have finally understood the code and also by looking through your tutorial ,i have come witht his final code.
i have initialised in the main routine the pwm port and the interrrupt control bits and for the itnerruption proces.. i have used the led working
thanks for ur help
PWM_PERIOD_MATCH
btfss PIR1,TMR2IF ;test on the trm2 interrupt flag
goto PWM_PERIOD_MATCH ; if reset keep checking
bcf PIR1,TMR2IF ; if set reset the flag
goto wait
wait NOP
return
Hetal said:1) Whats the main program supposed to be doing?.
the main program is initialising the ports and its helping for my pwm .. so basically i am doing my pwm of 60 percent duty cycle in the main program.
2) What's the interrupt routine supposed to be doing?.
well u mentioned to me previously to use interrupts .. the timer2 interrupts. so was it for my LEDS that i will be using. ?
3) Extra one - why interrupts at all?.
well i dont know i had aproblem of using two programs as i mentioned i want my LED to be workign as a traffic light... inconsequential of wht happens to my pwm output and i also want pwm to be working
so incase if i am not using interrupts can ijust include the code by calling a subroutine.. will it work continuously that was my question....
Initalise PIC
Set PWM to 60%
Loop
Set Traffic lights to 1
Call delay
Set Traffic lights to 2
Call delay
Set Traffic lights to 3
Call delay
Goto Loop
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?