![]() | ![]() | ![]() |
| | |||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
| | LinkBack | Thread Tools | Display Modes |
| | (permalink) | |
| Here is the code: Code: list p = 16F84A org 00h ; the reset vector is defined as address 00hex goto setup ; and we tell it to go to 'setup' ;.......Variables.......................................................... cblock 0Ch half_t sum sample1 overflow cnt endc ;.......Equates............................................................ w EQU 00h _tmr0 EQU 01h _status EQU 03h _option EQU 01h _portb EQU 06h ;=======Subroutines======================================================== ;~~~~~~~Delay Loop~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ delay clrf _tmr0 ; Start tmr0 dloop movf _tmr0,w ; Read tmr0 into w, w holds time subwf half_t,w ; half_t - tmr0 btfss _status,2 ; Check half_t - tmr0 = 0 goto dloop ; result is not 0 retlw 0 ; they are equal, return ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ freq bsf _portb,0 ; Output high... call delay ; for duration of 'half_t' bcf _portb,0 ; Output low... call delay ; for duration of 'half_t' retlw 0 ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;************************************************************************** setup bsf _status,5 ;move into bank 1 movlw b'00000000' ;porta as output movwf _portb ; movlw b'00000101' ;prescaler is /64 movwf _option ; bcf _status,5 ;back to bank 0 clrf _portb ;clears porta ;.......................................................................... ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ begin bsf _portb,1 movlw .37 movwf half_t call freq goto begin end ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;************************************************************************** ![]() As you can see the Duty cycle increases as the frequency goes up. This is due to a 'small' error in the 'delay' loop. This is how I am calculating the PWM: Quote:
Code: movlw .37 movwf half_t call freq As I am clearing tmr0 this takes another extra cycle per clearing? If so, this means on the 'on' it is 38*2 = 76 and on the off another 76 - this still does not explain the duty cycle skew.... Update - 15:43 +5GMT: I changed the TMR0 scaler to 1/32. This gives 31250/105 = 298 counts, but as I am only counting half - 149!
__________________ "Ambition is the last refuge of failure..." --Oscar Wilde "Success is not final, failure is not fatal: it is the courage to continue that counts." -- Winston Churchill | ||
| |
| | (permalink) |
| As I mentioned before, this comparing tmr0 and W is a strange way to do the delay - for a start it gives you two unnecessary instructions (movf and subwf) during the timing loop. By loading tmr0 with 255 minus the value you require (and also taking account of the 2 instruction cycles lost while writing to tmr0), you only need to check the tmr0 overflow flag. Doing it this way would reduce your delay 'jitter' time by at least 2uS, and make your code shorter as well. | |
| |
| | (permalink) |
| Ahh now I understand. Code: **removed Code: freq bsf _portb,0 ; Output high... movfw half_t movwf cnt call delay ; for duration of 'half_t' bsf _portb,0 ; Output high... movfw half_t movwf cnt call delay ; for duration of 'half_t' retlw 0 What do you think?
__________________ "Ambition is the last refuge of failure..." --Oscar Wilde "Success is not final, failure is not fatal: it is the courage to continue that counts." -- Winston Churchill | |
| |
| | (permalink) |
| This is the sort of routine I'm talking about, simply load W with the value you want, and 'call Delay' - bear in mind the timer will count upwards from this value till it overflows, so 245 would give a delay of 11 - or 200 would give a delay of 56 - the smaller the value, the longer the delay. Code: Delay MOVWF TMR0 ;load TMR0 from W BTFSS INTCON, T0IF ;wait for overflow GOTO $-1 RETURN | |
| |
| | (permalink) |
| Ahh okay! Code: delay movwf _tmr0 ; load this to the timer d1 btfss _intcon,2 ; if tmr0 overflow is not set goto d1 ; loop, else skip bcf _intcon,2 retlw 0 ; cnt = 0, so return Thanks Nigel! Update 23:33 +5GMT: Tested the following 16F84A code: Code: list p = 16F84A org 00h ; the reset vector is defined as address 00hex goto setup ; and we tell it to go to 'setup' ;.......Variables.......................................................... cblock 0Ch pulsewidth sum sample1 overflow cnt endc ;.......Equates............................................................ w EQU 00h _tmr0 EQU 01h _status EQU 03h _option EQU 01h _intcon EQU 0Bh _portb EQU 06h ;=======Subroutines======================================================== ;~~~~~~~Delay Loop~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ delay movwf _tmr0 ; load this to the timer d1 btfss _intcon,2 ; if tmr0 overflow is not set goto d1 ; loop, else skip bcf _intcon,2 return ; cnt = 0, so return ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ freq bsf _portb,0 ; Output high... call delay ; for duration of 'half_t' bcf _portb,0 ; Output low... call delay ; for duration of 'half_t' retlw 0 ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ;************************************************************************** setup bsf _status,5 ;move into bank 1 movlw b'00000000' ;porta as output movwf _portb ; movlw b'00000100' ;prescaler is /32 movwf _option ; bcf _status,5 ;back to bank 0 clrf _portb ;clears porta ;.......................................................................... ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ begin movlw .182 call freq goto begin end All this means is that the on delay is lasting a tad longer thant he off...I'm at a loss in spotting this..hrm!
__________________ "Ambition is the last refuge of failure..." --Oscar Wilde "Success is not final, failure is not fatal: it is the courage to continue that counts." -- Winston Churchill | |
| |
| | (permalink) |
| Maybe I should do this: Code:
delay btfss _intcon,2 ; if tmr0 overflow is not set
goto delay ; loop, else skip
bcf _intcon,2
return ; cnt = 0, so return
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
freq movwf _tmr0 ; load this to the timer
bsf _portb,0 ; Output high...
call delay ; for duration of 'half_t'
movwf _tmr0 ; load this to the timer
bcf _portb,0 ; Output low...
call delay ; for duration of 'half_t'
retlw 0
__________________ "Ambition is the last refuge of failure..." --Oscar Wilde "Success is not final, failure is not fatal: it is the courage to continue that counts." -- Winston Churchill | |
| |
| | (permalink) |
| Doing it this way does this: 105hz - 50.14% 210hz - 50.28% Any tips? Code: delay btfss _intcon,2 ; if tmr0 overflow is not set goto delay ; loop, else skip bcf _intcon,2 return ; return ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ freq movwf _tmr0 ; load this to the timer bsf _portb,0 ; Output high... call delay ; for duration of '256-w' bcf _portb,0 ; Output low... movwf _tmr0 ; load this to the timer call delay ; for duration of '256-w' retlw 0
__________________ "Ambition is the last refuge of failure..." --Oscar Wilde "Success is not final, failure is not fatal: it is the courage to continue that counts." -- Winston Churchill | |
| |
| | (permalink) |
| Perhaps you don't realise, but you're worrying about less than 1% change, as reported by your meter - who's accuracy probably won't be as high as that. I shouldn't worry about it!. | |
| |
| | (permalink) |
| Gotcha... :lol: My requirement is between 49-51% dutycycle but I'm just trying to see how close to 50% dead on I can get it
__________________ "Ambition is the last refuge of failure..." --Oscar Wilde "Success is not final, failure is not fatal: it is the courage to continue that counts." -- Winston Churchill | |
| |
| | (permalink) | |
| Quote:
But your meter is only so accurate, you're already closer than the meter can distinguish. Polling TMR0 is always going to give a slight variation, the few microseconds where you test the flag is always going to vary, depending on the exact instant the timer overflows. You could always use interrupts to try and prevent this, or (even easier) use simple software loops - where it takes exactly the same time every time. | ||
| |
| | (permalink) |
| Wy is it normal to overflow??? i mean doesn't that take some more cpu time and fault corrections..?? TKS | |
| |
| | (permalink) | |
| Quote:
| ||
| |