Forum: Compiler & IDEs Das verstehe ich nicht.


von Chricky (Gast)


Lesenswert?

Hallo zusammen,

ich habe folgenden Code auf einem ATMega162 laufen:
1
#define F_CPU 8000000UL
2
3
#include <uart.c>
4
#include <util\delay.h>
5
#include <string.h>
6
7
const char GrussStr1[] PROGMEM     = "Hallo...\r";
8
const char GrussStr2[] PROGMEM     = "Guten Tag...\r";
9
 
10
const char* const Gruesse[] PROGMEM = 
11
{
12
   GrussStr1,
13
   GrussStr2
14
};
15
16
void SendString_P(int UART, const PGM_P aString)
17
{
18
   char Data[128]     = "\0";
19
20
   strcpy_P(Data,aString);
21
   uart0_puts(Data);
22
}
23
24
int GetGruss(void)
25
{
26
   int Firma    = 1;
27
28
//   for (Firma=1; Firma<=2; Firma++)
29
   {
30
      SendString_P(0,Gruesse[Firma-1]);
31
32
      _delay_ms(2000);
33
   }
34
   return 0;
35
}
36
37
int main(void)
38
{
39
   int GrussNr;
40
41
   uart0_init(UART_BAUD_SELECT(19200,F_CPU));
42
   sei();
43
44
   while (1) 
45
   {
46
      GrussNr=GetGruss();
47
   }
48
   return 1;
49
}
Der µC sendet - wie erwartet - "Hallo..." an die Com.
Ändere ich in GetGruss int Firma    = 1; auf int Firma    = 2; sendet 
der µC - wie erwartet - "Guten Tag..." an die Com.
Nehme ich nun die for-schleife wieder rein erhalte ich nur noch 
ASCII(12)F.

Was läuft hier falsch?

(Die UART ist von Peter Fleury)

Gruß
Chricky

von Karl H. (kbuchegg)


Lesenswert?

Da das Array Grüesse selbst auch im FLash liegt, kannst du hier nicht 
einfach

     SendString_P(0,Gruesse[Firma-1]);

über eine Indexoperation zugreifen.

Du musst dir den bewussten Pointer zum Text selbst auch wieder mit einem 
pgm_read_word holen

      const PGM_P text = pgm_read_word( &Gruesse[Firma-1] );
      SendString_P( 0, text );

> Ändere ich in GetGruss int Firma    = 1; auf
> int Firma    = 2; sendet der µC - wie erwartet - "Guten Tag..."
> an die Com.

Es ist zwar auch in dem Fall falsch, allerdings rettet dich hier der 
Optimizer, der den ganzen Zugriff durch das Ergebnis ersetzt (das er ja 
kennt, weil es konstant ist). D.h. der Zugriff ins Gruesse Array, 
welcher eigentlich ins Flash gehen müsste (es aber nicht tut), findet 
überhaupt nicht statt. Und deswegen funkioniert das (und ist ein gutes 
Beispiel für: nur weil es funktionioert, muss es noch lange nicht 
richtig sein)

von Chricky (Gast)


Lesenswert?

Als Workaround funktioniert Folgendes:

int GetGruss(void)
{
   int Firma    = 1;

   for (Firma=1; Firma<=2; Firma++)
   {
      if (Firma==1) SendString_P(0,Gruesse[0]);
    if (Firma==2) SendString_P(0,Gruesse[1]);

      _delay_ms(2000);
   }
   return 0;
}

Wunder...

von Karl H. (kbuchegg)


Lesenswert?

Chricky schrieb:
> Als Workaround funktioniert Folgendes:

Wie schon gesagt:
'Funktioniert' bedeutet nicht, dass es richtig ist
Auch das ist immer noch falsch. Dein Programm funktioniert zufällig, 
weil dir der Optimizer unter die Arme gegriffen hat.

so wäre es richtig
1
      const PGM_P text = pgm_read_word( &Gruesse[Firma-1] );
2
      SendString_P( 0, text );

oder in einem Rutsch ohne Zwischenvariable
1
      SendString_P( 0, pgm_read_word( &Gruesse[Firma-1] ) );

von Chricky (Gast)


Lesenswert?

Hallo Karl Heinz Buchegger,

ja das macht Sinn! Danke. Manchmal sieht man eben den Wald nicht mehr...


Gruß
Chricky

von Chricky (Gast)


Lesenswert?

Das hat sich jetzt 2mal überschnitten...

Danke.

Gruß
Christian

von Karl H. (kbuchegg)


Lesenswert?

Allerdings würde ich anstelle deiner SendString Funktion die originale 
bevorzugen. In der Fleury Lib ist nämlich schon eine Funktion drinnen, 
die einen String aus dem Flash ausgeben kann
1
      uart0_puts_p( 0, pgm_read_word( &Gruesse[Firma-1] ) );

und die hat nicht die Beschränkung auf 128 Zeichen, so wie deine 
SendString_P

von Chricky (Gast)


Lesenswert?

Hallo Karl Heinz Buchegger,

ja, die habe ich gesehen. Ich muß allerdings noch Steuer- und 
Prüfzeichen anhängen. Ich hatte die Funktionen nur aufs Nötigste 
zusammengestrichen...

Gruß
Christian

von Karl H. (kbuchegg)


Lesenswert?

Chricky schrieb:
> Hallo Karl Heinz Buchegger,
>
> ja, die habe ich gesehen. Ich muß allerdings noch Steuer- und
> Prüfzeichen anhängen. Ich hatte die Funktionen nur aufs Nötigste
> zusammengestrichen...

Dann sieh dir an, wie Peter den String aus dem Flash ausgibt. Ohne 
Array.
Das kannst du auch.

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.