Here are some interesting observations about the size of the assembly code (and by extension, the size of the object code) for various ways of using the WAIT statement. All were generated on a PIC18F877A specified at 20MHz:
(I hope the text formatting comes out readable after this is Posted...here goes!...)
It seems that the code produced by WAIT is most compact when its argument is a byte-size literal, as shown in Example 1. For anything larger than a byte argument, the argument should be assigned to a word-size variable which is then passed to WAIT, as shown in Example 3 If you pass WAIT a word-size literal, the generated code can become quite huge, as shown in Example 2. Example 2 uses 500 bytes more code memory than Example 3
BEWARE!!!
Joe
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Trying to save space on PIC10f I did the following:
sub ledwait
wait 1 sec
return
Calling ledwait from main results in underflow error.
Only way to use wait, is to put 'wait 1 sec' on every occurrence which is very expensive in memory resources.
Any suggestions?
Al
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The problem there is that the 10F chips only have a very limited stack. There are 2 levels - calling ledwait from main uses a level, calling delay_s (the second delay sub) from ledwait uses another level, and the call from delay_s to delay_ms (the millisecond delay sub) uses a third. Since there are only 2 stack levels, there will be an overflow when delay_ms is called, and then an underflow when it tries to return from ledwait to main.
The only solution to this is to not use the second length delay from a subroutine on the 10F. I'd really suggest upgrading to a 12F6xx if you want to program a small PIC with GCBASIC - it will program a 10F but there are many limitations.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hmm, just wondering if PIC10F cpu defined that delayms could be reentrant with a counter to bring its effective delay the same as calling the ms delay sub?
Thanks vm for the info. I'll work around it somehow, as the 10f is needed for one application we are doing here.
sub ledwait
'provides one second delay for 10f family
count=0
do
wait 100 msec
until ++count=11
return
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
GCBASIC doesn't allow the ++ style increment used in C, so you'd have to increment count on the last line of the loop:
sub ledwait
'provides one second delay for 10f family
count=0
do
wait 100 msec
count += 1
until count = 10
end sub
Another alternative is to use Wait 1000 ms. It'll generate almost the same amount of code as Wait 100 ms (one extra instruction to be exact), since the millisecond delay always uses 16 bits to store the delay length:
sub ledwait
'provides one second delay for 10f family
wait 1000 ms
end sub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am experiencing bizarre behavior using a ms wait and timer1 in a program on a PIC 16F690. If i increase my wait from 25 ms to 75 ms my pulse length measurement bounces around all over the place. does not make any sense since it has no functional relation to my measurement code where I start and stop timer1. Any ideas on this?
Maybe a 75ms delay tends to end some time in the middle of a pulse and you're pulse timing code sees a one and starts timing from somewhere in the middle. If you add a line to check the pulseIn line is low first like this -
clearTimer 1
wait until pulseIn off
wait until pulseIn on
StartTimer 1
wait until pulseIn off
etc
the code will wait until there is a rising edge on pulseIn before starting its measurement. You might miss measuring some pulses though if thats whats happening.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Here are some interesting observations about the size of the assembly code (and by extension, the size of the object code) for various ways of using the WAIT statement. All were generated on a PIC18F877A specified at 20MHz:
(I hope the text formatting comes out readable after this is Posted...here goes!...)
Example 1) "WAIT 1 us":
movlw 2
movwf DELAYTEMP
DelayUS1
decfsz DELAYTEMP,F
goto DelayUS1
Example 2) "WAIT 1000 us"
movlw 255
movwf DELAYTEMP
DelayUS1
decfsz DELAYTEMP,F
goto DelayUS1
movlw 255
movwf DELAYTEMP
DelayUS2
decfsz DELAYTEMP,F
goto DelayUS2
movlw 255
movwf DELAYTEMP
DelayUS3
decfsz DELAYTEMP,F
goto DelayUS3
movlw 255
movwf DELAYTEMP
DelayUS4
decfsz DELAYTEMP,F
goto DelayUS4
movlw 255
movwf DELAYTEMP
DelayUS5
decfsz DELAYTEMP,F
goto DelayUS5
movlw 255
movwf DELAYTEMP
DelayUS6
decfsz DELAYTEMP,F
goto DelayUS6
movlw 135
movwf DELAYTEMP
DelayUS7
decfsz DELAYTEMP,F
goto DelayUS7
Example 3) "DIM time as word"
"time = 1000"
" Wait time us"
movlw 232
movwf TIME
movlw 3
movwf TIME_H
movwf SysWaitTempUS_H
movf TIME,W
movwf SysWaitTempUS
call Delay_US
It seems that the code produced by WAIT is most compact when its argument is a byte-size literal, as shown in Example 1. For anything larger than a byte argument, the argument should be assigned to a word-size variable which is then passed to WAIT, as shown in Example 3 If you pass WAIT a word-size literal, the generated code can become quite huge, as shown in Example 2. Example 2 uses 500 bytes more code memory than Example 3
BEWARE!!!
Joe
PS:
My bad typing in the part I used for my tests....it's a 16F877A, not an 18F877A
Joe
Also my bad....
I mean't to say that "WAIT 10000 us" would use 500 bytes more memory than the "WAIT time us" equivalent.
GCBASIC now has a longer delay, which it will insert when more than 770 clock cycles of delay are required. This should help with the bloat!
Trying to save space on PIC10f I did the following:
sub ledwait
wait 1 sec
return
Calling ledwait from main results in underflow error.
Only way to use wait, is to put 'wait 1 sec' on every occurrence which is very expensive in memory resources.
Any suggestions?
Al
The problem there is that the 10F chips only have a very limited stack. There are 2 levels - calling ledwait from main uses a level, calling delay_s (the second delay sub) from ledwait uses another level, and the call from delay_s to delay_ms (the millisecond delay sub) uses a third. Since there are only 2 stack levels, there will be an overflow when delay_ms is called, and then an underflow when it tries to return from ledwait to main.
The only solution to this is to not use the second length delay from a subroutine on the 10F. I'd really suggest upgrading to a 12F6xx if you want to program a small PIC with GCBASIC - it will program a 10F but there are many limitations.
Hmm, just wondering if PIC10F cpu defined that delayms could be reentrant with a counter to bring its effective delay the same as calling the ms delay sub?
Thanks vm for the info. I'll work around it somehow, as the 10f is needed for one application we are doing here.
sub ledwait
'provides one second delay for 10f family
count=0
do
wait 100 msec
until ++count=11
return
sri count=10
GCBASIC doesn't allow the ++ style increment used in C, so you'd have to increment count on the last line of the loop:
sub ledwait
'provides one second delay for 10f family
count=0
do
wait 100 msec
count += 1
until count = 10
end sub
Another alternative is to use Wait 1000 ms. It'll generate almost the same amount of code as Wait 100 ms (one extra instruction to be exact), since the millisecond delay always uses 16 bits to store the delay length:
sub ledwait
'provides one second delay for 10f family
wait 1000 ms
end sub
There is no context as to how the waits are being implemented. But if Port pins are being toggled, then one could use something like:
PulseOut GP1, 1000 ms
I am experiencing bizarre behavior using a ms wait and timer1 in a program on a PIC 16F690. If i increase my wait from 25 ms to 75 ms my pulse length measurement bounces around all over the place. does not make any sense since it has no functional relation to my measurement code where I start and stop timer1. Any ideas on this?
Thanks,
Mark
**********************************************************code
' initialize timer, prescaler 8
initTimer1 OSC, PS1_8
Dper = 0
period = 0
perL = 0
perH = 0
Do 'Main program Do
per1 = period
clearTimer 1
wait until pulseIn on
StartTimer 1
wait until pulseIn off
StopTimer 1
perH = TMR1H
perL = TMR1L
if perH < 11 then
period = 0
end if
if perH > 10 then
period = ((perH-11)*256 + perL)/2
end if
If period >= per1 then
Dper = period - per1
end if
If period < per1 then
Dper = per1 - period
end if
set led0 off
set led1 off
set led2 off
set led3 off
if Dper > 3 then
set Led0 on
if Dper > 6 then
set led1 on
if Dper > 10 then
set led2 on
if Dper > 15 then
set led3 on
end if
end if
end if
end if
wait 25 ms
loop
Maybe a 75ms delay tends to end some time in the middle of a pulse and you're pulse timing code sees a one and starts timing from somewhere in the middle. If you add a line to check the pulseIn line is low first like this -
the code will wait until there is a rising edge on pulseIn before starting its measurement. You might miss measuring some pulses though if thats whats happening.