Forum: Mikrocontroller und Digitale Elektronik Timer0 löst PCINT1 Interrupt aus?


von dost0011 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe meinen Code jetzt so runtergestrickt, dass er nur noch aus dem 
besteht, was NICHT funktioniert...

Ich nutze für eine Fast PWM einen Timer0 und der löst mir (warum auch 
immer) einen PCINT1 Interrupt aus (zumindest in der AVR-Studio 
Simulation2)

AVRSTudio 4.19
ATTINY 85

Bitte schaut Euch mal die Datei im Anhang an und erklärt mir woher 
dieser ungewünschte Reset kommt, wenn der Timer0 von 255 auf 0 springt. 
Ich schnalls echt nicht warum es eine Verbindung zwischen den beiden 
Größen gibt...

Vielen Dank.

von Hallo (Gast)


Lesenswert?

1
ISR(PCINT0_vect)
2
{
3
  _NOP();
4
}

Müsste es nicht "PCINT1_vect" heissen?

von Thomas E. (thomase)


Lesenswert?

dost0011 schrieb:
> Ich nutze für eine Fast PWM einen Timer0 und der löst mir (warum auch
> immer) einen PCINT1 Interrupt aus (zumindest in der AVR-Studio
> Simulation2)
Ich hab' den Simulator noch nie benutzt. Aber hardwaremässig ist das 
natürlich Unsinn.

