USART sendet nur kryptische Zeichen zurück

#3241684
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
}
Angehängte Dateien:
#3241700
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)
Gast #3241716
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.
#3241722
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 ?
#3241927
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!
#3241931
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 ;)
Gast #3241945
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.
Gast #3241952
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!")
#3241972
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren