Forum: Mikrocontroller und Digitale Elektronik USART sendet nur kryptische Zeichen zurück


von Peter C. G. (ilem0n)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

Folgendes Problem ich nutze einen ATMega8 und Atmen Studio 6.
Ich versuche eine Kommunikation mit Hilfe des USART aufzubauen.
Folgenden Code habe ich aus den Tutorials.
Es sollte mir Also eigentlich genau das zurückschicken was ich ihm 
sende.

Anbei ein Foto von dem was ich zurück bekomme.

Kann mir das jmd erklären ?
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
#ifndef F_CPU
6
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
7
#define F_CPU 4000000UL
8
#endif
9
10
#define BAUD 9600UL
11
12
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
13
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
14
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
15
16
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
17
#error Systematischer Fehler der Baudrate gršsser 1% und damit zu hoch!
18
#endif
19
20
void uartInit(void);
21
22
int main(void)
23
{
24
  //PORTB als Eingänge mit internen Pull-Ups ausser PB0 & PB1 setzen 
25
  DDRB = 0x00;
26
  PORTB = 0xFC;
27
  
28
  //PORTC die ersten 4 Bits auf Ausgänge setzten 
29
  DDRC = 0x0F;
30
  
31
  uartInit(); //USART init
32
  sei();    //Interrupts erlauben
33
  
34
  //Hauptschleife 
35
    while(1)
36
    {
37
    PORTC |= (1<<PC2);
38
    _delay_ms(1000) ;
39
    PORTC &= ~(1<<PC2);
40
    _delay_ms(1000);
41
    }
42
}
43
44
//############# UART ###########
45
void uartInit(void)
46
{
47
  UBRRH = (unsigned char) (UBRR_VAL >> 8);
48
  UBRRL = (unsigned char) UBRR_VAL;
49
  
50
  UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE) | (1<<TXCIE) ;
51
  UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
52
}
53
54
#define UART_MAXSTRLEN 10
55
56
volatile uint8_t uart_str_complete = 0;     // 1 .. String komplett empfangen
57
volatile uint8_t uart_str_count = 0;
58
volatile char uart_string[UART_MAXSTRLEN + 1] = "";
59
ISR(USART_RXC_vect)
60
{
61
  unsigned char nextChar;
62
  
63
  // Daten aus dem Puffer lesen
64
  nextChar = UDR;
65
  if( uart_str_complete == 0 ) {  // wenn uart_string gerade in Verwendung, neues Zeichen verwerfen
66
  
67
    // Daten werden erst in uart_string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
68
    if( nextChar != '\n' &&
69
    nextChar != '\r' &&
70
    uart_str_count < UART_MAXSTRLEN ) {
71
      uart_string[uart_str_count] = nextChar;
72
      uart_str_count++;
73
    } else {
74
      uart_string[uart_str_count] = '\0';
75
      uart_str_count = 0;
76
      uart_str_complete = 1;
77
      uartPutStr(uart_string);
78
    }
79
  }
80
}
81
82
//++++++++++ SEND +++++++++++
83
int uartPutChar(unsigned char c)
84
{
85
  while (!(UCSRA & (1<<UDRE)))
86
  ;
87
  UDR = c;
88
  return 0;
89
}
90
void uartPutStr (char *s)
91
{
92
  while (*s)
93
  {
94
    uartPutChar(*s);
95
    s++;
96
  }
97
}

von Sebastian H. (technik_freak)


Lesenswert?

Hallo,

Ich habe bzgl. deinem Problem folgende Fragen:

1) Kommunikation im µC ist bei 9600 Bd. Wie ist diese am PC 
eingestellt?(kann u.U. falsch eingestellt sein)

2) Wie ist die Verbindung hergestellt worden [RS232 / USB-IC(FT232) 
UART-Kabel ...]? Leitungen richtig angeschlossen (GND nicht vergessen)

3) 4MHz entnehme Ich deinem Programmcode. Welche Art von Taktquelle 
(Intern? Quarz...)?

3.1) Hast du einen SP für uns? (ist immer hilfreich)

von Ralf G. (ralg)


Lesenswert?

