Fehlermeldung ist in der Aufrufezeile:
../Main.c:180: warning: passing argument 4 of 'SPI_get_measured' from
incompatible pointer type
Funktionskopf ist in der Header Datei gleich wie der Funktionskopf hier
(nur halt mit ; am ende)
Kann mir jemand sagen, was hier der Fehler ist und ob der Code überhaupt
so funktioniert?? (Ich möchte, dass nach dem Abarbeiten der Funktion in
der Hauptfunktion sich measured_length usw. verändert hat.)
Und hier habe ich noch den 2ten Fehler:
Fehlermeldung:
../Main.c:141: error: incompatible type for argument 2 of
'USART_parameters'
Im Prinzip verstehe ich nicht ganz wie ich genau damit arbeiten muss,
wenn ich z.b. ein Array über Pointer übergebe bzw. wenn ich ein von mir
definiertes struct time übergebe.
Gast wrote:
> Öhm, habe gerade gemerkt, dass mans auch so schreiben kann:>
Yep. Strukturen sind vollwertige Datentypen.
Mann kann ein Strukturobjekt einem andern zuweisen.
Mit Arrays geht das nicht.
Sind deine Probleme mit der Übergabe von Arrays bereits ausgeräumt, oder
brauchst du noch Hilfe?
> wenn ich z.b. ein Array über Pointer übergebe
Im Prinzip ist es sehr einfach.
Bei jeder Verwendung des Array-Namens ohne einen Index (also das Zeugs
in den eckigen Klammern) wird dieser Ausdruck umgeformt und bildet die
Startadresse des Arrays.
1
intmain()
2
{
3
intWerte[20];
4
5
foo(Werte);
6
}
In der Parameterliste beim Aufruf von foo wird das Arrays Werte ohne
einen Index benutzt. Das Array degeneriert' daher in seine Startadresse
und diese wird an die Funktion foo übergeben.
Folgerichtig muss foo daher einen Pointer auf int annehmen um Zugang zum
Array zu erhalten. Dank der Definition, wie Indexzugriffe in ein Array
abgebildet werden, kann man innerhalb der Funktion ganz normale
Index-Syntax benutzen
> wenn ich ein von mir> definiertes struct time übergebe.
Du übergibst die einfach.
Hier ist deine Funktion
1
uint8_tUSART_parameters(structtime*start2,
2
structtimeend2,
3
uint32_t*sampling_rate2,
4
uint32_t*measurement_mask1,
5
uint32_t*measurement_mask2)
6
{
7
...
8
}
Beachte: Das erste Argument ist ein Pointer zu einer struct time.
Das zweite Argument ist aber eine struct time selber, also kein Pointer.
Steht genau so da.
Hier der Aufruf
Warum übergibst du daher im 2-ten Argument eine Adresse, also einen
Pointer?
Das 2-te Argument deiner Funktion ist kein Pointer, sondern eine struct
time!
Und genau das sagt dir auch der Compiler
../Main.c:141: error: incompatible type for argument 2 of
'USART_parameters'
Mit den Datentypen für das 2-te Argument stimmt was nicht.
Der Aufrufer will eine Adresse übergeben, die Funktion will aber ein
struct time Objekt.
Und lege dir dringend ein C-Buch zu, Pointerarithmetik lernt man nicht
per trial and error! In Fall 1 bist du kurz davor, an den voellig
falschen Platz im Speicher zu schreiben...
Du solltest dir auch solche Dinge gleich wieder abgewöhnen
> for(uint8_t i = 0; i <= 31; i++)
In C wird bei 0 angefangen zu zählen und das hat ein paar Implikationen.
Zb. den, das die Sichtweise der Dinge in so einer Schleife darin
besteht, dass beim Vergleich auf 'die Anzahl' der abzuarbeitenden
Elemente geprüft wird. Eine Zählschleife, die über ein Array arbeitet,
hat praktisch immer die Form
for( i = 0; i < Anzahl_Elemente; ++i )
Jeder C-Programmierer der sowas sieht, erkennt das in 2/10 Sekunden und
denkt nicht mehr gross darüber nach, welchen Zweck so eine Schleife
erfüllt und welches die Grenzen für i sind.
Erst wenn die Schleife nicht mehr diese Form hat, wird darüber
nachgedacht, warum sie anders als gewohnt aussieht und analysiert warum
das so ist.
Ok Ok mal langsam,
warum hast du ++i geschrieben anstatt i++? Das "i++" wird doch erst nach
dem ersten Schleifendurchlauf ausgeführt, was zu folge hätte, dass man
zuerst bei Index 0 beginnt usw.
Ich habe mehrere C-Bücher zu Hause, allerdings sitze ich gerade in der
Schule und bin unter ziemlichen Zeitdruck mit meinem Projekt, ich habe
leider keine Zeit, ein C Buch zu lesen. Ich habe vor ein paar Jahren
einige gelesen, ich arbeite zur Zeit nur mit dem, was ich noch weiß.
So eine Frage hätte ich noch, hierzu 2 Codestücke:
Code 1:
und hier Code2:
[c]
oid SPI_get_measured(uint8_t *measured_length, uint32_t
*measurement_mask_low, uint32_t *measurement_mask_high, uint32_t
*measured)
{
measured_length = 0;
// Werte von Register Page 0 holen
SPI_write_register(0b01111110,0x00UL); // Stelle Register
Page 0 ein
for(uint8_t i = 0; i <= 31; i++)
{
if(measurement_mask_low && (0x01UL << i))
{
measured[i] = SPI_read_register(i);
measured_length++;
}
}
// Werte von Register Page 1 holen
SPI_write_register(0b01111110,0x01UL); // Stelle Register
Page 1 ein
for(uint8_t i = 32; i <= 35; i++)
{
if(measurement_mask_high && (0x01UL << (i-32))) // -32 weil bei
i=32 es Bit 0 in High Maske ist
{
measured[i] = SPI_read_register(i-32); // -32 weil bei i=32
es Addresse 0 hat
measured_length++;
}
}
// Werte von Register Page 3 holen
SPI_write_register(0b01111110,0x03UL); // Stelle Register
Page 3 ein
for(uint8_t i = 36; i <= 39; i++)
{
if(measurement_mask_high && (0x01UL << (i-32))) // -32 weil bei
i=36 es Bit 4(start bei 0) in High Mask ist
{
measured[i] = SPI_read_register(i-30); // -30 weil bei i=36
es die Addresse 6 hat
measured_length++;
}
}
}
[c]
In beiden Varianten übergebe ich ja die Addresse und die wird in einem
Pointer abgespeichert.
Warum muss ich dann bei Variante 1 später schreiben:
*start2 = start;
und bei Variante 2:
measured_length = 0;
Also einmal mit * und einmal ohne. Wenn ich beim 1ten Beispiel ohne *
mache gibt es einen Fehler und wenn ich bei Variante 2 mit * mache auch!
Kann mir das jemand bitte noch erklären?
Funktionieren überhaupt beide Programmstücke so, dass nach beendigung
der Funktion die Werte sich auch geändert haben?
Danke schonmal an alle hier, die geantwortet haben. Ihr habt mir
wirklich weiter geholfen!
was soll denn
"measured_length = 0" bringen? measured_length ist ein pointer und zeigt
somit auf 0. (Wobei die implizite Konvertierung von int nach uint8_t*
eine Warnung erzeugen sollte).
EDIT: Ups, sehe gerade das steht schon über mir :D
Gast wrote:
> Ok Ok mal langsam,>> warum hast du ++i geschrieben anstatt i++? Das "i++" wird doch erst nach> dem ersten Schleifendurchlauf ausgeführt, was zu folge hätte, dass man> zuerst bei Index 0 beginnt usw.
An dieser Stelle und mit diesem Datentyp ist es völlig Wurscht, ob du
++i oder i++ schreibst. Der Effekt ist in beiden Fällen der gleiche: i
wird um 1 erhöht, und nur darauf kommt es an.
C++ programmierer haben sich aber angewöhnt ++i zu nehmen, wenn beide
Varianten möglich sind. Bei nicht eingebauten Datentypen (zb. bei
eigenen Iteratorklassen) kann dann nämlich der Optimierer besser
arbeiten, weil ein temporäres Objekt von Haus aus wegfällt.
> Ich habe mehrere C-Bücher zu Hause, allerdings sitze ich gerade in der> Schule und bin unter ziemlichen Zeitdruck mit meinem Projekt,
Lass mich raten: Zu spät angefangen? Komplexität unterschätzt?
> ich habe> leider keine Zeit, ein C Buch zu lesen. Ich habe vor ein paar Jahren> einige gelesen,
Zumindest etwas.
> ich arbeite zur Zeit nur mit dem, was ich noch weiß.
Keine gute Idee.
Array Übergabe in C ist eigentlich ziemlich Basic-Knowledge. Wenn du das
schon vergessen hast, wage ich nicht daran zu denken, welche Lücken sich
sonst noch auftun :-)
Also: Abends nochmal ein C-Buch deiner Wahl reinziehen. Die ersten paar
Kapitel über Variablen und +-*/ Operatoren kannst du ja überspringen :-)
> In beiden Varianten übergebe ich ja die Addresse und die wird in einem> Pointer abgespeichert.> Warum muss ich dann bei Variante 1 später schreiben:>> *start2 = start;
Weil start2 ein Pointer ist. Mit dem * wird der Pointer dereferenziert
und die Struktur auf die der Pointer zeigt als ganzes angesprochen.
> und bei Variante 2:>> measured_length = 0;
must du nicht.
Nur macht das was ganz anderes als du erwartest :-)
Das setzt einfach nur den Pointer auf 0. Der Pointer zeigt also auf
nichts mehr. Wenn du den Pointer in weiterer Folge benutzen willst um
auf die Daten zuzugreifen, wirds einen schönen Absturz geben :-)
> mache gibt es einen Fehler und wenn ich bei Variante 2 mit * mache auch!
Das kann nicht sein. Zumindest keinen Compilerfehler.
Zur Laufzeit könnte es abstürzen, weil der Aufrufer keine gültige
Adresse in measured_length übergeben hat.
Naja Komplexität unterschätzt triffts schon. µC programmierung einlesen,
sämtliche Datenblätter lesen UART,SPI,SD-Karten programmierung und FAT32
implementierung einlesen und sämtliche RFCs für sonstiges lesen hats
schon in sich.
Natürlich kann ich noch andere Programmiersprachen, wie z.b. C# wodurch
ich mich auch bei komplexeren Sachen auskenne, allerdings gibt es dort
ja keine Pointer und daher ist die übergabe von Arrays auch anders.
Das mit measured_length = 0; die Addresse umgeschrieben wird habe ich
mir auch schon gedacht, allerdings bekomme ich bei folgendem Code die
folgende Meldung:
SPI_write_register(0b01111110,0x00UL);// Stelle Register Page 0 ein
7
for(uint8_ti=0;i<32;++i)
8
{
9
if(*measurement_mask_low&&(0x01UL<<i))
10
{
11
measured[i]=SPI_read_register(i);
12
*++measured_length;
13
}
14
}
15
16
// Werte von Register Page 1 holen
17
SPI_write_register(0b01111110,0x01UL);// Stelle Register Page 1 ein
18
19
for(uint8_ti=32;i<36;++i)
20
{
21
if(*measurement_mask_high&&(0x01UL<<(i-32)))// -32 weil bei i=32 es Bit 0 in High Maske ist
22
{
23
measured[i]=SPI_read_register(i-32);// -32 weil bei i=32 es Addresse 0 hat
24
*++measured_length;
25
}
26
}
27
28
// Werte von Register Page 3 holen
29
SPI_write_register(0b01111110,0x03UL);// Stelle Register Page 3 ein
30
for(uint8_ti=36;i<40;++i)
31
{
32
if(*measurement_mask_high&&(0x01UL<<(i-32)))// -32 weil bei i=36 es Bit 4(start bei 0) in High Mask ist
33
{
34
measured[i]=SPI_read_register(i-30);// -30 weil bei i=36 es die Addresse 6 hat
35
*++measured_length;
36
}
37
}
38
}
Diese 3 Warnungen bekomme ich:
../SPI.c:207: warning: value computed is not used
../SPI.c:219: warning: value computed is not used
../SPI.c:230: warning: value computed is not used
Was mache ich dagegen?
Gast wrote:
> Diese 3 Warnungen bekomme ich:>> ../SPI.c:207: warning: value computed is not used> ../SPI.c:219: warning: value computed is not used> ../SPI.c:230: warning: value computed is not used>> Was mache ich dagegen?
Des Englischen bist du aber schon mächtig, oder?
Da steht
Wert ausgerechnet wird nicht benutzt
Oder in etwas besserem Deutsch: Hier wird zwar was ausgerechnet, aber
niemand verwendet das Ergebnis weiter. Willst du dir das mal genauer
ansehen oder bist du damit einverstanden, dass ich die Berechnung
zumindest zum Teil rausschmeisse. Den wenn eine Berechnung ein Ergebnis
liefert, welches eh keinen interessiert, braucht man auch die Berechnung
meistens nicht (von Seiteneffekten mal abgesehen, aber darum kümmere ich
mich als Compiler schon)
Da ich mit deinen Zeilennummern nichts anfangen kann, kann ich nur raten
waroauf sich der Compiler bezieht
*++measured_length;
was macht das?
measured_length da ist mal ein Zeiger
++measured_length dieser Zeiger wird um 1 erhöht
*++measured_length und anschliessend wird der Wert von der
Speicherstelle geholt, auf die der
erhöhte Zeiger zeigt
und weiter ... niemand macht was mit dem Wert :-)
Was du aber wahrscheinlich wolltest: Den int, auf den der Zeiger zeigt,
um 1 erhöhen.
measured_length du hast einen Zeiger
* measured_length der zeigt auf einen Wert, diesen
Wert brauchen wir mal ...
++ * measured_length ... um ihn um 1 zu erhöhen.
Ja schon, aber es geht doch darum, dass diese Werte über einen Pointer
übergeben werden und dann später nachdem diese Funktion aufgerufen
wurde, weiter benutzt werden!
also Aufruf:
SPI_get_measured(&measured_length, &measurement_mask_low,
&measurement_mask_high, measured);
und ca. 6 codezeilen darunter steht:
USART_send(measured_length);
Also wird die Variable benutzt.... aber naja ist ja egal, ist nur eine
Warnung. Danke an alle, die mir geholfen haben!
Gast wrote:
> Ja schon, aber es geht doch darum, dass diese Werte über einen Pointer> übergeben werden und dann später nachdem diese Funktion aufgerufen> wurde, weiter benutzt werden!
Scroll nochmal zurück. Ich hab noch eine Ergänzung angebracht, die deine
Frage beantworten wird.
Gast wrote:
> Also wird die Variable benutzt.... aber naja ist ja egal, ist nur eine> Warnung.
Falsche Einstellung.
Du solltest Warnungen immer ernst nehmen.
In der professionellen Entwicklung werden die Compiler oft auf die
höchste Warnstufe eingestellt und Warnungen wie Fehler behandelt.
Und das aus gutem Grund!
Wenn der Compiler eine Warnung gibt, hat er meistens damit recht, dass
da irgendwas faul ist.
Hmmm ok, ist mir eigentlich auch schon aufgefallen, dass es da meistens
irgendetwas hat. Aber was mir auch aufgefallen ist ist, dass AVR Studio
manchmal 0 Warnings angibt und wenn ich dann irgendetwas am Code ändere
(z.b. ; lösche und wieder hinzugebe) dann 2 Warnings z.b. auftauchen...
Wenn wir gleich dabei sind, vielleicht kannst du mir bei noch etwas
helfen. Ich benutze für die SD-Karte eine Bibliothek und dort gibt es
auch 2 Warnings:
1
unsignedcharmmc_read_csd(char*buffer)
2
{
3
cmd[0]=0x40+MMC_SEND_CSD;
4
send_cmd();
5
6
if(wait_start_byte())
7
{
8
MMC_PORT|=1<<MMC_CS;//MMC Chip Select -> High (deactivate);
9
returnMMC_NOSTARTBYTE;
10
}
11
12
mmc_read_buffer(buffer,16);
13
mmc_stop_read_block();
14
return(MMC_OK);
15
}
Hier gibt es beim Aufruf von mmc_read_buffer(buffer,16); einen Fehler:
../mmc_lib.c:218: warning: pointer targets in passing argument 1 of
'mmc_read_buffer' differ in signedness
Der 2te Fehler ist das gleiche, nur etwas später.
mmc_read_buffer sieht so aus:
Sorry wegen Doppelpost, habe gerade den Fehler selbst gefunden.
Einmal char und einmal unsigned char...
Tut mir leid, ich werde das nächste mal selbst etwas länger über so ein
Problem nachdenken, bevor ich poste. Sorry.
Trotzdem noch einmal ein großes Danke an alle hier!
Gast wrote:
> Hmmm ok, ist mir eigentlich auch schon aufgefallen, dass es da meistens> irgendetwas hat. Aber was mir auch aufgefallen ist ist, dass AVR Studio> manchmal 0 Warnings angibt und wenn ich dann irgendetwas am Code ändere> (z.b. ; lösche und wieder hinzugebe) dann 2 Warnings z.b. auftauchen...
Das liegt daran, dass der Compiler erkennt, dass sich nichts geändert
hat und deswegen das File nicht nochmal kompiliert. Also gibt er auch
nicht die Fehler aus diesem File aus.