I am working with a PIC 18F microcontroller from Microchip to continuously generate a rectangular signal. The code for the signal itself is at label5
.
I need to generate 255*20 pulses of this signal. So basically, I need to repeat the instructions from the first 4 lines at label 5 for 255*20 times. Because I cannot have numbers higher than 2^8, I needed to write the number this way.
label5 BSF portd,5
call timer1
BCF portd,5
call timer2
In the code below I tried to achieve this behavior. I gave variable1
the value of 255 and I decremented from this value until variable1
was zero, in which case I returned at label2
and restarted the program. Everytime I decremented the variable1
I called label4
. A similar things happens at label4
. Here I have another variable, variable2
, that is also decremented until it hits zero (and here comes the main signal generation program, repeated with each decrement operation), in which case, the program returns.
Can someone please tell me if I am on the right track ?
label2 movlw .255
movwf variable1
label3 call label4
decfsz variable1,1
goto label3
goto label2
; """"""""""""""
label4 movlw .20
movwf variable2
label5 BSF portd,5
call timer1
BCF portd,5
call timer2
decfsz variable2,1
goto label5
return
end
```
The general recommendation is to use timers to burn time, some would argue interrupts to have a possibility of putting the chip in a lower powered mode. But with processors like the PIC18 where you can count instructions and very accurately from that determine execution time to use simple loops to burn time.
Two ways to make a loop take longer and I am very rusty on my PIC coding so consider this psuedo-code:
variable2 = 0
label:
decfsz variable2,1
goto label
That essentially is 256 loops yes? and you can count instructions including the extra clock or whatever for the time that it is zero...
variable2 = 0
label:
nop
nop
decfsz variable2,1
goto label
Adding nops can burn more time (yes I may still not understand if it is time you are burning or simply want more loops).
Or if you want to make it more loops and you only have 8 bits to count with then nest the loops
variable1 = 20
variable2 = 0
outer:
inner:
; other stuff goes here?
decfsz variable2,1
goto inner
decfsz variable1,1
goto outer
the inner loop will count 256 times, the outer loop will count 20 so you get 20*256 total loops
I have used this type of approach to make very accurate signals that couldn't be made by using a timer with this processor a much more efficient instruction set and faster processor would need to be used to have done the same thing with a timer if even possible. But you would instead buy a product that has a timer peripheral that does what you are trying to do or a portion of it, for example infrared remote you can get some ST products that take two timer outputs and have the and gate in the chip, so you can have a hardware generated carrier signal and a hardware generated gate, but generate the duration of the gate via software. with the pic I just had some small loops to do the same thing and it was all timed by counting instructions.
I would not use this approach on a cortex-m, maybe an msp430, maybe an avr, but not something pipelined and not something that was purchased IP from someone else (arm doesn't make chips, st and nxp and others make chips and simply purchase IP from arm as well as most of the rest of the chip is not arm IP and each vendor can tweak the ip when the get it so the same core (cortex-m0+ rev x.y for example) in different chips does not necessarily behave the same).