Du setzt aber PB1:
>PORTB = (1<<PIN_Trittfrequenz)|(
Und das ist ein Pinchange. Denn vorher war der 0. Und das Interrupt-Flag 
wird unabhängig vom Interrupt-Enable gesetzt. Sonst könnte man das ja 
nicht pollen.
Einfach das PCIF im GFIR vor sei() löschen. 1 reinschreiben!

mfg.

von Thomas E. (thomase)


Lesenswert?

Thomas Eckmann schrieb:
> Und das Interrupt-Flag
> wird unabhängig vom Interrupt-Enable gesetzt. Sonst könnte man das ja
> nicht pollen
Das stimmt so nicht. Ist auch bischen unlogisch, weil die Maske noch 
nicht gesetzt ist.
Gesetzt wird das Interrupt-Flag, wenn PCIEx gesetzt wird(ist). Je 
nachdem wann man den Pullup schaltet. Klar, wenn er zuletzt gesetzt 
wird, ist es auch nicht anders zu erwarten.

//Taste, Pin Change Interrupt PCINT8
   PORTC |= (1 << 0);
   PCMSK1 |= (1 << PCINT8);
   PCICR = (1 << PCIE1);

egal in welcher Reihenfolge.
Setzt man den Pullup, nimmt ihn wieder weg und dann PCIEx passiert gar 
nichts.

Also das ist auf jeden Fall zu machen:
>Einfach das PCIF im GFIR vor sei() löschen. 1 reinschreiben!

So ist das beim Atmega48pa. Beim 644p tritt dieses Phänomen nicht auf.
Also mal so mal so. Beim Tiny85 ist es scheinbar so wie beim 48.

mfg.

von dost0011 (Gast)


Lesenswert?

Natürlich muss dass PCINT1_vect heissen. Man bin ich ein Trottel. Habe 
die Hardware umbesinnend und vergessen den Interrupt mit anzupassen.

Das mit dem PinChange war mir nicht bewusst, dass ich bereits ein 
IntFlag bekomme, auch wenn SEI noch nicht freigegeben ist.
Das das setzen eines Pullup Widerstandes zu einem PINCHANGE führt, war 
mir auch nicht klar.

Vielen Dank!!!

von Peter D. (peda)


Lesenswert?

dost0011 schrieb:
> Natürlich muss dass PCINT1_vect heissen.

Wie soll das gehen?
Der ATtiny85 hat keinen PCINT1_vect.


Peter

von Hallo (Gast)


Lesenswert?

Stimmt, es ist PCINT1/PB1 u. muss PCINT0_vect lauten ...PCINT0_vect war 
also doch richtig.

von Hannes L. (hannes)


Lesenswert?

Verwechselt da jemand PCINT und INT0?

...

von dost0011 (Gast)


Lesenswert?

Shit jetzt komme ich doch durcheinander.
Wenn es einen PCINT1 Pin gibt, aber keinen dazugehörigen Interrupt - wie 
nutze ich dann diese PIN Funktion überhaupt?

Ich benötige

- einen ext. Int
- einen PINChange Int
- 2 AD Eingänge
- 1 PWM Ausgang.

Ich dachte das haut genau hin mit dem ATTINY 85...

Könnt ihr das nochmal besrätigen bzw. verneinen?

Danke.

von Hannes L. (hannes)


Lesenswert?

dost0011 schrieb:
> Shit jetzt komme ich doch durcheinander.
> Wenn es einen PCINT1 Pin gibt, aber keinen dazugehörigen Interrupt

Doch, den gibt es. Du musst nur zwischen PCINT-Portpins und 
PCINT-Interrupt-Vektoren unterscheiden. Das (für Dich noch) 
Unübersichtliche dabei ist, dass die Pins bitweise nummeriert sind, die 
PC-Interrupts aber byteweise bzw. Portweise (ein Port (und damit ein 
PCI-Handler) kann bis zu 8 Bits bzw. Pins haben). Alle Pins des ATTiny85 
liegen auf PortB, also gibt es nur einen PCI-Handler für alle Portpins, 
und das ist PCINT0.

> - wie
> nutze ich dann diese PIN Funktion überhaupt?

Indem Du in der PC-Interrupt-Maske nur den benötigten Portpin (also sein 
Bit, in Deinem Falle Bit 1 für PCINT1, da dieser auf PB1 liegt) 
aktivierst. Somit wirkt nur ein Pegelwechsel an PB1 auf den 
PCINT0-Interrupt, alle anderen Portpins werden ja (von Dir) per 
Maskierung als Interrupt-Quelle deaktiviert.

>
> Ich benötige
>
> - einen ext. Int           PB2, Pin 7, INT0
> - einen PINChange Int      PB1, Pin 6, PCINT1
> - 2 AD Eingänge            PB3, Pin2, ADC 3 und PB4, Pin 3, ADC2
> - 1 PWM Ausgang.           PB0, Pin 5, OC0A

Solltest Du die schnellere PWM über die PLL des Timer1 brauchen, dann 
ginge es so:

> - einen ext. Int           PB2, Pin 7, INT0
> - einen PINChange Int      PB0, Pin 5, PCINT0
> - 2 AD Eingänge            PB3, Pin 2, ADC3 und PB4, Pin 3, ADC2
> - 1 PWM Ausgang.           PB1, Pin 6, OC1A

Der PCINT0-Handler (als ISR) bleibt derselbe (es gibt ja nur diesen), es 
ist lediglich ein anderes Bit (Bit 0 statt Bit 1) zu maskieren.

>
> Ich dachte das haut genau hin mit dem ATTINY 85...

Ja sicher haut das hin, sogar in mehreren Varianten. Du solltest aber 
die PWM-Endstufe so gestalten, dass der daran angeschlossene Verbraucher 
während des ISP nicht Amok läuft.

>
> Könnt ihr das nochmal besrätigen bzw. verneinen?
>
> Danke.

...

von dost0011 (Gast)


Lesenswert?

Ich traue es mich ja kaum zu fragen, aber könntet ihr das angehängte 
Programm so modifizieren, dass es  funzt?
Sonst befürchte ich, dass dieser Thread nie enden wird :-)

von Peter D. (peda)


Lesenswert?

Ein PCINTx_vect ist immer für bis zu 8 Pins zuständig, also:
PCINT0_vect: PCINT0..7
PCINT1_vect: PCINT8..15 usw.

