Hallo liebes Forum,
ich habe mal wieder ein Anfängerproblem und komme ohne Hilfe nicht
weiter.
Und zwar will ich (erstmal) per Tastendruck eine Nachricht per UART über
die serielle SS senden.
Das funktioniert auch super, die Daten kommen richtig am PC an.
Nur habe ich Probleme beim Interrupt EXT0.
Leider löst dieser aus sobald ich den LED Ausgang umschalte. Und er
funktioniert auch mit dem Taster nicht.
Ich habe bei anderen Projekten schon Interrupts benutzt, finde aber
trotzdem keinen Fehler.
Die Potenziale am PB0 sind OK (pulled high) und werden auch nicht durch
den Ausgang beeinflusst.
Habe das ganze sogar schon auf PB1 EXT1 umprogrammiert dort verhält es
sich aber gleich.
Vielen dank im Voraus!
Max M. schrieb:> Maximilian G. schrieb:>> static uint8_t Taste = 0;>> Warum "static" ?
Weil minimal notwendige Sichtbarkeit ausreichend ist.
> Mach da mal ein "volatile" draus.
Das fehlt zwar, ist aber keine Alternative zu static.
Max M. schrieb:> Carl D. schrieb:>> Weil minimal notwendige Sichtbarkeit ausreichend ist.>> Bei einer globalen Variablen?!> LOL!
Manche machen Projekte, die aus mehr als einem Source-File bestehen.
Die verstehen das.
Naja ich wollte mir eigentlich gleich einen sauberen programmierstil
angewöhnen deshalb.
Hatte es auch mit short und int (ohne static) versucht genau das
gleiche.
Hab es nun auch mit volatile probiert --> selbes Ergebnis.
Maximilian G. schrieb:> Nur habe ich Probleme beim Interrupt EXT0.
Hmm, eigenartig. Der kommt in deinem Code überhaupt nicht vor...
Wie kann er da Probleme machen?
Eine Taste auf einen Intrrupt ? Genau. Das macht man nicht so.
Eine Taste entprellt man mit einem timer. Bedeutet man fragt alle Tasten
in einem timer ab. Zb Alle 10ms.
Alles andere ist quatsch.
Weg mit dem Troll schrieb:> Eine Taste auf einen Intrrupt ? Genau. Das macht man nicht so.> Eine Taste entprellt man mit einem timer. Bedeutet man fragt alle Tasten> in einem timer ab. Zb Alle 10ms.> Alles andere ist quatsch.
Naja der Sendevorgang sollte ersteinmal entprellung genug sein.
Und warum den code weiter verkomplizieren wenn er noch nichteinmal so
funktioniert...
Der Sendevorgange entprellt ? Nein tut er nicht. Die erste Flanke ergibt
einen Interrupt. Also Zeichen ins UART. 0.1ms spaeter der Prell. Das
naechste Zeichen ins Uart, weil das Uart schon wieder leer ist.
Hi
Du bist anscheinend relativ neu im uC Business der AVR.
Weil der AVR so einfach ist, muss man eine 1 schreiben, damit eine 0
ankommt. Sieht bestimmt in deinem Datenblatt auch aus wie "... , or it
can be cleared by writing a one to its bit location." (UCSRA).
Ansonsten rödelt dein Senden(""); was raus. Sollte nicht sein. Warum
Fußgeprüf? Warum loop0 anstatt Zeigerarithmetik?
Stück für Stück. Teste ersmal das Senden() ohne Interrupt, dann nur
Interrupt mit LED und am Ende beides Kombiniert. Oder nimm einen
Debugger. Oder Simulator.
go on
neuer PIC Freund schrieb im Beitrag #6187009:
> Hi>> Du bist anscheinend relativ neu im uC Business der AVR.>> Weil der AVR so einfach ist, muss man eine 1 schreiben, damit eine 0> ankommt. Sieht bestimmt in deinem Datenblatt auch aus wie "... , or it> can be cleared by writing a one to its bit location." (UCSRA).
Habe im Datenblatt nichts dazu gefunden...
Sender wird mit 1 eingeachaltet...
>> Ansonsten rödelt dein Senden(""); was raus. Sollte nicht sein. Warum> Fußgeprüf? Warum loop0 anstatt Zeigerarithmetik?
Also das Senden funktioniert einwandfrei, fußgeprüft weil ich auch einen
leeren String mit Endzeichen ("\0") senden will.
Wie meinen? Quasi nur pointer++?
Würde sagen ist historisch gewachsen... Wie gesagt bin noch etwas neu..
Maximilian G. schrieb:> Habe im Datenblatt nichts dazu gefunden...> Sender wird mit 1 eingeachaltet...
Ist auch richtig so. Nur Interrupt-Flags werden durch schreiben einer 1
gelöscht, aber die benutzt du gar nicht.
Oliver
TXC brauchst du nur auswerten, wenn du sowas wie Halbduplex-RS485
machst.
Bevor du den Sender ausschaltet, solltest du überprüfen, ob alle deine
Daten übertragen wurde.
Das kannst du per TXC erreichen.
Warum man den aber "dauernd" ein- und ausschalten muss, ist mir unklar
(vielleicht habe ich die Begründung aber auch einfach überlesen).
STK500-Besitzer schrieb:> Warum man den aber "dauernd" ein- und ausschalten muss, ist mir unklar> (vielleicht habe ich die Begründung aber auch einfach überlesen).
Naja wird nach der gesamten Zeichenkette ausgeschaltet nicht nach jedem
Zeichen.
Du hast recht, dass es nicht nötig ist ich dachte nur es wäre vllt
sauberer so und so kann ich die Funktion auch einfacher wiederverwenden.
Btw. Hast du auch mit der letzten abfrage recht ich muss vermutlich die
schleife umbauen da sonst eventuell das letzte zeichen nicht gesendet
wird...
Maximilian G. schrieb:> ich dachte nur es wäre vllt> sauberer so und so kann ich die Funktion auch einfacher wiederverwenden.
Nö.
Sauber ist es, den TXD permanent an der UART zu belassen und nicht auf
low oder floatend zu setzen.
Auch RXD abschalten ist gefährlich, da so die Startbiterkennung
fehlschlagen kann.
> Funktioniert immernoch.
Und ich frag mich wie. Initial Value von TXC ist 0. Beim erstmaligen
Aufruf von Senden() sollte dein Code bis zum Sankt-Nimmerleinstag oder
Watchdog in
1
while(!(UCSRA&&(1<<TXC)));// Warten bis vorheriger Sendevorgang fertig
verweilen. Welchen AVR verwendest du eigentlich?
Ansonsten lass TXC einfach außen vor. Brauchst du nicht.
Maximilian G. schrieb:> Du hast recht, dass es nicht nötig ist ich dachte nur es wäre vllt> sauberer so und so kann ich die Funktion auch einfacher wiederverwenden.
Die Schnittstelle schaltet man bei der Initialisierung ein.
Zusammen mit dem Empfang (RXE) und der Konfiguration bestehen aus der
Baudrate und dem Datenwortbreite (z.B. 8N1).
Sofern du nicht irgendwelche Halbduplex-Schnittstellen implementieren
willst (z.B. RS485), brauchst du dich für TXC nicht interessieren.
Das Flag zeigt dir an, wenn die letzten Daten den Sendepuffer verlassen
haben.
UDRE zeigt dir an, ob im Sendepuffer platz für ein neues Byte ist.
> Btw. Hast du auch mit der letzten abfrage recht ich muss vermutlich die> schleife umbauen da sonst eventuell das letzte zeichen nicht gesendet> wird...
Du schmeoßt einfach die Ein-Ausschalt-Orgie und das TXC-Geraffel aus der
Übertragungsfunktion.
Einzig die UDRE-Abfrage am Anfang ist nötig.
while(!(UCSRA&&(1<<UDRE)));// Warten bis Buffer leer
6
UDR=*pInput;// Daten in Buffer schreiben
7
pInput++;
8
}
9
}
Soo abgeändert.
neuer PIC Freund schrieb im Beitrag #6187234:
> Und ich frag mich wie. Initial Value von TXC ist 0. Beim erstmaligen> Aufruf von Senden() sollte dein Code bis zum Sankt-Nimmerleinstag oder> Watchdog in> while (!(UCSRA && (1 << TXC))); // Warten bis vorheriger> Sendevorgang fertig
Ehrlich gesagt wundert mich das gerade selbst, ist ja klar ein Fehler.
neuer PIC Freund schrieb im Beitrag #6187234:
> Welchen AVR verwendest du eigentlich?
Ich verwende einen AtTiny2313A
Ich habe zur Zeit nur ein Smartphone zur Verfügung und kann deshalb
nicht nachschauen.
DDRB = (1 << PORTB1);
PORTB = (1 << PORTB0);
Ist denn sicher das PORTB1 das selbe wie PB1 ist?
Wenn das Atmel Studio verwendet wird, kann man sich im Debugmodus die
I/0 eunfach anschauen.
Maximilian G. schrieb:> ich habe mal wieder ein Anfängerproblem und komme ohne Hilfe nicht> weiter.
Das glauben wir dir gern und ungeprüft - aber es ist nicht relevant.
Also: Schreib zuerst mal, was du überhaupt für einen Chip benutzt und
dann, was du damit für ein Problem hast. Ansonsten wird das Ganze zu
einem Textadventure, wo man die Informationen nur scheibchenweise
herauskriegt - wenn überhaupt.
Maximilian G. schrieb:> Nur habe ich Probleme beim Interrupt EXT0.> Leider löst dieser aus sobald ich den LED Ausgang umschalte.
Dann lies zuvörderst das zugehörige Manual! Manche Interrupts sind
flankengetriggert, andere sind pegelgetriggert. Manche Interrupts werden
automatisch zurückgesetzt, wenn der zugehörige Handler ausgeführt wird,
andere muß man dediziert zurücksetzen, sonst kommen sie unmittelbar
immer wieder.
Und manche Chips haben Interrupts auf Zustandswechsel eines Portes, die
eben auf alle Portpins und deren Änderung reagiert - andere Chips
haben dafür spezielle Register, wo man sich aussuchen kann, auf welche
Pins der Int kommen soll und auf welche eben nicht.
Sowas sollte man lesen, bevor man seine Schaltung und Leiterplatte
macht.
W.S.
W.S. schrieb:> Und manche Chips haben Interrupts auf Zustandswechsel eines Portes, die> eben auf alle Portpins und deren Änderung reagiert - andere Chips> haben dafür spezielle Register, wo man sich aussuchen kann, auf welche> Pins der Int kommen soll und auf welche eben nicht.>> Sowas sollte man lesen, bevor man seine Schaltung und Leiterplatte> macht.
Tolle Antwort die mich sehr motiviert, mich weiter mit der Materie zu
beschäftigen.
Außerdem habe ich das Datenblatt gelesen. Es kann natürlich sein, dass
ich etwas überlesen habe aber selbst dann kann man doch jemanden nett
auf seine Fehler hinweisen. Anstatt einfach ein "lies halt die
Anleitung" rauszuhauen.
Auszug aus dem Datenblatt:
• Bit 6 – INTF0: External Interrupt Flag 0
When an edge or logic change on the INT0 pin triggers an interrupt
request, INTF0 becomes set (one). If the I-bit in SREG and the INT0 bit
in GIMSK are set (one), the MCU will jump to the corresponding Interrupt
Vector. The flag is cleared when the interrupt routine is executed.
Alternatively, the flag can be cleared by writing a logical one to it.
This flag is always cleared
when INT0 is configured as a level interrupt.
Danke für die Antworten bisher.
Werde mich heute Abend mal nochmal dahinterklemmen.
Maximilian G. schrieb:> Es kann natürlich sein, dass> ich etwas überlesen habe aber selbst dann kann man doch jemanden nett> auf seine Fehler hinweisen. Anstatt einfach ein "lies halt die> Anleitung" rauszuhauen.
Was erwartest du?
Daß jemand anderes hier sich durch dein Vorhaben hindurchwühlt bis er
den Fehler findet, ohne daß du ihn mit wirklich ausreichenden
Informationen versehen hast?
Oder daß du gelobt wirst (und wofür)?
Nein mein Lieber, dir anzuraten, das Manual gründlich zu lesen und zu
verstehen, ist bei dieser Sachlage der einzige wirklich sinnvolle Rat.
Alles andere wäre nur Rätselraten.
Und nochwas: du scheinst einer von der fordernden und zugleich
undankbaren Sorte zu sein. Ich hab dir im Schnelldurchgang all die
wahrscheinlichen Ursachen genannt, die zu einem quasi "dauerhaften"
Interrupt führen können - aber das Manual zu deinem Chip lese ich nicht
stellvertretend für dich durch. Das machst du gefälligst selber.
W.S.
Ich möchte hiermit die Diskussion beenden:
W.S. schrieb:> Und nochwas: du scheinst einer von der fordernden und zugleich> undankbaren Sorte zu sein.W.S. schrieb:> Nein mein Lieber,
Ich bin der Meinung solche Antworten gehören nicht in ein Fachforum.
Außerdem würde ich ihnen nahelegen ihre Umgangsformen noch einmal zu
überdenken. Auch wenn ihre fachlichen Kenntnisse die meinen bei weitem
übersteigen, gibt es ihnen nicht das Recht herablassende Kommentare zu
meiner Person zu verfassen!
@Maximilian G:
W.S. kann einfach nicht anders.
Er hat selber von nichts ne Ahnung aber spielt den Oberlehrer.
Vor allem zeigt er selbst unterirdische Verhaltensweisen (wie fu gemerkt
hast), aber wenn man mal selber zu dem Typen mal etwas unfreundlich ist
fängt er gleich an rumzuflennen.
Also:
Lass den dummen Troll einfach links liegen.
Vielen dank nochmal für die vielen Tipps.
Habe das ganze Ding jetzt nochmal geschrieben und auf den Interrupt
verzichtet.
Werde mich dann morgen nochmal an den Interrupt ranwagen.
Soweit funktioniert alles und ich bin auch zufrieden.
Eine Frage hätte ich allerdings noch:
warum löst
1
constuint32_tTeiler_Baud=(TAKT/(BAUD*16))-1;
immer einen Integer ov aus? kann der Compiler nicht mit mehr als 8 Bit
rechen? ((4800 * 16) > int)
Das sollte er doch automatisch machen wenn er doch eine 32Bit breite
Variable beschreibt?
Genutzt wird Atmel Studio mit einem AtTiny2313A
Holger L. schrieb:> DDRB = (1 << PORTB1);> PORTB = (1 << PORTB0);
Wieder dieser Shift Sch...
Muss ja in die Hose gehen. Benutzt endlich richtige defines.
Maximilian G. schrieb:> Das sollte er doch automatisch machen wenn er doch eine 32Bit breite> Variable beschreibt?
Das Schreiben erfolgt nach der Rechnung, also nach dem int-Überlauf.
Der Compiler arbeitet streng nach den Vorrangregeln, Hellsehen ist nicht
sein Ding.