Forum: Compiler & IDEs PROGMEM Problem


von Nino K. (lnino)


Lesenswert?

Hi an alle.

Ich habe eine Funktion mit welcher man einen Text am LCD scrollend 
ausgeben kann. Da ich aber nicht immer den Code eingeben möchte, möchte 
ich eine eigene lib daraus machen. Entweder kommen beim compelieren 
immer neue Fehlermeldungen oder am Display erscheinen nur schwarze 
Striche.

Hier der Code der Funktion innerhalb eines normalen C Projekts. So 
funktioniert er ohne Probleme:
1
#define F_CPU 14745600
2
3
#include <stdio.h>
4
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <avr/pgmspace.h>
8
#include <inttypes.h>
9
10
#include "../libnerdkits/delay.h"
11
#include "../libnerdkits/lcd.h"
12
  
13
  // prototypes
14
  void scroll_line_two(char);
15
16
int main() {
17
18
  lcd_init();
19
  lcd_home();
20
  
21
  scroll_line_two("TEST");
22
23
while(1) {   
24
25
} 
26
  
27
  return 0;
28
}
29
30
void scroll_line_two(char a)
31
{
32
  int8_t scrollPos=0;   
33
34
  uint8_t i;   
35
36
  const char *linetwo = PSTR(a);
37
38
  uint8_t linetwolen = strlen_P(linetwo);
39
  
40
    while(1) {   
41
 
42
    lcd_line_two();     
43
44
      for(i=0; i<20; i++) {     
45
46
      lcd_write_data(pgm_read_byte(linetwo + ((scrollPos+i)%linetwolen)));   
47
      }     
48
49
    scrollPos = (scrollPos + 1) % linetwolen;     
50
  
51
    delay_ms(200); 
52
    }
53
}

Wenn ich nun versuche die Funktion in eine eigene Lib zu geben um sie 
dann mittels include einzubinden, geht der Code plötzlich nicht mehr. 
Habe mich dann im Netz etwas umgesehen und dann herausgefunden, dass ich 
char* statt char schreiben muss, usw. Aber die richtige Kombination 
scheine ich nicht gefunden zu haben.

Hier der Code in der lcd4x20ext.c und lcd4x20ext.h

lcd4x20ext.c
1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3
#include <inttypes.h>
4
#include <stdio.h>
5
6
#include "lcd.h"
7
#include "delay.h"
8
9
void scroll_line_two(char* a)
10
{
11
  int8_t scrollPos=0;   
12
13
  uint8_t i;   
14
 
15
  const char *linetwo = PSTR(a);
16
17
  uint8_t linetwolen = strlen_P(linetwo);
18
  
19
    while(1) {     
20
    lcd_line_two();     
21
22
      for(i=0; i<20; i++) {        
23
      lcd_write_data(pgm_read_byte(linetwo + ((scrollPos+i)%linetwolen)));   
24
      }     
25
 
26
    scrollPos = (scrollPos + 1) % linetwolen;     
27
  
28
    delay_ms(200); 
29
    }
30
}

lcd4x20ext.h
1
#ifndef __LCD4x20EXT_H
2
#define __LCD4x20EXT_H
3
4
void scroll_line_two(char* a);
5
6
#include <stdio.h>
7
int lcd_putchar(char x, FILE *stream);
8
9
#endif

Und hier noch das C Project in welchem ich versuche die lcd4x20ext.h zu 
includen und darauf zuzugreifen.

lcd4x20ext.c
1
#define F_CPU 14745600
2
3
#include <stdio.h>
4
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <avr/pgmspace.h>
8
#include <inttypes.h>
9
10
#include "../libnerdkits/delay.h"
11
#include "../libnerdkits/lcd.h"
12
#include "../libnerdkits/lcd4x20ext.h"
13
  
14
int main() {
15
16
  // fire up the LCD
17
  lcd_init();
18
  lcd_home();
19
  
20
  scroll_line_two("TEST TEST TEST TEST");
21
22
// Main loop. 
23
while(1) {   
24
25
} 
26
  
27
  return 0;
28
}

