Forum: Mikrocontroller und Digitale Elektronik 12F683 Wieviele Befehle packt ein Interrupt? (Assembler))


von Wolf R. (Firma: Monster AG) (ik-student)


Lesenswert?

Hallo,

ich (Anfänger) bin beim Programmieren an einen Punkt gekommen, wo ich 
feststellen muss, dass meine Interrupt-Routine (TMR0 Interrupt) nicht 
mehr ordnungsgemäß funktioniert. Wenn ich einen gewissen stupiden 
Schritt (irgendwelche flags setzen um LED zum Leuchten zu bekommen) in 
einem Unterprogramm rauslasse funktioniert wieder alles. Vorab ich habe 
und muss alle Programmteile im Interrupt laufen lassen. Gibt es eine 
bestimmte Grenze wo in der Routine so viele Befehle drinnen sind, dass 
der Interrupt nicht mehr richtig funktionieren kann? So was ähnliches 
wie einen "worst-case" ?

Danke im Voraus
Gruß Wolf

von Severino R. (severino)


Lesenswert?

Es würde helfen, wenn Du den Programmcode posten würdest. Idealerweise 
auf das Minimum abgespeckt, um das Problem aufzuzeigen, und in beiden 
Versionen (also die die nicht funktioniert und die mit dem 
Unterprogramm, die funktioniert).

Hast Du das Ganze in Hardware getestet und/oder mit dem Simulator?

Sind die Banks korrekt ausgewählt?

Ist die Interrupt-Routine so lang, dass sie noch immer läuft wenn der 
nächste TMR0 Interrupt kommt?

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Das kannst du dir doch selber ausrechnen, bzw. abzählen. Die Timer 
werden doch mit dem selben Takt getaktet wie die Befehle abgearbeitet 
werden. Wenn also der Prescaler des Timer0 auf 1:1 steht, läuft der 
Timer0 nach genau 256 Befehlen über und erzeugt einen Interrupt. Bei 
Prescaler 2:1 entsprechend 512 Befehle usw. Wenn deine Interruptroutine 
mehr wie 256 (512, ...) Befehle abarbeiten muss dann trifft ein neuer 
Interupt ein, bevor der alte beendet wurde.

Du solltest die ISR so kurz wie möglich machen und den Rest in der 
Hauptroutine. Im Simulator siehst du übrigens wunderbar wie viele 
Befehle zwischen zwei Haltepunkten abgearbeitet werden.

Sven

von crazy horse (Gast)


Lesenswert?

Und dann noch die Zeit für Interruptaufruf, reti und evtl. Sicherungen 
diverser Register. Kenne aber den PIC nicht, um zu wissen, wieviel Takte 
das konkret kostet.
Eine ISR sollte jedenfalls nicht in die Nähe von 100% Prozessorzeit 
kommen :-)
Auch möglich sind evtl. stackprobleme.

von Wolf R. (Firma: Monster AG) (ik-student)


Lesenswert?

Danke für die schnelle Antwort!

@Severino R. wenn der TMR0 Interrupt kommt schalte ich ihn wieder aus, 
also kann kein anderer Interrupt in die Quere kommen, banks etc. sind in 
der Initialisierung alle richtig ausgewählt.

Aber das mit dem Simulator klingt interessant, aber da habe ich noch 
nicht so die große Ahnung, ich habe schon versucht damit zu arbeiten 
aber irgendwie habe ich es noch nicht geschafft mit Interrupts zu 
simulieren, da muss doch irgendwie der Interrupt simuliert ausgeführt 
werden, kann man das irgendwo einstellen ? ich arbeite momentan mit dem 
MPLAB IDE v8.10.

Einfacher wäre es richtig debuggen zu können aber leider geht das wohl 
mit diesem PIC nicht, nur simulieren !?


Gruß

von Severino R. (severino)


Lesenswert?

Wolf Retlaw wrote:
> banks etc. sind in der Initialisierung alle richtig ausgewählt.

Und später beim Ansprechen von Registern?

