Ich bin ein Neuling in der Mikrocontroller-Programmierung. Ich habe ein hohes Programmierverständnis, aber ich beteilige mich an der Entwicklung von CPUs/Mikrocontrollern mit geringem Hebel.
Ich möchte diese einfache Übung machen, um eine Reihe von LEDs für jeweils 1 Sekunde ein- und auszuschalten.
Ich habe diese Baugruppe ausprobiert (dachte an zwei LEDs):
List P=18F4550
include <P18F4550.inc>
CONFIG FOSC = INTOSC_EC ;INTOSC_EC ; Internal oscillator
CONFIG PWRT= ON ; Power-up Timer Enable bit
CONFIG BOR=OFF ; Brown-out Reset disabled in hardware and software
CONFIG WDT=OFF ; WDT disabled
CONFIG MCLRE=ON ; MCLR pin enabled
CONFIG PBADEN=OFF ; PORTB<4:0> pins are configured as digital I/O
CONFIG LVP=OFF ; Single-Supply ICSP disabled
CONFIG DEBUG = OFF ; Background debugger disabled
CONFIG XINST = OFF ; Extended Instruction disabled
;******************************Variables***********************************
count equ 0x00
;**********************************************************************************
org 0x0000
movlw 0x62
movwf OSCCON ;Working at 4 MhZ
clrf TRISD ;D port as output
;leds OFF so far
LGHTLOOP
bcf PORTD,0
call DELAY
bsf PORTD,0
CALL DELAY
bcf PORTD,1
call DELAY
bsf PORTD,1
CALL DELAY
bra LIGHTLOOP
DELAY
movlw .1000
movwf count
LOOP2
DECFSZ count,F
bra LOOP2
nop
return
end
Ich habe versucht, es mit der Proteus-Software zu simulieren, mit dieser Konfiguration:
Ich kann tatsächlich sehen, wie LEDs ein- und ausgeschaltet werden, aber nichts wie eine Sekunde, egal wie ich mich movlw .255
in DELAY
der Subroutine ändere. Ich habe es mit verschiedenen höheren Werten versucht und das gleiche seltsame Verhalten bekommen.
Was habe ich falsch gemacht?
Das Zählen der Befehlszyklen bei Unterprogrammen mit movlw .255
sollte mehr als 1 Sekunde dauern, denke ich. Aber die Simulation zeigt es immer noch schneller. Das Hinzufügen von zwei weiteren LEDs lässt es noch schneller erscheinen.
Das Problem besteht darin, dass der decfsz
Befehl implizit mit einem Ein-Byte-Register (8 Bit) arbeitet. Der größte Wert, den ein solches Register aufnehmen kann, ist hex FF (dezimal 255). Wenn Sie versuchen, auf dezimal 1000 (hex 3E8) zu initialisieren count
, setzen Sie dieses Register wirklich nur auf die niederwertigen 8 Bits dieses Werts oder E8 (dezimal 232).
Um diese Einschränkung des decfsz
Befehls zu umgehen, besteht die übliche Technik darin, eine "Verschachtelung" aus zwei Schleifen zu erstellen, die jeweils eine separate Variable verwenden. Dies würde es Ihnen ermöglichen, den inneren Schleifenkörper bis zu 65535 Mal auszuführen (hex 0xFFFF).
; control variable for inner loop
i equ 0
; control variable for outer loop
j equ 1
; initialize j with the MSBs of the loop count
movlw .1000 >> 8
movwf j
; initialize i with the LSBs of the loop count
movlw .1000 & 0xFF
movwf i
loop:
; body of loop here
nop
; end of inner loop
decfsz i
bra loop
; end of outer loop
decfsz j
bra loop
Beachten Sie, dass die innere Schleife so oft ausgeführt wird, i
wie bei der ersten Iteration der äußeren Schleife initialisiert wird. Danach läuft es jedes Mal 256 Mal.
nop
, erfordert jede Iteration 4 Maschinenzyklen, was bedeutet, dass Sie 250.000 Iterationen ausführen müssen. Das ist zu viel für die doppelt verschachtelte Schleife, also können Sie entweder mehr Anweisungen in den Schleifenkörper einfügen oder eine dritte Schleifenebene hinzufügen.Das brauchen Sie:
http://www.piclist.com/cgi-bin/delay.exe
wahrscheinlich die nützlichste Website, die je erstellt wurde. (Nach diesem!)
Es sollte beachtet werden, dass dies zwar Ihr Problem lösen wird, Ihnen aber auch absolut nichts darüber beibringen wird, wie Sie Ihr eigenes programmieren können, obwohl Sie es herausfinden können, wenn Sie den generierten Code lesen.
Die andere Antwort sollte richtig gelesen werden, wenn Sie ein echtes Verständnis wünschen. Dies ist nur, um Sachen zum Laufen zu bringen.
diegoaguilar
diegoaguilar
diegoaguilar
Samuel
diegoaguilar
nop
endlich eine. Das sollte die Verzögerung auslösen.Samuel
Spehro Pefhany