Hallo zusammen, habe folgendes Problem und zwar soll mein Programm sobald ich die Backspace taste betätige ein zeichen zurück gehen und bei 10 zeichen die zeichenkette ausgeben. Jedoch geht er nicht in die If Bedingung hinein nun meine Frage Wieso?. Wenn ich in die If bedingung ein 'a' oder so reinmache dann funktioniert es aber sobald ich in die If bedingung Backspace reinmache geht es nicht mehr. Ich hoffe ihr könnt mir helfen. Als Anhang lade ich euch mal mein Programm hoch Mit freundlichen Grüßen Lars
Das angehängte rar File ist defekt. Mache das bitte ohne Packprogramm. Und beschrieeb dein problem präziser: > Jedoch geht er nicht in die If Bedingung hinein welche? > Wenn ich in die If bedingung ein 'a' oder so reinmache Ich mache in die Kloschüssel rein. Was meinst du damit?
Ich konnte das rar File mit einem anderen Programm öffnen. Der eigentliche Quelltext ist:
1 | #include <avr/io.h> // Headerdatei einbinden zur Registerdefinition |
2 | #include <avr/interrupt.h> |
3 | #include <string.h> |
4 | |
5 | #define CHAR_CR (char)0x0D // Zeichen f. Carriage Return
|
6 | #define CHAR_LF (char)0x0A // Zeichen f. Line Feed
|
7 | #define CHAR_BEEP (char)0x07 // Zeichen f. Beep
|
8 | #define CHAR_BSP (char)0x08 // Zeichen f. Backspace
|
9 | #define CHARBUF_SIZ 50 // Standard-Puffergröße
|
10 | |
11 | #define ERR_NO_ERR 0
|
12 | #define ERR_BUF_OVFL -1
|
13 | #define ERR_TX_OVRRUN -2
|
14 | |
15 | |
16 | ISR(USART0_TX_vect); |
17 | ISR(USART0_RX_vect); |
18 | |
19 | #define EOL_STR_LEN 3 // Länge des EOL-Strings
|
20 | // (inklusive terminierender Null)
|
21 | char EOL_Str[EOL_STR_LEN] = {CHAR_CR, CHAR_LF, '\0'}; |
22 | |
23 | struct CharBuffer |
24 | {
|
25 | char Buffer[CHARBUF_SIZ]; |
26 | unsigned short BufPtr=0; |
27 | };
|
28 | //
|
29 | // Puffer für empfangene Zeichen
|
30 | //
|
31 | CharBuffer RXData; |
32 | |
33 | //
|
34 | // Puffer für zu sendende Zeichen
|
35 | //
|
36 | CharBuffer TXData; |
37 | |
38 | |
39 | int main(void) |
40 | {
|
41 | |
42 | UCSR0B = (1 << RXEN0) | (1 << RXCIE0) | (1<<TXEN0); // USART0 Receiver&Transmitter und RX Interput einschalten |
43 | |
44 | |
45 | UCSR0C = (1 << UCSZ00) | (1 << UCSZ01); |
46 | |
47 | UBRR0H = 0; // Einstellen der Baudrate |
48 | UBRR0L = 51; // Werte aus der Tabelle im Datenblatt |
49 | |
50 | sei(); |
51 | |
52 | // Hauptprogramm (Endlosschleife)
|
53 | |
54 | while(1) |
55 | {
|
56 | |
57 | |
58 | |
59 | }
|
60 | |
61 | return 0; |
62 | }
|
63 | |
64 | ISR(USART0_TX_vect) |
65 | {
|
66 | extern CharBuffer |
67 | TXData; |
68 | if (RXData.Buffer[RXData.BufPtr]&&(RXData.BufPtr == 0)) |
69 | {
|
70 | while (!(UCSR0A & (1 << UDRE0))) |
71 | {}
|
72 | UDR0 = CHAR_LF; |
73 | }
|
74 | if (RXData.Buffer[RXData.BufPtr]) |
75 | {
|
76 | |
77 | while (!(UCSR0A & (1 << UDRE0))) |
78 | {}
|
79 | UDR0 = RXData.Buffer[RXData.BufPtr]; |
80 | RXData.BufPtr++; |
81 | }
|
82 | else
|
83 | {
|
84 | while (!(UCSR0A & (1 << UDRE0))) |
85 | {}
|
86 | UDR0 = CHAR_CR; |
87 | while (!(UCSR0A & (1 << UDRE0))) |
88 | {}
|
89 | UDR0 = CHAR_LF; |
90 | UCSR0B = (1 << RXEN0) | (1 << RXCIE0) | (1<<TXEN0); |
91 | RXData.BufPtr = 0; |
92 | }
|
93 | |
94 | |
95 | }
|
96 | |
97 | ISR(USART0_RX_vect) |
98 | {
|
99 | extern CharBuffer RXData; |
100 | unsigned char RXChar; |
101 | RXChar = UDR0; |
102 | if(RXChar ==('b')) |
103 | {
|
104 | while (!(UCSR0A & (1 << UDRE0))) |
105 | {}
|
106 | UDR0 = CHAR_BSP; |
107 | if (RXData.BufPtr>0) |
108 | {
|
109 | RXData.BufPtr=RXData.BufPtr-1; |
110 | RXData.Buffer[RXData.BufPtr] = '\0'; |
111 | }
|
112 | }
|
113 | else
|
114 | {
|
115 | RXData.Buffer[RXData.BufPtr] = RXChar; |
116 | while (!(UCSR0A & (1 << UDRE0))) |
117 | {}
|
118 | UDR0 = RXChar; |
119 | RXData.BufPtr++; |
120 | |
121 | if(RXData.BufPtr==10) |
122 | {
|
123 | UCSR0B = (1<<TXCIE0) | (1<<TXEN0); |
124 | RXData.BufPtr = 0; |
125 | while (!(UCSR0A & (1 << UDRE0))) |
126 | {}
|
127 | UDR0 = CHAR_CR; |
128 | }
|
129 | }
|
130 | |
131 | }
|
Beitrag #5603206 wurde vom Autor gelöscht.
Warum sendest du in der receive ISR Daten obwohl du auch eine ISR für das Senden hast? > UDR0 = CHAR_BSP; > UDR0 = CHAR_CR; > UDR0 = RXChar; Warum hast du das geschrieben? > if(RXChar ==('b')) Wo hast du nun das 'a' hingemacht?
So jetzt mal Präziser erklärt: Mein Programm macht folgendes sobald ich ein Buchstabe in das Terminalprogramm (benutze PuttY) eingebe, tut das Programm automatisch nach 10 zeichen die Zeichenkette unterbrechen und abschicken. Nun soll man aber mit der Backspace taste ein zeichen zurück gehen können und damit dan das Zeichen ändern kann. Jedoch geht er nie in diese Bedingung rein. Wenn ich nun die Bedingung änder auf eine andere Taste zum zurückgehen von Zeichen funktioniert es einwandfrei. Nun war meine Frage wie ich das hinbekomm das es mit der Backspace taste auch funktioniert. Hab dazu mal ein Bild hochgeladen, da man hier nicht ein ganzen Ordner hochladen kann.
@Stefanus F. das 'b' hab ich geschrieben um zu testen ob das Rückwärtsgehen überhaupt funktioniert. Ändere das 'b' mal auf '\b' und dan wirst du sehen das die Bedingung nie wahr wird. Die Frage ist wieso??
Ich denke, es ist eine ganz schlechte Idee, in der Receive ISR darauf zu warten, dass du etwas senden darfst. Während dessen verpasst du andere empfangene Zeichen. In deinem Quelltext steht: > if(RXChar ==('b')) In deinem Screenshot steht: > if(RXChar ==('/b')) Ein backspace schreibt man aber so: '\b' Schalte mal alle Compiler Warnungen an, denn '/b' hätte er midnestens laut anmeckern müssen. Ein char kann nämlich nicht aus zwei bytes bestehen. Warum benutzt du nicht CHAR_BSP?
@Stefanus F hast Recht habe das Falsch gemacht aber dennoch funktioniert es nicht hab auch schon Probiert mit 0x08 Funktioniert aber auch nicht. Die frage bleibt immer noch warum. Es müsste eigentlich funktionieren da es mit den anderen Ascii zeichen auch funktioniert
@Stefanus CHAR_BSP hatte ich als erstes stehen hat aber auch nicht funktioniert. Deshalb habe ich alternativen Probiert, aber alles ohne Erfolg er geht einfach nicht mit Backspace in die Bedingung rein
:
Bearbeitet durch User
Eventuell sendet dein Terminalprogramm das Zeichen gar nicht. Viele Terminalprogramme werten die Eingabe Zeilenweise aus und senden sie erst, wenn du Enter drückst oder auf einen Send Button klickst. Mit Hammer Terminal kannst du auf jeden Fall alle Steuerzeichen senden. Hier ist eine Version für Java 8 und 9 (vielleicht auch neuere): http://stefanfrings.de/avr_tools/hterm.tar.gz, die originale geht nur bis Java 8.
Stefanus F. schrieb: > Ich denke, es ist eine ganz schlechte Idee, in der Receive ISR darauf zu > warten, dass du etwas senden darfst. Während dessen verpasst du andere > empfangene Zeichen. Hallo, wie würde es denn sauber gelöst aussehen? Kann man da den UDRE-Interput verwenden, um nicht versehentlich bereits ein Zeichen zu senden, obwohl man noch nicht "darf". MfG
AVR schrieb im Beitrag #5603251: > Kann man da den UDRE-Interput verwenden, um nicht versehentlich bereits > ein Zeichen zu senden, obwohl man noch nicht "darf". Dein Gegenüber sollte dir eigentlich sagen, wenn er bereit ist. (Stichwort RTR/CTS)
tefanus F. schrieb: >> Ich denke, es ist eine ganz schlechte Idee, in der Receive ISR >> darauf zu warten, dass du etwas senden darfst. Während dessen >> verpasst du andere empfangene Zeichen. AVR schrieb im Beitrag #5603251: > wie würde es denn sauber gelöst aussehen? Zunächst mal kann man ausnutzen, dass der UART genau so schnell sendet, wie er empfängt. Wenn es Dir lediglich darum geht, ein Echo zurück zu schicken, mach das ruhig so. Du sendest aber mehrere Zeichen, spätestens ab dem 2. musst du warten, dass der Sendepuffer frei wird. Das ist der Moment, wo du andere Empfangdaten verpasst. Richtig löst man das zum Beispiel mit Puffern. Alle empfangenen Daten werden (wie gehabt) von der Receive-ISR in den Puffer gelegt. Die Verabeitung der empfangenen Daten findet aber in der Haputschleife statt, nicht in der ISR. Für das Senden hast du einen zweiten Puffer. Alle zu sendenden Zeichen legst du in diesen Puffer ab, mit Ausnahme des ersten Zeichens, das legst du direkt in das UDR Register, damit der Sender aktiv wird. Also musst du beim Senden für jedes einzelne Zeichen unterscheiden: a) Ist der Puffer leer, dann UDR=c, sonst b) c in den Puffer legen. Die ISR für UDRE wird nach dem Senden jedes Zeichens aufgerufen. Nun ist es Aufgabe der entprechenden ISR, das nächste Zeichen aus dem Sende-Puffer in das UDR Register zu schreiben. Wenn es nichts mehr zu senden gibt, dann endet die ISR einfach, der Tx Sender wird dadurch inaktiv. Dafür gibt es sicher einige Tutorials, die es vorführen. Ich verzichte in meinem Programmen meistens auf diese Komplexität. Ich empfange mit ISR und Puffer, aber sende immer direkt (ohne Puffer). Der Nachteil dieser Vorgehensweise ist, dass mein Programm während des Senden in Warteschleifen hängt und nichts anderes tun kann. Auf jeden Fall soll man in der Receive ISR entweder gar nichts senden oder maximal ein Zeichen. Sonst musst du nämlich wie oben Warteschleifen in die ISR einbauen und damit stellt man sich selbst ein Bein. Warteschleifen und delays in ISR sind sehr häufig der Anfang von neuen Problemen. Ein häufiger Fall ist, Kommandos zeilenweise zu empfangen. Man will bis zum Zeilenumbruch empfangen und danach diese eine Zeile verarbeiten. Dazu kannst du in der Receive-ISR prüfen, ob der Zeilenumbruch erreicht wurde. Wenn ja, setzt du ein globales Flag auf 1. Das Hauptprogramm beschäftigt sich derweil mit anderen Aufgaben oder wartet einfach nur, bis dieses Flag auf 1 geht. Verarbeitete es die empfangene Zeile und setzt das Flag wieder auf 0, um für die nächste Zeile bereit zu sein. Vergiss nicht, die Variable für das Flag als volatile zu deklarieren und dass sie 8bit klein sein muss.
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.