> Aber das mit dem Simulator klingt interessant, aber da habe ich noch
> nicht so die große Ahnung, ich habe schon versucht damit zu arbeiten
> aber irgendwie habe ich es noch nicht geschafft mit Interrupts zu
> simulieren, da muss doch irgendwie der Interrupt simuliert ausgeführt
> werden, kann man das irgendwo einstellen ? ich arbeite momentan mit dem
> MPLAB IDE v8.10.

Setze einen Breakpoint am Anfang Deiner ISR, und Du wirst sehen, dass 
das Programm dort stoppt!!!

> Einfacher wäre es richtig debuggen zu können aber leider geht das wohl
> mit diesem PIC nicht, nur simulieren !?

Wenn das Problem beim Simulator nicht auftritt, wird Debuggen mit dem 
ICD2 (das meintest Du doch, oder?) erst interessant. Wenn das Problem 
beim Simulator auch auftritt, solltest Du mit dessen Hilfe den Fehler 
suchen. Im Simulator läuft der Timer synchron zu den Einzelschritten; 
beim ICD2 läuft der Timer halt weiter, wenn das Programm angehalten 
wird.

Es gibt einen speziellen PIC12F683, der PIC12F683-ICD. Der hat 
zusätzliche Pins, um mit den ICD2-Signalen die knappen Pins nicht zu 
blockieren.
Der PIC12F683-ICD ist montiert auf einem kleinen Print "Header-Print" 
von Microchip erhältlich: Artikel AC162058. Auf dem Header-Print 
befindet sich auch der RJ-12 Anschluss, und der Print hat auf der 
Unterseite Stifte im DIL8-Layout, um ihn an Stelle des PIC12F683 in die 
Schaltung zu stecken.

von Wolf R. (Firma: Monster AG) (ik-student)


Lesenswert?

@Severino R. wow danke dir, und Ja ich habe ICD2, wusste gar nicht dass 
es einen speziellen PIC gibt! der wird aber bestimmt einiges kosten g

Habe übrigens meinen Fehler gefunden, zuviele Calls haben ein Problem im 
Stack ausgeführt schäm

Aber der Thread hat trotzdem einige neue Informationen locken können :-)

Gruß Wolf

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Mit einem ICD2 kannst du auch direkt im PIC debuggen. A

ber der Simulator ist für solche kleineren Probleme ganz gut. Du gehst 
halt einfach Schritt für Schritt durch. Wenn der Timer einen Interupt 
auslößt, springt das Programm automatisch auf Adresse 4 und arbeitet 
dann weiter. Wenn du nicht 256 mal klicken willst, kannst du auch das 
Timer0 Register einfach mit z.Bsp 255 beschreiben und dann weiter 
klicken. Probier einfach ein bisschen rum. Gerade als Anfänger kann man 
da wunderschön die meisten Sachen simmulieren. Du hast jedes Register im 
Blick und kannst eigene Werte eingeben. Mit dem Stimulus Controller 
kannst du auch externe Ereignisse simulieren z.Bsp. das an RB0 eine 
L/H-Flanke auftritt oder das Über die Serielle ein bestimmtes Bitmuster 
eingelesen wird. Alles noch ganz ohne Hardware.

Also wenn ich das richtig interpretiere benötigt der PIC nach dem 
Interuptereignis 5 Befehlszyclen bis er den Befehl auf Adresse 4 
abgearbeitet hat, genauso dann wieder bei einem RETFIE. Dann kommen 
natürlich noch bis zu 10 Befehlen wo man die Register rettet und das 
Interupt-Ereignis abfragt (die 16F PICs kennen nur eine Interuptadresse, 
deshalb muss man als erstes feststellen welcher Interupt aufgetreten 
ist). Am Ende wieder das selbe. Da können schon mal 20-30 Befehle drauf 
gehen, bevor du in deiner Routine bist.

