Hallo,
Habe ein Quell Code geschrieben um Daten von einem uC über SPI in ein
externes Flash zu schreiben.
Benutze den LPC2129 und das flash At45Db161.
Beim compilieren kommen u.a. folgende Fehlermeldungen:
SPI_CS_FLASH ~= (1<<SPI_CSB); // CSB auf Null setzen
SPI.c(281,1): syntax error before '~' token
S0SPDR = opcode; //MAIN_MEMORY_PAGE_READ;
SPI.c(282,1): 'opcode' undeclared (first use in this function)
SPI.c(282,1): (Each undeclared identifier is reported only once
SPI.c(282,1): for each function it appears in.)
for (unsigned char k=0;k<7;k++)
{
S0SPDR = adressfeld[k]; // Daten an SPI
while (!(S0SPSR & (SPI_SPIF))); // Warten bis Daten gesendet
}
SPI.c(285,1): 'for' loop initial declaration used outside C99 mode
*data.pagecounter = (S0SPDR << 8);
SPI.c(296,1): 'data' undeclared (first use in this function)
SPI.c(405,1): 'for' loop initial declaration used outside C99 mode
SPI.c(424,1): left shift count >= width of type
\SPI.c(424,1): invalid lvalue in assignment
Weiß jemand evtl was mit denen anzufangen oder soll ich dazu noch den
passenden Quell Code mitschicken?
Bin halt noch ein Anfänger was dies angeht und weiß nicht wie ich die
Fehler beseitigen kann.
Bei der fehlermeldung SPI.c(296,1): Hab eine Struktur mit dem Namen
SPIDataBlock. Wie übergebe ich denn eine Struktur in einer Funktion?
Kann mir da jemand weiterhelfen?Wäre Euch sehr dankbar.
Grüße
Steff wrote:
> SPI_CS_FLASH ~= (1<<SPI_CSB); // CSB auf Null setzen> SPI.c(281,1): syntax error before '~' token
Versuche stattdessen:
SPI_CS_FLASH = SPI_CS_FLASH & (~(1<<SPI_CSB));
> S0SPDR = opcode; //MAIN_MEMORY_PAGE_READ;> SPI.c(282,1): 'opcode' undeclared (first use in this function)> SPI.c(282,1): (Each undeclared identifier is reported only once> SPI.c(282,1): for each function it appears in.)
Tja, "opcode" kennt der Compiler offenbar nicht. Wo ist denn das
definiert?
> for (unsigned char k=0;k<7;k++)> {> S0SPDR = adressfeld[k]; // Daten an SPI> while (!(S0SPSR & (SPI_SPIF))); // Warten bis Daten gesendet> }> SPI.c(285,1): 'for' loop initial declaration used outside C99 mode
Versuche es so:
unsigned char k = 0;
for (; k < 7; k++)
{ ...
Im alten C-Standard, auf den der Compiler offenbar eingestellt ist, darf
man Variablen nicht so im for-Konstrukt definieren. So wie angegeben
sollte es gehen.
> *data.pagecounter = (S0SPDR << 8);> SPI.c(296,1): 'data' undeclared (first use in this function)
Auch hier: Der Compiler findet "data" nicht. Es ist offenbar nicht oder
an falscher Stelle deklariert.
> SPI.c(405,1): 'for' loop initial declaration used outside C99 mode
Hier fehlt der dazugehörige Code - aber wahrscheinlich musst du hier
genauso wie oben den 1. Teil in for() vor die Schleife schreiben.
> SPI.c(424,1): left shift count >= width of type
Ohne Code... schwierig :)
> \SPI.c(424,1): invalid lvalue in assignment
dito...
> Weiß jemand evtl was mit denen anzufangen oder soll ich dazu noch den> passenden Quell Code mitschicken?
Das wäre schon ganz gut.
> Bin halt noch ein Anfänger was dies angeht und weiß nicht wie ich die> Fehler beseitigen kann.
Tutorials durchgearbeitet ... ?
> Bei der fehlermeldung SPI.c(296,1): Hab eine Struktur mit dem Namen> SPIDataBlock. Wie übergebe ich denn eine Struktur in einer Funktion?
SPIDataBlock data;
NameDerFunktion (&data);
Ob das & da hin muss, hängt davon ab, ob bei der Deklaration der
Funktion "SPIDataBlock* data" steht (dann muss das & hin) oder nur
"SPIDataBlock data" (ohne * => das & weglassen)
Ohne den kompletten Code kann man bei so einzelnen Fragmenten kaum was
korrigieren.
So wie das aussieht, hast du einen fertigen Code kopiert, und mit einem
anderen Compiler compiliert. Vor allem als Anfänger ist es ganz gut,
sich durchzulesen, wie so ein Flash angesprochen wird, und das dann
selber zu programmieren. So lernt man gut dazu.
Das opcode übergebe ich mit dieser funktion:
Prototyp:
extern void ReadDataFromFlash(unsigned short page,unsigned short
startbyte, unsigned short opcode,struct SPIDataBlock* data);
void ReadDataFromFlash(unsigned short page,unsigned short startbyte,
unsigned short opcode,SPIDataBlock* data)
{
Wenn ich es so schreib,dann müsste es doch eigentlich erkannt
werden,oder?
Das mit der FOR Schleife hat geklappt.
Hab den Code fast komplett alleine geschrieben,deshalb sind da auch so
viele Fehler drinn. Da wird man echt verrückt wenn nichts klappt.
Was bräuchtest du denn von dem Quellcode, wegen en anschaun?
Wär echt so super nett von dir wenn mir weiterhelfen könntest.
grüße
Steff wrote:
> Wenn ich es so schreib,dann müsste es doch eigentlich erkannt> werden,oder?
Eigentlich ja, das sieht so ziemlich richtig aus.
> Was bräuchtest du denn von dem Quellcode, wegen en anschaun?
Am besten die ganze Funktion inklusive der Stellen, an der die Fehler
auftreten.
> SPI.c(424,1): left shift count >= width of type> \SPI.c(424,1): invalid lvalue in assignment
Und diese Zeile 424 auch, plus die Stellen, an der die in dieser Zeile
vorkommenden Variablen deklariert sind.
> Hab den Code fast komplett alleine geschrieben,deshalb sind da auch so> viele Fehler drinn.
Ups, und ich wollte dich schon des kopierens beschuldigen ^^
kannst du damit schon was anfangen?
Meine anderen fehlermeldungen sind u.a.:
Die fehlermeldungen hängen glaub fast alle an dem selben Problem, weiß
nur nicht an welchem?!
at45db.h(57,1): useless storage class specifier in empty declaration
at45db.c(6,1): syntax error before 'data'
at45db.c(6,1): data definition has no type or storage class
at45db.c(17,1): syntax error before numeric constant
at45db.c(23,1): conflicting types for 'PageCounter'
at45db.c(8,1): previous declaration of 'PageCounter' was here
at45db.c(23,1): request for member 'pagecounter' in something not a
structure or union
at45db.c(23,1): data definition has no type or storage class
at45db.c(24,1): syntax error before '.' token
at45db.c(25,1): conflicting types for 'StartByteCounter'
at45db.c(9,1): previous declaration of 'StartByteCounter' was here
at45db.c(25,1): data definition has no type or storage class
at45db.c(31,1): conflicting types for 'StartByteCounter'
at45db.c(9,1): previous declaration of 'StartByteCounter' was here
at45db.c(31,1): request for member 'startbytecounter' in something not
a structure or union
at45db.c(31,1): data definition has no type or storage class
at45db.c(37,1): conflicting types for 'PageCounter'
at45db.c(8,1): previous declaration of 'PageCounter' was here
at45db.c(37,1): request for member 'pagecounter' in something not a
structure or union
at45db.c(37,1): data definition has no type or storage class
at45db.c(38,1): syntax error before '.' token
at45db.c(39,1): conflicting types for 'StartByteCounter'
at45db.c(9,1): previous declaration of 'StartByteCounter' was here
at45db.c(39,1): data definition has no type or storage class
at45db.c(43,1): syntax error before numeric constant
at45db.c(43,1): conflicting types for 'writeBuffer'
at45db.h(64,1): previous declaration of 'writeBuffer' was here
at45db.c(43,1): data definition has no type or storage class
at45db.c(47,1): syntax error before numeric constant
at45db.c(47,1): data definition has no type or storage class
at45db.c(48,1): syntax error before numeric constant
at45db.c(48,1): conflicting types for 'writePage'
at45db.h(63,1): previous declaration of 'writePage' was here
at45db.c(48,1): data definition has no type or storage class
at45db.c(54,1): syntax error before '*' token
at45db.c(57,1): syntax error before '-' token
at45db.c(57,1): conflicting types for 'ReadDataFromFlash'
at45db.c(57,1): note: an argument type that has a default promotion
can't match an empty parameter name list declaration
at45db.h(68,1): previous declaration of 'ReadDataFromFlash' was here
at45db.o" was not generated.
"
at45db.h(57,1): useless storage class specifier in empty declaration
SPI.c(31,1): syntax error before 'SPIDataBlock'
SPI.c(32,1): number of arguments doesn't match prototype
at45db.h(63,1): prototype declaration
SPI.c(42,1): syntax error before '~' token
SPI.c(44,1): 'opcode' undeclared (first use in this function)
SPI.c(44,1): (Each undeclared identifier is reported only once
SPI.c(44,1): for each function it appears in.)
SPI.c(53,1): left shift count >= width of type
SPI.c(53,1): invalid lvalue in assignment
SPI.c(87,1): syntax error before 'SPIDataBlock'
SPI.c(88,1): number of arguments doesn't match prototype
at45db.h(64,1): prototype declaration
SPI.c(99,1): syntax error before '~' token
SPI.c(101,1): 'opcode' undeclared (first use in this function)
SPI.c(110,1): 'data' undeclared (first use in this function)
SPI.c(129,1): 'for' loop initial declaration used outside C99 mode
SPI.c(136,1): left shift count >= width of type
SPI.c(136,1): invalid lvalue in assignment
SPI.c(140,1): conflicting types for 'SPI_WriteBuffer'
SPI.c(140,1): note: an argument type that has a default promotion can't
Kannst du damit was anfangen?
grüße
Kannst du die at45db.h mal posten? (du hast die SPI.h 2x gepostet :)
Ist in der Datei auch die Definition von SPIDataBlock drin? Die bräuchte
ich auch mal.
Und dann muss man aber immer "struct ein_toller_name" schreiben. Da das
viel zu umständlich ist, gibt es "typedef foo bar;" - das definiert
einen neuen Datentyp namens bar, der genau das gleiche enthält wie foo.
Wenn du also schreibst "typedef struct ein_toller_name blar;" hat danach
"blar" die gleiche Bedeutung wie "struct ein_toller_name". Du könntest
also schreiben:
1
structSPIDataBlock{// 1Struktur = 44Byte
2
...blabla...
3
};
4
typedefstructSPIDataBlockSPIDataBlock;
Dann kannst du im Code SPIDataBlock schreiben, ohne das struct davor. Da
das aber immer noch zu kompliziert ist, gibt es eine weitere
Vereinfachung:
1
typedefstructSPIDataBlock{
2
...blabla...
3
}SPIDataBlock;
Bewirkt das gleiche wie oben. Wenn du schreibst:
1
typedefstruct{
2
...blabla...
3
}SPIDataBlock;
Kannst du nicht mehr "struct SPIDataBlock" schreiben, sondern nur noch
das kurze SPIDataBlock.
Vermutlich dürfte das einige der anderne Fehler gleich mit verpuffen
lassen :)
vielen viele dank für die super Erklärung.
wenn ich das jetzt so abändere, dann kommt die Fehlermeldung:
request for member 'full_charge_cap' in something not a structure or
union
Die Fehlermeldung kommt an allen Stellen, die etwas mit der Struktur zu
tun haben.
Hab ich da was falsch gemacht?
wenn ich in einer funktion die komplette struktur übergeben will, dann
schreibt man das so,oder?
writeBuffer(FirstStartByte,BUF2_WRITE,data);
Wie mach ich es aber, wenn ich nur die letzten 4 byte einer struktur
übergeben will?
Hast du evtl noch was gefunden was du in meinem Coder anderst scheiben
würdest,weil es viell. so nicht funktioniert oder sowas? Wenn den Code
anschaust, dann siehst glaub gleich das der nicht irgendwoher kopiert
wurde*g*
grüße
Steff wrote:
> wenn ich das jetzt so abändere, dann kommt die Fehlermeldung:> request for member 'full_charge_cap' in something not a structure or> union
Ersetze z.B. in ReadDataFromFlash "*data." durch "data->". Also
"data->battery_mode = 37;" oder so.
> wenn ich in einer funktion die komplette struktur übergeben will, dann> schreibt man das so,oder?> writeBuffer(FirstStartByte,BUF2_WRITE,data);
Ja. So wird eine Kopie der Original-Struktur im Speicher angelegt; wird
sie verändert, bleibt das original so, wie es ist.
> Wie mach ich es aber, wenn ich nur die letzten 4 byte einer struktur> übergeben will?
Dann solltest du diese letzten 4 Bytes in einer eigenen struct
zusammenfassen und übergeben:
1
structcounters{
2
unsignedshortpagecounter;
3
unsignedshortstartbytecounter;
4
};
5
structSPIDataBlock{
6
...
7
structcounterscounters;
8
};
Zugriff dann z.B. über data->counters.pagecounter;
Dieses "struct counters" kannst du dann direkt deiner Funktion
übergeben.
> Hast du evtl noch was gefunden was du in meinem Coder anderst scheiben> würdest,weil es viell. so nicht funktioniert oder sowas?
Ich würde statt der endlosen SPI_WriteBuffer-Sequenz in der
writeBuffer-Funktion (verwirrende Namen übrigens) lieber die
SPI_WriteBuffer so abwandeln:
unsignedcharb=(unsignedchar)(data[n]);// Byte aus Speicher holen
5
S0SPDR=b;// Byte an SPI
6
while(!(S0SPSR&(SPI_SPIF)));// Warten bis Daten gesendet
7
}
8
}
void* enthält einfach eine RAM-Adresse, wobei nicht näher bekannt ist,
was sich dort befindet. Der C-Compiler nimmt an, der Programmierer weiß
es und wie die Daten korrekt zu verwenden sind. Dieser Funktion kannst
du also eine Stelle im RAM übergeben, an der sich zu sendende Daten
befinden, und wie viele Bytes es sind.
In writeBuffer löschst du die ganzen SPI_WriteBuffer-Aufrufe, und erstzt
sie durch ein schlichtes
1
SPI_WriteBuffer((void*)&data,sizeof(data));
Das hat den Vorteil, dass du SPIDataBlock beliebig verändern kannst, und
diese Speicher-Routinen funktionieren trotzdem noch ohne
AnpassunBeitrag "Fehlermeldungen beim compilieren von SPI Code".
Wenn du dann ein einzelne Variablen (wie int, short etc) versenden
willst, kannst du das ganz genauso machen:
Das sollte auch automatisch mit dem verschachtelten struct, also mit dem
eingebauten "struct counters" funktionieren.
So, und du darfst jetzt als Hausaufgabe eine SPI_ReadBuffer (void* data,
size_t length); schreiben, die das gleiche in umgekehrt macht :)
Es könnte jedoch passieren, dass die alten, im Flash gespeicherten Daten
nicht mehr mit dem neuen Programm kompatibel sind - deine alte
SPI_WriteBuffer schreibt ja immer zuerst das höherwertige Byte, es
könnte aber, abhängig von deinem Controller sein, dass die neue Variante
erst das niederwertige Byte speichert/liest (das müsste genau dann der
Fall sein, wenn der Controller Little Endian ist, wenn mich nicht alles
täuscht.).
hi,
echt super nett von dir das du mir so weiterhilfst.
du hast ja geschreiben:
>Dann solltest du diese letzten 4 Bytes in einer eigenen struct>zusammenfassen und übergeben:struct counters {> unsigned short pagecounter;> unsigned short startbytecounter;>};>struct SPIDataBlock {> ...> struct counters counters;>};
heisst das dann, dass ich die eine struktur mit den ganzen messwerten
schreib(ohne pagecounter und startbytecounter) und dann noch eine extra
struktur nur mit pagecounter und startbytecounter?oder hast du das
anderst gemeint?
Was wird denn durch den Pfeil gemacht?
>Ersetze z.B. in ReadDataFromFlash "*data." durch "data->". Also>"data->battery_mode = 37;" oder so.
Was hast du denn mit den 2 folgenden zeilen gemeint?
>const size_t length>size_t n = 0;
nochmal ganz herzlichen dank. Bin noch ganz am Anfang was das
Programmieren angeht und das von dir ist echt so wahnsinnig hilfreich.
Werd jetzt gleich mal anfangen und hoff,dass ich übers Wochenende fertig
werde.
Grüße
Ahh, das mit den Strukturen hab ich glaub verstanden. Das ist ja so das
struct counter im struct SPIDataBlock einfach mit eingebunden wird,oder?
Eine ganz kleine Frage hätte ich noch.
Du hast ja folgende Zeilen geschreiben:
>SPI_WriteBuffer(const void* data, const size_t length) {> size_t n = 0;> for (n = 0; n < length; n++) { // Schleife für jedes byte.> unsigned char b = (unsigned char) (data [n]); // Byte aus Speicher >holen> S0SPDR = b; // Byte an SPI> while (!(S0SPSR & (SPI_SPIF))); // Warten bis Daten gesendet> }>}
Fast alle Daten bestehen ja aus 2 Byte. Wie wird denn das in der
vorhergehenden Funktion gemacht?Hab mit dem const noch nie gearbeitet?!
grüße
Steff wrote:
> hi,> echt super nett von dir das du mir so weiterhilfst.
Kein Problem :)
> du hast ja geschreiben:>>Dann solltest du diese letzten 4 Bytes in einer eigenen struct>>zusammenfassen und übergeben:struct counters {>> unsigned short pagecounter;>> unsigned short startbytecounter;>>};>>struct SPIDataBlock {>> ...>> struct counters counters;>>};>> heisst das dann, dass ich die eine struktur mit den ganzen messwerten> schreib(ohne pagecounter und startbytecounter) und dann noch eine extra> struktur nur mit pagecounter und startbytecounter?> Ahh, das mit den Strukturen hab ich glaub verstanden. Das ist ja so das> struct counter im struct SPIDataBlock einfach mit eingebunden wird,oder?
Japp, ganz genau.
> Was wird denn durch den Pfeil gemacht?>>Ersetze z.B. in ReadDataFromFlash "*data." durch "data->". Also>>"data->battery_mode = 37;" oder so.
Du hast ja im Kopf der Funktion geschrieben "SPIDataBlock* data". Der
Stern * bewirkt, dass nur die Adresse, an der sich der SPIDataBlock im
RAM befindet, übergeben wird. So wird eben nicht das ganze struct
kopiert, sondern nur die Adresse. Diese data ist dann eine Zeiger bzw.
Pointer - es "zeigt" sozusagen an die Stelle, wo es im Speicher zu
finden ist.
Dann kannst du aber nicht mehr "data.battery_mode" schreiben, sondern
"data->battery_mode". Das bewirkt aber im Prinzip das selbe, also der
Zugriff auf ein Element eines struct's, von dem man einen Pointer hat.
Du hattest ja geschrieben "*data.battery_mode" - der Fehler waren
fehlende Klammern - mit "(*data).battery_mode" hätte es funktioniert.
data->battery_mode bewirkt genau das gleiche, sieht aber viel schöner
aus.
> Was hast du denn mit den 2 folgenden zeilen gemeint?>>const size_t length>>size_t n = 0;
Durch das const teilt man dem Compiler mit, dass man in der Funktion die
Variable length nicht verändern wird. Der Compiler kann dann ein
bisschen optimieren, z.B. das kopieren wegoptimieren. Der Datentyp
size_t ist definiert als "Unsigned integer type of the result of the
sizeof operator.". Also im Prinzip ein Variablentyp, der groß genug ist,
um die Größe eines structs zu beschreiben, das den ganzen RAM füllt. Das
ist meistens ein 32-bit-"unsigned int", kann aber auf einem
Mikrocontroller vielleicht auch kleiner sein, abhängig vom verfügbaren
Speicher.
Meine SPI_WriteBuffer-Funktion fasst einfach alle übergebenen Daten als
ein array von char's (also bytes) auf und versendet die. Übergibt man
einen 2-byte-Wert (wie short) dann denkt die Funktion, es handele sich
um ein array aus 2 char's, die einfach nacheinander gesendet werden. Und
das funktioniert mit allen Datentypen aller Größen.
Hast du das so gemeint mit dem struct?
struct counters
{
unsigned short pagecounter;
unsigned short startbytecounter;
};
typedef struct // 1Struktur = 44Byte
{
unsigned short battery_mode;
unsigned short temperature;
.
.
.
unsigned short year;
unsigned short reserve[2];
struct counters counters;
}SPIDataBlock;
oder kommt dann das typedef wieder weg?
Werd glau bei der Programmierung es so schreiben:(*data).battery_mode
also die zweite Möglichkeit. Sonst komm ich bissle durcheinander.
Steff wrote:
> Hast du das so gemeint mit dem struct?> [...]> oder kommt dann das typedef wieder weg?
Nene, so ist das genau richtig.
> Werd glau bei der Programmierung es so schreiben:(*data).battery_mode> also die zweite Möglichkeit. Sonst komm ich bissle durcheinander.
Naja, das (*data). ist auch verwirrend... Halt bei einem Pointer -> und
bei direktem Zugriff . das ist die übliche Version, so macht das jeder.
ja ok, du weisst es ja wie es geht, dann mach ich es auch so.
mal schaun ob ich jetzt weiterkomme, aber mit deiner Hilfe dürfte es zu
schaffen sein(hoffe ich mal*g*).
Steff wrote:
> also so wie ich das struct grad geschreiben hab,kann ich es genau> übernehmen?also für die große Struktur mit typedef und für die kleine> ohne?
Ja, das kannst du so übernehmen. Du kannst, wenn du willst, bei dem
kleinen auch noch ein typedef einbauen:
1
typedefstruct
2
{
3
unsignedshortpagecounter;
4
unsignedshortstartbytecounter;
5
}counters;
Dann kannst du dir da unten dass "struct" sparen, also statt "struct
counters" kannst du dann einfach nur "counters" schreiben:
Hallo
Eine Frage hätte ich noch.
hab ja dann die eine Struktur mit den Messdaten und die andere Struktur
mit den Countern.
Schreib die daten in ein Flash mit 4095 pages,wobei die 0.page für die
counter verwendet wird.
den startbytecounter muss ich nach dem eine Messdatenstruktur in eine
page geschreiben wurde um die Messdatenstukturgröße erhöhen. Den
pagecounter aber nur wenn eine page mit 12 messdatenstrukturen voll
geschreiben wurde. Wie mach ich das denn wenn ich die Messdatenstrukur
in eine page schreib das die counter nicht mit in die jeweilige page
geschreiben wird, sondern nur in die 0. page?
Grüße
>Wie mach ich das denn wenn ich die Messdatenstrukur>in eine page schreib das die counter nicht mit in die jeweilige page>geschreiben wird, sondern nur in die 0. page?
Laß die counter aus der Messdatenstruktur raus?
Wenn du sie nicht mitschreiben willst was sollen sie dann
dort? Oder zieh beim schreiben die Länge der counter
von der Messdatenstruktur ab.
Schlimm wäre es nicht wenn die auch mit hineingeschreiben werden oder
ist es dann evtl sogar leichter dann wenn ich die daten wieder auslesen
will und alles komplett mit hinein geschrieben wird?
Das Problem ist halt dann, das ich ja immer beide Funktionen in der
großen Funktion:void writeBuffer(unsigned short startbyte,unsigned short
opcode,SPIDataBlock data) ausführe. Oder versteh ich da was falsch?
Du willst ja offenbar die counter und die Messdaten separat speichern.
Die neue SPI_WriteBuffer-Funktion verschickt einfach nur Daten
beliebiger Länge über SPI.
Du könntest dir jetzt eine Funktion schreiben, die erst die Ziel-Page
über SPI verschickt (über SPI_WriteBuffer ((void*) &addressfeld, sizeof
(addressfeld));), und dann die Messdaten hinterher, und dann die
Ziel-Page 0 verschickt, und dann die counter. Das Aufrufen dieser
Funktion würde dann die messwerte und die counter an ihre entsprechenden
Stellen im Flash speichern.
> woher kommt denn in der funktion die du oben geschreiben hast das data> bei data.values her? muss man das nicht erst noch festlegen?
Ich hatte jetzt angenommen dass diese Aufrufe nach writeBuffer kommen,
und das data wird da ja als Parameter übergeben.
>Ich hatte jetzt angenommen dass diese Aufrufe nach writeBuffer kommen,>und das data wird da ja als Parameter übergeben.
Du hast recht.
Wie spreche ich denn eigentlich eine Struktur an die ineinander
verschachtelt sind?
ah ok danke
>Du könntest dir jetzt eine Funktion schreiben, die erst die Ziel-Page>über SPI verschickt (über SPI_WriteBuffer ((void*) &addressfeld, sizeof>(addressfeld));), und dann die Messdaten hinterher, und dann die>Ziel-Page 0 verschickt, und dann die counter. Das Aufrufen dieser>Funktion würde dann die messwerte und die counter an ihre entsprechenden>Stellen im Flash speichern
1.Vor jedem schreiben muss ich ja immer die page0 auslesen zwecks dem
pagecounter und dem startbytecounter.
mit: void ReadDataFromFlash(unsigned short page,unsigned short
startbyte, unsigned short opcode,SPIDataBlock* data)
2. auswerten der Counter
3. und danach würdest du dann die Funktion schreiben, die du oben
beschrieben hast? Aber was machst denn die Funktion mit dem adressfeld?
Steff wrote:
> 3. und danach würdest du dann die Funktion schreiben, die du oben> beschrieben hast? Aber was machst denn die Funktion mit dem adressfeld?
So wie ich das verstanden habe, muss man dem Flash über SPI die Adresse
mitteilen, an die man schreiben/lesen will, und deswegen hatte ich
geschrieben, dass du mit dem neuen SPI_WriteBuffer die
addressfeld-Variable verschicken kannst, die du ja auch schon erstellt
hast, um die Ziel-Adresse an den Flash zu schicken.
Hab es bis jetzt ja so:
dann müsste ich es ja evtl ao machen.
auslesen, auswerten der counter und dann...
Für die Messdaten:
1. in buffer schreiben an startbyte 0, da ja soweiso immer nur eine
messdatenstruktur reinkommt
2. kompletter bufferinhalt in die davor ermittelte page und startbyte
schreiben
Für die Counter:
1. aktuelle counter in buffer scheiben
2. bufferinhalt in page 0 schreiben.
die counter müsste ich ja eigentlich immer an die letzten 4 startbyte
schreiben, da ich ja nur die startbyte angeben kann, sonst würde er ja
beim lesen erstmal 500byte umsonst lesen um an die counterstände zu
kommen,oder?
void writeBuffer(unsigned short startbyte,unsigned short
opcode,SPIDataBlock data)
{
unsigned int adressfeld[3];
//startbyte im buffer
startbyte &= 0x03FF; // 0x03FF->
auf 10 bits beschränkt
/* in Buffer über SPI*/
adressfeld[0] = (unsigned char) 0x00; // 8 der 14
don't care bits
adressfeld[1] = (unsigned char) (startbyte >> 8) | 0x00; // die
restlichen 6 don't care bits + 2 der 10 bits des Startbytes
adressfeld[2] = (unsigned char) (startbyte & 0x00FF); // die
restlichen 8 Bits des Startbytes;
SPI_CS_FLASH ~= (1<<SPI_CSB); // CSB auf
Null setzen
S0SPDR = opcode; //BUF1_WRITE; // Opcode
(0x84) ausgeben(Kommando an SPI Bus)
while (!(S0SPSR & (SPI_SPIF))); // Warten
bis Daten gesendet
unsigned char k;
for (k=0; k<3; k++)
{
S0SPDR = adressfeld[k]; // Daten an
SPI
while (!(S0SPSR & (SPI_SPIF))); // Warten
bis Daten gesendet
}
//Schreiben des Messdatenblocks
SPI_WriteBuffer((void*) &data.values, sizeof (data.values));
//Schreiben der Counter
SPI_WriteBuffer((void*) &data.counters, sizeof (data.counters));
SPI_CS_FLASH |= (1<<SPI_CSB); //CSB auf 1 setzen
}
SPI_WriteBuffer(const void* data, const unsigned int length)
{
unsigned int n = 0;
for (n = 0; n < length; n++)
{
unsigned char byte = (unsigned char) (data [n]);
SOSPDR = byte;
while (!(S0SPSR & (SPI_SPIF))); // Warten
bis Daten gesendet
}
Morgen,
könntest du mir evtl sagen ob man das so schreiben könnte.Hab jetzt das
write buffer gesplittet.
Also das sind die jeweiligen Funktionsaufrufe:
//update von pagecounter und startbytecounter über Buffer2-> in page 0
writeBuffer(FirstStartByte,BUF2_WRITE,data.counters);
//Schreiben der Counter
SPI_WriteBuffer((void*) &data.counters, sizeof (data.counters));
writePage(FirstPage,
(MAX_NO_STRUCT-1)*sizeof(SPIDataBlock),BUF2_TO_MAIN_MEMORY_W_ERASE,data)
;
//Schreiben der Daten an den ermittelten freien Speicherbereich über
Buffer1
writeBuffer(FirstStartByte,BUF1_WRITE,data.values);
//Schreiben des Messdatenblocks
SPI_WriteBuffer((void*) &data.values, sizeof (data.values));
writePage(PageCounter, StartByteCounter, BUF1_TO_MAIN_MEMORY_W_ERASE,
data);
und so sehen die einzelnen funktionen aus:
void writeBuffer(unsigned short startbyte,unsigned short
opcode,SPIDataBlock data)
{
unsigned int adressfeld[3];
//startbyte im buffer
startbyte &= 0x03FF; // 0x03FF->
auf 10 bits beschränkt
/* in Buffer über SPI*/
adressfeld[0] = (unsigned char) 0x00; // 8 der 14
don't care bits
adressfeld[1] = (unsigned char) (startbyte >> 8) | 0x00; // die
restlichen 6 don't care bits + 2 der 10 bits des Startbytes
adressfeld[2] = (unsigned char) (startbyte & 0x00FF); // die
restlichen 8 Bits des Startbytes;
SPI_CS_FLASH ~= (1<<SPI_CSB); // CSB auf
S0SPDR = opcode; //BUF1_WRITE; // Opcode
(0x84) ausgeben(Kommando an SPI Bus)
while (!(S0SPSR & (SPI_SPIF))); // Warten
bis Daten gesendet
unsigned char k;
for (k=0; k<3; k++)
{
S0SPDR = adressfeld[k]; // Daten an
while (!(S0SPSR & (SPI_SPIF))); // Warten
bis
}
}
SPI_WriteBuffer(const void* data, const unsigned int length)
{
unsigned int n = 0;
for (n = 0; n < length; n++) //Schleife für
{
unsigned char byte = (unsigned char) (data [n]); //Byte aus Speicher
SOSPDR = byte;
while (!(S0SPSR & (SPI_SPIF))); // Warten bis
Daten
SPI_CS_FLASH |= (1<<SPI_CSB); //CSB auf 1
}
Hast du das gestern ung so gemeint oder hab ich dich bisschen
missverstanden?
Grüße
Am Ende von SPI_WriteBuffer fehlt aber noch eine Klammer zu } . Und wo
kommt das "SPI_CS_FLASH |= (1<<SPI_CSB);" da her ... ? SPI_WriteBuffer
sollte ja eigentlich nur Bytes über SPI übermitteln, und keine
Steuerbefehle, die müssten dann eigentlich in die aufrufenden
Funktionen.
Die Schleife am Ende von writeBuffer würde ich rausnehmen und durch
SPI_WriteBuffer ((void*) &addressfeld, sizeof (addressfeld)); ersetzen.
Und writeBuffer braucht ja den Parameter "SPIDataBlock data" gar nicht
mehr.
Aber ansonsten sieht das ganz gut aus.
PS: Wenn du C-Code postest, schreib davor
ein [ c ] und danach ein [ /c ] (natürlich ohne die Leerzeichen) - es
steht auch über dem Text-Eingabefeld unter "Formatierung".
>Und wo kommt das "SPI_CS_FLASH |= (1<<SPI_CSB);" her?
Das soll sagen das dir Übertragung abgeschlossen ist. Ja stimmt, seh
grad selber das es an der falschen Stelle steht, aber wüsste nicht wohin
wenn ich das SPI_WriteBuffer ((void*) &addressfeld, sizeof
(addressfeld)); auch schreibe.
oder müsste das SPI_CS_FLASH |= (1<<SPI_CSB);" eher nach den
Funktionsaufrufen stehen?
Du könntest ja eine Funktion "endTransfer" machen, die nur "SPI_CS_FLASH
|= (1<<SPI_CSB);" enthält; diese kannst du dann immer direkt nach
SPI_WriteBuffer aufrufen. Oder eben nicht - wenn du die Schleife am Ende
von writeBuffer ersetzt durch SPI_WriteBuffer, brauchst du es da ja
offenbar nicht.
Bei der Funktion endTransfer muss man nicht übergeben oder?Ich glaub
sonst müsste es mit dem in den Buffer reinschreiben klappen oder siehst
du noch irgendwelche offensichtliche Fehler?
grüße
Hab es eigentlich nicht so egnau auf das flash bezogen, eher auf die
Schreibweise. Aber das mit dem endTransfer kann ich schon so
machen,oder?
Muss jetzt mal die read Funktion schreiben. Das mach ich ja dann mit dem
->,oder?Also da wo ich *data.batterymode geschrieben hab, einfach den
Punkt durch -> ersetzen.
Hat das mit dem pfeil eigentlich irgendwas mit der dynamischen
Speicherplatz Reservierung zu tun?Oder bin ich da mit meiner Vermutung
auf dem falschen Weg?
Steff wrote:
> Aber das mit dem endTransfer kann ich schon so> machen,oder?
Ja. Probier es einfach aus: Ein Compilerlauf kostet nichts.
> Muss jetzt mal die read Funktion schreiben. Das mach ich ja dann mit dem> ->,oder?Also da wo ich *data.batterymode geschrieben hab, einfach den> Punkt durch -> ersetzen.
Ja.
> Hat das mit dem pfeil eigentlich irgendwas mit der dynamischen> Speicherplatz Reservierung zu tun?Oder bin ich da mit meiner Vermutung> auf dem falschen Weg?
Nein, hat es nicht. Das ist einfach nur eine Pointerdereferenzierung
(http://de.wikipedia.org/wiki/Dereferenzieren#Zeigeroperationen).
Bei der dynamischen Speicherreservierung werden Zeiger verwendet, daher
wird man dort oft auf -> treffen. Aber -> ist nicht darauf beschränkt.
Hab ja die 3 funktionsaufrufe mit:
[c]
// Schreiben des Messdatenblocks
SPI_WriteBuffer((void*) &(data.values), sizeof (data.values));
// Schreiben der counter
SPI_WriteBuffer((void*) &(data.counters), sizeof (data.counters));
// Schreiben der adressfelder
SPI_WriteBuffer((void*) &adressfeld, sizeof (adressfeld))
[c/]
Wie sieht denn dazu der prototyp aus, der in die Header kommt?
Sind beim compilieren schonmal weniger Fehler. Wenn ich das mit den
Pfeilen noch abändere, dann noch weniger
Könnte ich das eigenlich auch so schreiben?
void SPI_WriteBuffer (const void* data, const unsigned int length);
weil es sonst bisschen komisch aussieht, hab sonst noch nirgends das
const size_t length geschrieben.
Bei den anderen funktionen, wie:
writeBuffer(FirstStartByte,BUF2_WRITE,data.counters);
writePage(FirstPage,
(MAX_NO_STRUCT-1)*sizeof(SPIDataBlock),BUF2_TO_MAIN_MEMORY_W_ERASE,data)
;
ists mir auch nicht so ganz klar wie die aussehen sollen.
Weil bei den vielen Strukturen ineinander weiß ich nicht genau wie man
das dann schreibt
Steff wrote:
> Könnte ich das eigenlich auch so schreiben?> void SPI_WriteBuffer (const void* data, const unsigned int length);>> weil es sonst bisschen komisch aussieht, hab sonst noch nirgends das> const size_t length geschrieben.
Wahrscheinlich könntest du, ja. Aber vielleicht weiß dein Compiler ja,
dass der Controller keine 4 GB RAM hat, und definiert size_t als 2-Byte
Wert. Das size_t ist auch eher für PC-Anwendungen gedacht; falls das
Programm mehr als 4 GB ansprechen können soll, definiert man size_t als
64bit-Wert, und muss nicht alles ändern. Ich hab da jetzt
gewohnheitsmäßig size_t hingeschrieben, aber wenn es dir nicht gefällt,
kannst du auch unsigned int oder vermutlich auch unsigned short
schreiben. size_t dient halt der Portabilität, aber die hast du ja wegen
des direkten SPI-Register-Zugriffs sowieso nicht.
> Bei den anderen funktionen, wie:> writeBuffer(FirstStartByte,BUF2_WRITE,data.counters);>> writePage(FirstPage,> (MAX_NO_STRUCT-1)*sizeof(SPIDataBlock),BUF2_TO_MAIN_MEMORY_W_ERASE,data) ;>> ists mir auch nicht so ganz klar wie die aussehen sollen.> Weil bei den vielen Strukturen ineinander weiß ich nicht genau wie man> das dann schreibt
Genauso wie vorher, nur bei writeBuffer statt SPIDataBlock* musst du
halt counters* schreiben. Und writePage wurde ja gar nicht verändert.
Du hast ja geschreiben:
>Genauso wie vorher, nur bei writeBuffer statt SPIDataBlock* musst du>halt counters* schreiben. Und writePage wurde ja gar nicht verändert.
was macht man denn dann mit dem values?
Übergeb ja in writeBuffer nur writeBuffer(FirstStartByte,BUF2_WRITE);
Übergebe in Test.c über die Funktion writeSPIBlock(spiData); die Daten,
also ohne die pagecounter und startbytecounter.
spiData beschreibe ich wiefolgt:
spiData.battery_status=isOverChargedAlarm | isTerminateChargeAlarm
Passt die beschreibung, oder muss da noch .values rein?
In Test.c hab ich die Struktur so definiert:SPIDataBlock spiData;
In at45db.c ruf ich die Funktion wieder auf mit void
writeSPIBlock(SPIDataBlock data). Das kann aber nicht stimmen,oder?
Hallo
Schreib ja in der Funktion um das Flash auszulesen folgenden code:
void ReadDataFromFlash(unsigned short page,unsigned short startbyte,
unsigned short opcode,SPIDataBlock* data)
.
.
.
data->battery_mode = (S0SPDR << 8);
while (!(S0SPSR & (SPI_SPIF)));
data->battery_mode |= S0SPDR;
while (!(S0SPSR & (SPI_SPIF)));
Dieser Block kommt ja dann noch 15 mal für die anderen messwerte. Wie
kann man das denn so machen wie beim buffer beschreiben das man eine
allgemeine funktion hat und den Block nur einmal schreiben zu müssen?
Oder geht das in diesem Fall garnicht?
Grüße
Mach die SPI_ReadBuffer-Funktion ganz genauso wie die
SPI_WriteBuffer-Funktion, nur ohne das "const" bei "void* data" und
natürlich musst du die Daten aus dem SPI-Register nach "data [n]"
kopieren, anstatt umgekehrt.