Zu jedem Interrupt gibt es noch ein Maskenregister für die Auswahl der 8 
Portpins.
Wählt man mehr als einen Pin aus, muß man im Handler noch rauskriegen, 
welcher Pin den Interrupt ausgelöst hat. Das kann sehr tricky sein, da 
es leider kein dazugehöriges Flagregister gibt.


Peter

von Hannes L. (hannes)


Lesenswert?

dost0011 schrieb:
> aber könntet ihr das angehängte
> Programm so modifizieren, dass es  funzt?

Ich nicht, von C habe ich keine Ahnung. Ich werkele in Assembler und 
beziehe die benötigten Infos (trotz sehr schlechter Englisch-Kenntnisse) 
aus dem jeweiligen Datenblatt.

...

von Hannes L. (hannes)


Lesenswert?

Peter Dannegger schrieb:
> Wählt man mehr als einen Pin aus, muß man im Handler noch rauskriegen,
> welcher Pin den Interrupt ausgelöst hat.

Ich vermute mal, Atmel hat den PCI vorrangig für Tastenabfragen (auch 
Matrix) zum Aufwecken aus dem Tiefschlaf (nicht zum Entprellen) 
vorgesehen. Der Testballon dafür war der ATTiny28, der ja speziell für 
IR-Fernbedienungen konzipiert war.

> Das kann sehr tricky sein, da
> es leider kein dazugehöriges Flagregister gibt.

Das würde ich auch begrüßen, und wenn nur zum Zeitpunkt des Interrupts 
der Port (wie bei ICP der Timerstand) in ein Zwischenregister eingelesen 
würde. Man kann aber leider nicht alles haben...

...

von Peter D. (peda)


Lesenswert?

dost0011 schrieb:
> Ich traue es mich ja kaum zu fragen, aber könntet ihr das angehängte
> Programm so modifizieren, dass es  funzt?

Dazu müßte man erstmal wissen, was das Programm machen soll.
Ich weiß, es ist schwer, eine logisch aufgebaute und eindeutige 
Funktionsbeschreibung zu erstellen, aber Hellsehen ist noch viel 
schwerer.

Versuche mal so heranzugehen, daß mit Deiner Beschreibung jemand völlig 
fremdes das Programm erstellen kann, ohne nochmal nachfragen zu müssen.

Du wirst lachen, aber selbst wenn man ein Projekt selber programmiert, 
ist eine vollständige Beschreibung sehr hilfreich. Sie ist quasi der 
rote Faden in einem Labyrinth.


Peter

von dost0011 (Gast)


Lesenswert?

Jetzt wollte ich gerade anfangen alles zu erklären, aber erstens geht es 
mir ja um die Architektur - und die ist in meinem Programm mit 
Kommentaren erklärt - und außerdem traue ich mir das doch selber zu :-)
Aber dazu muss ich das Problem verstehen und das habe ich noch nicht.

Die Ausgansfrage war ja, wer löst mir eigentlich den Interrupt von 
PCINT0 aus? Antwort: der Timer0 von der PWM. Doch warum macht der das? 
Ich sehe da gar keinen Zusammenhang - auch nicht, wenn ich ins 
Datenblatt schaue.

So und dann Zielen eure Antworten darauf ab, dass ich nur einen 
PCINT_vec für die PCINT Pins habe. Antwort: mir doch egal, weil ich nur 
einen benötige.
Der andere soll ja der INT0 Interrupt sein. Und der hat doch hoffentlich 
seinen eigenen Vector, oder?

Vielen Dank für eure Geduld. Bin mir aber sicher, dass hierbei viel 
gelernt wird...

von Hannes L. (hannes)


Angehängte Dateien:

Lesenswert?

dost0011 schrieb:
> Jetzt wollte ich gerade anfangen alles zu erklären, aber erstens geht es
> mir ja um die Architektur - und die ist in meinem Programm mit
> Kommentaren erklärt

