mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART sendet nicht das was er soll (kein offset problem)


Autor: Robert Maucher (robert_maucher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Ich benutze Robostix bord von Gumstix. (8Mhz Intern, mega128)

An diesem Board möchte ich gern einen UART Verbindung zum PC betreiben.
Leider macht diese Verbindung nicht das was sie soll.

Ich habe zuerst eine eigene Routine geschrieben, die ich auch in anderen 
Projekten schon genutzt habe und die Ports angepasst.
Leider hat das nicht Funktioniert.
Als nächstes habe ich die bewährte UART Routine von Peter Fleury benutzt 
um sicher zu gehen das in der Implementierung nichts falsch ist. leider 
hat das auch nicht geklappt.

Um das Problem einzukreisen habe ich jeden Schnick Schnack entfernt und 
nur eine einfache UART Implementierung genommen.
#define USART_BAUDRATE_0 2400UL
#define UBRR_0 ((F_CPU+USART_BAUDRATE_0*8)/(USART_BAUDRATE_0*16)-1)
int main(void){
  UBRR0H = (uint8_t) (UBRR_0>>8);
  UBRR0L = (uint8_t) (UBRR_0 & 0xFF);
  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
  UCSR0C = (3 << UCSZ0);
  int16_t i = -12345;
  unsigned char s[]={'k','a','t','z','e','\0'};
  void USART_Transmit( unsigned char data )
  {
    /* Wait for empty transmit buffer */
    while ( !( UCSR0A & (1<<UDRE0)) )
         ;
    /* Put data into buffer, sends the data */
    UDR0 = data;
  }

  void uart3_puts (char *s)
  {
      do{   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
          USART_Transmit(*s);
          s++;
      }while (*s);
  }

  while(1){

Ein einzelnens Zeichen ausgeben funktioneirt
USART_Transmit('e');//Ausgabe: e

Ein Zeichen aus dem char Array (s)auszugeben auch
USART_Transmit(s[3]);//Ausgabe: z

Eine Zahl im Terminal hochzählen lassen mit einer For-Schleife
for(i=0;i<=4;i++){
        USART_Transmit(i+0x30);
        USART_Transmit(',');
}//Ausgabe: 0,1,2,3,4

Was nicht Funktioniert ist ein Array in einer Schleife auszugeben.
for(i=0;i<=4;i++){
        USART_Transmit(s[i]);
}//Ausgabe: S (Undefiniertes Zeichen) T (Undefiniertes Zeichen)

Ich hab zuerst an ein Buffer oder Timing Problem gedacht aber wenn ich 
mehrere Zeichen direkt einzeln Ausgebe dann ist die Ausgabe auch 
korrekt.
USART_Transmit(s[0]);
USART_Transmit(s[1]);
USART_Transmit(s[2]);
USART_Transmit(s[3]);
USART_Transmit(s[4]);
USART_Transmit('\n');//Ausgabe: Katze

Ich hoffe das ihr mir Helfen könnt, denn ich bin mit meinem Latein am 
ende.

gruß,
Robert

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>int main(void){
>  UBRR0H = (uint8_t) (UBRR_0>>8);
>  UBRR0L = (uint8_t) (UBRR_0 & 0xFF);
>  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
>  UCSR0C = (3 << UCSZ0);
>  int16_t i = -12345;
>  unsigned char s[]={'k','a','t','z','e','\0'};
>  void USART_Transmit( unsigned char data )
>  {

Die Definition einer Funktion (USART_Transmit) in einer Funktion (main) 
erzeugt bei deinem Compiler keinen Fehler?

Ich spekuliere im Moment darauf, dass in dem Fehlerbeispiel das Feld s 
nicht mehr gültig ist, wenn die Funktion USART_Transmit es abarbeiten 
will.

Meiner Ansicht nach würde es bei der Fehlersuche helfen, wenn du exakt 
die verwendeten Quellcodes anhängen würdest.

Autor: Robert Maucher (robert_maucher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein hat nicht mal ne Warnung gegeben.
Hab die 2 Funktionen jetzt auserhalb der main deklariert.
Aber das Problem besteht Immernoch.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert Maucher schrieb:
> Nein hat nicht mal ne Warnung gegeben.

Ist eine gcc Erweiterung.

Das wird vielleicht in irgendeiner der nächsten ISO-C Versionen kommen. 
IMHO ist das aber in C nicht wirklich so der große Brüller, so dass es 
eigentlich keinen Grund gibt, so etwas zu machen.

In C regeln sich viele Probleme, bei denen man nach Funktionen in 
Funktionen schreit, durch die Aufteilung in mehrere Source Code Files 
von alleine, so dass dieses Feature nicht sooooo nachgefragt ist.

> Hab die 2 Funktionen jetzt auserhalb der main deklariert.
> Aber das Problem besteht Immernoch.

Wie schon gesagt:
Zeige bitte den kompletten Code

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Funktion uart3_puts änderst du mal so um
void uart3_puts (char *s)
{
  while( *s ) {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
    USART_Transmit(*s);
    s++;
  }
}

damit ist schon mal der Fehler, das du das \0 Zeichen mitüberträgst, weg 
(oder war das Absicht?)

Autor: Robert Maucher (robert_maucher)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Robert Maucher schrieb:
> Nein hat nicht mal ne Warnung gegeben.
> Hab die 2 Funktionen jetzt auserhalb der main deklariert.
> Aber das Problem besteht Immernoch.

Die Quellcodes ist im Moment nur dieser eine.
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>

#define USART_BAUDRATE_0 2400UL
#define UBRR_0 ((F_CPU+USART_BAUDRATE_0*8)/(USART_BAUDRATE_0*16)-1)

void USART_Transmit( unsigned char data )
  {
    /* Wait for empty transmit buffer */
    while ( !( UCSR0A & (1<<UDRE0)) )
         ;
    /* Put data into buffer, sends the data */
    UDR0 = data;
  }

  void uart3_puts (char *s)
  {
      do{   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
          USART_Transmit(*s);
          s++;
      }while (*s);
  }
int main(void){
  UBRR0H = (uint8_t) (UBRR_0>>8);
  UBRR0L = (uint8_t) (UBRR_0 & 0xFF);
  UCSR0B = (1 << RXEN0) | (1 << TXEN0);
  UCSR0C = (3 << UCSZ0);
  unsigned char s[]={'k','a','t','z','e','\0'};


  while(1){
//    USART_Transmit('K');
//    USART_Transmit('a');
//    USART_Transmit('t');
//    USART_Transmit('z');
//    USART_Transmit('e');
//    USART_Transmit('\n'); //geht

//    uart3_puts (s); //geht nicht

//    USART_Transmit(s[0]);
//    USART_Transmit(s[1]);
//    USART_Transmit(s[2]);
//    USART_Transmit(s[3]);
//    USART_Transmit(s[4]);
//    USART_Transmit('\n'); //geht

    int i;
    unsigned char dummy;
    for(i=0;i<=4;i++){
      _delay_ms(1000);
      USART_Transmit(i+0x30); //geht
      USART_Transmit('\n');
    }
    for(i=0;i<=4;i++){
      _delay_ms(1000);
      USART_Transmit(s[i]);//geht nicht
      USART_Transmit('\n');
    }
  }
}

Autor: Robert Maucher (robert_maucher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Die Funktion uart3_puts änderst du mal so um
>
>
> void uart3_puts (char *s)
> {
>   while( *s ) {   /* so lange *s != '\0' also ungleich dem
> "String-Endezeichen" */
>     USART_Transmit(*s);
>     s++;
>   }
> }
> 
>
> damit ist schon mal der Fehler, das du das \0 Zeichen mitüberträgst, weg
> (oder war das Absicht?)

Ja war ein Fehler. ich habe die while irgendwann mal gegen eine do while 
ausgetauscht und das s++ in der Schleife vergessen zu löschen.

Das Problem mit der for Schleife besteht immer noch, da es mit der 
uart3_puts nichts zu tun hat, aber trotzdem danke.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert Maucher schrieb:

> Das Problem mit der for Schleife besteht immer noch,

Ich sehs.
Aber ich sehe nichts, was das von dir beschriebene Verhalten erklären 
könnte.

Kann es sein, dass du mit der Baudrate ein klein wenig daneben bist 
(interner RC-Oszillator) und bei dieser Übertragung einfach zuviele 
Zeichen am Stück gesendet werden und sich der Empfänger nicht richtig 
synchronisieren kann.

Autor: Robert Maucher (robert_maucher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das habe ich mir auchgedacht, aber wenn ich
USART_Transmit(s[0]);
USART_Transmit(s[1]);
USART_Transmit(s[2]);
USART_Transmit(s[3]);
USART_Transmit(s[4]);
USART_Transmit('\n');
dauernd in der while(1) drin habe dann passt alles.
Und was anders macht die For Schleife eigentlich auch nicht.

Hab mir noch gedacht das es einen Jitter geben könnte der mir ein 
Problem Macht, aber da passt alles.

bin Inzwischen auf 2400 Baud runter weniger kann ich nicht.
(Im Datenblatt steht das ein maximaler Fehler von 0,2% bei 2400 Baud 
ist.)

Das Problem lässt mich langsam durchdrehen.

Werde jetzt mal alles in Assamler coden um zu schauen (was ich eher 
nicht denk) ob im avr-gcc ein bug ist. was anderes kann ich mir nicht 
mehr vorstellen.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Robert Maucher (robert_maucher)

>Werde jetzt mal alles in Assamler coden um zu schauen (was ich eher
>nicht denk) ob im avr-gcc ein bug ist. was anderes kann ich mir nicht
>mehr vorstellen.

;-)
Selten so gelacht. Lern erstmal ein paar Grundlagen.

http://www.mikrocontroller.net/articles/AVR_Checkl...

MFG
Falk

Autor: Robert Maucher (robert_maucher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falk Brunner schrieb:
> @  Robert Maucher (robert_maucher)
>
>>Werde jetzt mal alles in Assamler coden um zu schauen (was ich eher
>>nicht denk) ob im avr-gcc ein bug ist. was anderes kann ich mir nicht
>>mehr vorstellen.
>
> ;-)
> Selten so gelacht. Lern erstmal ein paar Grundlagen.
>
> http://www.mikrocontroller.net/articles/AVR_Checkl...
>
> MFG
> Falk

Danke erst mal,

-ich habe nur einen Internen Takt zu verfügung.
-die verbindung und die Übertragung funktioniert Prinzipiell
-zeichen könne ohne fehler übertragen werden wenn man sie einzeln von 
hand eingibt (z.b. USART_Transmit('q');) sowie aus einen Array genommen 
werden (z.b. USART_Transmit(s[1]);)
-zeichenketten gehen nicht (uart3puts ...)
-einzelne zeichen in einem Array mit einer forschleife ausgeben geht 
nicht

Grundlagen habe ich schon Durchgelesen.

gruß Robert

Ps: Hilfsbedürftige ins Lächerliche zu ziehen ist nicht die feine Art

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich spekuliere, dass es Unterschiede im Funktionsaufruf gibt. Deshalb: 
Wie ist die M103 Fuse des Atmega128 eingestellt? Kannst du ein 
Disassemblerlisting (oder das HEX-File) bereitstellen?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert Maucher schrieb:

> -ich habe nur einen Internen Takt zu verfügung.

Das ist schon mal ziemlich schlecht.


Nur testweise:
probier mal Folgendes
void USART_Transmit( unsigned char data )
{
  /* Wait for empty transmit buffer */
  while ( !( UCSR0A & (1<<UDRE0)) )
    ;
  /* Put data into buffer, sends the data */
  UDR0 = data;

  _delay_ms( 1 );
}

wenns dann geht, dann hast du ziemlich sicher ein Problem mit dem 
internen Oszillator.

Du kannst auch mal probieren, auf 2 Stoppbits zu erhöhen.

> Ps: Hilfsbedürftige ins Lächerliche zu ziehen ist nicht die feine Art

Wenn jemand den internen Oszillator zur UART Übertragung benutzt, ist 
jegliches Mitleid fehl am Platze.

Autor: Robert Maucher (robert_maucher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Robert Maucher schrieb:
>
>> -ich habe nur einen Internen Takt zu verfügung.
>
> Das ist schon mal ziemlich schlecht.
>
>
> Nur testweise:
> probier mal Folgendes
>
>
> void USART_Transmit( unsigned char data )
> {
>   /* Wait for empty transmit buffer */
>   while ( !( UCSR0A & (1<<UDRE0)) )
>     ;
>   /* Put data into buffer, sends the data */
>   UDR0 = data;
> 
>   _delay_ms( 1 );
> }
> 
>
> wenns dann geht, dann hast du ziemlich sicher ein Problem mit dem
> internen Oszillator.
>
> Du kannst auch mal probieren, auf 2 Stoppbits zu erhöhen.

das geht auf jedenfall
auch ohne delay

ich hab nur probleme mit

einer String (char array) ausgabe

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert Maucher schrieb:

> das geht auf jedenfall
> auch ohne delay
>
> ich hab nur probleme mit
>
> einer String (char array) ausgabe

Probiers einfach!

An deiner String Ausgabe ist nichts falsch.
Es könnte aber sein, dass dein Optimizer die Schleifenvariante schneller 
realisieren kann, als wenn du die Aufrufe einzeln machst. Mit ein wenig 
Pech reicht das dann schon, dass du mit dem Timing daneben bist.

Autor: Robert Maucher (robert_maucher)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Die M103 ist deaktiviert da ich später beide Uarts brauche

Autor: Robert Maucher (robert_maucher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert Maucher schrieb:
> Karl heinz Buchegger schrieb:
>> Robert Maucher schrieb:
>>
>>> -ich habe nur einen Internen Takt zu verfügung.
>>
>> Das ist schon mal ziemlich schlecht.
>>
>>
>> Nur testweise:
>> probier mal Folgendes
>>
>>
>> void USART_Transmit( unsigned char data )
>> {
>>   /* Wait for empty transmit buffer */
>>   while ( !( UCSR0A & (1<<UDRE0)) )
>>     ;
>>   /* Put data into buffer, sends the data */
>>   UDR0 = data;
>>
>>   _delay_ms( 1 );
>> }
>> 
>>
>> wenns dann geht, dann hast du ziemlich sicher ein Problem mit dem
>> internen Oszillator.
>>
>> Du kannst auch mal probieren, auf 2 Stoppbits zu erhöhen.
>
> das geht auf jedenfall
> auch ohne delay
>
> ich hab nur probleme mit
>
> einer String (char array) ausgabe

Nein macht kein Unterschied,
Ich habe jetzt auch mit verschiedenen Zeiten Rumgespielt, aber hat auch 
keine Veränderung gegeben.


von der Timing her müsste es eigentlich kein Problm geben, da
for(i=0;i<=4;i++){
  USART_Transmit(i+0x30); //geht
  USART_Transmit('\n');
}

auch ohne Probleme ausgegeben wird

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann hilft alles nichts.
Ein Assembler Listing muss her

Autor: Robert Maucher (robert_maucher)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Dann hilft alles nichts.
> Ein Assembler Listing muss her

Hier die Listings und die Maps

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde dir raten nochmal sehr gründlich und eindringlich die M103C 
Fuse zu überprüfen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Ich würde dir raten nochmal sehr gründlich und eindringlich die M103C
> Fuse zu überprüfen.

Das lässt sich relativ leicht prüfen.
Einfach den Optimizer komplett ausschalten, so dass er nichts inlinen 
kann. Wenns beim ersten Funktionsaufruf kracht, dann wars die Fuse

So dumm ist der Geadnke gar nicht.
Selbst wenn der Compiler alle Funktionen inlined, das Array kann er beim 
besten Willen nicht in einem Register halten.
Liegt das SRAM aber falsch (durch die Fuse) werden falsche Daten 
gelesen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> So dumm ist der Geadnke gar nicht.

Hey, hattest du etwa gedacht, ich hätte das "einfach mal so" 
hingeschrieben? ;-)

Karl heinz Buchegger schrieb:
> Liegt das SRAM aber falsch (durch die Fuse) werden falsche Daten
> gelesen.

Wenn die Fuse gesetzt ist, ist dort, wo die Daten liegen, gar kein RAM. 
Und bei den direkten Aufrufen (USART_Transmit(s[0]);) werden die 
Zugriffe auf die Daten natürlich durch den Optimizer gleich durch die 
Zeichen ersetzt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Karl heinz Buchegger schrieb:
>> So dumm ist der Geadnke gar nicht.
>
> Hey, hattest du etwa gedacht, ich hätte das "einfach mal so"
> hingeschrieben? ;-)

Jetzt hab ich mich in die Nesseln gesetzt.
Ich hab die Fuse jetzt nur im Zusammenhang mit Funktionsaufrufen gesehen 
und laut ListFile hat der Compiler, was ich so gesehen habe, alles 
inline gemacht.

(Sieh die Aussage als Selbstgespräch mit mir selber an :-)

Autor: Robert Maucher (robert_maucher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Stefan Ernst schrieb:
>> Ich würde dir raten nochmal sehr gründlich und eindringlich die M103C
>> Fuse zu überprüfen.
>
> Das lässt sich relativ leicht prüfen.
> Einfach den Optimizer komplett ausschalten, so dass er nichts inlinen
> kann. Wenns beim ersten Funktionsaufruf kracht, dann wars die Fuse
>
> So dumm ist der Geadnke gar nicht.
> Selbst wenn der Compiler alle Funktionen inlined, das Array kann er beim
> besten Willen nicht in einem Register halten.
> Liegt das SRAM aber falsch (durch die Fuse) werden falsche Daten
> gelesen.

10011001 low fuse (0x99)

11100100 high fuse (0xE4)

11111111 efuse (0xFF)-> für kombi m103 oxFD

Autor: Robert Maucher (robert_maucher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert Maucher schrieb:
> Karl heinz Buchegger schrieb:
>> Stefan Ernst schrieb:
>>> Ich würde dir raten nochmal sehr gründlich und eindringlich die M103C
>>> Fuse zu überprüfen.
>>
>> Das lässt sich relativ leicht prüfen.
>> Einfach den Optimizer komplett ausschalten, so dass er nichts inlinen
>> kann. Wenns beim ersten Funktionsaufruf kracht, dann wars die Fuse
>>
>> So dumm ist der Geadnke gar nicht.
>> Selbst wenn der Compiler alle Funktionen inlined, das Array kann er beim
>> besten Willen nicht in einem Register halten.
>> Liegt das SRAM aber falsch (durch die Fuse) werden falsche Daten
>> gelesen.
>
> 10011001 low fuse (0x99)
>
> 11100100 high fuse (0xE4)
>
> 11111111 efuse (0xFF)-> für kombi m103 oxFD

 hab das Problem Gefunden

es war der komi Modus und die Fuse war nicht gestezt

war ein Fehler in der Makefile
hatte einen Tippfehler bei der e fuse ein read (r) anstatt write (w)

Danke euch allen für die Hilfe

gruß Robert

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Robert Maucher (robert_maucher)

> hab das Problem Gefunden
>es war der komi Modus und die Fuse war nicht gestezt

>war ein Fehler in der Makefile
>hatte einen Tippfehler bei der e fuse ein read (r) anstatt write (w)

Und wieder einmal triumphiert die AVR Checkliste.

MfG
Falk

Autor: Robert Maucher (robert_maucher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja die Checkliste ist schon wichtig, noch wichtiger ist die eigene 
Unfähigkeit zu tippen zu überwinden schande über mich

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.