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
Danke noch mal. Dann werde ich das mal so ausprobieren. Gruß Mousse-T
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
1 | void timer0_init(void) |
2 | {
|
3 | TCCR0A |= (1<<WGM01); // CTC Mode |
4 | TCCR0B |= (1<<CS00 | 0<<CS01 | 1<<CS02); //Prescaler 1024 |
5 | TCNT0 = 0; // Vorbelegung mit 0 |
6 | 0CR0A = 30518; // Vergleichsregister belegen |
7 | |
8 | TIMSK |=(1<<OCIE0A); // Compare Match Interuppt |
9 | }
|
ISR
1 | ISR (TIMER0_COMP_vect) |
2 | {
|
3 | // 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
Fehler:Das OCR0A kann natürlich nur Werte <256 haben. ICh muss dann in der ISR bis 500 incrementieren und dann die verbidung beenden...
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
Timeout auf die Zeichenfolge ? Windows kann egal be welcher Baudrate auch schon mal 100ms oder so aussetzen. Das kann dann noch vom Treiber abhaengen.
Deswegen wollte ich auch ca. 500ms warten. BIn mal gespannt obs dann funktioniert ;-)
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:
1 | void timer0_init(void) |
2 | {
|
3 | TCCR0A |= (1<<WGM01); // CTC Mode |
4 | TCCR0B |= (1<<CS00 | 0<<CS01 | 1<<CS02); // Prescaler 1024 |
5 | TCNT0 = 0; // Vorbelegung mit 0 |
6 | 0CR0A = 255; // Vergleichsregister belegen |
7 | |
8 | TIMSK |=(1<<OCIE0A); // Compare Match Interuppt |
9 | }
|
ISR
1 | ISR (TIMER0_COMP_vect) |
2 | {
|
3 | variable++; |
4 | |
5 | if(variable == 30) |
6 | {
|
7 | // 500ms abgelaufen, Verbindung beenden
|
8 | }
|
9 | // 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...
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.