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.
1 | ISR(PCINT0_vect) |
2 | {
|
3 | _NOP(); |
4 | }
|
Müsste es nicht "PCINT1_vect" heissen?
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.
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.
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!!!
dost0011 schrieb: > Natürlich muss dass PCINT1_vect heissen. Wie soll das gehen? Der ATtiny85 hat keinen PCINT1_vect. Peter
Stimmt, es ist PCINT1/PB1 u. muss PCINT0_vect lauten ...PCINT0_vect war also doch richtig.
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.
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. ...
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 :-)
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
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. ...
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... ...
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
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...
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? ...
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...)
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. ...
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...
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. ...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.