Forum: Mikrocontroller und Digitale Elektronik Beim Senden mit USART werden die Zeichen zweimal ausgegeben


von Sven (Gast)


Lesenswert?

Ich beschäftige mich grad damit vom USART an ne Konsole aufm PC etwas zu 
senden. Funzt auch soweit, nur erhalte ich jedes Zeichen das ich schicke 
doppelt in der Ausgabezeile. Änder ich das zeichen, wird das zuvor 
gesendete Zeichen zuerst geschickt. Muss ich irgendwie den Datenpuffer 
nach dem senden löschen? Könnte jemand mal bitte über meinen 
Programmcode drüber schauen ? das wäre sehr nett.

Gruß Sven
1
//***************************************
2
// Test der USART Schnittstelle, ATMEGA88
3
//***************************************
4
/* 
5
  UART-Init: 
6
Berechnung des Wertes für das Baudratenregister 
7
aus Taktrate und gewünschter Baudrate
8
*/
9
 // defines
10
//*************************
11
#define FCPU 18432000
12
#define FOSC 18432000// Clock Speed
13
#define F_CPU 18432000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
14
                         // Ohne ergeben sich unten Fehler in der Berechnung
15
#define BAUD 9600UL      // Baudrate
16
#define MYUBRR FOSC/16/BAUD-1 
17
// Berechnungen
18
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
19
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
20
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
21
 
22
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
23
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
24
#endif 
25
26
// includes
27
//*************************
28
#include <inttypes.h>
29
#include <avr/io.h>
30
31
// function prototypes
32
//*************************
33
void USART_Init(unsigned int ubrr);
34
void USART_Transmit(unsigned char data);
35
36
// main
37
//*************************
38
 
39
int main(void)
40
{
41
  USART_Init(MYUBRR);
42
  
43
  
44
  USART_Transmit(0x23);
45
  
46
}
47
48
// USART initialization
49
//*************************
50
void USART_Init(unsigned int ubrr)
51
{
52
   // Set baude rate  
53
  UBRR0H = (unsigned char)(ubrr>>8);
54
     UBRR0L = (unsigned char)ubrr;
55
   
56
   // enable transmittler TXD0
57
    UCSR0B |= (1<<TXEN0);                         
58
   
59
   // set frame format: 8data, 2stop bits
60
  UCSR0C |= (1<<USBS0)|(1<<UCSZ00)|(1<<UCSZ01);  
61
}
62
 
63
64
// USART Transmit
65
//*************************
66
void USART_Transmit(unsigned char data)
67
{
68
  
69
  // Wait for empty transmit buffer
70
  while(!(UCSR0A & (1<<UDRE0)))
71
  {
72
  
73
  }
74
  
75
  // Put data ito buffer, sends the data
76
  UDR0 = data;
77
}

von Sven (Gast)


Lesenswert?

Kann mir den wirklich keiner weiterhelfen?

von OhneGlaskugel (Gast)


Lesenswert?

Das Programm gibt ein 0x23 aus, sonst nix. Wo ist denn die Verarbeitung 
der eigehenden Zeichen?

von Sven (Gast)


Lesenswert?

Ich sende bisher keine Daten zurück. Ich sende lediglich ein Zeichen 
also 0x23 an den PC. Mich interessiert nur warum ich auf meiner 
PC-Konsole ## angezeigt bekomm. Weshalb werden zwei Zeichen gesendet?

von XXX (Gast)


Lesenswert?

Hallo

Lokales Echo an/aus??

Gruß
Joachim

von g457 (Gast)


Lesenswert?

mach mal sowas rein wie..
1
while (1)
2
{
3
   _delay_ms(1000);
4
   USART_Transmit('x');
5
}
und schau dann, ob die Zeichen noch immer paarig kommen.

von Sven (Gast)


Lesenswert?

Ich habe eben festgestellt dass die Zeichen nicht doppelt gesendet 
werden sondern immer das zuvor gesendete Zeichen nochmal mitgeschickt 
wird. Habe ich beispielsweise zuerst 0x23 (#) gesendet und anschließend 
im Programmcode auf 0x25 (%) umgeschrieben, compiliert und geflasht so 
erhalte ich auf der Konsole #%. Also es hat den Anschein dass sich das 
vorige Zeichen noch in irgendeinem Zwischenspeicher befindet und mit 
gesendet wird.

Jetz hab ich noch folgendes versucht:
1
while(1)
2
  {
3
    USART_Transmit(0x23);
4
    USART_Transmit(0x25);
5
  }

und ich bekomme schön aufeinanderfolgende Zeichen mit #%#%#% usw.
Prima!

Lasse ich nun beispielsweise die while(1) wieder weg und sende quasi nur 
zwei Zeichen erhalte ich folgenden Murx auf der Konsole #\xe5#%

Hier mal die Schnitsttelle die ich zwischen Controller und PC verwende
--> http://www.chip45.com/download/Infosheet_littleUSB_090923.pdf

Was hat es mit dem lokalen Echo auf sich?

Sorry ich bin blutiger Anfänger auf dem Gebiet und wäre dankbar über 
jegliche Hilfe. An dieser Stelle schon mla Danke für die bisherigen 
Antworten.

Gruß Sven

von Clair Grube (Gast)


Lesenswert?

Sven schrieb:
> Was hat es mit dem lokalen Echo auf sich?

Das kommt aus der Konsolen-Zeit.
Die hatten eine Tastatur und einen Monitor
Die Tastatur sendete Zeichen an den Konsolenserver
Der Monitor empfing Zeichen vom Konsolenserver.

Aber die Zeichen von der Tastatur wurden nicht an den Monitor geschickt. 
Dafür war der Konsolenserver verantwortlich.
Schickt der Konsolenserver die Tastenanschläge nicht automatisch auch 
wieder an den Monitor so konnte mann zwar tippen, sah aber nix am 
Monitor.
Das automatische zurückschicken der Zeichen an den Monitor nennt man 
Echo.

Macht der Server das aber nicht, so war sah man nicht, was man gerade 
getippt hat. Irgendwie unpraktisch. Deshalb konnte man Terminals so 
einstellen, dass sie selber die getippten Zeichen gleich anzeigten, ohne 
dass der Server diese zurückschicken musste. Lokakes Echo genannt.

von Heiko (Gast)


Lesenswert?

Hallo Sven,

das mit der While Schleife ist deshalb angegeben worden, da Dein 
Programm nicht in DOS aufgerufen wird und nach einer Abarbeitung beendet 
wird. Im MC-Bereich wird ein main() nur einmal aufgerufen, durchlaufen 
und am Ende (ohne Rücksprung) natürlich auch beendet, was eigentlich im 
MC-Bereich nicht passieren darf. Wenn am Ende des Programmes nur noch 
NULL(en) stehen, wird der komplette Speicher mit NOP durlaufen und der 
Programmcounter fängt irgendwann bei 0 wieder an. Dann könnte es sein, 
das main() nochmals durchlaufen wird und Dein Zeichen nochmals gesendet 
wird, bis der Prozessor in irgenwelchen Schleifen oder Interrupts hängt.
Wahrscheinlich liegt Dein UART_Init und Dein UART_Transmit aber im 
Adressraum hinter main() und deshalb passiert die Ausgabe zwei mal.
Verhindere einfach die Beendigung von main() und schon wird die Ausgabe 
nur einfach passieren.

Heiko

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
Noch kein Account? Hier anmelden.