Guten Tag!
Derzeit arbeite ich an einer Ladeschaltung fuer LiIon-Akkus, welche
soweit funktioniert. Zur Stromsteuerung verwende ich das
Digi-Potentiometer MCP4151, welches über SPI angesteuert wird.
Ladezeit-Timer ist der TMR0-Overflow-Interrupt (10ms-Interval).
Das Assemblerprogramm wurde mit MPASM geschrieben.
Das Problem:
Öfters, zu unbestimmtem Zeitpunkt,während des Ladevorganges, wird der
TMR0-Interrupt unvorhergesehen beendet und nicht mehr weiter ausgeführt.
Ich vermute, dass sich dieser Interrupt und der MSSP-Interrupt bei der
Datenübertragung durch das MSSP2-Modul in die Quere kommen und so ein
undefinerter Zustand entsteht.
Hat mir jemand einen Tip zur Abhilfe?
Ottmar
1
WiperValue_Set:
2
; 16-Bit Command, used to set wiper position
3
; Bit 15:8 Data1 Address (4bits), Command(2bits), Data (2bits)
4
; Bit 7;0 Data0 = value to be written to wiper-memory,
5
; is handed over through WREG
6
; Übergabe: Wiper_Value wird vom im WREG in Data0übernommen
Ottmar K. schrieb:> CALL WiperValue_Out ;Actual Wipervalue->LCD (MVP4151.P0W)
Das könnte zu lange dauern oder der HW-Stack (2 waren's glaube ich. Eine
haste damit ja schon wech) überlaufen?!
PS: Oh, wie modern. ;) Der hat 16 HW-Stacks. Das wirds dann wohl eher
nicht der Grund sein(?).
> Öfters, zu unbestimmtem Zeitpunkt,während des Ladevorganges, wird der> TMR0-Interrupt unvorhergesehen beendet und nicht mehr weiter ausgeführt.
Was soll das heißen, "unvorhergesehen beendet"? Hast du einen Watchdog
aktiv?
Ok, hier der betreffende Code, alles andere wie ADC, LCD usw klappt ja.
Nur sobald ich die Subrutine "Charge_Ctrl" aufrufe, wird nach
unregelmäigen Zeitabständen ca. 4-9 Minuten die ISR nicht mehr
aufgerufen (wurde mit LED
Kontrolliert, vgl. CTRL_LEDOFF/ CTRL_LEDON.
mit Grüßen Ottmar
@foobar
BANKSEL hat nichts mit Interrupts zu tun.
>BANKSEL label< ist lediglich ein vordefiniertes Macro, das der ASM-Compiler so
umsetzt, dass im Bank Select Register (BSR) das richtige Byte gesetzt ist um die
Register welche im gewählten Bank-Speicherbereich, liegen ansprechen zu können.
Anstatt movlw b'00001000' ;b3=1
movwf BSR
ist BANKSEL ANSELB
einfacher zu schreiben und schaltet z.B. beim 16F1827 zu Bank 3 um, in
welchen die Register für die Analogeingänge ANSELx zu finden sind.
Schon klar - aber im Interrupt muss das BSR ja evtl auch korrekt gesetzt
sein (und dann auch restauriert werden).
Wie gesagt, seit Ewigkeiten nix mehr mit den Teilen gemacht. Keine
Ahnung, ob das BSR bei ISR-Einsprung auf Standardwerte gesetzt wird oder
ob in seiner ISR nur Register benutzt werden, bei denen das BSR keine
Rolle spielt.
foobar schrieb:> Wie gesagt, seit Ewigkeiten nix mehr mit den Teilen gemacht. Keine> Ahnung, ob das BSR bei ISR-Einsprung auf Standardwerte gesetzt wird oder> ob in seiner ISR nur Register benutzt werden, bei denen das BSR keine> Rolle spielt.
Das Dingelchen hat ein "Schattenregister" für
1
•Wregister
2
•STATUSregister(exceptforTOandPD)
3
•BSRregister
4
•FSRregisters
5
•PCLATHregiste
(was ein Luxus:)
@TO
Sleep(?) hat da aber seine Tücken. Auch ein Reset, manipuliert an den
IRQ-Flags!?
PS: Es scheint aber nur eines zu geben.
Der "CALL" in der ISR, scheint da doch etwas mehr Zuwendung brauchen,
bzw. müsste man sich da noch selber drum kümmern und die Register
sichern?!
Ottmar K. schrieb:> Öfters, zu unbestimmtem Zeitpunkt,während des Ladevorganges, wird der> TMR0-Interrupt unvorhergesehen beendet und nicht mehr weiter ausgeführt.
Was meinst Du damit?
Irgendwo muß die CPU doch weitermachen oder bleibt sie stehen?
Du zeigst leider nicht den kompletten Interrupthandler, sondern nur 2
Include-Zeilen. Und auf magische Weise geht es zum "isr_tmr0".
Zeile 91 u. 125 sehe ich "bcf PORTA". Ich würde grundsätzlich immer "bcf
LATA" verwenden, um Portbits zu manipulieren.
Der TMR0 wird auf ".100" gesetzt. Das heisst, dass der Timer jetzt noch
156 mal zählt bis das IR-Flag gesetzt wird, ist es auch das, was du
möchtest?
P.S.
Ich sehe leider nicht wie und wo du die Variablen gesetzt hast.
In der ISR gilt übrigens "Bankselect" auch, d.h. wen du vor der ISR z.B.
auf Bank4 warst und nun den TMR0 bedienen willst, musst du natürlich auf
die entsprechende Bank schalten.
Nur wenn du die ISR verlässt wird die vorherige Bank automatisch von der
CPU über das Schattenregister wieder gewählt.
Gruss Herbert
In deiner Quelle steht das:
ORG 0x0004 ;INTERRUPT-VECTOR
#INCLUDE <01_ISR_LiIon.INC>
#INCLUDE <02_INIT_LiIon.INC>
und darauf folgt
main:
und viel weiter unten steht deine Interrupt-Service-Routine. Und die
endet mit
isr_end:
RETFIE
Das sieht für mich so aus, daß deine Service-Routine niemals
abgearbeitet wird - es sei denn, in <01_ISR_LiIon.INC> wird sie mit
normalem CALL aufgerufen. Dann aber ist das RETFIE völlig fehl am Platz.
Und ich vermisse die Rettung und Restaurierung von W und Status. Das
wäre das Mindeste.
Ganz generell sieht deine Quelle ziemlich unübersichtlich aus. OK, das
mag an dem Assembler von MicroChip liegen. Ich benutze da meinen
eigenen.
Also: Die PIC16 haben einen gemeinsamen Einsprung bei Interrupts, der
bei Adresse 4 liegt. Man sollte die ISR etwa so beginnen (hier wird auch
noch FSR gerettet):
ORG 4
Interrupt:
MOVWF RetteW ; W retten
SWAPF Status,W ; Flags in W holen
BCF RP0
MOVWF RetteFlags ; Flags retten
MOVF FSR,W
MOVWF RetteFSR
.. ab hier folgt die eigentliche Interruptbehandlung
für alle Interrupts
Und am Ende der ISR müssen zumindest W und Status restauriert werden:
IEnd: MOVF RetteFSR,W
MOVWF FSR
SWAPF RetteFlags,W ; gerettete Flags in W
MOVWF Status ; Flags restaurieren
SWAPF RetteW,F ; W restaurieren
SWAPF RetteW,W
RETFIE
Vielleicht wird bei dir das ganze Drumherum von dem Zeug erledigt, was
in der o.g. Include-Datei steckt. Aber dann ist ein RETFIE bei dir ein
Fehler deinerseits.
W.S.
Nun gut, wenn Du uns den Interruptcode nicht zeigen willst, Dein Bier.
In jedem Fall muß da ein BANKSEL stehen, um IO oder RAM zuzugreifen. Der
Interrupt weiß ja nicht, welche Bank gerade aktiv ist.
Wer ist denn dieser Dattalo?
Der Entprellcode kommt mir sehr bekannt vor und auch die Variablennamen
darin.
Peter D. schrieb:> In jedem Fall muß da ein BANKSEL stehen
Also Peter, wenn du dich mit den PIC16 nicht so sehr auskennst, dann
halte doch einfach mal die Finger still.
Sowas wie BANKSEL ist kein Maschinenbefehl, sondern ein Makro und
bewirkt, daß die RP0..RPx irgendwie gesetzt werden. Und die waren
zumindest bei den PIC16, die ich kenne, alle im Statusbyte. Wenn man
also das Statusbyte löscht, dann ist automatisch Bank 0 in Mode. Und
wenn man seine in der ISR benutzten Variablen im Bereich $70..$7F
ansiedelt, dann ist die gerade aktuelle Bank schnurz. Und wenn am
ISR-Ende das Statusbyte restauriert wird, dann ist damit auch die
Bankzuweisung automatisch restauriert.
Es mag da bei den PIC16, die mit vierstelliger Nummer daherkommen,
irgendetwas anders sein als bei den älteren mit nur dreistelliger
Nummer, aber das nachzulesen, ist eher die Obliegenheit des TO.
W.S.
p.s.
Peter D. schrieb:> Wer ist denn dieser Dattalo?> Der Entprellcode kommt mir sehr bekannt vor und auch die Variablennamen> darin.
Bist du versehentlich im falschen Thread gelandet?
W.S. schrieb:> Und ich vermisse die Rettung und Restaurierung von W und Status. Das> wäre das Mindeste.
Das trifft auf diese neueren Pics nicht mehr zu. Die neueren PiC 16f
haben jetzt für genau diesen Zweck die automatische Rettung, auch die
Ports werden durch latches sicherer gemacht.
von W.S. (Gast)
31.05.2022 10:52
> Sowas wie BANKSEL ist kein Maschinenbefehl, sondern ein Makro und> bewirkt, daß die RP0..RPx
Und die neueren Pics haben ein BSR-Register, mit dem kann nun
fortlaufend in den Banken gesurft werden.
Herbert
W.S. schrieb:> Es mag da bei den PIC16, die mit vierstelliger Nummer daherkommen,> irgendetwas anders sein als bei den älteren mit nur dreistelliger> Nummer, aber das nachzulesen, ist eher die Obliegenheit des TO.u
Es ist sogar einiges anders bei den vierstelligen. Wenn du immer noch
mit dem pic16f84 arbeitest, solltest du in diesem thread besser nicht so
laut daherkommen...
W.S. schrieb:> Wenn man> also das Statusbyte löscht, dann ist automatisch Bank 0 in Mode.
Dann zeig mir dochmal die Stelle im Code, wo das erfolgt, ich sehe die
nicht.
Nach der Vectoradresse verschwindet die Ausführung in einem Include.
Ich nehme mal an, das BANKSEL automatisch weiß, ob es STATUS oder BSR
beschreiben muß. Ich würde die Register daher nicht zu Fuß anfassen,
sondern immer den vorgesehenen Befehl nehmen.
Peter D. schrieb:> Ich nehme mal an, das BANKSEL automatisch weiß, ob es STATUS oder BSR> beschreiben muß. Ich würde die Register daher nicht zu Fuß anfassen,> sondern immer den vorgesehenen Befehl nehmen.
Nun, sowas wie BANKSEL ist nicht der liebe Gott. Und daß du Angst davor
hast, Register selbst zu lesen oder zu beschreiben, ist deine
Ängstlichkeit und damit dein Problem.
Fazit: hier weiß keiner außer dem TO, was sich nun tatsächlich in der
ominösen Includedatei befindet. Aber da zwischen dieser und der
Behandlung des Timers noch so einiges anderes an Code steht, ist es sehr
wahrscheinlich, daß die Behandlungsroutine per CALL gerufen wird und
folglich selbst nicht per RETFIE beendet werden sollte.
W.S.
W.S. schrieb:> Und daß du Angst davor> hast, Register selbst zu lesen oder zu beschreiben, ist deine> Ängstlichkeit und damit dein Problem.
Nö, ich habe damit kein Problem.
Wenn der Assembler was automatisch machen kann, dann lasse ich ihn das
auch machen und eliminiere damit unnötige Fehlerquellen.
Daß bei vielen Bänken dem STATUS die Bits ausgehen, dürfte klar sein.
Peter D. schrieb:> Nö, ich habe damit kein Problem.
Sei mal ehrlich zu dir selbst. Du schriebest:
"Ich würde die Register daher nicht zu Fuß anfassen"
Aber das hat mit dem seltsamen Problem des TO nix zu tun. Bei seinem
Zeug ist der Wurm drin und wir spekulieren hier herum, wo er denn
stecken könnte. Na ja, gute Nacht sozusagen.
W.S.
Nun ja, mit dem Code will ich nicht geizen, ist nur ziemlich viel. Ich
hänge mal alle INC-Files an, auch die *.lst-Datei, in der man sehen
kann, dass die verschiedenen INCLUDE-Files vom Compiler korrekt
zusammengeführt worden sind.
Indem ich INC-Files verwende, vereinfacht sich m.E. die Übersicht,
während ein einziges ASM-File bei größerem Code dann doch
unübersichtlier ist. Da sich dann nur die wichtigen aktuell zu
bearbeitenden Programmteile im ASM-File befinden.
@Teo
"Sleep" ist vom Debugging reingerutscht. Beim "echten Probelauf hatte
ich es natürlich entfernt.
@Herbert
Korrekt! Ich merke es mir künftig: vom Port lesen, zum LAT-Register
schreiben, dürfte aber für das Problemchen nicht ausschlaggebend sein.
Der TMR0-overflow-interrupt wird mit dem TMR0-Prescaler grob und mit dem
Preset des TMR0 + evtl. einigen 'nop' genau eingestellt. Daher der
Preset auf 100. Das ist beabsichtigt und funktioniert auch korrekt
Bankumschaltung - wie schon gesagt, übernehmen die "Enhanced Midrange
PIC" in eigener Regie. Ein Bankwechsel oder ein 'CALL' findet in der ISR
nicht statt.
Bein Eintritt in die ISR ist Bank0 automatisch vorgegeben. Diese wird
während der ISR beibehalten.
@Peda
das Programm läuft weiter, nur die ISR wird nicht mehr aufgerufen.
"magisch-> vgl. 'LiIon_1s_Lader.lst'
Interrupt-code ist nun anbei.
Die Entprell-Routine habe ich vor Jahren von www.piclist.com und dem
dortigen Link zu http://www.dattalo.com:80/technical/software.
Die Seite existiert jedoch nicht mehr)
@ WS
Die ISR wird genau dort eingefügt und auch beendet wo dies mit
#INCLUDE <01_ISR_LiIon.INC>
bezeichnet ist.
Ottmar K. schrieb:> @ WS> Die ISR wird genau dort eingefügt und auch beendet wo dies mit> #INCLUDE <01_ISR_LiIon.INC>> bezeichnet ist.
Naja, dann ist das ja ok. Ich hab mir eben mal dein Listfile angesehen.
Ist erstmal verwirrend, daß du am Anfang eine Breitseite von
Umbenennungen vornimmst. Aber OK, du nimmst ja einen anderen Assembler
als ich.
Was mir aber dennoch aufgefallen ist, ist daß du ohne jegliche Prüfung
das Interruptflag vom Timer0 ablöschst.
Bei mir sieht das etwa so aus:
ORG 4
Interrupt:
... diverse Rettungen
SKIP T0IF
GOTO _i1
; Interrupt aus Timer 0 --> InCounter
BCF T0IF
... sonstige Bearbeitung vom Timer0
_i1: SKIP TMR1IF
GOTO _i2
; Interrupt aus Timer 1 --> RefCounter
BCF TMR1IF
... sonstige Bearbeitung vom Timer1
_i2: ... abtesten von sonstigen Interrupts
... diverse Restaurierungen
RETFIE
Jedenfalls ist das bei den PIC16 mit dreistelligen Nummern so, daß es
nur einen einzigen Einsprung in die Interruptbehandelungen gibt und der
ist im Codesegment bei Adresse 4. Da drin muß man selber testen, welches
Interrupt-Flag aktiv ist und welche Behandlung folglich vonnöten ist.
W.S.
W.S. schrieb:> Was mir aber dennoch aufgefallen ist, ist daß du ohne jegliche Prüfung> das Interruptflag vom Timer0 ablöschst.
@ W.S.: So wie ich init.inc gelesen habe, ist nur bei TMR0 der Interrupt
aktiviert.
@ Ottmar: Hast du die errata-Datei vom Microchip schon angeschaut? Nach
grobem Durchsehen des Codes ist mir nichts Verdächtiges aufgefallen, du
hast alles gut dokumentiert.
Noch was, in "LiIon_1s_Lader.ASM" hat es sehr viele "call"und "goto".
Vielleicht solltet du nochmal Zeile um Zeile nachprüfen, ob alles
korrekt ist, z.B. kann ein "goto" in einer "call"-Routine verheerende
Folgen haben.
Es funktioniert!
Inzwischen habe ich den Code nochmals, auch unter Berücksichtigung der
gegebenen Hinweise überarbeitet. Ich kann den Grund nicht benennen, aber
das Programm läuft nun durch. Inzwischen wurden mehrere Akkus geladen,
ohne das dabei der genannte Fehler aufgetreten ist.
Bleibt mir also nur noch eines zu sagen:
Besten Dank an alle Ratgeber!
Ottmar
Ottmar K. schrieb:> Bleibt mir also nur noch eines zu sagen...
Was da bleibt, ist immer noch die Ungewißheit, wenn man die konkrete
Ursache nicht herausgefunden hat.
W.S.