Kann mir jemand sagen, was ich da noch falsch mache?

Vielen Dank für die Hilfe.

von Karl H. (kbuchegg)


Lesenswert?

El Nino schrieb:

> Hier der Code der Funktion innerhalb eines normalen C Projekts. So
> funktioniert er ohne Probleme:

Glaub ich nicht.
Der ist voller Fehler


> Habe mich dann im Netz etwas umgesehen und dann herausgefunden, dass ich
> char* statt char schreiben muss,

Du solltest dich weniger im Netz umsehen, sondern besser ein C-Buch, 
nämlich dein ganz persönliches C-Buch zu Rate ziehen


>   const char *linetwo = PSTR(a);
>

Du kannst hier nicht PSTR benutzen.
PSTR ist ein Makro, welches einen konstanten Text während des 
Compilierens ins Flash verschiebt und einen Pointer darauf liefert. Du 
hast hier keinen konstanten Text! Die Verschiebung, und damit die 
Anwendung des PSTR muss bereits der Aufrufer der Funktion machen. 
Derjenige, der die Stringkonstante hat, muss sie mittels PSTR ins Flash 
verlagern.

D.h. der Aufrufer der Funktion gibt dir bereits den korrekten Pointer 
ins Flash:

void scroll_line_two(char* linetwo)
{
....


> int main() {
>
>   // fire up the LCD
>   lcd_init();
>   lcd_home();
>
>   scroll_line_two("TEST TEST TEST TEST");

und hier dann

   scroll_line_two( PSTR("TEST TEST TEST TEST") );

von Nino K. (lnino)


Lesenswert?

Hi Karl Heinz,

danke für deine Rückmeldung.

Ich hoffe ich habe dich richtig verstanden, dass der Code dann 
folgendermaßen aussehen soll:

lcd4x20ext.c
1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3
#include <inttypes.h>
4
#include <stdio.h>
5
6
#include "lcd.h"
7
#include "delay.h"
8
9
void scroll_line_two(char* linetwo)
10
{
11
  int8_t scrollPos=0;   
12
13
  uint8_t i;   
14
 
15
  //const char *linetwo = PSTR(a);
16
17
  uint8_t linetwolen = strlen_P(linetwo);
18
  
19
    while(1) {     
20
    lcd_line_two();     
21
22
      for(i=0; i<20; i++) {        
23
      lcd_write_data(pgm_read_byte(linetwo + ((scrollPos+i)%linetwolen)));   
24
      }     
25
 
26
    scrollPos = (scrollPos + 1) % linetwolen;     
27
  
28
    delay_ms(200); 
29
    }
30
}

lcd_test.c
1
#define F_CPU 14745600
2
3
#include <stdio.h>
4
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <avr/pgmspace.h>
8
#include <inttypes.h>
9
10
#include "../libnerdkits/delay.h"
11
#include "../libnerdkits/lcd.h"
12
#include "../libnerdkits/lcd4x20ext.h"
13
  
14
int main() {
15
16
  // fire up the LCD
17
  lcd_init();
18
  lcd_home();
19
  
20
  scroll_line_two( PSTR("TEST TEST TEST TEST") );
21
22
// Main loop. 
23
while(1) {   
24
25
} 
26
  
27
  return 0;
28
}

Ist das so korrekt oder stehe ich noch auf der Leitung?

Danke für deine Hilfe.

von Nino K. (lnino)


Lesenswert?

Habe nun versucht den Code dementsprechend umzuschreiben.

Wenn ich aber versuche mit meinem makefile das umzuwandeln, dann erhalte 
ich folgenden Fehler:
1
ed/scrolling_text_embedded.c:24: undefined reference to `scroll_line_two'
2
make: *** [scrolling_text_embedded.hex] Error 1

In Zeile 24 steht folgendes:
1
scroll_line_two( PSTR("TEST TEST TEST TEST TEST") );

EDIT: Habe nun den Fehler gefunden. Habe in meinem Makefile nicht das 
korrekte .o file angegeben.

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.