Hallo lieben Mitleser, kurz zu meinem Vorhaben: Ich möchte mittels Handy-Mega8-Uart einen Interrupt auslösen. Also wenn das Handy über die Tx-Leitung ein String mit "RING\c\r" sendet (sprich angerufen wird) soll der Controller mit dem Signal aus dem "Schlaf" geholt werden. Nun habe ich einiges über Interrupts gelesen (auch das Datenblatt dahingehend befragt) allerdings sind mir einige Dinge noch unklar. Wird ein Interrupt bei jedem Empfangen eines "RING"-Strings ausgelöst, oder wie habe ich mir das vorzustellen? Welchen Interrupt-Vektor würdet ihr für so einen Fall verwenden? Wie würdet ihr das realisieren, dass der mega8 bei einer empfangenen "aktivität" auf der Rx-Leitung, nur ein einziges mal in die Interrupt-Routine springt, diese abarbeitet (Zeitunkritisch, kann länger dauern, wegen Anruf Eingabeaufforderung etc) und dann wieder schläft? Muss die Interrupt-Routine eigentlich in einer bestimmten Zeit abgearbeitet werden, oder ist das dem Controller egal, solange es mir egal ist? :-) Welcher "Schlaf"-Modus bietet sich hier an? (so, dass auf Uart-Aktivitäten der Controller geweckt wird und was könnten da die Energieeinsparungen sein gegenüber Dauerbetrieb und Polling?) ich würd mich über jede Hilfe und für jeden Bruchteil einer Antwort auf meine ca1000 Fragen sehr freuen... MFG Elko
Ein Interrupt wird durch ein >einzelnes< Ereignis ausgelöst, meist eine positive oder negative Flanke eines Signals oder ein komplett an der UART eingetroffenens Zeichen. Wenn die UART eingesetzt wird, kann diese nach jedem Zeichen einen UART-Int auslösen. In der Int-Routine wird die Folge der Zeichen kontrolliert (aufgesammelt), und wenn dann die richtige Zeichenfolge z. B nach dem zehnten Zeichen (bzw.Int)erkannt ist, kann der Kontroller zu weiteren Aktionen schreiten. Ich hab' das Datenblatt nicht im Kopf, aber wahrscheinlich kann man nach der Interrupt-Routine den Kontroller jedesmal schlafen schicken und durch den nächsten UART-Int wieder aufwecken. Eventuell muss man auch durch die erste Signalflanke den Kontroller aufwecken und ihn für einige Zeit, vom Timer-Int gesteuert, wach lassen. Wenn dann nicht der richtige String eingetroffen ist, rücksetzen,schlafen legen und auf neuen String warten.
Was die UART-Geschichte angeht, so ist das AVR-Tutorial immer eines Blickes Wert: http://www.mikrocontroller.net/articles/AVR-Tutorial:_UART
Ich bin da selbst Anfänger und habe mich selbst kürzlich mit Sleep Mode und Aufwecken beschäftigt. Daher hier eine Spekulation dazu: Du könntest die RX Leitung (TTL vom Handy direkt oder TTL-Seite des RS232-TTL) zusätzlich auf den INT0 vom AVR geben und dadurch den AVR sogar aus dem Sleep Mode Power Down wecken. Das Aufwachen per INT0 wird ausgelöst, wenn an INT0 ein LOW Pegel anliegt. Es ist also sicher zu stellen, dass im Ruhezustand (Spezialfall Handy ist aus beachten!) ein HIGH Pegel anliegt. Der AVR wacht dann beim Startbit auf. Ob die Aufwachzeit noch ausreicht, um das erste "RING" teilweise zu detektieren, muss man testen (ich spekuliere: es reicht nicht). Beim zweiten RING sollte der AVR wach sein. Wesentlich schneller als der Power Down Mode ist der Stand By Mode wach. Die mehrfache Abarbeitung des INT0 beim Empfangen kann man ignorieren oder du kannst den INT0 nach dem Aufwachen abschalten. Das Abschalten benutze ich im Beispiel Suppentimer [[Pollin Funk-AVR-Evaluationsboard]]. Beim externen Interrupt an sich muss man, habe ich gelesen, beachten, dass das sehr empfindlich gegen elektromagnetische Störungen sein kann und dass der AVR ggf. öfters durch Fehlalarme aufgeweckt wird. Also wäre die Software so zu schreiben, dass der AVR nach dem Aufwachen das RING prüft und bei Fehlalarm schnellstens wieder pennen geht.
Vielen vielen Dank für die Antworten... @stefan: das hört sich schon sehr interessant an... Meinst du die Rx Leitung vom Handy oder vom uC? Warscheinlich meinst du den Tx des Handys zusätzlich auf int0 legen? allerdings stehe ich noch ein wenig auf dem schlauch was die implementierung der prüfung betrifft. wie könnte ich das (am einfachsten) realisieren, dass nach dem RING geprüft wird? programmiere übrigens in C... wäre für jede Hilfe dankbar... MFG Elko
Freie Auswahl TX vom Handy oder RX vom AVR. Die beiden sind ja irgendwo verbunden. Dazwischen kann sich ein Pegelwandler RS232-TTL befinden. Aber: Handys haben eigentlich nie echte RS232-Pegel (ausser ein entsprechendes Handykabel für PC_Anschluss wird benutzt, dann ist der Pegelwandler im Kabel), so dass man einen Pegelwandler vergeblich sucht. Aufpassen mit welchen Pegeln das Handy arbeitet 0V/5V oder 0/3.3V oder... Bei einem Pegelwandler ist es im Prinzip Geschmackssache, wo die TX/RX Kreuzung gemacht wird - auf der Handyseite oder auf der AVR-Seite. Beim Programmieren gehe ich gerne schrittweise vor, anstatt alles auf einmal stemmen zu wollen. Hier würde das bedeuten, zuerst ein UART Programm zu schreiben, das in einer Hauptschleife ein "RING" auswerten kann. Das würde ich auch erstmal mit einem PC und Terminalprogramm simulieren statt mit einem Handy. Dann eine INT0-Funktion dazu zu packen. Dann ein Sleep dazu zu packen. Wie eine UART abgeprüft wird, wird im AVR GCC Tutorial beschrieben. Und der Rest auch ;-) Vielleicht helfen dir auch meine Beispiele s. Link o. weiter. Beim 8-Bit Z#hler und der Uhr ist UART (Polling) drin und im Suppentimer ist INT0/Sleep drin.
Danke nochmal... Das mit den Pegeln etc ist alles klar, auch jetzt die hardwaremäßige umsetzung und Uarts habe ich auch schon aufgebaut, allerdings habe ich konkrete probleme bei der Prüfung selbst, ob die Zeichenkette RING empfangen wurde oder nicht. Da der Controller ja wahrscheinlich die ersten paar zeichen wegen dem aufwachen verwerfen wird. Würdest du die empfangenen zeichen in ein Array übertragen und dann auf die Zeichenfolge "RING" prüfen (wenn ja wie gross sollte der array sein?) Wenn ich das volle RING erfassen möchte, bietet sich doch ein größeres array an, oder (vielleicht doppelt so lang wie das "RING\c\r"?) Vielen Dank für die Mühe... LG Elko
noch was, wäre es sinnvoll, dass in der Rx-Int-Routine das empfangene Zeichen überprüft wird und sobald ein "R" empfangen wird, das R in Array[0] übertragen wird... sobald ein "I" empfangen, das I in Array[1] übertragen wird etc. und in der Rx-Int-Routine wird dann geprüft ob das Array == "RING" entspricht. Verstehe ich das richtig, dass ich den INT0-interrupt nur für das aufwachen benutze und danach ausschalte und dass das empfangen der zeichen über den Uart-Rx-INT läuft? LG Elko
Bei dem Puffer (Array ist OK) würde ich erstmal nicht geizen. 2*RING
plus Nullbyte (!) hört sich zweckdienlich an.
Empfangene Zeichen unter Beachtung der Grösse reinschreiben dabei \r
verwerfen. Jedesmal den Puffer hinter dem aktuellen Zeichen mit Nullbyte
abschliesse. Bei einem \c auswerten und anschliessend die Füllposition
auf den Pufferanfang zurücksetzen. Ebenso zurücksetzen beim Erreichen
des Puffergrösse. Auswertung mit strncmpi ggf. mit Vorauswahl, ob die
mitgezählte Zahl der Zeichen im Puffer genau 4 ist.
EDIT:
> noch was...
Das ist mir zu kompliziert gedacht.
Die Empfangsroutine würde ich universell gestalten. Sie soll eine Zeile
per UART in einen Puffer schreiben. Wie gross der Puffer ist, kann
konfiguriert werden. Danach kümmert sich der Rest des Programms um die
Auswertung der Zeile.
Dadurch bekommt man eine universelle UART-Zeileneinleseroutine und nicht
nur eine RING-Einleseroutine. BZW. gibt es bereits fertige Libraries für
ersteres.
Ich habe vor ein paar Jahren eine Freisprecheinrichtung für ein Mobiltelefon entwickelt. Ich hatte mich für zwei Interruptlevel (per Software, da AVR sowas nicht in Hardware unterstützt) entschieden. USART-IRQs im hohen Level über Ringpuffer. Den Parser im niedrigen Level per Timer-Interrupt. Das ganze habe ich per State-Machine gemacht. Einfach Zeichen aus dem Ringpuffer holen bis zum Zeilenende-Zeichen, danach dann Stringvergleich mit den erwarteten Strings - hier nur "RING". Flag setzen und die Arbeit wird in der Hauptroutine erledigt.
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.