Das Menü wird korrekt aufgebaut (Display) und ich kann mit dem Cursor
zwischen den drei Menüpunkten wandern. Doch egal welchen Menüpunkt ich
anwähle (activ = 0,1,2) nach dem Drücken der OK (KEY_OK) Taste wird
IMMER der else Zweig ausgeführt:
1
input&=~KEY_OK;
2
if(menu[active].function)
3
{
4
clearDOGL();
5
menu[active].function();
6
drawMenu(menuSize,menu);
7
drawBar("Einstellungen");
8
charChainDOGL(active+2,0,NOINVERSE,">");
9
}
10
else
11
running=false;
Sicherlich nur ein kleiner Schnitzer irgendwo aber ich finde ihn nicht
=/...
Viele Grüße, Nico
if( menu[active].function )
Was genau soll das darstellen? Greifst du damit auf ein Strukt in einer
Liste zu, und dann auf funktion.
Oben machst du:
menu[active].function();
Poste mal den ganzen Code
Das ist alles zugehörige an Code.
>Was genau soll das darstellen? Greifst du damit auf ein Strukt in einer>Liste zu, und dann auf funktion.
Die Zeile prüft ob es zu dem angewählten Menüpunkt (die Variable active
ist der Index für das Array (welches aus den Structs besteht - siehe
main)) eine Funktion vorhanden ist. Dies ist bei "Energieoptionen" und
"Informationen" der Fall. Nur bei Exit nicht.
1
structsMenuEntrymeControll[]=
2
{
3
{"Energieoptionen",mEnergy},
4
{"Informationen",mInfo},
5
{"Exit"}
6
};
Wähle ich den Menüpunkt 1 (Informationen) an und klicke OK, dann würde
ich erwarten, dass die zugehörige Funktion aufgerufen werden würde, doch
er geht immer in den else-Zweig.
Hier würde er dann verweilen, bis ich wieder OK gerückt hätte.
Nochmal,
ist es absicht, das du oben if( menu[active].function ) und unten
menu[active].function() stehen hast??? Ich glaube der Fehler rührt wohl
daher
Wie gesagt in dem IF rufst du nicht die Funktion auf, da müssen Klammern
hin, wenn das was zurück geben soll
So hast du nur den Pointer, wenn du die Klammer weg lässt, nicht den
Rückgabewert
Soll wohl ( menu[active].function() ) heißen?
Ich seh keinen Fehler, ausser vielleicht einem race auf input, aber der
kann ja nicht in den else-Zweig führen. Kannst du die Änderungen von
active irgendwie mitprotokollieren?
Mike, er will an der Stelle die Funktion nicht aufrufen, er will prüfen
ob die Funktionsadresse NULL ist (=Exit). Nico, du solltest in deiner
struct da mal explizit 0 hinschreiben ...
Mike Mike schrieb:> Nochmal,>> ist es absicht, das du oben if( menu[active].function ) und unten> menu[active].function() stehen hast??? Ich glaube der Fehler rührt wohl> daher
Mit der Zeile:
>> if( menu[active].function )
Beabsichtige ich zu prüfen ob es bei dem angewählten Menüpunkt eine
Funktion gibt, sprich ob der Funktionszeiger auf eine Funktion zeigt
oder eben nicht.
Und die Zeile:
>> menu[active].function();
Soll diese Funktion dann aufrufen..
Nochmal zu:
>> if( menu[active].function )
Ich habe doch oben in der main ein Array angelegt, dass drei Elemente
des structs beinhaltet. Dieses Struct beinhaltet wiederum ein Array aus
chars und einen Funktionspointer. Und wenn der Funktionspointer nicht
definiert wird (das wäre dann beim Eintrag "Exit" der Fall), dann zeigt
dieser Zeiger quasi auf NULL und somit würde der Else-Zweig ausgeführt.
lokale Variablen werden nicht default initialisiert. Auch dann nicht,
wenn sie in einer Struktur stecken.
Ist aber jetzt wachrscheinlich nicht dein Problem.
Frank M. schrieb:> Was soll man mit einem Code anfangen, wo nirgendwo gezeigt wird, wann> und wo die Variable "active" gesetzt bzw. geändert wird?
Wird doch oben gezeigt im Code, musst du gucken.
Frank M. schrieb:> Was soll man mit einem Code anfangen, wo nirgendwo gezeigt wird, wann> und wo die Variable "active" gesetzt bzw. geändert wird?
Sorry, falsch gelesen. Ich ziehe meinen Beitrag zurück :-)
Frank M. schrieb:> Was soll man mit einem Code anfangen, wo nirgendwo gezeigt wird, wann> und wo die Variable "active" gesetzt bzw. geändert wird?
Das passiert in void mControll (uint8_t menuSize, struct sMenuEntry
menu[]);
Initialisiert mit 0
und bei Tastendruck wird die Variable verändert
Sebastian W. schrieb:> Anscheinend zerhaut es dir den stack? Mach deine struct doch mal> testweise global.
Das ist es! Aber ist der Stack so klein? Ich meine so tief gehe ich doch
eigentlich gar nicht, oder?
Der stack ist wohl nicht zu klein, der stack wird wohl zerschossen. Aber
wo? Das könnte überall sein. Hast du beim Testen bisher immer auch Exit
getestet? Wenn dann die NULL in der struct fehlt, wird vielleicht
zufällig eine Funktionsadresse angesprungen, und der Code dort macht
üble Sachen mit dem SP?
Das eine Zufällige Adresse drinsteht sollte klar sein, und das damit
auch Exit aufgerufen werden kann ist auch klar, aber er meint ja, dass
sein Problem wäre, dass er in den else Fall rutscht.
Und das kann ja nur passieren, wenn ein Nullpointer vorhanden ist.
Jetzt wäre die Frage, wann passiert das den.
Immer, direkt beim Einstieg, oder sporadisch.
Meiner Meinung nach wird doch alles ab*acken, wenn er zu einer falschen
Adresse springt, also kann das Programm auch nicht wirklich
weiterlaufen, oder?
Folgendes (gerade debuggt):
* Ich gehe mit OK in die Funktion mControll
* Ich drehe den Drehgeber, sodass das Display Exit als angewählt zeigt
* Die Variable activ hat nun den Wert 0x02
* Ein weitere Klick OK bringt mich zur if/else
* activ ist definitiv(!) 2
* Es geht in den else-Zweig
* Und somit zurück zu main
So, dass ist bei Exit ja auch so gewollt.
Neues Szenario:
* Ich gehe mit OK in die Funktion mControll
* Ich drehe den Drehgeber, sodass das Display Informationen als
angewählt zeigt
* Die Variable activ hat nun den Wert 0x01
* Ein weitere Klick OK bringt mich zur if/else
* activ ist definitiv(!) 1
* Es geht in den else-Zweig
* Und somit zurück zu main
Das ist nur leider nicht gewollt.
> Was passiert denn wenn du einen direkten Ausruf machst in der Main mit> meControll[0].function()> meControll[1].function()> meControll[2].function()
Das wiederum funktioniert!
1
voidmain(void)
2
{
3
uint8_tactContrast=DEFAULT_CONTRAST;
4
5
/*Datenstruktur für den Menübaum erstellen*/
6
structsMenuEntrymeControll[]=
7
{
8
{"Energieoptionen",mEnergy},
9
{"Informationen",mInfo},
10
{"Exit",NULL}
11
};
12
13
initPIC();
14
configPWM();
15
initSPI();
16
initDOGL(&actContrast);
17
18
charChainDOGL(0,0,NOINVERSE,"Warte auf Taste");
19
20
while(1)
21
{
22
if(input&KEY_OK)
23
{
24
input&=~KEY_OK;
25
26
meControll[1].function();
27
28
// mControll(ARRAY_SIZE(meControll),meControll);
29
clearDOGL();
30
charChainDOGL(0,0,NOINVERSE,"Warte auf Taste");
31
}
32
}
33
}
So bringt mich der Tastendruck direkt in die Funktion mInfo.
Und kannst du den Ausdruck menu[active].function auch auswerten, welcher
Wert rauskommt? Ich sehe nicht, aus welchem Grund da NULL rauskommen
sollte...
Und das Struct global funktioniert?
Ok, vielleicht läuft der Stack wirklich über. Wie ist denn die
Speicherbelegung zur Zeit? Du benutzt ja sehr viele Textkonstanten die
alle sowohl flash als auch SRAM fressen ...
Ne andere Frage
Das Strukt wo steht das denn?? In der Main?
Denn der Typ struct sMenuEntry findet man ja nur in der Main?
D.h. wenn du eine Funktion auserhalb hast, kennt die diesen Typen doch
garnicht.
Eventuell ist das dein Problem
Mike Mike schrieb:> Hab das mal gerade am PC Probiert, ich würde so den Fehler "invalid use> of undefined type 'struct sMenuEntry' bekommen
Entschuldigung, ich denke da habe ich versehentlich Informationen
vorenthalten; Die Datei main.c, in der das hier alles stattfindet,
includiert die Datei main.h, welche wiederum dies beinhaltet:
1
typedefvoid(*pMenuFnct)(void);
2
3
structsMenuEntry
4
{
5
chartext[20];
6
pMenuFnctfunction;
7
};
Somit sollte dieser Typ global bekannt sein, oder?
Um die anderen Fragen zu beantworten habe ich mal einen Screenshot
gemacht. Ach und: Ja, wenn ich das Struct nicht innerhalb von main
sondern global definiere, dann geht es.
Ja so ist es global, aber was meinst du mit
>Ja, wenn ich das Struct nicht innerhalb von main>sondern global definiere, dann geht es.
??
Innerhalb der main Funktion oder innerhalb der main.c
Sebastian W. schrieb:> Ok, vielleicht läuft der Stack wirklich über. Wie ist denn die> Speicherbelegung zur Zeit? Du benutzt ja sehr viele Textkonstanten die> alle sowohl flash als auch SRAM fressen ...
Kann man sowas auch anders, sprich speicheroptimierter, lösen?
Aber ich kann mir nicht vorstellen, dass das zum Fehler führt, oder
überhaupt ein Fehler ist. Evtl zeigt er nur struct*, denn es wird ja vom
Funktionspointer der richtige Typ erkannt, aber die Werte sind NULL.
Kannst du mal zum Spass in der void mControll (uint8_t menuSize, struct
sMenuEntry menu[]) den Funktionspointer noch mal zuweisen und kucken obs
dann geht?
innerhalb der main definiere, dann geht der Aufruf
1
meControll[1].function();
solange ich es direkt in main mache. Rufe ich allerdings die mControll
auf und versuch dann dort den Aufruf (mit active als Index), dann geht
es nicht mehr.
Wenn ich das Array oberhalb von main, also global, definiere, dann kann
ich die mControll aufrufen und es klappt auch der Aufruf dort.
in der main.h legt du scheinbar einen neue Variable an. Du musst sie
dort nur mit extern kennzeichnen. du hast also 2 Stukturen mit anderm
Inhalt und gleichem namen.
Okay.
Was du machst, ist den Typen Global definieren, das ist ja okay.
Aber wenn du in der Main dir ein Feld anlegst mit Inhalt und den Pointer
übergibst solltest du von jeder Funktion drauf auch arbeiten können...
Deine drawMenu() ändert aber nichts am menu oder? Schreib zur Sicherheit
noch ein const vor den Pointer.
Woran machst du eigentlich fest, dass du immer in den else Zweig kommst?
Der else Zweig bricht die Schleife ab.
Aber nur weil die Schleife abgbrochen wird, bedeutet das nicht
zwangsläufig, dass das über den else passiert.
Peter II schrieb:> in der main.h legt du scheinbar einen neue Variable an. Du musst sie> dort nur mit extern kennzeichnen. du hast also 2 Stukturen mit anderm> Inhalt und gleichem namen.
Du meinst aus dem:
1
/*Menü Struktur*/
2
typedefvoid(*pMenuFnct)(void);
3
4
structsMenuEntry
5
{
6
chartext[20];
7
pMenuFnctfunction;
8
};
Soll ich das machen:?
1
/*Menü Struktur*/
2
typedefvoid(*pMenuFnct)(void);
3
4
externstructsMenuEntry
5
{
6
chartext[20];
7
pMenuFnctfunction;
8
};
Das verstehe ich nicht.. Damit ist doch noch keine Variable bzw. Array
erzeugt?
> Aber wenn du in der Main dir ein Feld anlegst mit Inhalt und den Pointer> übergibst solltest du von jeder Funktion drauf auch arbeiten können...
Das scheint auch der Fall zu sein, sonst könnte meine drawMenu Funktion
ja auch nicht die Menüpunkte aufs Display schreiben oder?
Karl Heinz Buchegger schrieb:> Woran machst du eigentlich fest, dass du immer in den else Zweig kommst?>> Der else Zweig bricht die Schleife ab.> Aber nur weil die Schleife abgbrochen wird, bedeutet das nicht> zwangsläufig, dass das über den else passiert.
Sorry.
Zu spät gesehen
> * activ ist definitiv(!) 1> * Es geht in den else-Zweig> * Und somit zurück zu main>> Das ist nur leider nicht gewollt.
Muss erst mal nachlesen, was in der Zwischenzeit alles passiert ist :-)
Prüfe in der if (...) explizit auf != NULL und setzt beim else die
Klammer:
if( menu[active].function != NULL )
{
clearDOGL();
menu[active].function();
drawMenu(menuSize, menu);
drawBar("Einstellungen");
charChainDOGL(active+2,0,NOINVERSE,">");
}
else
{
running = false;
}
Ich habe schon die lustigsten Dinge erlebt wenn in der if Anweisung
keine explizite steht.
Die Klammer sollte nicht das Problem sein, der Compiler darf eigentlich
keine Probleme damit habe: ich habe aber auch schon anderes erlebt
(Fehler im Compiler!).
Eigentlich ja.
Extern heißt doch in dem Fall nur, dass es sich nur um eine Deklaration
handelt?
Aber unten legt er sich doch nur vom selben Typen 3 Stück an.
Wie Karl Heinz schon gesagt hat, mach mal in den Else Zweig eine weiter
Debugvariable rein, und schau ob die erreicht wird.
Karl Heinz Buchegger schrieb
> Sorry.> Zu spät gesehen>> Muss erst mal nachlesen, was in der Zwischenzeit alles passiert ist :-)
Kein Problem, komme selbst kaum noch hinterher..
@Alex und Mike: Okay.. Ich versuche es, uno Momento
Und wenn alles nichts hilft:
Zippe den kompletten Code zusammen und poste das mal.
Mein Bauch sagt, dass dein Problem wo anders liegt und nicht im
gezeigten Code. Hier siehst du nur die Symptome. Aber die Ursache ist
was anderes. Denn eigentlich ist das Gezeigte IMHO alles korrekt.
Dann funktioniert das auch.
Bei deinem Letzten Screenshot war auch schön zu sehen, dass input den
Wert 1 hatte, aber der dazugehöriger Pointer hatte den Wer NULL.
Prüfe mal vor Aufruf der Funktion, welchen Wer der Pointer in der Main
hat, und welchen direkt nach dem Einstig in die Funktion.
Alex schrieb:> Prüfe in der if (...) explizit auf != NULL und setzt beim else die> Klammer:
Hat leider auch nicht geholfen. Das gesamte Projekt nun anbei.
Schon mal viele Dank an alle!
Hallo Nico.
Wenn Du deine Struct global definierst, ist die Adresse dieser Struct
jedem (also global) bekannt.
Wenn Du diese allerdings in main() definierst, dann ist sie nur dort
lokal bekannt, solange Du nicht die Adresse der Struct an mControll(...)
übergibst.
Versuchs mal so:
@WDT:
Ich habe mal gelernt der Name eines Arrays ist die Adresse auf sein
erstes Element von daher...?! Aber ich versuche es dennoch.
Nachtrag: ...Genau
WDT schrieb:> Hallo Nico.>> Wenn Du deine Struct global definierst, ist die Adresse dieser Struct> jedem (also global) bekannt.
Na ja.
Das will man hier aber nicht.
Der Dreh besteht ja darin, dass man im Endeffekt 15 verschiedene Arrays
im Programm hat und der Funktion per Argument mitgibt, welches sie
bearbeiten soll.
D.h. globale ist hier keine Option.
> Versuchs mal so:>>
1
mControll(ARRAY_SIZE(meControll),&meControll);
Ohne & ist schon richtig.
Der Name eines Arrays steht in Argumentlisten automatisch für einen
Pointer auf das erste Element.
Oh my. != NULL, wow.
Wir können glaube ich davon ausgehen das die Funktionspointer mit null
überschrieben werden. Das scheint der Debugger ja zu bestätigen. Aber
warum?
Nico, in welche Richtung wächst der Stack auf deinem Prozessor?
Ich frage, weil im Debugger 'menu' auf 0x66 zu liegen kommt, und wenn
wie mir scheint der Stack gegen 0 wächst dann kommt da ja bald der
IO-Bereich ...
LG, Sebastian
Mike Mike schrieb:> Du hast zwei verschiedene mControll funktionen, einmal in der main.c,> einmal in der menu.c
Die menu.c ist derzeit kein Bestandteil des Projektes. Ich hatte
ursprünglich die ganzen Menüfunktionen in der menu.c, habe es dann aber,
aufgrund der Probleme und des für mich noch neuen Compilers, erstmal in
main.c gelassen.
(Habe die menu.c und das includiren der menu.h (welche ohnehin leer war)
mal gelöscht - und auch das gab keine Änderung)
Sebastian, zu deiner Frage mit dem Stack: Da bin ich gerade etwas
überfragt. Ich versuche es mal nachzulesen (Datenblatt ist übrigens im
Ordner /docs).
5.1.2.2 Return Stack Pointer (STKPTR)
The STKPTR register (Register 5-1) contains the Stack
Pointer value, the STKFUL (stack full) Status bit and
the STKUNF (Stack Underflow) Status bits. The value
of the Stack Pointer can be 0 through 31. The Stack
Pointer increments before values are pushed onto the
stack and decrements after values are popped off the
stack. On Reset, the Stack Pointer value will be zero.
The user may read and write the Stack Pointer value.
This feature can be used by a Real-Time Operating
System (RTOS) for return stack maintenance.
After the PC is pushed onto the stack 31 times (without
popping any values off the stack), the STKFUL bit is
set. The STKFUL bit is cleared by software or by a
POR.
Sebastian W. schrieb:> Oh my. != NULL, wow.>> Wir können glaube ich davon ausgehen das die Funktionspointer mit null> überschrieben werden.
So siehts wohl aus.
Nico. Kann es sein, dass dein Text Feld früher mal eine andere Länge
hatte?
Lösche mal alle Object Dateien und compiliere ALLES neu. Achte drauf,
dass auch wirklich alles kompiliert wird!
In den Header Files hat er sich zwar die Dinge unlogisch und nicht
geschickt verteilt, aber so richtig einen Fehler seh ich da auch nicht
drinnen.
Nico M. schrieb:> Mike Mike schrieb:>> Du hast zwei verschiedene mControll funktionen, einmal in der main.c,>> einmal in der menu.c>> Die menu.c ist derzeit kein Bestandteil des Projektes. Ich hatte> ursprünglich die ganzen Menüfunktionen in der menu.c, habe es dann aber,> aufgrund der Probleme und des für mich noch neuen Compilers, erstmal in> main.c gelassen.> (Habe die menu.c und das includiren der menu.h (welche ohnehin leer war)> mal gelöscht - und auch das gab keine Änderung)
Das war keine gute Idee.
Teil dir die Dinge ruhig auf. Das darf kein Problem sein.
in menu.h kommt alles menüspezifische:
Zunächst mal ist das die Strukturdefinition.
Und dann sind das die Prototypen der Funktionen, die du zum Abarbeiten
von Menüs brauchst. Also die Control Funktion und die Draw Funktion.
Alles andere fliegt raus!
Also auch deine Info und die andere Funktion.
Die hat da drinn nichts verloren. Denn das ist keine allgemeine Menü
Funktion, sondern gehört zu einem spezifischen Menü.
Aus main.h mistest du aus dem gleichen Grund aus.
Alles was dem Themenkreis nach zur 'allgemeinen Menübehandlung' gehört,
fliegt da raus.
Und natürlich auch mit den C-Files. Die Funktionen sauber nach
Themenkreisen aufteilen und in die jeweiligen Files stecken.
Damit hast du dann erst mal eine saubere Trennung zwischen dem 'Menü an
sich' und dem Code, der diese FUnktionalität benutzt.
(Hintergrund: ich kann nämlich wirklich nichts großartiges finden, was
dieses Verhalten erklären könnte. Mglw. ist da in der Toolchain
irgendwas schief gelaufen. Hatte ich schon mal (mit einem anderen
Compiler). Da sucht man sich einen Wolf)
Karl Heinz Buchegger schrieb
> Nico. Kann es sein, dass dein Text Feld früher mal eine andere Länge> hatte?
Meinst du in der Deklaration die Größe von 20 oder bei der Definition?
> Lösche mal alle Object Dateien und compiliere ALLES neu. Achte drauf,> dass auch wirklich alles kompiliert wird!
1) Was heißt alle, ich konnte nur eines finden.
2) Wie kann/soll ich sicherstellen, dass alles kompiliert wurde?
> In den Header Files hat er sich zwar die Dinge unlogisch und nicht> geschickt verteilt, aber so richtig einen Fehler seh ich da auch nicht> drinnen.
Ich würde mich freuen, wenn du mir etwas darüber sagen könntest.
Nico M. schrieb:> Karl Heinz Buchegger schrieb>> Nico. Kann es sein, dass dein Text Feld früher mal eine andere Länge>> hatte?> Meinst du in der Deklaration die Größe von 20 oder bei der Definition?
Die 20 stehen nur bei der Deklaration.
ALso hier
struct sMenuEntry
{
char text[20];
pMenuFnct function;
};
waren die 20 früher mal anders?
>>> Lösche mal alle Object Dateien und compiliere ALLES neu. Achte drauf,>> dass auch wirklich alles kompiliert wird!> 1) Was heißt alle, ich konnte nur eines finden.
Auf deinem Pfad zum Projekt muss es irgendwo ein
main.o, menu.o, dogl.o, isr.o geben.
lösche alle runter
> 2) Wie kann/soll ich sicherstellen, dass alles kompiliert wurde?
Gibt es in deiner IDE kein Logging Fenster, in der Meldungen
durchlaufen, was beim Build alles passiert?
> Ich würde mich freuen, wenn du mir etwas darüber sagen könntest.
Siehe die unmittelbar vorhergehende Post
Einfach alles aus dem build Verzeichnis löschen, nur den Sourcecode
übrig lassen, dann sollte alles neu compiliert werden.
Mit den Header Files meint er folgendes:
Nur die Main Funktion in der main.c und in der main.h das nötigste.
Eigentlich sollte alles in die menu.c und menu.h ausgelagert werden was
eben mit deiner Menüführung zu tun hat. Display Steuerung in eine
display.h und display.c, etc.
So hast du alles sauber aufgeräumt.
Und dann bindest du alles über das main-File ein.
Karl Heinz Buchegger schrieb:>> Ich würde mich freuen, wenn du mir etwas darüber sagen könntest.> Siehe die unmittelbar vorhergehende Post
Das hatte ich zu spät gesehen, hattest deinen Beitrag wohl noch einmal
bearbeitet. Zu meiner Verteidigung: Genau so hatte ich es auch alles bis
dieses Problem auftrat..
Ich werde das Projekt jetzt nochmal komplett neu machen. Ich hole mir
die C und H Dateien raus, lösche das Projekt erstelle ein neues und
binde die Dateien wieder ein. Ich melde mich..
So sollte deine menu.h aussehen.
Da ist alles drinnen was zu einem 'Menü' gehört. Ob die drawMenu
Funktion bzw. die drawBar Funktion da drinnen aufscheinen sollten, kann
ich so nicht sagen, weil ich nicht weiß, ob diese Funktionen nicht auch
Anwendungen ausserhalb eines Menues haben.
Aber: da ist jetzt nichts mehr drinnen, was NICHT mit allgemeinen Menues
zu tun hat. UNd im speziellen ist nichts mehr drinnen, was zu einem
SPEZIELLEN Menu gehört. Nur lauter allgemeine Dinge, die man braucht,
wenn man ein Menü machen und in Betrieb nehmen will. Die allerdings
werden tatsächlich benötigt und um die führt kein Weg herum.
Kleiner Tipp für die Zukunft, Leg dir einen Projektordner an und in
diesem Umterordner, dor speichere deine Zwischenstände immer ab. Und
nummeriere einfach die Ordner durch. So kannst du immer auf ältere
Stände zurückgreifen.
Hat mir schon sehr oft geholfen.
* Diese Funktion schreibt die Statusbar mit variablen Text
88
*
89
* pName: Der Text, welcher in der Statusbar stehen soll
90
*/
91
voiddrawBar(constuint8_t*pName)
92
{
93
uint8_tk=0;
94
95
charChainDOGL(0,0,INVERSE,pName);
96
97
while(*pName)
98
{
99
k+=font[(*pName)-32][0];
100
pName++;
101
}
102
103
while(k<128)
104
{
105
sendSPI(0xFF);
106
k++;
107
}
108
/*Dies sollte noch dynamisch gestaltet werden!*/
109
drawSignDOGL(0,122,INVERSE,BAT_FULL);
110
}
Und das ist die zugehörige menu.c
Die Funktionen mEnergy und mInfo haben da drinn nichts verloren. Die
gehören zu einem speziellen Menü, aber nicht zur allgemeinen
Menüverwaltung.
Im Prinzip bin ich auch mit dem
#include "main.h"
unglücklich.
Denn der sollte nicht da sein.
Den main.h brauchst du nur deswegen, weil du Zugriff auf die globale
Variable input brauchst. Die allerdings sollte gar nicht in main.h sein,
sondern in einem isr.h (welches du nicht hast), weil dort die Encoder
Auswertung drinnen ist, und die Variable da logisch dazugehört.
Funktionen und globale Variable nach Themenkreisen sortieren!
Das ist das Um- und Auf um komplexere Programme, die aus mehreren Teilen
und daher auch mehreren Files bestehen, in den Griff zu kriegen. Und
ausserdem ist es die Grundvoraussetzung für Wiederverwendbarkeit :-)
Vielen Dank, nochmal.
@KHB: Genau so hatte ich es und habe ich es nun wieder.
@Mike: Ich denke auch, dass ist keine schlechte Idee (hatte bisher immer
nur eine ältere Version in der Cloud).
Noch eine allgemeine Frage:
Die Datei main.c - In wie weit kann ich bzw. sollte ihr hier Funktionen
rein pfeffern. Denn zum Beispiel die Funktion für meinen Drehgeber,
dafür lohnt es sich doch nicht eine extra C Datei zu erstellen.. Also in
wie weit schreibt man IN die main.c?
> Ich werde das Projekt jetzt nochmal komplett neu machen.
Bin gespannt.
Denn wie gesagt. So einen richtigen Showstopper-Fehler kann ich nicht
entdecken. Das gezeigte Verhalten dürfte eigentlich nicht auftreten.
IMHO.
Nico M. schrieb:> Die Datei main.c - In wie weit kann ich bzw. sollte ihr hier Funktionen> rein pfeffern. Denn zum Beispiel die Funktion für meinen Drehgeber,> dafür lohnt es sich doch nicht eine extra C Datei zu erstellen.. Also in> wie weit schreibt man IN die main.c?
Stell dir die Frage:
WEnn ich ein neues Programm schreiben würde, könnte ich dann diese
Funktion dort gebrauchen - ja oder nein?
Sprich: handelt es sich bei der FUnktion um etwas das du nur ganz
speziell in diesem einen Projekt benötigst, oder ist das ganze mehr von
der Form: tja, eigentlich ist das ein Baustein, den man überall
einsetzen wird. Wenn ich ein neues Projekt mache und dort einen
Drehgeber einsetzen will, dann ist das doch im Grunde genau der gleiche
Code. In dieser Funktion ist nichts drinnen, was sie jetzt irgendwie
speziell an dieses Projekt binden würde.
Funktionsgruppen abzusplitten und in eigene C/H Files auszulagern lohnt
sich praktisch immer. Aber wichtig: Man sollte für den abgesplitteten
Teil schon so was wie eine Überschrift formulieren können, in der das
Wort 'MOdul' vorkommt. Du hast ein Modul für ein LCD. Du hast ein MOdul
für einen Drehencoder. Du hast ein Modul für Menüs. Du hast ein Modul
für einen PID Regler. Du hast ein Modul für lineare Transformationen. Du
hast ein Modul für Soundausgabe. Du hast ein Modul für allgemeine
Hilfsfunktionen. Du hast ein Modul für ...
Einfach nur jede Funktion in ein eigenes C File auszulagern ist dann
doch übers Ziel hinausgeschossen.
Aber dein Hauptmenü: das wäre zb etwas. was man aus main.c rausnehmen
könnte und selbst wieder in ein eigenes File stecken könnte. Denn da
gehören ja zb die Aufbaudefinition, Funktionen die vom Menü aufgerufen
werden dazu und das ganze hat auch eine gewisse kritische Masse an
Komplexität überschritten, die es lohnenswert erscheinen lässt, dafür
eine in sich abgeschlossene Einheit, ein Modul, zu schaffen.
Danke, danke, danke!
Ich bin derweil erstmal dabei eine vernünftige Struktur herzustellen was
C/H Dateien betrifft, kann daher noch einen Augenblick dauern bis ich
das Projekt neu erstelle.
Nico M. schrieb:> Danke, danke, danke!>> Ich bin derweil erstmal dabei eine vernünftige Struktur herzustellen was> C/H Dateien betrifft, kann daher noch einen Augenblick dauern bis ich> das Projekt neu erstelle.
Ist schon ok.
Lass dir Zeit.
Die jetzt investierte Zeit kriegst du später 10-fach wieder.
das kostet dann auch nicht 2*20byte auf dem Stack nur für die Menütexte
die ja auch im Flash stehen könnten. Kann sein dass ich was übersehe,
ich habe den Thread aus Zeitgründen nicht komplett gelesen.
Sebastian W. schrieb:> ... und dann ist der Fehler weg und wir bekommen nie heraus was nun> wirklich die Ursache war ... ;)
Wenn nicht noch wer eine geniale Idee hat, fürchte ich werden wir das
sowieso nicht rauskriegen. Ist zwar unbefriedigend aber im Moment siehts
danach aus.
Hoffen wir mal die Umkehrung: Das sich im neuen Projekt nicht wieder
dasselbe Symptom zeigt.
Alter Falter, da hat mich der Compiler aber gut mit errors/warnings
beworfen ^^ Bevor ich das Projekt jetzt neu aufsetzte wäre es super wenn
ihr mal einen klitze kleinen Blick über die Strukturen werfen könnt (nur
grob).
Mike Mike schrieb:> Was ich nur grade sehe, das> typedef unsigned char uint8_t;>> machst du nur einmal, nicht mehrfach!
Aber dann müsste ich ja überall, wo ich das verwende, das Headerfile
einbinden, in dem im es einmal geschrieben hab?
Ja aber ich sehe keine Warnings, oder Errors zu deinem Sourcecode.
Wenn du in der Main verschiedene Headerdateien einbindest, und da kommen
immer die gleichen typedefs vor, sollte der Compiler eigentlich meckern.
Ich würde isr.[ch] in input.[ch] umbenennen und keyPressed und encoder
da mit rüberschieben: Braucht sonst keiner. lastKeyDown und encState
brauchen dann auch nicht extern zu sein. input würde auch in isr.c und
nicht in main definiert. Dann noch eine initInput-Prozedur.
Das wird dann jetzt aber langsam auch ein wenig Geschmackssache ...
uint8_tinput=NO_KEY;// Maskiertes Byte für Eingabezustände
2
uint8_tlastKeyDown=NO_KEY;// Letzter Zustand
3
uint8_tencState=0x00;// Zustand des Drehgebers (Default V00)
Diese globale Variablen gehören nicht in main.c. Die letzten beiden
werden dort nicht mal verwendet ... Eine main.h braucht man sowieso
nicht. Denn das würde bedeuten, dass ein anderes Modul vom Hauptprogramm
abhängig ist. Das wäre extrem schlechtes Softwaredesign.
Wenn Du globale Variablen brauchst, dann definier sie in dem Modul, zu
dem sie gehören. In der Headerdatei zu diesem Modul werden sie mit
extern deklariert. Wenn ein anderes Modul auf diese Variablen zugreifen
muss, bindet es den entsprechenden Header ein. Es deklariert nicht
einfach selber Variablen, die zu anderen Modulen gehören!
Am besten lässt man globale Variablen aber komplett sein, wenn man keine
sehr guten Gründe hat. Man braucht sie nämlich nicht. Man kann alles mit
Modulvariablen (static) abdecken. Sämtliche Interaktion zwischen Modulen
finden dann nur über Funktionsaufrufe statt. Das erleichtert den
Überblick über das Programm enorm.
Lies Dir am besten mal diesen Artikel durch. Da wird genau erklärt, wie
man ein Programm richtig in c- und h-Dateien aufteilt:
http://www.mikrocontroller.net/articles/FAQ#Header_File.2C_wie_geht_das.3F
Danke Fabian, das klingt gut!
Um mal zu dem eigentlichen Problem zurück zu kommen:
Ich bin nicht sicher ob es bei der Fehlersuche hilft aber wenn ich im
Array nur ein Element habe:
Wenn ich doch nur genug Kenntnisse über den Stack hätte :P
Aber das kann doch auch nicht sein, das der so schnell voll wäre...
Wie gesagt, prüf genau vor dem Funktionseintritt und direkt danach,
welche Werte die Funktionspointer haben und poste das Ergebnis
Ich weiß über den Stack nur, das dort Rücksprungadressen gespeichert
werden und bisschen kleinkram. Aber die paar Funktionsaufrufe dürfen
kein Problem sein.
Was ich vermute ist dein Charset:
const unsigned char font[95][6] =
{
{1,0x00}, // Space
{1,0x5E}, // !
{3,0x06,0x00,0x06}, // "
{5,0x28,0x7C,0x28,0x7C,0x28}, // #
{5,0x24,0x2A,0x7F,0x2A,0x10}, // $
{3,0x62,0x18,0x46}, // %
{5,0x30,0x4C,0x5A,0x24,0x50}, // &
{1,0x06}, // '
{2,0x3C,0x42}, // (
{2,0x42,0x3C}, // )
{5,0x28,0x10,0x7C,0x10,0x28}, // *
{3,0x10,0x38,0x10}, // +
{1,0xC0}, // ,
{3,0x10,0x10,0x10}, // -
{1,0x40}, // .
{3,0x60,0x18,0x06}, // /
{4,0x3C,0x42,0x42,0x3C}, // 0
{3,0x44,0x7E,0x40}, // 1
{4,0x44,0x62,0x52,0x4C}, // 2
{3,0x4A,0x4A,0x34}, // 3
{4,0x1E,0x10,0x7C,0x10}, // 4
{3,0x4E,0x4A,0x32}, // 5
{4,0x3C,0x4A,0x4A,0x30}, // 6
{3,0x62,0x12,0x0E}, // 7
{4,0x34,0x4A,0x4A,0x34}, // 8
{4,0x0C,0x52,0x52,0x3C}, // 9
{1,0x48}, // :
{2,0x80,0x68}, // ;
{3,0x10,0x28,0x44}, // <
{3,0x28,0x28,0x28}, // =
{3,0x44,0x28,0x10}, // >
{3,0x02,0x52,0x0C}, // ?
{5,0x3C,0x42,0x52,0x2A,0x3C}, // @
{4,0x7C,0x12,0x12,0x7C}, // A
{4,0x7E,0x4A,0x4A,0x34}, // B
{4,0x3C,0x42,0x42,0x24}, // C
{4,0x7E,0x42,0x42,0x3C}, // D
{3,0x7E,0x4A,0x4A}, // E
{3,0x7E,0x0A,0x0A}, // F
{4,0x3C,0x42,0x52,0x34}, // G
{4,0x7E,0x08,0x08,0x7E}, // H
{3,0x42,0x7E,0x42}, // I
{3,0x42,0x42,0x3E}, // J
{4,0x7E,0x08,0x14,0x62}, // K
{3,0x7E,0x40,0x40}, // L
{5,0x7E,0x04,0x08,0x04,0x7E}, // M
{5,0x7E,0x04,0x18,0x20,0x7E}, // N
{4,0x3C,0x42,0x42,0x3C}, // O
{4,0x7E,0x12,0x12,0x0C}, // P
{4,0x3C,0x42,0x42,0xBC}, // Q
{4,0x7E,0x12,0x12,0x6C}, // R
{4,0x44,0x4A,0x4A,0x30}, // S
{3,0x02,0x7E,0x02}, // T
{4,0x3E,0x40,0x40,0x3E}, // U
{5,0x06,0x18,0x60,0x18,0x06}, // V
{5,0x3E,0x40,0x3E,0x40,0x3E}, // W
{5,0x42,0x24,0x18,0x24,0x42}, // X
{4,0x9E,0xA0,0xA0,0x7E}, // Y
{4,0x62,0x52,0x4A,0x46}, // Z
{2,0x7E,0x42}, // [
{3,0x06,0x18,0x60}, // Backslash
{2,0x42,0x7E}, // ]
{3,0x20,0x10,0x20}, // ^
{4,0x80,0x80,0x80,0x80}, // _
{2,0x04,0x08}, // `
{4,0x20,0x54,0x54,0x78}, // a
{4,0x7E,0x44,0x44,0x38}, // b
{4,0x38,0x44,0x44,0x28}, // c
{4,0x38,0x44,0x44,0x7E}, // d
{4,0x38,0x54,0x54,0x58}, // e
{2,0x7C,0x0A}, // f
{4,0x98,0xA4,0xA4,0x7C}, // g
{4,0x7E,0x04,0x04,0x78}, // h
{1,0x7A}, // i
{2,0x40,0x3A}, // j
{4,0x7E,0x10,0x28,0x44}, // k
{1,0x7E}, // l
{5,0x7C,0x04,0x78,0x04,0x78}, // m
{4,0x7C,0x04,0x04,0x78}, // n
{4,0x38,0x44,0x44,0x38}, // o
{4,0xFC,0x24,0x24,0x18}, // p
{4,0x18,0x24,0x24,0xFC}, // q
{2,0x7C,0x04}, // r
{4,0x48,0x54,0x54,0x20}, // s
{3,0x04,0x3E,0x44}, // t
{4,0x3C,0x40,0x40,0x3C}, // u
{5,0x0C,0x30,0x40,0x30,0x0C}, // v
{5,0x3C,0x40,0x3C,0x40,0x3C}, // w
{5,0x44,0x28,0x10,0x28,0x44}, // x
{4,0x9C,0xA0,0xA0,0x7C}, // y
{3,0x64,0x54,0x4C}, // z
{3,0x08,0x36,0x41}, // {
{1,0xFF}, // |
{3,0x41,0x36,0x08}, // }
{4,0x20,0x10,0x20,0x10}, // ~
};
Kannst du das nicht mit progmem machen?
Ich kann mich nur daran erinnern das ich das Problem mal hatte, aber auf
nem Winzlingscontroller
Die Menüstruktur ist imo ungeschickt gewählt. Du musst doch vermutlich
die Texte zur Laufzeit nicht mehr verändern. Also reicht ein char* auf
ein Stringliteral statt einem char-Array mit fester Länge.
Außerdem legst Du das komplette Array in der main-Funktion auf dem Stack
an. Mach daraus lieber eine Modulvariable:
Fabian O. schrieb:
> Du musst doch vermutlich die Texte zur Laufzeit nicht mehr verändern.> Also reicht ein char* auf ein Stringliteral statt einem char-Array mit> fester Länge.
Dadurch, dass ich kein Array fester Länge sondern einen Pointer auf eine
feste Zeichenkette verwende spare ich Speicherplatz richtig?
> Außerdem legst Du das komplette Array in der main-Funktion auf dem Stack> an.
Wieso liegt das Array auf dem Stack? Ich denke auf dem Stack werden nur
Rücksprungadressen gespeichert?
Mike Mike schrieb:
> Kannst du das nicht mit progmem machen?
Mit dem Begriff kann ich leider nichts anfangen.
Und wenn wir schon dabei sind, kannst du gleichzeitig noch deine
Zeichenketten etwas kürzer machen. Wenn du ja sagst, es geht mit einem
Element.
Dann schau mal ob es mir allen Dreien geht, aber schreibs so:
static struct sMenuEntry meControll[] =
{
{ "E", mEnergy },
{ "I", mInfo },
{ "X" , 0 },
};
Ich weiß leider auch nicht wie das jetzt mit dem Stack ist, vllt. können
die Profis was dazu sagen.
Wenn du dein großes Array anlegst, dann wird das in den RAM gelegt.
Mit Progmem bekommst du das ganze im Flash abgespeichert:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#progmem_und_pgm_read_xxx
Sind immerhin über 500Byte die du da verbläst
Noch ein allgemeiner Tipp:
Es hat sich bewährt, dass man sämtliche Funktionen und Strukturen, die
ein Modul nach außen anbietet, mit dem Modulnamen (= Dateiname) als
Präfix versieht. Dann weiß man nämlich auf einen Blick, in welche Datei
man schauen muss, wenn man eine bestimmte Funktion sucht.
In Deinem Fall also beispielsweise statt
Dann weiß man wie gesagt sofort, wo man nachsehen muss. Und man macht
sich dabei auch ganz von alleine Gedanken, welche Funktionen eigentlich
zusammengehören.
Ich habe beispielsweise erstmal sämtliche Dateien nach mEnergy() und
mInfo() durchsuchen müssen, bis ich sie in setup.h gefunden habe. Das
darf nicht sein. Stell Dir mal vor, Dein Projekt wird größer ... da
findest Du dich ja ohne Suchfunktion nie mehr zurecht.
Vergiss das mit dem PROGMEM, das betrifft nur AVRs. Ich weiß nicht, wie
es beim PIC bzw. Deinem Compiler funktioniert, ein Array nicht in den
RAM, sondern den Programmspeicher (Flash) zu legen. Eventuell reicht es
schon, das Array const zu machen:
1
staticconststructsMenuEntrymeControll[]=
2
{
3
{"Energieoptionen",mEnergy},
4
{"Informationen",mInfo},
5
{"Exit",0},
6
};
Nico M. schrieb:> Wenn ich es jetzt so schreibe wie Fabian vorgeschlagen hat, dann geht> es. Aber dann ist das Array ja auch wieder global =| Soweit waren wir ja> schon..
Das Array ist nicht global. Es ist nur innerhalb von main.c sichtbar
(deshalb das static). Was soll daran schlimm sein?
Das ist sehr wohl so global, wenns auserhalb der main ist.
Aber das mit dem Progmem war nicht auf seine drei Menüoptionen bezogen,
sondern auf sein fast 600Byte Charset Array!
> Das Array ist nicht global. Es ist nur innerhalb von main.c sichtbar> (deshalb das static). Was soll daran schlimm sein?
Es ist nicht mehr auf dem (Software-)Stack. Wir wüssten aber alle gerne,
wieso meControll zerschossen wird, wenn es auf dem Stack liegt ...
Sebastian W. schrieb:> Es ist nicht mehr auf dem (Software-)Stack. Wir wüssten aber alle gerne,> wieso meControll zerschossen wird, wenn es auf dem Stack liegt ...
Achso. Das kleine Wörtchen "Software" hatte mir gefehlt. Hier werden
Variablen etc. gesichert, damit sie, wenn man über den LIFO Stack wieder
in Funktionen zurück kehrt, diese wieder bzw. noch vorhanden sind. Habe
ich das richtig verstanden?
Nico M. schrieb:> Dadurch, dass ich kein Array fester Länge sondern einen Pointer auf eine> feste Zeichenkette verwende spare ich Speicherplatz richtig?
Wenn die Zeichenketten unterschiedlich lang sind, ja. So kostet jeder
Eintrag die Länge des Strings + Terminierungsbyte + Größe eines Zeigers.
Wenn Du feste Zeichenketten verwendest, kostet dagegen jeder Eintrag die
maximale Länge (+ das Terminierungsbyte).
>> Außerdem legst Du das komplette Array in der main-Funktion auf dem Stack>> an.> Wieso liegt das Array auf dem Stack? Ich denke auf dem Stack werden nur> Rücksprungadressen gespeichert?
Alle lokalen Variablen, die Du in einer Funktion definierst, werden auf
dem Stack angelegt, sofern sie der Compiler nicht wegoptimiert bzw. in
Registern ablegt. Das gilt auch für die main-Funktion.
Variablen, die nicht auf dem Stack sollen, musst Du entweder in der
Funktion als static definieren (dann sind sie nur innerhalb der Funktion
sichtbar) oder außerhalb der Funktion als Modulvariable (mit static)
bzw. globale Variable (ohne static).
Nico, du solltest (nach deiner Verschönerungsaktion) vielleicht mal die
Adressen aller auto-Variablen deines Programms überprüfen. Vielleicht
geht bei der Bildung dieses komischen Aufrufgraphen (siehe Compiler User
Manual) was schief und irgendwelche auto-Variablen landen auf derselben
Adresse wie deine Funktionspointer?
Sebastian W. schrieb:> Es ist nicht mehr auf dem (Software-)Stack. Wir wüssten aber alle gerne,> wieso meControll zerschossen wird, wenn es auf dem Stack liegt ...
Ach so, wart ihr schon so weit. Ich habe zugegebenermaßen nicht den
ganzen Thread gelesen ...
Fabian O. schrieb:> Vergiss das mit dem PROGMEM, das betrifft nur AVRs. Ich weiß nicht, wie> es beim PIC bzw. Deinem Compiler funktioniert, ein Array nicht in den> RAM, sondern den Programmspeicher (Flash) zu legen. Eventuell reicht es> schon, das Array const zu machen
Mal am Beispiel des font Arrays: Das Array habe ich ja als const
deklariert. Somit habe ich eine Belegung von 6% RAM und 14% FLASH. Wenn
ich das const vor dem Array entferne, dann habe ich 43% RAM und 13%
FLASH.
Also würde ich sagen (XC8 Compiler):
* const --> FLASH
* sonst --> RAM
Mit static legst du es ja im Heap an.
Dann lass es doch da wenn es dich nicht stört.
Gibts hier keine Profis, die sagen können, warum das auf dem Stack so
viele Probleme bereitet?
Mike Mike schrieb:> Mit static legst du es ja im Heap an.> Dann lass es doch da wenn es dich nicht stört.
Nein, mit static liegt es im Datensegment. Auf dem Heap würde es liegen,
wenn man den Speicher mit malloc() alloziert.
> Gibts hier keine Profis, die sagen können, warum das auf dem Stack so> viele Probleme bereitet?
In der Version mit den char-Zeigern sind es ja nur noch ein paar Byte.
Das sollte eigentlich keine Probleme machen. Wenn da was überschrieben
wird, ist das ein Programmfehler. Der kann aber überall sein.
@Nico: Du hast ja anscheinend einen Debugger. Hast Du den Inhalt der
Strukturen zwischen der funktionierenden und nicht funktionierenden
Variante mal verglichen? Falls es im nicht funktionierenden Programm zu
Beginn passt, musst Du überwachen, ob bzw. wann die Werte darin
überschrieben werden.
Noch etwas, das mir aufgefallen ist: Das Array font definierst Du in
jeder c-Datei, die font.h einbindet, neu als globale Variable. Das ist
großer Murks. Wenn es schon eine globale Variable sein soll, dann mach
es wenigstens so:
1
// font.h
2
externconstunsignedcharfont[95][6];
3
externconstunsignedcharsign[3][6];
1
// font.c
2
constunsignedcharfont[95][6]={...};
3
constunsignedcharsign[3][6]={...};
Wobei der Name sign für eine globale Variable ziemlich bescheuert ist.
Da kommt man nicht auf die Idee, dass das zum Font gehören soll.
Pack doch die Batteriesymbole mit in den normalen Font hinten dran und
definiere BAT_FULL, BAT_OK und BAT_EMPTY entsprechend. Dann brauchst Du
nicht mal eine eigene Funktion für Symbole, sondern nimmst die ganz
normale für Zeichen bzw. Text.
Nico M. schrieb:> Verzeihung, dass habe ich glatt überlesen.> Das ist direkt vor dem Aufruf.> [open_tree.png]
Die Adresse von input liegt in einer Lücke innerhalb von meControll?
Dieser compiler ist aber hoch intelligent.
Dauert noch etwas. Das Problem ist i.M. der Umgang mit der IDE. Ich
versuche gerade eine Speicherzelle permanent zu überwachen, indem ich
die Adresse dieser eingebe.. Doch wenn ich aus main z.B. in meControll
wechsele macht er wieder alle watches weg und ich kann nix hinzufügen
sondern nur die, die in meControll gerade zur Verfügung stehen.. Dann
scheint es allerdings schon zu spät zu sein.. nerv
Nico, lies mal Abschnitt 6 in
http://ww1.microchip.com/downloads/en/DeviceDoc/xc8-v1_12-readme.pdf. Da
ist ein Compilerproblem erwähnt das auf unser Problem passen könnte:
Initialization of auto structures Structures which are auto cannot be
initialized. Simply define the structure and assign values separately.
Also, kannst du meControl1 mal wie gehabt in main() definieren, aber die
Werte einzeln setzen?
LG, Sebastian
PS: In dem Dokument sind noch weitere Probleme beschrieben, auf die du
achten solltest, z.B.:
Functions returning pointers (XC8-344)
Wrong watch valuesConstant index into int arrayIndirect function callsProcedural abstraction, mit einer extrem abstrakten Beschreibung ;)
Pointer assignmentsAssignment to pointer member of a union (XC8-341)
WTF ist das denn für ein Compiler?! Meinen die das ernst? Abseits von
trivialen Programmen kann man sich da ja im Prinzip auf nichts
verlassen:
Call to empty function after comparison (XC8-398):
Code which calls a function containing no statements (an empty
definition) which is preceded by an if() statement may fail for 16F1xxx
parts. If the assembler optimizer is enabled, the call to the empty
function, or subsequent code may fail. Adding any code, such as NOP();,
to the empty function is enough to work around this issue.
Functions returning pointers (XC8-344):
If a function returns a pointer, the size of this pointer is larger than
1 byte, and also larger than the total size of all the parameters passed
to this function, then the memory used by the return value may not be
allocated. The function's return value may overwrite other local
variables and lead to code failure. Consider adding a dummy parameter to
the function with the same size as the return value type.
Constant index into int array:
If a constant is used as the index into an array of const int type, the
element read may be incorrect. This issue does not affect arrays of
different types, or when the index is a variable.
Indirect function calls:
The parameters to functions called indirectly via a pointer may not be
passed correctly if the following conditions are met. [...]
Pointer assignments:
In PRO mode, if a pointer assignment is made where one of the pointers
is a member of a structure, the compiler may fail to copy the whole
pointer, causing the pointer to register an incorrect address.
usw.
Fabian O. schrieb:> WTF ist das denn für ein Compiler?!
Microchip halt. Die Idee das ein IC Hersteller gute compiler baut muss
nicht immer stimmen. Aber mit Fehlern wird offen umgegangen.
Nico schrieb:> Der Compiler ist ja nun auch noch relativ neu..
Den Spruch höre ich bei Mplab gefühlt seit Version 5.x ;-)
Also so schlimm finde ich es jetzt nicht. Aber das liegt evtl. auch
daran, das ich es nicht besser weiß. Womit programmiert ihr denn eure
z.B. oder sind hier nur böse Zungen am Werk, welche schlecht reden ohne
selber mal damit gearbeitet zu haben?
Sebastian W. schrieb:> Initialization of auto structures Structures which are auto cannot be> initialized. Simply define the structure and assign values separately.>> Also, kannst du meControl1 mal wie gehabt in main() definieren, aber die> Werte einzeln setzen?
Das funktioniert! Ist aber umständlich. Ich denke, dann werde ich bei
der Version mit in main() als static definiert bleiben.