- Was hast du für eine Taktquelle angeschlossen?
- Welche Frequenz?
- Teilst du das in den Projekteinstellungen dem Programm auch mit?

von Falk B. (falk)


Lesenswert?


von c-hater (Gast)


Lesenswert?

Peter C. Glade schrieb:

> Ich versuche eine Kommunikation mit Hilfe des USART aufzubauen.
> Folgenden Code habe ich aus den Tutorials.
> Es sollte mir Also eigentlich genau das zurückschicken was ich ihm
> sende.
>
> Anbei ein Foto von dem was ich zurück bekomme.
>
> Kann mir das jmd erklären ?

Nö. Zumal der Screenshot ganz offensichtlich nichts direkt mit einer 
Kommunikation per USART zu tun hat, sondern die aufgezeichnete 
Kommunikation IP-basiert ist.

Egal, wie nun diese USART-Daten durch das IP-Netz transportiert werden, 
es gibt auf jeden Fall reichlich Stellen, an denen es hakeln kann.

Sinnvolle Hinweise kann man ohne weitere Details zur Abwicklung der 
Kommunikation wohl kaum geben.

von Peter C. G. (ilem0n)


Lesenswert?

Also die Frequenz habe ich am µC mit den Fuses gesetzt (Int. RC Osc. 
4MHz; Start-up-time: 6CK +64ms), sowie im Atmel Studio Toolchain unter 
Symbols definiert.

Die Kommunikation läuft über ein WLAN Modul (Wiznet WI610wi) selches 
Über eine serielle Schnittstelle verfügt. Dort ist folgende Einstellung: 
Baud 9600, 8bit, keine Parität, 1 Stoppbit

Via TCP Test Tool schicke ich die Daten also an das Modul welche diese 
auf die serielle Schnittstelle ausgeben. und umgekehrt.

Bei einem vorigen Projekt hat diese Kommunikation auch wunderbar 
funktioniert, allerdings ist dieses Programm diesmal im 
Interruptbetrieb. Das ist der einzige Unterschied.


> 3.1) Hast du einen SP für uns? (ist immer hilfreich)

Was bedeutet SP ?

von Georg G. (df2au)


Lesenswert?

Es soll wohl auch nur einmal gesendet werden... oder an welcher Stelle 
wird uart_str_complete nach dem Senden wieder gelöscht?
Nächste Frage: Sendet dein Terminalprogramm wirklich \n oder \r am 
Zeilenende? Sonst sendest du bis der Puffer voll ist.

von Dietrich L. (dietrichl)


Lesenswert?

Peter C. Glade schrieb:
> Int. RC Osc.

Möglicherweise ist der Takt zu ungenau. Du kannst Dir ja die 
Datenleitung mal mit einem Oszi anschauen, und/oder einen externen Quarz 
oder Quarzgenerator verwenden.

Gruß Dietrich

von Georg G. (df2au)


Lesenswert?

Du gibst den Tx-fertig Interrupt frei, hast aber keinen Handler dafür 
installiert. Das kann auch in die Beinkleider gehen.

von Peter C. G. (ilem0n)


Lesenswert?

Also ich habe jetzt das ganze nochmal mit einem 4MHz Quarz Oszillator 
aufgebaut. Offenbar hat mir die Ungenauigkeit der Internen Frequenz 
einen Streich gespielt. Allerdingss würde mich interessieren wieso es im 
Interruptbetrieb nicht funktioniert wo es doch ohne wunderbar lief ?

von Karl H. (kbuchegg)


Lesenswert?

Peter C. Glade schrieb:

> Allerdingss würde mich interessieren wieso es im
> Interruptbetrieb nicht funktioniert wo es doch ohne wunderbar lief ?

Das Programm von da oben kann nicht korrekt funktioniert haben. Du 
gibst hier
1
  UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE) | (1<<TXCIE) ;
