Hallo Forum, benötige eine Möglichkeit die daten die über Uart0 empfängt auf ein Steuerzeichen prüft und gleich wieder auf Uart1 weiter sendet. Hat jemand sich mit einer solchen Aufgabe schonmal auseinander gesetzt? Habe irgendwie keine so richtige Idee! Gruß Volker
1 | int
|
2 | main(void) |
3 | {
|
4 | uint8_t c; |
5 | |
6 | init_uarts(); |
7 | for (;;) { |
8 | c = UDR0; |
9 | if (c == ein_Steuerzeichen) { |
10 | /* do whatever you need */
|
11 | }
|
12 | UDR1 = c; |
13 | }
|
14 | return 0; |
15 | }
|
Oder an was dachtest du? (Obiges setzt natürlich voraus, dass die Baudraten auf beiden Seiten gleich sind.)
Hallo Jörg, diese Lösung habe ich auch schon angedacht, nur wenn ich einen ganzen Datenstrom habe kann es dann nicht passieren das ich gesendete Zeichen während meiner Prüfroutine verlieren kann? Danke und Gruß Volker
Das hängt von deiner Prüfroutine ab. Du willst uns aber auch nicht verraten, was du denn genau beim Eintreffen deines Sonderzeichens vorhast, insofern ist dir schwer wirklich zu raten. Eine andere Variante wäre es, den Empfänger interrupten zu lassen, in der ISR dann das empfangene Zeichen nur zu testen und damit ein Flag zu setzen (volatile nicht vergessen!) und sofort danach neu auszugeben. Die main loop kann dann das Flag testen (und löschen) und ihrererseits ihre langwierigen Operationen ausführen.
ja, am Ende soll es möglich sein ein Gerät von einem PC aus über den Repeater zu Programmiern. Um das Gerät reseten zu können muss ich schauen wann das Programmieren beendet ist, dies erfolgt nach dem als letztes eine Zeichenfolge z.B. 0000FFFF vom PC gesendet wurde. Das ganze soll mit 9600 Baud funktionieren. Habe das ganze mit Peter Fleury's uartlib mal probiert und bekomme nach geraumer Zeit einen Buffer Overflow. Das erklärre ich mir so, daß die Empfangsinterruptroutine ständig beansprucht wird und somit kein senden mehr möglich ist. Werde mich aber jetzt mal hinsetzen und mir das USART-Kapitel im Manual genau anschauen. Vielen Dank und Gruß Volker
Ich denke, dass der einfache Interrupt-Weg dafür funktionieren sollte.
1 | volatile uint8_t rx_char, updated; |
2 | |
3 | SIGNAL(SIG_UART0_RECV) |
4 | {
|
5 | uint8_t c; |
6 | |
7 | c = UDR0; |
8 | UDR1 = c; |
9 | rx_char = c; |
10 | updated = 1; |
11 | }
|
12 | |
13 | int
|
14 | main(void) |
15 | {
|
16 | uint8_t state = 0, c; |
17 | |
18 | init_uarts(); |
19 | sei(); |
20 | |
21 | for (;;) { |
22 | if (updated) { |
23 | updated = 0; |
24 | c = rx_char; |
25 | switch (state) { |
26 | case 0: |
27 | case 1: |
28 | if (c == 0) state++; |
29 | else state = 0; |
30 | break; |
31 | case 2: |
32 | case 3: |
33 | if (c == 255') state++; |
34 | else state = 0; |
35 | if (state == 4) { |
36 | state = 0; |
37 | pull_external_reset(); |
38 | }
|
39 | }
|
40 | }
|
41 | }
|
42 | |
43 | return 0; |
44 | }
|
Die Interruptverarbeitung sollte bei einem kontinuierlichen Datenstrom von 9600 Bd selbst bei 1 MHz Takt kein Thema sein. Die Zeichen kommen dann ca. alle 1 ms, d.h. zwischen den Zeichen verbleiben knapp 1000 Takte für die Verarbeitung. Die ISR selbst braucht 28 Takte (wenn ich mich nicht verzählt habe), also 28 µs. Die main loop braucht so 20 ... 30 Takte pro Umlauf (je nach Zustand). Eigentlich könnte man am Ende auch noch ein sleep_mode() plus einen NOP dransetzen, um die restlichen 950 µs lang Strom zu sparen. Der Zustand kann sich ja ohnehin erst ändern, nachdem es einen neuen Rx-Interrupt gab. Den NOP braucht man, weil der meiner Erinnerung nach nach dem Aufwachen abgearbeitet wird, bevor die Rx-ISR angesprungen wird, diese aber setzt ja erst das "updated"-Flag. Ggf. nach dem Aufwachen so lange Kreise laufen, bis "updated" erschienen ist.
>>Habe das ganze mit Peter Fleury's uartlib mal probiert und bekomme >>nach geraumer Zeit einen Buffer Overflow. Überlauf gibt es immer, sobald mehr Zeichen gesendet als empfangen werden: bei gleicher Baudrate versteht sich. Fügst Du vielleicht in Deinen Audgangsdatenstrom noch Zeichen ein ? Dann gibt es nach 'geraumer Zeit' Probleme. Oder werden eventuell LFs nach CR-LF expandiert ???
Hier mal der erste Ansatz von mir! @Jörg: Vielen vielen Danke, möchte dich aber nicht von deiner Arbeit abhalten. Gruß Volker
Ich würde den Koloss von Peter Fleury dafür nicht benutzen. Du hast einen Empfänger mit 9600 Bd und einen Sender mit 9600 Bd. Es kann dir bei ordentlicher Programmgestaltung also gar nicht passieren, dass der Empfänger überläuft. Warum also ...zig Tests für Dinge, die nicht auftreten können? (Ich gehe mal davon aus, dass du nicht noch flow control oder sowas brauchst.) Guck dir doch mal mein Template an. Du solltest doch wirklich ausreichend Reserven haben, die von dir gewünschte Aktion innerhalb der entsprechenden Zeit auszuführen.
Hallo Jörg, ja du hast recht ich werde mal eine einfachere Lössung anstreben als die von Peter. Eigentlich sollte es ohne FIFO funktionieren es kann ja eigentlich nichts dazwischen funken wenn der Controller nur diese Aufgabe erledigen soll. Alle anderen Aufgaben werden während dieser Aktion eh abgeschaltet. Gruß Volker
Hallo Jörg, habe neue Erkenntnisse gesammelt. Der im Anhang verwendete Code funktioniert wenn ich schneller sende als empfange wunderbar. Bei gleicher Baudrate aber nicht. Werde dann woll doch nicht um einen Zwischenspeicher herum kommen. Denke aber das dieser dann auch wieder überläuft? Gruß Volker
> Der im Anhang verwendete Code funktioniert wenn ich schneller sende > als empfange wunderbar. Bei gleicher Baudrate aber nicht. Das wundert mich, sollte man analysieren. Ich hätte mir zwar den Test auf UDRE geklemmt, aber das sollte sich nicht fatal auswirken. Bei gleicher Baudrate sollte der Sender ja wohl wieder bereit sein, zumal er ein Byte puffern kann.
Also wenn die Bytes wirklich Start an Stop kommen, dann muß der Quarz geringfügig schneller sein, damit nicht langsamer gesendet als empfangen wird. Der erste Sender sollte daher ab und zu mal Pausen machen oder mit 2 Stopbits senden. Peter
Hallo Peter, danke für deine Antwort,das mit 2 Stopbits werde ich auch mal ausprobieren. Gruß Volker
Hallo Jungs, geht jetzt alles wie gewollt lag aber nicht am Wiederholer sondern an meiner Sendeeinheit. Nun habe ich das Teil zwischen 2 PC's gehängt und es geht ab wie die Feuerwehr am Stück 100kbyte geschickt und keinen Fehler. Na ja aber jetzt habe ich wenigsten gelernt wie mann einen FIFO bastelt. Danke an Alle und Gruß Volker
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.