Ein Interupt kommt dir innerhalb der ISR normalerweise sowiso nicht in 
die Quere, da der PIC das GIE-Flag deaktiviert sobald er in die ISR 
springt. Damit sind alle Interupts abgeschaltet, solange die ISR läuft. 
Allerdings können trozdem Ereignisse auftreten, welche das entsprechende 
Bit wieder enabeln. Sobald die ISR verlassen wird und es trat 
zwischendurch ein Ereignis auf springt der PIC sofort wieder in ISR und 
arbeitet den Interupt ab. Also angenommen deine ISR benötig 1000 
Befehle, dann würde der Timer0 mit Prescaler 1:1 in dieser Zeit 3x das 
T0IF setzen. Damit gehen dir die Interupts verloren und dein Programm 
arbeitet nicht korrekt.

Stell dein Prog doch mal hier ein, dann können wir mal drüber schauen. 
Eventuell gest du die Sache ja falsch an.

Gruß
Sven

von Severino R. (severino)


Lesenswert?

Wolf Retlaw wrote:
> @Severino R. wow danke dir, wusste gar nicht dass es einen speziellen
> PIC gibt! der wird aber bestimmt einiges kosten *g*

Wenn das Ding hilft, Zeit zu sparen... Kostenlos gibt es das Teil nicht, 
aber es ist ja ein Entwicklungswerkzeug, das man dann nicht in der 
fertigen Schaltung belässt, sondern wieder benutzen kann.

Bei Farnell EUR 18.00

> Habe übrigens meinen Fehler gefunden, zuviele Calls haben ein Problem im
> Stack ausgeführt schäm

Wow! mehr als sieben CALLs in einer ISR!!!

von Sven S. (stepp64) Benutzerseite


Lesenswert?

So schön wie das ist mit den Unterprogrammen, aber bei einer Stacktiefe 
von 8 muss man schon aufpassen und es nicht übertreiben mit den Calls. 
Ein Call benötigt auch zwei Befehlszyklen und das Return dann auch 
wieder. Für ein Unterprogramm mit 2-3 Befehlen also unnötig. Dann doch 
lieber wieder copy and paste...

Sven

von Severino R. (severino)


Lesenswert?

Sven Stefan wrote:
> Dann doch lieber wieder copy and paste...

Oder ein MACRO.

von Wolf R. (Firma: Monster AG) (ik-student)


Lesenswert?

Macro?

von Sven S. (stepp64) Benutzerseite


Lesenswert?

Ja, du definierst ein paar Zeilen Code als Macro und rufst dann im 
Programm an der Stelle das Macro auf, wo du den definierten Programmcode 
einfügen willst. Ist eigentlich nur ein optischer Trick um den Quellcode 
übersichtlicher zu gestalten. Der Compiler fügt beim Übersetzen genau 
den Quellcode an der Stelle ein wo du das Macro aufrufst. Du sparst 
damit also keinen Speicherplatz.

Bsp:
1
;Macro definieren
2
Bank0  macro
3
  bcf STATUS,RP0  ;Bank 0
4
  bcf STATUS,RP1
5
  endm
6
7
;Macro aufrufen
8
         Bank0

An der Stelle wo du das Macro aufrufst werden vom Compiler beim 
übersetzen die beiden Befehlszeilen eingefügt. Im Quellcode steht aber 
nur Bank0 als Befehl.

Sven

von Severino R. (severino)


Lesenswert?

@ Wolf:
Falls Du MACROs nicht kennst: Du kannst auch "Argumente" verwenden, also 
eine Art Parameter, welche jedoch (anders als bei z.B. Funktionsaufrufen 
in Hochsprachen) zur Assemblierzeit (und nicht erst zur Laufzeit) 
ersetzt werden.
Deshalb müssen die Argumente Konstanten sein.

Näheres im Manual von MPASM sowie z.B.:
http://www.fernando-heitor.de/component/option,com_smf/Itemid,121/topic,1245.0/

von Wolf R. (Firma: Monster AG) (ik-student)


Lesenswert?

Ok,

vielen Dank an euch! Heute habe ich wieder einiges gelernt :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.