den Transmit Complete Interrupt frei für den du keinen Handler hast. 
Sobald das erste Zeichen raus gegangen ist, wird der Interrupt ausgelöst 
und das Versäumnis, dass du keinen Handler hast mit einem µC-Reset 
bestraft. Was dann die UART mit dem nächstenb halb empfangenen Zeichen 
macht, steht in den Sternen. Da werden dann wohl ein paar Bits während 
des Resets verloren gegangen sein. Das könnten dann genau die fehlenden 
Bits sein, die dir die Übertragung versauen.

Ergo: Man gibt keinen Interrupt frei, für den man keinen Handler hat. 
Niemals!

von Peter C. G. (ilem0n)


Lesenswert?

Das hab ich jetzt auch schmerzlich lernen müssen ^^
Allerdings hatte ich es vorher (ohne Ext. Quarz) auch ohne den TXCIE 
versucht mit selbigen Ergebnis.

In dem prozessualen Projekt habe ich gewartet das am UDR etwas 
geschrieben wird (was auch der einzige Trigger war den ich brauchte). 
Dann hab ich dies in einen Puffer geschrieben und aufs nächste Zeichen 
gewartet.
Hat wunderbar funktioniert auch ohne Quarz.

Nun mit Interrupts habe ich plötzlich Probleme mit der Taktfrequenz ?

Da geht mir der Zusammenhang irgendwo ab.

PS: Vielen Dank für die tolle Hilfe ;)

von Michael (Gast)


Lesenswert?

Peter C. Glade schrieb:
> #include <avr/io.h>
> #include <util/delay.h>
> #include <avr/interrupt.h>
>
> #ifndef F_CPU
> #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit
> 4000000"
> #define F_CPU 4000000UL
> #endif

Woher stammt eigentlich diese sinnfreie Reihenfolge?
Erst muß F_CPU festgelegt werden und dann die delay.h eingebunden 
werden. Sonst kommt da nur Mist raus.

von icke (Gast)


Lesenswert?

Michael schrieb:
> Erst muß F_CPU festgelegt werden und dann die delay.h eingebunden
> werden.

Das hat der Compiler auch mit Sicherheit mit einer Warnung ausgegeben. 
Aber es gibt immerwieder Leute, die Warnungen konsequent übersehen... 
("Es kompiliert doch, also muss es doch richtig sein!")

von Peter C. G. (ilem0n)


Angehängte Dateien:

Lesenswert?

Frisch Kompiliert.

No Errors, No Warnings.

Ich könnte allerdings auf die Zeile ebensogut verzichten F_CPU ist unter 
"Symbols" in Atmel Studio definiert.

Was wohl auch der Grund dafür ist das keine Warnung kommt ^^

Danke für den Hinweis, beim spielen und probieren gibts ja oft 
Code-Leichen ^^

von Karl H. (kbuchegg)


Lesenswert?

Peter C. Glade schrieb:

> Ich könnte allerdings auf die Zeile ebensogut verzichten F_CPU ist unter
> "Symbols" in Atmel Studio definiert.

Das ist auch gut so.

Immer mehr setzt sich die Erkenntnis durch, dass das hier
1
#ifndef F_CPU
2
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
3
#define F_CPU 4000000UL
4
#endif
keine so gute Idee ist.
Wenn F_CPU nicht durch das Makefile, oder wie in deinem Fall die IDE, 
definiert wird, dann ist es am besten dieses als Fehler zu werten und 
den Programmierer zu zwingen, dieses Versäumnis nachzuholen.
Aber dieses 'Nachdefinieren' innerhalb des Source Codes ist ein 
fehleranfälliger Stolperstein.

von Peter C. G. (ilem0n)


Lesenswert?

Als Laie auf diesem Gebiet bin ich dann mal dem Tutorial zum Opfer 
gefallen ^^

Ja es passiert leider sooft das Wichtige Details durch solche Codes 
umgangen werden, das macht es grade für Anfänger nicht grade leichter.

von Karl H. (kbuchegg)


Lesenswert?

Peter C. Glade schrieb:
> Als Laie auf diesem Gebiet bin ich dann mal dem Tutorial zum Opfer
> gefallen ^^

"Nichts ist so schwer auszurotten, wie schlechte Gewohnheiten"

Zumal dieser Punkt ja auch durchaus kontrovers diskutiert werden kann.

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.