mikrocontroller.net

Forum: Compiler & IDEs Problem mit string.


Autor: martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

folgender Code:

char text[] ="HelloAVR";
text[0]='H';
text[1]='e';
for(int ci=0; text[ci] != '\0'; ++ci)
{
   putch(text[ci]);
}
putch('\n');

(putch gibt das Zeichen auf dem uart aus, geht auch)

erzeugt folgende Ausgabe auf dem Terminal:
Heì\0x01\0x0f\0x01\0x03\0x02

Das verstehe ich nicht. warum funktioniert die Zuweisung in der 
initialisierung nicht?

Vielleicht kann mir jemand einen Tip geben?

Danke!
MFG
Martin

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist kein komplettes Programm. Die Ursache kann in dem nicht 
angegebenen Teil stecken.

Autor: martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/io.h> // I/O Funktionen
#include <stdint.h> // Datentypen z.B. uint32_t
#include <avr/pgmspace.h>
#define F_CPU      14745600UL
#include <util/delay.h>
#include <string.h>


#define HW_VER   0x02
#define SW_MAJOR 0x01
#define SW_MINOR 0x12
#define BAUD_RATE    115200
#define DECRYPT 0
#define ENCRYPT 1
#define SIG1  0x1E
#define SIG2  0x97
#define SIG3  0x02
#define PAGE_SIZE  0x80U  //128 words
#define UART1


#define LED_DDR  DDRB
#define LED_PORT PORTB
#define LED_PIN  PINB
#define LED      PINB7

#define SW_DDR  DDRF
#define SW_PORT PORTF
#define SW_PIN  PINF
#define SW0     PINF7 //Schalter0 an Pin 7
#define SW1     PINF6 //Schalter1 an Pin 6
#define mswait 10

struct flags_struct {
  unsigned flag_1 : 1; // Schalter; 0: SW0 1: SW1
  unsigned flag_2 : 1;
  unsigned flag_3 : 1;
  unsigned flag_4 : 1;
  unsigned flag_5 : 1;
  unsigned flag_6 : 1;
  unsigned flag_7 : 1;
  unsigned flag_8 : 1;
} flags;

void wait10ms(uint16_t xms);
void inituart(void);
void lese_Schalter(void);
void putch(char ch);
char getch(void);

int main(void)
{
  flags.flag_2 = 0;
  SW_DDR &= ~(1 << SW0); //Ausgang=1 Eingang=0 daher l?schen
  SW_DDR &= ~(1 << SW1);
  SW_PORT |= (1 << SW0); //Bei Eingang steuer Port die 
Pull-up-Widerst?nde!
  SW_PORT |= (1 << SW1); // hier: Pull-up auf EIN!

  asm volatile("nop\n\t");
  LED_DDR |= (1 << LED); // LED auf Ausgang
  LED_PORT &= ~(1 << LED); // LED EIN
  inituart();

  for (;;)
  {
           char text[] = "HelloAVR";
           //PGM_P text = {"HelloAVR"};
           text[0]='H';
     text[7]='R';
  for(int ci=0; text[ci] != '\0'; ++ci)
  {
    putch(text[ci]);
  }
  putch('\n');
}
  }
}

void inituart()
{
    UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
    UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
    UCSR1A = 0x00; //
    UCSR1C = 0x06;
    UCSR1B = _BV(TXEN1)|_BV(RXEN1);

    // bei neueren AVRs steht der Status in UCSRA/UCSR0A/UCSR1A
    while (!(UCSR1A & (1<<UDRE)))  // warten bis Senden moeglich
    {
    }

    PGM_P welcome = {"HelloAVR; Matthias Vogt - build 070106\n\r"};
  for(int i=0; welcome[i] != '\0'; ++i)
  {
    putch(welcome[i]);
  }
}

void putch(char ch)
{
   while (!(UCSR1A & _BV(UDRE1)));
   UDR1 = ch;
}

char getch(void)
{
  while(!(UCSR1A & _BV(RXC1)));
    return (UDR1);
}

Autor: martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Neuere Versin, sorry. Diese geht aber genausoenig!



#include <avr/io.h> // I/O Funktionen
#include <stdint.h> // Datentypen z.B. uint32_t
#include <avr/pgmspace.h>
#define F_CPU      14745600UL
#include <util/delay.h>
#include <string.h>


#define HW_VER   0x02
#define SW_MAJOR 0x01
#define SW_MINOR 0x12
#define BAUD_RATE    115200
#define DECRYPT 0
#define ENCRYPT 1
#define SIG1  0x1E
#define SIG2  0x97
#define SIG3  0x02
#define PAGE_SIZE  0x80U  //128 words
#define UART1


#define LED_DDR  DDRB
#define LED_PORT PORTB
#define LED_PIN  PINB
#define LED      PINB7

#define SW_DDR  DDRF
#define SW_PORT PORTF
#define SW_PIN  PINF
#define SW0     PINF7 //Schalter0 an Pin 7
#define SW1     PINF6 //Schalter1 an Pin 6
#define mswait 10

