bsodmike
New Member
Here is the code:
And the output:
**broken link removed**
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:
NOTE!
The .37 is the PWM loading value, it defines the on/off time. 37*2 = 74 ; 15626/74 = 211hz
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!
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
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;**************************************************************************
And the output:
**broken link removed**
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:
Clock Speed: 4 Mhz
Program Speed: 4 Mhz/4 = 1 Mhz
TMR0 prescaler: 1 Mhz/64 = 15625 hz
Time for one TMR0 pulse is 1/15626 = 64µs
To measure the time for 100 hz let us consider the following:
1/100 = 0.01s ; 0.01/64µs = 156 TMR0 pulses.
Check: 1/(100*64µs) = 156
Therefore the 50% duty cycle is achieved by performing the following:
• Set output high
• Count TMR0 such that it is 156/2 (which is 50hz)
• Set output low
• Count TMR0 such that it is 156/2 (which is 50hz)
The above example will create a 100 hz signal with a duty cycle of 50%
NOTE!
Code:
movlw .37
movwf half_t
call freq
The .37 is the PWM loading value, it defines the on/off time. 37*2 = 74 ; 15626/74 = 211hz
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!