Naja, das ist äußerst spartanisch. Es ist z.B. nicht zu erkennen, wie 
die Signale für Trittfrequenz und Geschwindigkeit generiert sind, also 
ob diese prellen können, welche Frequenzen da zu erwarten sind oder 
wasauchimmer. Ein externer Interrupt ist nämlich nicht immer die beste 
Wahl beim Einlesen von externen Pegelwechseln.

> - und außerdem traue ich mir das doch selber zu :-)

Achso? - Und warum fragst Du?

> Aber dazu muss ich das Problem verstehen und das habe ich noch nicht.
>
> Die Ausgansfrage war ja, wer löst mir eigentlich den Interrupt von
> PCINT0 aus? Antwort: der Timer0 von der PWM. Doch warum macht der das?

Na weil in PCMSK alle Bits gesetzt sind und somit alle Portpins den PCI 
triggern können.

> Ich sehe da gar keinen Zusammenhang - auch nicht, wenn ich ins
> Datenblatt schaue.

Dann hast Du nur halb ins Datenblatt geschaut. Denn in der 
Registerbeschreibung zu PCMSK steht unter Initial Value, dass alle 
relevanten Bits nach der Initialisierung gesetzt sind. Und wenn Du per 
Programm mit
  /* PIN Change Mask Register -> Trittfrequenz */
  sbi(PCMSK,PCINT1);
ein bereits gesetztes Bit nochmal setzt, dann werden die restlichen Bits 
davon noch lange nicht zurückgesetzt...

Schreib:
        PCMSK = 1<<PCINT1
Dann funktioniert das auch.

>
> So und dann Zielen eure Antworten darauf ab, dass ich nur einen
> PCINT_vec für die PCINT Pins habe.

So ist es...

> Antwort: mir doch egal, weil ich nur
> einen benötige.

Naja, manchmal ist es aber ganz nützlich, wenn man versteht was man tut.

> Der andere soll ja der INT0 Interrupt sein. Und der hat doch hoffentlich
> seinen eigenen Vector, oder?

Ein Blick ins Datenblatt, Kapitel Interrupt, hätte Dir die Liste der 
Interrupt-Handler gezeigt...

>
> Vielen Dank für eure Geduld. Bin mir aber sicher, dass hierbei viel
> gelernt wird...

Bist Du sicher?

...

von dost0011 (Gast)


Lesenswert?

Hallo Hannes,

so es läuft. Und ich bin dir dankbar.
Aber jetzt mal unter uns:

Ich habe 2 Fehler gemacht:
- Beim setzen des Pullup Widerstandes versehentlich einen Interrupt 
ausgelöst
- Davon ausgegangen, dass PCMSK mit 0 initialisiert ist

Fehler zu machen ist nie toll, aber ich finde, das hier hält sich noch 
im Rahmen, wenn man das erste Mal ein größeres Projekt mit mehreren 
Interrupts angeht.

Danke an alle, auch wenn es etwas länger gedauert hat, bis die 2 
eigentlichen Probleme "erkannt" wurden. Alles umzuschmeissen (PWM von 
KanalA auf KanalB usw) ist hier gar nicht nötig...

Anmerkungen wie:
<Naja, das ist äußerst spartanisch. Es ist z.B. nicht zu erkennen, wie
die Signale für Trittfrequenz und Geschwindigkeit generiert sind, also
ob diese prellen können, welche Frequenzen da zu erwarten sind oder
wasauchimmer. Ein externer Interrupt ist nämlich nicht immer die beste
Wahl beim Einlesen von externen Pegelwechseln.>

... bringen mir doch gar nichts.

Ich habe extra nicht den ganzen Code geschickt, und die ISRs leer 
gelassen, damit die Fehlersuche einfach wird.
Es bringt doch nichts, dann eine neues Fass aufzumachen mit:
- ext. Interrupts nicht immer geeignet
- Prellen?
- Frequenz der Signale

Hätte ich nicht immer wieder so "dämlich" nachgehakt, dann wäre jetzt 
alles umgestellt, aber funktionieren würde es immer noch nicht, weil die 
entscheidende Antwort erst gestern abend kam...