void wait10ms(uint16_t xms);
void inituart(void);
void lese_Schalter(void);
void putch(char ch);
char getch(void);

int main(void)
{
  SW_DDR &= ~(1 << SW0); //Ausgang=1 Eingang=0 daher l?schen
  SW_DDR &= ~(1 << SW1);
  SW_PORT |= (1 << SW0); //Bei Eingang steuer Port die
Pull-up-Widerst?nde!
  SW_PORT |= (1 << SW1); // hier: Pull-up auf EIN!

  asm volatile("nop\n\t");
  LED_DDR |= (1 << LED); // LED auf Ausgang
  LED_PORT &= ~(1 << LED); // LED EIN
  inituart();

  for (;;)
  {
     char text[] = "HelloAVR";
     text[0]='H';
     text[7]='R';
     for(int ci=0; text[ci] != '\0'; ++ci)
     {
        putch(text[ci]);
     }
     putch('\n');
   }
}

void inituart()
{
    UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
    UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
    UCSR1A = 0x00; //
    UCSR1C = 0x06;
    UCSR1B = _BV(TXEN1)|_BV(RXEN1);
}

void putch(char ch)
{
   while (!(UCSR1A & _BV(UDRE1)));
   UDR1 = ch;
}

char getch(void)
{
  while(!(UCSR1A & _BV(RXC1)));
    return (UDR1);
}

Autor: martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Code des Programmes hab ich übrigens hauptsächlihc aus Beispielen 
aus dem Internet zusammenkopiert, auch den Teil mit dem String,daher 
könnte der Fehler auch irgendwo anders liegen.

Gruß
Martin

Autor: martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mit der EZuweisung scheint aber was fault zu sein.
     char text[] = "HelloAVR";
hier:
     text[0]='H';
     text[7]='R';
habe ich das ja eingefügt, und "H" und "R" kommen an. nur der Rest der 
nicht nochmal neu zugewiesen wird wird "zerstückelt":
"aH%ì\0x01\0x0f\0x01\0x03R"

als Hexdump:
0x61 a
0x48 H
0x25 EM
0xec
0x01 SOH
0x0f SI
0x01 SOH
0x03 ETX
0x52 R
0x0a LF
 a,H,R,LF sind OK.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich rate anhand der Namen der IO-Register, dass es für einen Atmega128 
sein soll.

Sourcecode #2 kompiliert nicht mit:

AVR Studio    4.12.498  Service Pack 4
GUI Version    4, 12, 0, 491
AVR Simulator    1, 0, 1, 8
ATMEGA8    243

Operating System
Major      4
Minor      10
PlatformID    1
Build      67766446
 A

Plugins:
AVRPLUGINAVRASMOBJECT  1, 0, 0, 43
STK500DLL      1, 0, 1, 0
AVRPLUGINAVRGCCPLUGIN  1, 0, 0, 6

Fehlermeldungen im Build-Fenster:

Build started 7.1.2007 at 16:49:44
avr-gcc.exe  -mmcu=atmega128 -Wall -gdwarf-2  -O0 -fsigned-char -MD -MP 
-MT martin_text.o -MF dep/martin_text.o.d  -c  ../martin_text.c
../martin_text.c: In function `main':
../martin_text.c:57: error: 'for' loop initial declaration used outside 
C99 mode
make: *** [martin_text.o] Error 1

Ich habe statt dem for ein while benutzt
for (;;)
{
    char text[] = "HelloAVR";
    text[0]='H';
    text[7]='R';
#if 0
    for(int ci=0; text[ci] != '\0'; ++ci)
    {
        putch(text[ci]);
    }
#else
    {
  int ci = 0;
  while(text[ci] != '\0')
  {
    putch(text[ci]);
    ci += 1;
  }
    }
#endif
    putch('\n');
}

Damit funktioniert die Routine im AVR Simulator.

Autor: Stefan (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im Anhang die AVR Simulation mit korrektem Inhalt in UDR1.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der C99 Fehlermeldung bin ich nachgegangen und danach die Source wieder 
abgeändert:
#if 1
    {
        int ci;
        for(ci=0; text[ci] != '\0'; ++ci)
        {
            putch(text[ci]);
        }
    }
#else
    {
        int ci = 0;
        while(text[ci] != '\0')
        {
            putch(text[ci]);
            ci += 1;
        }
    }
#endif

Funktioniert im AVR Simulator auch.

Autor: martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke für die Mühe. Aber kannst du dir vorstellen, wo der Fehler sein 
kann?
Wenn ich jeden Buchstaben einzeln zuweise:

  char text[10];
  text[0]='H';
  text[1]='e';
  text[2]='l';
  text[3]='l';
  text[4]='o';
  text[5]='A';
  text[6]='V';
  text[7]='R';
  text[8]='\0';

geht es auch: HelloAVR

Es liegt also an der Zuweisung: char text[] = "HelloAVR";
:confused:

MFG
Martin

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kann im Moment nicht live auf einem Atmega128 testen. Läuft dein 
Projekt im AVR Simulator und kannst du das Fehlverhalten dort auch 
beobachten?

Ich kann den Fehler provozieren, wenn ich den falschen AVR Typ im AVR 
Studio einstelle (beim AVR Simulator und/oder im Projekt).

Bitte kontrolliere deine Projekteinstellungen zum Prozessortyp beim 
Kompilieren.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab' mir einen ATmega128 in den STK gesteckt und die Baudrate auf 9600
geändert, weil das gerade mein angeklemmtest Terminal macht:
loAVR
     HelloAVR
             HelloAVR
                     HelloAVR
                             HelloAVR
                                     HelloAVR
                                             HelloAVR
                                                     HelloAVR
                                                             HelloAVR
                                                                     HelloAVR
usw. usf.

Da du offenbar Probleme mit den initialisierten Daten hast, vermute ich
die Ursache eher in deinem avr-objcopy-Kommando.

(Ich habe deine zweite Version genommen, mit -std=gnu99 compiliert auf
einem AVR-GCC 4.1.1.)

Autor: martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

meine Optionen:

Compiler:
avr-gcc -c -fmessage-length=0 -Wall -Wstrict-prototypes 
-I/usr/avr/include -mmcu=atmega128 -minit-stack=__stack -O0 
-fshort-enums -fpack-struct -funsigned-char -funsigned-bitfields 
-std=gnu99 -g2

Linker:
-lm -Wl,-Map=$(@:%.elf=%.map) --cref --oformat=elf32-avr

Objectcopy:
avr-objcopy -O ihex HelloAVR.elf HelloAVR.hex

MFG

Autor: Stefan (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im AVRSimulator läuft es auch mit diesen Optionen. Ich habe das Projekt 
gepackt und angefügt, vielleicht ist das "funktionierende" HEX-File 
interessant für dich. Toolchain war WinAVR-20060125 aus AVRStudio heraus 
bedient. Bei mir heisst das Projekt anders. Leider kann man damit nur 
auf ASM-Ebene in AVRStudio debuggen. Ich habe es auf die Schnelle nicht 
geschafft, das externe Makefile so anzupassen, dass AVRStudio die 
C-Source akzeptiert. Aber das bisschen ASM-Code hat man auch schnell so 
im Blick.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Hexfile funktioniert auch auf einem realen ATmega128.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich habe es auf die Schnelle nicht geschafft, das externe Makefile so
> anzupassen, dass AVRStudio die C-Source akzeptiert.

Hab's raus: Es ist ein schädlicher Zeilenumbruch in der Zeile mit den 
CFGLAS drin ;-) Das muss alles in eine Zeile... Jetzt geht in diesem 
Projekt auch Debugging auf C-Source Ebene in AVRStudio.

Merke: Makefiles nicht mit beliebigen Editoren bearbeiten! Wenn der 
Editor auf automatische Zeilenumbrüche eingestellt ist oder Tabs in 
Leerzeichen wandelt oder \n zu \r\n macht, kann es schwer auffindbaren 
Ärger geben...

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
s/CFGLAS/CFLAGS/ ;-)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles sowas sollte ein Editor ja auch nicht machen...

Zeilen im Makefile kann man umbrechen, indem man am Ende ein \
notiert (aber dann direkt danach das Newline!).

Autor: martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke euch! Das Hex File läuft bei mir auch.

Nur weiß ich leider immer noch nicht wie ich es selbst compilieren kann.

Deine AVRStudio-Files kann ich leider nicht gebrauchen, da ich unter 
LINUX arbeite. Aber wenn die Flags so auch bei dir gehen, kann das ja 
der Fehler auch nicht sein.

wisst ihr vielleicht noch eine "Schraube" an der ich drehen kann?

Danke und Grüße
Martin

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Macht deine Toolchain unter Linux auch die *.lss und *.map Dateien? Wie 
sehen die im Vergleich zur funktionierenden Version aus?

Aus dem Listing (*.lss) kann man sehen wie char text[] gefüllt wird und 
aus dem Map-File (*.map), wo die Daten herkommen.

Bei deinem Programm stammt "HelloAVR" ja aus dem FLASH-ROM, wird von 
dort von __do_copy_data ins SRAM kopiert (.data Bereich zwischen 
__data_start und __data_end) und wird dann in main() über Register auf 
den Stack kopiert.

Wie Jörg schon schrieb, ist da irgendwas faul.

Was findest du vielleicht anhand der funktionierenden Variante heraus.

Achtung: Ich habe allerdings noch zwei globale char Variablen vom 
Debuggen her im Programm vergessen. Die Zuweisungen sind zwar 
auskommentiert, aber der Platz wird noch angelegt.

Autor: martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Dateien werden auch generiert. Das werde ich mir mal anschauen!

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.