pcnerd
Take a parachute, and jump!
Best,
Ik ben bezig een menuutje te bouwen, nu heb ik de tekst daarvan als volgt opgeslagen in het geheugen:
static char menu_base[4][16] PROGMEM =
{
{"1:Manual Contr."},
{"2:Time Control."},
{"3:Use Wireless."},
{"4:Setup Contrl."}
};
en zo nog 2 van die dingen
om nu met 1 functie een elke van deze 3 menu's (en later waarschijnlijk nog meer) weer te geven, heb ik deze functie in het leven geroepen:
void menu_display(char menu) {
char * textpointer;
unsigned int i;
switch(menu) {
case 'B': //Base menu:
textpointer = menu_base;
break;
case 'M': //Manual control menu:
textpointer = menu_control;
break;
case 'S': //Setup menu
textpointer = menu_setup;
break;
}
for (i=0; i<4; i++) {
lcd_putc(' ');
lcd_puts_p(textpointer[i]);
lcd_putc('\n');
}
}
Nu het leuke, als ik "textpointer" in het laatste gedeelte vervang door menu_base werkt alles perfect, echter nu ik 1 van die 3 menu_'s wil weergeven op deze manier gaat het mis, er zou een pointer moeten worden gemaakt naar die bewuste menu_x, maar dat gaat dus mis want ik krijg ofwel een toewijzings error, of wel een warning:
warning: assignment from incompitable pointer type
waarna ik een paar maffe tekentjes op m'n lcd krijg, iig niet de text in het menu dus.
Is er iemand die me uit een weg kan wijzen uit deze pointer impasse?
Ik ben niet heel bekend met deze functie maar:
lcd_puts_p(textpointer[i]);
lijkt mij een string te verwachten, terwijl 'textpointer' 1 character zal geven.
[code]
lcd_puts_p(&textpointer);
[/code]
Je hoeft volgens mij alleen een & toe te voegen om het adres naar de string door te geven.
[Bericht gewijzigd door jgovers op (38%)]
klein is fijn
Moderator
Pas je code tags in de startpost even aan pcnerd, als ik het doe kan je 'm daarna zelf niet meer wijzigen.
pcnerd
Take a parachute, and jump!
kif: had het net zelf gezien (ook 13s na je post gewijzigd
).
jgovers:
normaal gesproken doe je lcd_puts_p(PSTR("blaat")); ofzo om iets uit het progmem weer te geven.
Jouwn oplossing doet wel meer dan mijn huidgie code, maar hij pakt in plaats van de 2e string uit de array bij i=1 niet de 2e string maar de 1e string van af het 2e karakter
ik krijg dus:
1:manual ...
:manual..
Manual...
anual...
ook niet de bedoeling
.
Dat zou normaal gewoon moeten werken, lijkt erop dat index adressering niet kijkt naar de declaratie van jouw var.
probeer dan dit eens:
lcd_puts_p(&textpointer[i*16]);
[Bericht gewijzigd door Henry S. op (58%)]
pcnerd
Take a parachute, and jump!
dat werkt dan weer wel goed, alleen krijg ik nog steeds 3 van die irritante warnings:
warning: assignment from incompitable pointer type
Nu zie ik waarom het niet goed gaat! Een pointer van een dubbele array toekennen aan een enkele, dat gaat nooit goed.
Je moet je het volgende doen:
char * textpointer; -> char **textpointer;
En dan kun je wel zoals onderstaand gebruiken.
lcd_puts_p(&textpointer[i]);
[Bericht gewijzigd door Henry S. op (28%)]
pcnerd
Take a parachute, and jump!
helaas, warnings en het zelfde als mijn eerste post na mijn openingspost, maar dan met stapjes van 2 karakters i.p.v. 1 karakter...
Erg vreemd, wat voor compiler gebruik je eigenlijk?
(probeer char *textpointer[]; eens voor de grap?)
[Bericht gewijzigd door Henry S. op (53%)]
pcnerd
Take a parachute, and jump!
avr-gcc, met [] error: size missing, met daarin 16 drie error's voor de assignments:
incompitable types in assignment
Laatste poging, voor ik naar bed ga.
void menu_display(char menu) {
char * textpointer;
unsigned int i;
switch(menu) {
case 'B': //Base menu:
textpointer = (char*)menu_base;
break;
case 'M': //Manual control menu:
textpointer = (char*)menu_control;
break;
case 'S': //Setup menu
textpointer = (char*)menu_setup;
break;
}
for (i=0; i<4; i++) {
lcd_putc(' ');
lcd_puts_p(&textpointer[i*16]);
lcd_putc('\n');
}
}
[Bericht gewijzigd door Henry S. op (18%)]
doorslagspanning
tja...
Ik weet niet precies wat de routine lcd_puts_p precies doet, maar het lijkt erop dat deze de gehele string na de eerste itteratie al geheel weergeeft. Het lijkt erop dat het niet nodig is om de pointer met de index te verhogen. Als je dit wel doet, lijkt het alsof hij bij elke itteratie de oude string overschrijft beginnend vanaf een karakter verder...
Dan krijg je dus:
1:manual ...
:manual..
Manual...
anual...
Waarom doe je die itteratie van 4 eigenlijk?
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
@pcnerd: moet dat niet lcd_puts_P() zijn?
#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))
[Bericht gewijzigd door pros op (94%)]
Te weinig C op AVR gedaan om er een gefundeerd antwoord op te geven. Persoonlijk zou ik het in de hoek van storage class zoeken. Een 'gewone' char * zal (tenzij je het ergens anders afdwingt) wel ergens naar een stuk RAM pointen. Je menu's staan in flash. Dat is een andere memory range.
Vervolgens ga je dan wel gewoon displayen, en ja, wat op dat address in flash staat, staat hoogstwaarschijnlijk (zeg maar: zeker) niet ook daar in RAM.
Ik zou het eens zoeken in de declaratie van die pointer. Kun je die naar PROGMEM laten pointen (en gaat de rest het dan nog snappen?)
laat me raden je krijg die incompatible type error 3 x ?
krijg je trouwens geen lijn nummer waar de error zich bevind ?
wat doe je hier ?
textpointer = menu_base;
textpointer is * dus verwacht een adress
hoe stop je een address mee ?
textpointer = &menu_base;
leest voor mij als txtpointer = address of menu_base
wil je 2e item sturen (time control)
[1]
textpointer = &menu_base[1];
als het goed is
SparkyGSX
Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
@Marco69: als ik me goed herinner, staat in de AVR alles in dezelfde geheugenruimte; er is voor een pointer dus geen verschil tussen flash of RAM.
@TS: je verwacht nogal wat magie van de compiler als je textpointer[ ] gaat gebruiken. De compiler weet niet beter of dat is een pointer naar een character array.
Het handigste (en snelste) is om van je menu een char array van 68 tekens te maken, en na elke regel een nul character op te nemen. Je kunt dan textpointer + 17 * i meegeven aan die print routine.
Met een twee dimensionale array worden er, als ik het goed heb, 4 extra pointers gebruikt waar je niets nuttigs mee doet.
ik heb ff dit geprobeert omdat ik zoiets voor me eigen lcd debugging nodig heb en me main kan opschonen
alhoewel ik een error op PROGMEM iets van expecting 'asm' or _atrributes_
pcnerd
Take a parachute, and jump!
Op 2 juni 2009 00:06:28 schreef jgovers:
Laatste poging, voor ik naar bed ga.void menu_display(char menu) { ... }
Verrek, dat werkt
, geen errors e.d., naja, ik heb wel overal PROGMEM bijstaan maargoed.
@pros: nope 
@sould3mon: Goed geraden of goed gelezen, het klopt iig, maar omdat dit een array is mag de huidige methode worden toegepast, anders krijg ik het adres van de pointer naar de array.
@Sparky: deze 2dimensionale array is onder water niks meer dan een grote char array dus dat heeft weinig zin.
@sould3mon hierboven:
Het is de bedoeling dat jouw geintje wordt uitgevoerd in mijn for-loop, die geeft namelijk 4 strings uit de array op het display weer (later krijgt het menu meerdere opties zodat je er doorheen kunt lopen en de functie een argument en code om ervoor te zorgen dat je de juiste 4 opties van de zoveel op het scherm hebt).
Maar de methode van jgovers werkt tot nu toe het best, huidige code:
void menu_display(char menu) {
const char * textpointer;
unsigned int i;
switch(menu) {
case 'B': //Base menu:
textpointer = (char * PROGMEM)menu_base;
break;
case 'M': //Manual control menu:
textpointer = (char * PROGMEM)menu_control;
break;
case 'S': //Setup menu
textpointer = (char * PROGMEM)menu_setup;
break;
}
for (i=0; i<4; i++) {
lcd_putc(' ');
lcd_puts_p(&textpointer[i*16]);
lcd_putc('\n');
}
}
geeft keurig alle 4 de strings uit de 2 dimensionale array weer onder elkaar op het 4 regelig LCD
.
Wat je nu dus doet, is het spul gewoon casten. Ik vermoed dat je hetzelfde had bereikt wanneer textpointer het juiste type had gehad.
pcnerd
Take a parachute, and jump!
@marco:Ik heb praktisch alle types gebruikt en bij elke kreeg ik een error, maar als jij nog een suggestie hebt hoor ik hem graag
.
@echo:al geprobeerd dus, zelfde resultaat.
Hmz... Nee, sorry... Heb wel redelijk wat ervaring met C in diverse smaken en varianten, zowel Linux, Unix als 8051 based. Ook redelijk wat ervaring met AVR, maar dan assembly. Op de AVR is mijn C echter zo minimaal dat ik het niet zo uit m'n mouw schud... Nou ja, als je die compiler zo naar je hand kunt zetten, dan moet het maar zo... Mocht ik nog een 'brainwave' hebben, dan post ik 'm wel 
En zo?
char menu_base[4][16] PROGMEM =
{
{"1:Manual Contr."},
{"2:Time Control."},
{"3:Use Wireless."},
{"4:Setup Contrl."}
};
void menu_display(char menu) {
char (* PROGMEM textpointer)[16];
unsigned int i;
switch(menu) {
case 'B': //Base menu:
textpointer = menu_base;
break;
case 'M': //Manual control menu:
textpointer = menu_control;
break;
case 'S': //Setup menu
textpointer = menu_setup;
break;
}
for (i=0; i<4; i++) {
lcd_putc(' ');
lcd_puts_p(textpointer[i]);
lcd_putc('\n');
}
}