Hallo zusammen,
hier ist mal ein C-Code-Dissassemling von der Dutyvalue-Funktion eines
CCP-PWM-Programs,bei dem ich gerne wissen würde wie man mit
Assemblercode diese Funktion schreiben würde?
Mir ist nicht klar wenn ich eine 2 Byte große Variable anlege, wie diese
sich in zwei 8bittige aufteilt und dann zusammenhängend arbeitet?
__pcstackBANK0 hat der Compiler erzeugt, dir Declaration dazu sehe ich
leider nicht!?
Ebenso ist 0x21 der andere Teil der 16bit-Variable.
Eine Festwerteingabe von zb.1000 dezimal, müsste hier also mit
irgendeiner Funktion gemacht werden, die in High und Lowbits aufteilt??
Das Dutyregister kann 10bittig sein (Wert 1023) damit kommt man durch
den ganzen Wertebereich.
Der Compiler hat jedenfalls zwei 8bit-Files angelegt, die irgendwie
zusammenhängend verarbeitet werden?Ich will das ganze mal in
uncompiliertem Assembler-Code sehen!?
Rudi R. schrieb:> Hallo zusammen,
Servus,
> hier ist mal ein C-Code-Dissassemling von der Dutyvalue-Funktion eines> CCP-PWM-Programs,bei dem ich gerne wissen würde wie man mit> Assemblercode diese Funktion schreiben würde?
bei Fragen zu Assembler sollte man unbedingt die genaue Bezeichnung des
uC angeben. PICs haben teils spezifische Instruktions-Implementierungen,
die man dann auch gerne im "Instruction Set Summary" nachschlagen
möchte.
Die Instruktionen schauen nach einem PIC16 aus, aber welcher ist es
genau?
> Mir ist nicht klar wenn ich eine 2 Byte große Variable anlege, wie diese> sich in zwei 8bittige aufteilt und dann zusammenhängend arbeitet?
Naja, die zwei Byte bleiben auch zwei Byte. "Zusammenhängend arbeiten"
können sie durch die Beachtung/Behandlung des Carry-Flag der ALU. Das
nur nebenbei, denn bei ANDWF/ANDLW spielt Carry keine Rolle.
> __pcstackBANK0 hat der Compiler erzeugt, dir Declaration dazu sehe ich> leider nicht!?
Wenn man sich den Opcode von ANDWF anschaut, sieht man ja den Daten bzw.
Adressteil. Die Deklaration des Platzhalters ist hier erstmal nicht so
wichtig. Nur zu Info, die Variable wird auf einem Datenstack gehalten
d.h. ihre Adresse ist nicht zwingend bei jedem Aufruf der (leider nicht
vollständig gezeigten Funktion) gleich.
1
00D905A0ANDWF__pcstackBANK0,F
Der Opcode von ANDWF ist "00 0101 dfff ffff", dabei ist 'd' das
Direction-Bit und die 'f' stehen für eine Adresse im GPRAM. ANDWF kann
Werte von 0..127 verarbeiten, also 7 Bit. In der obigen Zeile steht also
die Adresse 0100000b == 0x20, das ist die niedrigste Adresse im GPRAM.
> Ebenso ist 0x21 der andere Teil der 16bit-Variable.> Eine Festwerteingabe von zb.1000 dezimal, müsste hier also mit> irgendeiner Funktion gemacht werden, die in High und Lowbits aufteilt??
Jein, die Aufteilung ist durch die Reihenfolge der Instruktionen
gegeben. Das untere (LSB) ist an der Adresse 0x20 abgelegt, das höhere
(MSB) an der Adresse 0x21.
> Das Dutyregister kann 10bittig sein (Wert 1023) damit kommt man durch> den ganzen Wertebereich.
Es ist 10 Bit breit und weil in ein Byte nur 8 Bit passen, stehen die
verbleibenden 2 in einem weiteren Byte. Das verUNDen von 0x03ff in
C-Zeile 84 sorgt dafür, dass in 0x20 und 0x21 die 6 msb Null sind, also
10 Bit "übrigbleiben", so kann man 0x20 und 0x21 nach der späteren
Schiebeoperation direkt in die 2 Byte des "Duty-Register" übertragen.
> Der Compiler hat jedenfalls zwei 8bit-Files angelegt, die irgendwie> zusammenhängend verarbeitet werden?> Ich will das ganze mal in> uncompiliertem Assembler-Code sehen!?
Dann muss man das selber schreiben.
Nachtrag:
>>
1
>88:{
2
>89:dutyValue<<=6;
3
>00E13006MOVLW0x6
4
>00E20140MOVLB0x0
5
>00E335A0LSLF__pcstackBANK0,F
6
>00E40DA1RLF0x21,F
7
>00E50B89DECFSZWREG,F
8
>00E628E3GOTO0xE3
In den ASM-Zeilen 00E3 und 00E4 spielt Carry eine Rolle. Was bei LSLF
nach links aus dem LSB "herausgeschoben" wird, kommt beim RLF von rechts
ins MSB. Beantwortet das deine Fragen wenigstens zum Teil?
Vielleicht noch fürs Verständnis, wie in ASM mit Datentypen umgegangen
werden kann: Die der in C geschriebenen Schiebeoperation folgende
Zuweisung soll die oberen 8 Bit von dutyValue nach CCPR1H übertragen.
Das muss "der Assembler" aber gar nicht machen, hier nimmt er einfach
das auf 0x21 liegende MSB (das ist es per Konvention) und überträgt es
übers W-Register nach CCPR1H. Die MOVLB-Instruktionen sind wegen der
Bankumschaltung nötig, da Daten aus dem GPRAM in Bank0 in ein SFR in
Bank6 übertragen werden müssen.
Meister E. schrieb:>> Mir ist nicht klar wenn ich eine 2 Byte große Variable anlege, wie diese>> sich in zwei 8bittige aufteilt und dann zusammenhängend arbeitet?>> Naja, die zwei Byte bleiben auch zwei Byte. "Zusammenhängend arbeiten"> können sie durch die Beachtung/Behandlung des Carry-Flag der ALU. Das> nur nebenbei, denn bei ANDWF/ANDLW spielt Carry keine Rolle.
Na es sind doch aber jeweils 1 Byte die zusammen eine 2 Byte-Einheit
bilden!?
Wie ist es mit dem Überlauf der LSB bei 256...dann wird doch in der
weiteren 8Byte-Einheit weitergeschrieben!?Wie geht der Sprung?Das sehe
ich hier nicht.
Wenn ich das jetzt als Assemblercode selbst schreiben will, müsste ich
von einer Variable zur nächsten wechseln um dort die folgenden Bits
weiterschreiben zu lassen.
Ich habe das mal mit diesem einfachem Code hier probiert, doch das File
der Adresse 0x21 blieb leer obwohl ich ja 1023 an die Variable übergeben
hatte, die ich als 2bytige angelegt habe, hier der PICAS-Test-Code:
Rudi R. schrieb:> Meister E. schrieb:>>> Mir ist nicht klar wenn ich eine 2 Byte große Variable anlege, wie diese>>> sich in zwei 8bittige aufteilt und dann zusammenhängend arbeitet?>>>> Naja, die zwei Byte bleiben auch zwei Byte. "Zusammenhängend arbeiten">> können sie durch die Beachtung/Behandlung des Carry-Flag der ALU. Das>> nur nebenbei, denn bei ANDWF/ANDLW spielt Carry keine Rolle.>> Na es sind doch aber jeweils 1 Byte die zusammen eine 2 Byte-Einheit> bilden!?
Ja, dann sind wir uns ja (fast) einig :)
Zwei Byte bleiben aber immer zwei Byte, eine "Einheit" bilden sie nur,
wenn der ASM-Code die Einzel-Bytes so behandelt, dass am Ende das
Ergebnis stimmt, von allein geht das nicht.
Aber in Deinem Code hast Du trotzdem versucht, gleich 10 Bit in ein Byte
zu schreiben:
1
MOVLW0x03FF;16Bit0000001111111111(1023)geladen
Hat der Assembler da gar nicht gemeckert? Mehr als die letzten 8 Bits
(11111111b) wird er in MOVLW nicht unterbringen können.
> Wie ist es mit dem Überlauf der LSB bei 256...dann wird doch in der> weiteren 8Byte-Einheit weitergeschrieben!?Wie geht der Sprung?Das sehe> ich hier nicht.
Es gibt keinen "Sprung", der Überlauf ist im/am Carry-Flag zu sehen. Und
um dieses sinnvoll zu nutzen, muss der gesamte Code das berücksichtigen.
Alle Instruktionen müssen so gewählt werden, dass die Information im
Carry-Flag so lange bestehen bleibt bis die gesamte Verarbeitung
abgeschlossen ist.
Schau nochmal in den Code von gestern. __pcstackBANK0 liegt auf Adresse
0x20, das höherwertige Byte auf Adresse 0x21 könnte man auch als
__pcstackBANK0+1 betrachten, das hätte Dich vielleicht weniger
irritiert.
> Wenn ich das jetzt als Assemblercode selbst schreiben will, müsste ich> von einer Variable zur nächsten wechseln um dort die folgenden Bits> weiterschreiben zu lassen.
Genau, das ist völlig richtig.
> Ich habe das mal mit diesem einfachem Code hier probiert, doch das File> der Adresse 0x21 blieb leer obwohl ich ja 1023 an die Variable übergeben> hatte, die ich als 2bytige angelegt habe, hier der PICAS-Test-Code:
Obwohl Du oben richtig lagst, hast Du hier einen Fehler gemacht. Du
kannst nicht 1023 in einem Datentyp speichern, der nur bis 255 geht.
Wie im gestern gezeigten Compilat muss sich das aufteilen auf zwei Byte,
eins in dem 0xff steht und ein Byte in dem 0x03 steht. Das Byte mit den
0x03 ist aber "256 mal soviel Wert" wie da steht. So kommt man auf
3*256+255=1023.
Ist es jetzt klarer?
Ok, hier habe ich Dein Testprogramm mal so geschrieben, dass es
funktioniert:
1
bankselPORTA
2
bsfBANKMASK(PORTA),0;PoweronLED@RA0
3
bankseldutyvalue
4
movlw0xFF;dieseunddienächsteZeilekann
5
andwfdutyvalue,f;mansichsparen,einverUNDenmit
6
;0xffändertdenWertindutyvalue
7
;nämlichüberhauptnicht
8
movlw0x03
9
bankseldutyvalue+1;dutyvalue+1könnteineiner
10
;anderenBankstehenalsdutyvalue
11
;(außermanhatdasaktivvermieden)
12
13
andwfdutyvalue+1,f;hierbleibennurdieBits0und1
14
;indutyvalue+1stehen
15
movfdutyvalue+1,w;weildervorigeBefehlseinErgebnis
16
;indutyvalue+1ablegt,mussmandenWert
17
;jetztwiederinsW-Registerholen
18
bankselPORTD
19
movwfPORTD;jetztdasW-RegisternachPORTDschreiben,
20
;dannwerdenauchRD0undRD1gesetzt
So sieht das aus. Man kann mit einer 8-Bit CPU eben nur so tun, als
hätte man größere Datentypen zur Verfügung. Stell Dir vor, du möchtest
einen 32-Bit Wert über eine serielle Schnittstelle übertragen, da
sendest Du vier Byte hintereinander und das empfangende System muss
wissen, in welcher Reihenfolge die Bits in den Bytes stehen und die
Reihenfolge der Bytes muss auch vorher ausgemacht sein, dann kann der
Wert im Zielsystem auch wieder richtig zusammengebaut werden.
Wenn du das innerhalb eines 8-Bit Systems machst, stimmt die Reihenfolge
der Bits schonmal, um den Rest musst Du Dich aber selbst kümmern.
Werkzeuge liefert der Befehlssatz genügend. Nenn doch bitte mal den
PIC-Typ, den Du konkret benutzt, dann kann ich ein Beispiel zeigen, dass
die vorhandenen Werkzeuge optimal ausnutzt. Weil z.B. nicht jeder PIC16
den Befehl ADDWFC kennt, mit dem man eine Addition mit Überlauf bequem
vornehmen kann.
Meister E. schrieb:> So sieht das aus. Man kann mit einer 8-Bit CPU eben nur so tun, als> hätte man größere Datentypen zur Verfügung. Stell Dir vor, du möchtest> einen 32-Bit Wert über eine serielle Schnittstelle übertragen, da> sendest Du vier Byte hintereinander und das empfangende System muss> wissen, in welcher Reihenfolge die Bits in den Bytes stehen und die> Reihenfolge der Bytes muss auch vorher ausgemacht sein, dann kann der> Wert im Zielsystem auch wieder richtig zusammengebaut werden.> Wenn du das innerhalb eines 8-Bit Systems machst, stimmt die Reihenfolge> der Bits schonmal, um den Rest musst Du Dich aber selbst kümmern.> Werkzeuge liefert der Befehlssatz genügend. Nenn doch bitte mal den> PIC-Typ, den Du konkret benutzt, dann kann ich ein Beispiel zeigen, dass> die vorhandenen Werkzeuge optimal ausnutzt. Weil z.B. nicht jeder PIC16> den Befehl ADDWFC kennt, mit dem man eine Addition mit Überlauf bequem> vornehmen kann.
Hallo Danke erst einmal für deine Hilfe, damit kann ich schon was
anfangen!...habe natürlich selbst weiter im Code geschaut um nach
brauchbare stellen zu gucken, da habe ich noch folgendes interessantes
gefunden!:
Hier geht es in einer weiteren Funktion darum für dutyvalue eine
Ersatzvariable zu beschreiben...die in Dutyvalue kopiert wird.Das hier
ist eine Zustandsabfrage von 2 Tastern die über TMR1-interrupt zyklisch
vollzogen wird und die Ersatzvariable bearbeitet...da ist diese
Überlaufaktion zu sehen, die du hier meinst!hiermit wird diese Variable
in ihren Grenzen definiert...zu deiner Frage welcher PIC hier bei mir
verwendet wird:es ist der PIC16F18877, den ich durch ein Lehrbuch wählte
in dem andere Beispiele durchgenommen werden.:0)
Rudi R. schrieb:> Hallo Danke erst einmal für deine Hilfe, damit kann ich schon was> anfangen!...habe natürlich selbst weiter im Code geschaut um nach> brauchbare stellen zu gucken, da habe ich noch folgendes interessantes> gefunden!:
Gerne, freut mich dass meine Beiträge nützlich sind.
> Hier geht es in einer weiteren Funktion darum für dutyvalue eine> Ersatzvariable zu beschreiben...die in Dutyvalue kopiert wird.Das hier> ist eine Zustandsabfrage von 2 Tastern die über TMR1-interrupt zyklisch> vollzogen wird und die Ersatzvariable bearbeitet...da ist diese> Überlaufaktion zu sehen, die du hier meinst!hiermit wird diese Variable> in ihren Grenzen definiert...zu deiner Frage welcher PIC hier bei mir> verwendet wird:es ist der PIC16F18877, den ich durch ein Lehrbuch wählte> in dem andere Beispiele durchgenommen werden.:0)>>>
1
73:if(++counter>=512)counter=0;
2
>// Variable Counter hochzählen
3
>007D3001MOVLW0x1
4
>007E07F8ADDWFcounter,F
5
>007F3000MOVLW0x0
6
>00803DF9ADDWFC0x79,F
7
>00813002MOVLW0x2
8
>00820279SUBWF0x79,W
9
>00833000MOVLW0x0
10
>00841903BTFSCSTATUS,0x2
11
>00850278SUBWFcounter,W
12
>00861C03BTFSSSTATUS,0x0
13
>00872889GOTO0x89
14
>0088288AGOTO0x8A
15
>0089288CGOTO0x8C
16
>008A01F8CLRFcounter
17
>008B01F9CLRF0x79
18
>74:}
19
>75:if(IO_RB0_PORT==1&&IO_RB1_PORT==0)
Ok, ich glaube hier müssen wir jetzt bremsen. Sowohl das Beispiel als
das Compilat sind nicht wirklich sinnvoll, sowas macht eine kostenlose
Compiler-Version um einem die Kaufvariante schmackhafter zu machen. Die
selbe Funktionalität kann man mit nur 6 oder 7 Instruktionen erreichen,
ganz ohne ADDWFC...
Meister E. schrieb:> Ok, ich glaube hier müssen wir jetzt bremsen. Sowohl das Beispiel als> das Compilat sind nicht wirklich sinnvoll, sowas macht eine kostenlose> Compiler-Version um einem die Kaufvariante schmackhafter zu machen. Die> selbe Funktionalität kann man mit nur 6 oder 7 Instruktionen erreichen,> ganz ohne ADDWFC...
OK,das hatte der Autor (Hanna Tam) hier im Buch auch erwähnt!...Ich habe
sowas schon geahnt und beschäftige mich nun mit den grundsätzlichen
Instruktionen vom Assembler...Nun muss ich sagen, das der
C-Codegenerator einem natürlich auch entgegenkommt, wenn man nur
Standardfunktionen benötigt, die nicht weiter verkoppelt und mit
Sonderfunktionen verbunden werden.Hier springt nähmlich eine Variable
für die andere ein und dadurch gibt es haufenweise GOTOs,die man so nur
schlecht auseinander Pflücken kann.Also gerade als Anfänger eine
bombastische Aufgabe.OK, wenn ich in Zukunft einfach mal logisch mit den
gegebenen Instruktionen arbeite, werde ich das wohl genau so sehen wie
du jetzt!;o)
Das sieht man erst,wenn man schon einige Programme und Probleme durch
hat denke ich.Ich danke mal wieder für die Mühe einem Einsteiger zu
helfen!Solche Leute wie du machen das Forum zu einem echt brauchbarem
Tool!
Das mit "counter+1" hatte ich bisher in noch keinem Assemblercode
gesehen, das muss ich doch nun gleich mal ausprobieren!
grundsätzlich ist die Seite https://www.sprut.de/index.htm ja sehr gut
dokumentiert, da hat sich jemand sehr große Mühe gegeben.Schade das hier
solche Variablen nicht beschrieben wurden, hier ist bei PWM in den
Beispielen nur das Lowregister benutz worden.Ich hätte lieber die volle
Bandbreite der Pulsmodulierung um später flexibler einstellen zu
können.(das ist für ein neuartiges Ladegerät für Bleiakkus)...muss ich
mir selbst bauen, gibt es so noch nicht auf dem Markt. Ich lade zwar
schon mit dem Prinzip sehr gut aber ich muss immer die Spannung
überwachen, was irgendwie blöd ist.
Gruß André :)
Hallo André,
vielen Dank für die Rückmeldung, so machts Spaß!
Edit:
Klingt interessant, was Du da vor hast. Würde mich freuen noch mehr
darüber zu erfahren, vielleicht magst Du Dein Projekt ja hier in der
Rubrik "Projekte & Code" vorstellen?
Meister E. schrieb:> Hallo André,>> vielen Dank für die Rückmeldung, so machts Spaß!>> Edit:> Klingt interessant, was Du da vor hast. Würde mich freuen noch mehr> darüber zu erfahren, vielleicht magst Du Dein Projekt ja hier in der> Rubrik "Projekte & Code" vorstellen?
Kann ich dann gern machen.
Nur kurz zudem was das Ding bei mir machen soll:
Die PWM soll für einen Step-UP Wandler am Ausgang einstellbar sein(für
unterschiedliche Spulen,die dann über einen MOSFET kurzgeschlossen
werden können bis deren Magnetfeld aufgebaut ist.
Die Energie, die die Spule nach dem Abschalten wieder abgibt soll auf
eine größere Kondensatorbank gehen.In dem Projekt habe ich 0,68F die ich
auf ca 30V bringe.
Wenn die Spannung erreicht ist, wird ein anderer Mosfet angesteuert, der
die Kondensatorbank über einen Bleiakku kurzschließt.Da fließt
kurzzeitig eine Menge Strom!(je nach Innenwiderstand der Batterie)
Der Kondensator wird aber nur auf ca 20V wieder entladen(über eine
andere Pulsweite im Millisekundenbereich.
Je besser die Batterie noch in Schuss ist, um so kürzer dürfen diese
Impulse dann sein und die Spannung am Kondensator kann auch
runtergestellt werden.
Das ist alles dann nach dem John Bedini-Prinzip...und das funktioniert
bisher mit meinem analogen Aufbau sehr gut.Die Batterien werden nicht
überhitz, es gibt weniger Gasung und man hat bei ca.15-16V Ladespannung
alles an Sulfhationen wieder umgewandelt, was nicht schon zu sehr großen
Kristallen herangewachsen ist!Und das ist heute leider immer durch die
unvollständigen Aufladungen von Standardgeräten der Fall!
Mein Solarregler macht zb. schon bei 14,2V Schluss...das ist nicht gut
für die Haltbarkeit der Batterie, weil so jedes mal nicht umgewandelte
Kristalle zurückbleiben, die dann auch noch immer größer werden, bis die
Kapazität merklich, frühzeitig sinkt.
Hier kommen noch kleine Phänomene dazu.(die Spannung nach erreichten
15,8V oder höher,bleibt nach abklemmen noch eine ganze Weile bei 13V
stehen!)
Ich glaube der Typ Bedini hat Recht mit seiner Energie aus dem Vakuum
oder wie auch immer.Nach Batteriekonditionierung,mehrfachen Ladungen und
Entladungen nur mit Strömen unter C/20, brauchen diese immer weniger
Zeit für die Ladung, weil die Platten immer glatter werden.(und eine
Batterie sollte niemals zu lange ruhen)
Nikola Tesla meinte ebenfalls, dass das Vakuum sehr viel mehr Energie
hat als wir uns vorstellen können!Der Casimir-effekt ist auch schon
entdeckt worden, doch wer redet denn mal über die Energie des Vakuums?
Und irgendwie ist unser Sonnensystem auch ein Perpetum,wenn man das mal
überdenkt,mir ist nicht bekannt, dass irgendwelche
Umrundungsgeschwindigkeiten um die Sonne abnehmen!?
Das Projekt ist eigenartig aber ich muss zeitig genug die Ladung
abschalten können,um später die Energieaufnahme messen zu können!?
Behauptung Bedinis:gut konditionierte Batterien nehmen im besten Fall
weniger Energie aus dem Eingangsstromkreis, als sie letztendlich
aufgenommen haben. Vermutlich Kaltströme der "Gegenseite" die an den
Zuleitungen zur Batterie mitwandern und keinen Leiter brauchen(Strudel,
Wirbel um den Leiter) ...keine Ahnung aber ich wills wissen.(Kalte
Fusion???)...halbwegs plausible Erklärungen gibt es dazu bereits
schon.Zb. Konstantin Meyl https://youtu.be/nWfI5hYvE88 Und ich glaube da
ist was...ich weiß auch nicht... auch wenn man mich jetzt für einen
Spinner hält! ;o)
Peter D. schrieb:> Rudi R. schrieb:>> 00DD 1E0E BTFSS CCP1CON, 0x4>> 00DE 28E0 GOTO 0xE0>> 00DF 28E1 GOTO 0xE1>> 00E0 28E7 GOTO 0xE7>> Hier sind aber 2 GOTOs zuviel.
Ja ich weiß...der Codegenerator MCC und das Dissassemling spuckt mir
auch noch die C-Code rein, die letztlich gar nicht aufgerufen
werden!?...nun ja, wer will über umgewandelte C-Code Assemblercode
lernen?? :o)
Vielleicht mal für jemanden der auch mit 8BIT-Mikros und Assemlercoden
rumfummelt. Hier habe ich jetzt mal meine TMR1 Interruptroutine und den
Variablentest, den ich zur Funktion gebracht habe,nachdem ich einige
Schlamper-Fehler finden musste.
Die Variablen Counterhigh und Counterlow, werden dann als nächstes an
die CCP1-Dutyvalue- Register übergeben oder ich nehme direkt die
Register dafür.
Timer1-Rollover lässt hier ein mal die Sekunde durch die
Tasterabfrageroutine laufen.Hier kann man noch mit Macros optimieren
usw.aber ich habe wie gesagt den umgewandelten C-Code studiert...und das
kam dabei raus!
;PORTRegister// 1 = Port pin is > V IH // 0 = Port pin is < V IL
212
213
CLRFPORTA
214
CLRFPORTB
215
CLRFPORTC
216
CLRFPORTD
217
CLRFPORTE
218
219
;ANSELANALOGSELECTREGISTER// 1 = Analog input. Pin is assigned as analog input (1) . Digital input buffer disabled. // 0 = Digital I/O. Pin is assigned to port or digital special function.
;ODCONOPEN-DRAINCONTROLREGISTER// 1 = Port pin operates as open-drain drive (sink current only) // 0 = Port pin operates as standard push-pull drive (source and sink current)
238
239
CLRFODCONA
240
CLRFODCONB
241
CLRFODCONC
242
CLRFODCOND
243
CLRFODCONE
244
245
;SLRCONSLEWRATECONTROLREGISTER// 1 = Port pin slew rate is limited // 0 = Port pin slews at maximum rate
246
247
MOVLW0xFF
248
MOVWFSLRCONA
249
MOVLW0xFF
250
MOVWFSLRCONB
251
MOVLW0xFF
252
MOVWFSLRCONC
253
MOVLW0xFF
254
MOVWFSLRCOND
255
MOVLW0x07
256
MOVWFSLRCONE
257
258
;INLVLINPUTLEVELCONTROLREGISTER// 1 = ST input used for PORT reads and interrupt-on-change // 0 = TTL input used for PORT reads and interrupt-on-change