Und ja, ich lerne was daraus (und nicht nur ich...)

von Hannes L. (hannes)


Lesenswert?

dost0011 schrieb:
> Es bringt doch nichts, dann eine neues Fass aufzumachen mit:

Na unter "ein Fass aufmachen" verstehe ich was Anderes, da brennt die 
Luft...
;-)

> - ext. Interrupts nicht immer geeignet

Ist aber so, es gibt mehr Leute als Du denkst, die prellende mechanische 
Kontakte an Interrupts anschließen.

> - Prellen?

Ja sicher, mechanische Kontakte prellen nunmal, was Gift für Interrupts 
ist. Ebenso ist es bei optischer Erfassung (Lichtschranken), wenn 
Vibration im Spiel ist.

> - Frequenz der Signale

Ereignisse unter 1 kHz fragt man besser durch Pollen im Timer-Interrupt 
ab.

>
> Hätte ich nicht immer wieder so "dämlich" nachgehakt, dann wäre jetzt
> alles umgestellt,

Hätte ich Enten gekauft, dann wären die Hühner nicht ersoffen...

Aber Du hast schon recht, ich hätte ohne Deine Nachfragen Deinen 
Quälcode nie gelesen. Denn ich mag kein C, ich programmiere AVRs in 
Assembler, auch den ATTiny85 (z.B. Soundmodul für Modellbahn, Diesel mit 
Anlasser, Glocke und Horn, sowie Dampf mit Glocke und Pfeife). Erst 
Deine Behauptung, alles wissenswerte stünde im Quälcode, brachte mich 
dazu, da mal reinzusehen.

> aber funktionieren würde es immer noch nicht,

Der Hinweis betreffs Timer1 hatte schon seinen Sinn. Timer1 hat eine PLL 
im Vorteiler, damit lassen sich 16-fach höhere PWM-Frequenzen erzeugen.

> weil die
> entscheidende Antwort erst gestern abend kam...

Die hättest Du aber selbst durch aufmerksameres Lesen des Datenblattes 
finden können.

...

von dost0011 (Gast)


Lesenswert?

Wenn man immer wüsste, wo man schauen soll...
Aber nix für ungut.
Bin ja so froh, dass es Euch Experten gibt, auch wenn man dann ab und zu 
was aufs Dach kriegt (wenn man dämlich nachfragt...)
Aber vielleicht muss das so sein :-)

Habe gerade was im Simulator gefunden, was nicht astrein ist:

Rebuild -> Debug ON -> Reset Cycle Counter -> Stimuli File geladen -> 
Run
--> alles funzt (Stoppmarke bei #2000000 wird ausgeführt)

Nun das gleiche, aber statt einem Rebuild ein Build und dann gestartet.
--> Stoppmarke bei #2000000 wird scheinbar übersprungen, Programm hält 
bei #4000000, obwohl es hier gar kein Stoppereigniss gibt...

Das ist mir schon mal aufgefallen.
Nur wenn man einen kompletten Rebuild macht, scheint alles zu funzen.

Lästig, auch, weil man jedes mal wieder neu das Stimuli File einbinden 
muss...

von Hannes L. (hannes)


Lesenswert?

dost0011 schrieb:
> auch wenn man dann ab und zu
> was aufs Dach kriegt

Das siehst Du wohl etwas überempfindlich...

Ich meine nicht, dass mein Tonfall Deinem gegenüber unangemessen war:

dost0011 schrieb:
> und außerdem traue ich mir das doch selber zu

Den Rest kommentiere ich nicht, ich habe keine Ahnung von C und will auf 
meine alten Tage damit auch nicht mehr beginnen.

...

von Krapao (Gast)


Lesenswert?

Hannes schrieb:
> Na unter "ein Fass aufmachen" verstehe ich was Anderes, da brennt die
> Luft... ;-)

So was?

Having a Barrel of Fun - YouTube
http://www.youtube.com/watch?v=ANoKOmGOong

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.