![]() |
![]() |
![]() |
|
|
|||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
|
|
Thread Tools | Display Modes |
|
|
(permalink) |
|
hi guys,
i am pretty new in dis field of micro-controllers, could you guys please help me by sharing how to generate a 50 hz PWM , am using 16f877 as pic and 20MHz crystal oscillator. can i generate this pwm using software methods? actually my purpose is to control a servo motor with pwm 50 hz(20ms) and to vary between 1ms to 2ms duty cycle to obtain the angular motion of servo. we have budget constraints, so keen to know the software method that can be adopted. thanks in advance.... |
|
|
|
|
|
|
(permalink) |
|
Hi cgsumesh77,
If you were using a 4 MHz or 16 MHz crystal it would be relatively easy to use the PWM module plus some (interrupt) software for that solution. Unfortunately, a 20 MHz clock isn't the best frequency to use with the Timer 2 prescalers. Still, here's one possible solution for a 16 MHz clock which you might like to study. Basically, you setup the PWM module with a 1 KHz (1 msec) period and you use 20 of these 1 msec PWM "frames" to make up your 20 msec Servo period. At the end of each "frame" you setup the duty cycle for the next PWM "frame". At the end of 20 "frames" (20 msecs) you start over. Regards, Mike Code:
;******************************************************************
;
; // setup a 1000 usec PWM period with PR2 = 249 and prescaler
; // 16:1 (16 MHz clock) for 20 PWM 'frames' per 20 msec Servo
; // period and 1 usec pulse width resolution
;
; int servo = 1500; // 0..20000 in 1 usec 'ticks'
; int width = 0; // ISR work variable
; int frame = 1; // frame number 1..20
;
; void ISR()
; { PIR1bits.TMR2IF = 0; // clear Timer 2 interrupt flag
; if (--frame == 0) // if end of the 20 msec period
; { frame = 20; // reset for new 20 msec period
; width = servo; // reset 'width' work variable
; }
; if ((width > 1000) // if width > 1000 usecs
; { CCPR1L = 250; // do a 100% duty cycle frame
; CCP1CONbits.CCP1Y = 0; //
; CCP1CONbits.CCP1X = 0; //
; width -= 1000; // subtract 1000 usecs
; }
; else
; { CCP1CONbits.CCP1Y = (width & 1);
; CCP1CONbits.CCP1X = (width & 2);
; CCPR1L = (width >> 2); // 0..249 (0..999 usecs)
; width = 0; // force remaining frames to 0%
; }
; }
;
ISR_vect
;
; save main program context
;
movwf W_ISR ; save W-reg |B?
swapf STATUS,W ; doesn't change STATUS bits |B?
movwf S_ISR ; save STATUS reg |B?
clrf STATUS ; force bank 0 |B0
;
bcf PIR1,TMR2IF ; clear Timer 2 interrupt flag |B0
;
; check for start of new 20 msec servo period
;
decfsz frame,F ; end of 20 msec period? |B0
goto doframex ; no, branch, else |B0
movlw d'20' ; reset pwm frame number |B0
movwf frame ; |B0
movf servo,W ; setup 'pulse' work variable |B0
movwf width ; for new 20 msec servo period |B0
movf servo+1,W ; |B0
movwf width+1 ; |B0
doframex
movlw low(1000) ; width = width - 1000 |B0
subwf width,F ; |B0
movlw high(1000) ; |B0
skpc ; |B0
movlw high(1001) ; |B0
subwf width+1,F ; |B0
movlw d'250' ; assume 100% duty cycle frame |B0
bcf CCP1CON,CCP1Y ; |B0
bcf CCP1CON,CCP1X ; |B0
bc setdutyx ; borrow? no, branch, else |B0
movlw low(1000) ; |B0
addwf width,F ; |B0
movlw high(1000) ; |B0
skpnc ; |B0
movlw high(1001) ; |B0
addwf width+1,F ; |B0
btfsc width,1 ; |B0
bsf CCP1CON,CCP1X ; |B0
btfsc width,0 ; |B0
bsf CCP1CON,CCP1Y ; |B0
rrf width+1,F ; |B0
rrf width,F ; |B0
rrf width+1,F ; |B0
rrf width,W ; W = 0..250 |B0
clrf width ; force 0% duty cycle for the |B0
clrf width+1 ; remaining pwm frames |B0
setdutyx
movwf CCPR1L ; set duty cycle for next frame |B0
;
; restore main program context
;
swapf S_ISR,W ; |B0
movwf STATUS ; restore STATUS |B?
swapf W_ISR,f ; don't screw up STATUS |B?
swapf W_ISR,W ; restore W-reg |B?
retfie ; return from interrupt |B?
Last edited by Mike, K8LH; 21st May 2008 at 09:51 PM. |
|
|
|
|
|
|
(permalink) |
|
hi mike... thanks for the help man... let me try it out tomorrow in my lab...
|
|
|
|
|
|
|
(permalink) |
|
hi mike...
could i get the codes in c or assembly, or else can you please explain a bit more elaborated way, bcoz am still a bit unclear about how exactly does it works. i can generate a 1.22 khz instead of 1khz using 20Mhz frequency. then where should i connect my motor to.... am i going to get my 50 hz frequency from the pwm out pin of pwm module? is there a way that i can adjust this 1.22 khz to get a 1khz and then use the interrupt method to get a 50 hz frequency.. am using IAR work bench to compile my files... am really a beginer in dis stream... thanks for the help Last edited by cgsumesh77; 23rd May 2008 at 01:23 AM. |
|
|
|
|
| Bookmarks |
| Thread Tools | |
| Display Modes | |
|
|
|
|
||||
| Thread | Thread Starter | Forum | Replies | Latest |
| PIC 50Hz square | barkerben | Micro Controllers | 21 | 17th December 2007 11:12 AM |
| 50Hz Vs. 60Hz | samcheetah | General Electronics Chat | 19 | 1st October 2004 06:20 PM |
| 110V 50HZ adapter | bandit | General Electronics Chat | 2 | 13th August 2004 08:00 AM |
| Getting 230V 50Hz from Car Battery | Clyd3 | Electronic Projects Design/Ideas/Reviews | 11 | 13th July 2004 11:52 PM |
| 50hz transmitter | dark_conqueror | Electronic Projects Design/Ideas/Reviews | 1 | 10th November 2003 08:09 PM |