Das verstehe ich nicht.

Gast #2929144
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
#2929255
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)
Gast #2929263
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...
#2929270
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] ) );
#2929282
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
Gast #2929321
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

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