Hallo zusammen,
ich habe ein Ethernet - RS232 Gateway auf Basis von Ulrichs Webserver
aufgebaut, mit ATMEGA 644. Ich habe jetzt nur noch ein Problem.
Ich möchte wenn keine Daten mehr an der RS232 für das Ethernet ankommen
die Verbindung zum Netzwerk beenden. Dazu habe ich mir zwei
Möglichkeiten überlegt.
1. ein Timer der nach einer Zeit abläuft, wenn keinen neuen zeichen an
der RS232 angekommen sind
2. Das RXCn:USART Receive Complete Bit im UCSRnA auf Null prüfen
Welche ist die bessere Variante für mein Vorhaben oder gibt es andere
Möglichkeiten?
Danke
Gruß Mousse-T
>1. ein Timer der nach einer Zeit abläuft, wenn keinen neuen zeichen an>der RS232 angekommen sind
Besser...
>2. Das RXCn:USART Receive Complete Bit im UCSRnA auf Null prüfen
Das wird gesetzt, sobald ein Byte komplett empfangen wurde. Also auch,
wenn danach noch mehr Daten kommen.
Hi,
das USART Receive Complete Flag zeigt Dir nur an, ob das aktuell
empfangene Zeichen vollständig empfangen wurde. Wenn Du aber feststellen
möchtest, ob keine weiteren Zeichen mehr kommen, bietet sich eher eine
"Time Out"-Funktion an (Deine Lösung 1, eventuell mehrere Timer Zyklen
nutzen; rücksetzen, falls doch wieder Zeichen eintreffen).
Gruß
Fred
Danke für die Antworten. Dann werde ich mir das mit den Timern noch mal
genauer anschauen, denn so aus dem Stand wüsste ich noch nicht wie ich
das realisieren sollte.
Ich dachte an sowas: Der Timer wird aktiviert wenn eine verbindung
aufgebaut wird. Er wird dann immer wieder zurückgesetzt wenn ein zeichen
Empfangen wurde. Wenn kein zeichen mehr mehr kommt, läuft der Timer aus
und löst ein Interrupt aus, mit dem ich dann die Verbindung beenden
kann.
Kommt das in etwas so hin?
Gruß Mousse-T
Hi,
> Ich dachte an sowas: Der Timer wird aktiviert wenn eine verbindung> aufgebaut wird. Er wird dann immer wieder zurückgesetzt wenn ein zeichen> Empfangen wurde. Wenn kein zeichen mehr mehr kommt, läuft der Timer aus> und löst ein Interrupt aus, mit dem ich dann die Verbindung beenden> kann.
Ja, sollte so klappen!
Gruß
Fred
Ich habe mich jetzt etwas eingelesen und rausgefunden, dass man das über
das Overflow oder Compare Match Interuppt machen kann.
Was wäre denn im meinem fall besser? Nochmal dazu. Der Timer soll
gestartet(initialisiert) werden wenn eine Verbindung aufegaubt wird und
soll dann ca. 500ms laufen bis der Interupt auslöst.
Damit der Interuppt nicht auslöst wenn ein zeichen an der RS232 kommt,
soll dann dort der Timer wieder zurückgesetzt werden. Auf 0?
Gruß Mousse-T
Hi,
> ...., dass man das über> das Overflow oder Compare Match Interuppt machen kann.> Was wäre denn im meinem fall besser? ...
Vermutlich wirst Du Deine 500 ms mit einem CompareMatch Interrupt
einfacher realisieren können als mit einem OVF-Interrupt. Falls Du mit
dem OVF-Int (und den entsprechenden Vorteilern) auch auf die gewünschte
Zeit kommt, spielt es keine Rolle, welchen Interrupt Du nimmst.
> soll dann dort der Timer wieder zurückgesetzt werden. Auf 0?
Ja, denn Du willst doch wieder einen 500ms Zyklus starten. Lies Dir aber
genau durch, was beim Schreiben des TCNT Registers zu beachten ist
(evtl. Vorteiler vorher auf 0).
Gruß
Fred
So, ich habe mir das mal im Datenblatt angeschaut und hoffe das es so
richtig ist.
16000000 MHZ/1024 = 15625 // Prescaler auf 1024
15625 / 256 = 61,035 // Bei diesem Wert gibts ein
überlauf 1ms???
61,035 * 500 = 30517,578 // Für das
Vergleichsregister bei 500ms
INIT
// Keine Daten von der Seriellen erhalten. Verbindung beenden
4
}
Ich würde dann TCNT0 = 0; jedes mal setzen, wenn ein zeichen empfangen
wurde.
So ich hoffe das es stimmt, wenn nicht, dann sollte es wenigstens ein
guter Ansatz sein ;-)
Gruß Mousse-T
Hi,
> Fehler:Das OCR0A kann natürlich nur Werte <256 haben. ICh muss dann in> der ISR bis 500 incrementieren und dann die verbidung beenden...
Du verwendest doch einen ATmega644 - oder? Dann nimm einfach den
Timer/Counter 1; das ist ein 16 Bit Timer mit 16 Bit Output Compare
Registern.
Gruß
Fred
Hallo,
> 16000000 MHZ/1024 = 15625 // Prescaler auf 1024> 15625 / 256 = 61,035 // Bei diesem Wert gibts ein
Diese Rechnung stimmt nicht, oder ich weiß nicht, was Du rechnest.
Die Timer-Einheit (timer tick) bei 16 MHz F_CPU und Vorteiler=1024 ist
1024/16000kHz=64us. Zeit bis zum 8-Bit OVF also 256*64us=16,384ms.
Gruß
Fred
Mousse-T wrote:
> So, ich habe mir das mal im Datenblatt angeschaut und hoffe das es so> richtig ist.>> 16000000 MHZ/1024 = 15625 // Prescaler auf 1024
OK. Dein Timer kann also in 1 Sekunde 'theoretisch' bis 15625
zählen.
Da er aber ein 8 Bit Timer ist, ...
> 15625 / 256 = 61,035 // Bei diesem Wert gibts ein> überlauf 1ms???
... bedeutet dass, das er nicht bis 15625 zählen kann, sondern immer
nur bis 255. Das allerdings 61.035 mal in der Sekunde.
> 61,035 * 500 = 30517,578 // Für das> Vergleichsregister bei 500ms
Und wie bitte schön stellst du dir vor, dass ein 8 Bit Register
bis 30517 zählen soll? Das kommt maximal bis 255. Dann beginnt
es wieder bei 0.
WEnn du bei Overflows bleiben willst dann reicht es daher
aus, wenn in deiner Overflow ISR eine zusätzliche 8-Bit
Variable bis 30 hochgezählt wird (du erinnerst dich? Der
Timer produziert knapp 61 Overflows in der Sekunde).
Das sind dann ungefähr 500ms. Auf ein paar zerquetschte mehr
oder weniger kommt es bei einem Timeout ja nicht an.
Danke für die Antworten. Werde es mal am Montag ausprobieren.
Timer1 kann ich nicht nehmen, der wird schon für was anderes verwendet.
@Karl Heinz
Ja den fehler habe ich dann auch bemerkt. Siehe Post unter der Rechnung
;-)
Gruß Mousse-T
So jetzt fasse ich noch mal alles zusammen und hoffe, dass ich alles
richtig verstanden habe.
16000000 MHZ/1024 = 15625 // Prescaler auf 1024
Der Timer kann also in 1 Sekunde 'theoretisch' bis 15625 zählen.
15625 / 256 = 61,035 // Bei diesem Wert ist 1ms
vorbei
bedeutet dass, das er nicht bis 15625 zählen kann, sondern immer
nur bis 255. Das allerdings 61.035 mal in der Sekunde.
Also brauche ich eine Variable in der ISR die bis 30 hochgezählt wird,
damit ich auf 500ms komme.
So jetzt noch mal der Code:
INIT:
// Keine Daten von der Seriellen erhalten. Verbindung beenden
10
}
In meiner ISR_USART würde ich dann bei jedem Empfangene zeichen die
variable auf 0 setzten, richtig?
1
ISR(USART)
2
{
3
....
4
// Zeichen empfangen
5
variable=0;
6
}
Also wenn ich jetzt alles richtig verstanden habe, sollte es so
funktionieren, wenn nicht, dann bitte korigieren.
Einfacher wäre es wohl mit einer 16 Bit Timer, weil da sie ISR nur 1 mal
aufgerufen wird, aber der wird schon wo anderes verwendent.
Danke schon mal
Gruß Mousse-T
Hallo zusammen.
Der Timer Funktioniert jetzt zum Teil. Initialisiert und gestartet wird
der Timer beim Verbindungsaufbau.
Ich habe in die ISR(TIMER0_COMPA_vect) eine Usart ausgabe eingebaut die
was ausgibt wenn die variable = 60 ist. Damit hatte ich jede Sekunde
eine Ausgabe am Usart. Somit funktioniert der Timer schon mal.
Aber sobald ich Daten sende, kommt auf der Serielen keine Ausgabe mehr
von der ISR. Der Timer müsste doch trotzdem weiter laufen, oder verstehe
ich mal wieder was falsch???
Gruß Mousse-T
Mousse-T wrote:
> Ich habe in die ISR(TIMER0_COMPA_vect) eine Usart ausgabe eingebaut die> was ausgibt wenn die variable = 60 ist. Damit hatte ich jede Sekunde> eine Ausgabe am Usart. Somit funktioniert der Timer schon mal.>> Aber sobald ich Daten sende, kommt auf der Serielen keine Ausgabe mehr> von der ISR. Der Timer müsste doch trotzdem weiter laufen, oder verstehe> ich mal wieder was falsch???
Von wo nach wo "Daten sende"? Zum µC? Ist doch klar, du setzt doch deine
Timeout-Variable beim Empfang von Zeichen wieder zurück auf Null.
Das habe ich zu dem Zeitpunkt noch nicht gemacht, weil ich erst mal
wissen wollte ob der Timer überhaupt Funktioniert.
Daten senden heisst vom PC über Netzwerk an den AVR. Wenn ich das mache
kommt der AVR nicht mehr in die ISR vom Timer. Das sollte er doch oder?
Gruß
Mousse-T wrote:
> Daten senden heisst vom PC über Netzwerk an den AVR. Wenn ich das mache> kommt der AVR nicht mehr in die ISR vom Timer. Das sollte er doch oder?
Dann musst du mal einen Blick in den Netzwerk-Code werfen. Wird dort der
Timer vielleicht auch verwendet? Oder werden dort womöglich die
Interrupts global für längere Zeit abgeschaltet (kann ich mir aber eher
nicht vorstellen)?
Den Timer0 habe ich ausschliesslich für diesen Zweck verwendet.
Liege ich aber in der Annahme richtig, dass der Timer weiterlaufen
müsste solange er nicht gestoppt wird oder die Interuppts abgeschaltet
werden?
Mousse-T wrote:
> Den Timer0 habe ich ausschliesslich für diesen Zweck verwendet.
Ich dachte, du benutzt für das Netzwerk Fremdcode? Da musst du mal
reinschauen.
> Liege ich aber in der Annahme richtig, dass der Timer weiterlaufen> müsste solange er nicht gestoppt wird oder die Interuppts abgeschaltet> werden?
Ja.
Ja für das netzwerk benutze ich Fremdcode. Aber das ist nur der 16 Bit
Timer im Einsatz und die Interrupts werden nicht abgeschaltet.
Aber anscheinend wird was anderes gemacht, wenn der Timer aufhört zu
arbeiten... Muss ich dann noch mal genauer anschauen...
Wenn das Ganze im Sekundentakt laufen soll, kannste auch einen
Uhrenquarz 32,768 kHz an den asynchronen Timer hängen. Bei einem
Teilerfaktor von 128
zählt der dann im Sekundentakt. Mehr als 255 Sekunden willst Du ja nicht
warten, oder?
Damit ersparst Du dir ein ewiges CMP-Match / Overflow gebastel, wenn
intern noch andere Zeitbasen benutzt werden sollen.
Nur so als kleiner Hinweis ;-)
Ja das könnte ich auch machen, nur wollte ich eigentlich damit auskommen
was da ist ;-).
Ich wünschte mir nur noch einen 16Bit Timer. Da würde die ISR nur einmal
aufgerufen werden bei 500ms Timeout und nicht 30 mal wie beim 8Bit.
Auf jeden fall muss ich mal schauen, warum der Timer nicht
weiterläuft...
Danke an alle...