Hallo Zusammen! Ich habe in meinem Programm in einem Header ein ca. 6kbyte Array gespeichert. Direkt ins Flash also so: const uint8_t rawData[7668] PROGMEM = {...} In meinem main will ich nun verschiedene Werte abfragen, was sich etwas schwierig gestaltet. Wenn ich nun rawData[1] verwende, so kann ich diesen Wert auslesen. Wenn ich z.B. rawData[x] verwende und x in meinem Hauptprogramm deklariere (globale Variable), so funktioniert der Zugriff nicht. Wenn ich in meinem Header diese Zeile einfüge: prog_uint16_t x = 0; Dann funktioniert zwar der Zugriff aus dem Main, allerdings hat ein x++, Beispielsweise kein Ereignis zur Folge. Was mich also interessieren würde, wie kann ich eine Variable, die im Flash gespeichert ist überschreiben? Ich hoffe das Problem ist verständlich erklärt. Gruss
Electronics'nStuff schrieb: > Was mich also interessieren würde, wie kann ich eine Variable, die im > Flash gespeichert ist überschreiben? Gar nicht. ROM = Read Only Memory. mfg.
> prog_uint16_t x = 0; > Dann funktioniert zwar der Zugriff aus dem Main, allerdings hat ein x++, > Beispielsweise kein Ereignis zur Folge. Ist ja logisch, ein Pointer im Programm Speicher ist read-only. b=rawData[x] Addiert x zum Pointer auf rawdata. Dann wird die RAM(!) Zelle gelesen, auf die der Pointer Zeigt. Die Daten liegen aber gar nicht im RAM. Lies Dir mal diese Seite durch: http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html Für den Zugriff auf dem Programmspeicher brauchst Du die dort beschriebenen Funktionen.
Thomas Eckmann schrieb: > Electronics'nStuff schrieb: >> Was mich also interessieren würde, wie kann ich eine Variable, die im >> Flash gespeichert ist überschreiben? > Gar nicht. > ROM = Read Only Memory. > > mfg. Das ist nicht richtig. --- Schau' im Datenblatt deines Controllers in das Kapitel "Flash Programming". Bei einigen Controllermn ist es möglich aus der Anwendung den Flashspeicher zu verändern. Ist aber nur sinnvoll für seltene Änderungen, da der Flash-Speicher z. B. nur 10.000 mal neu beschrieben werden kann.
Hmm.. Also wenn ich das so habe: const uint8_t rawData[7668] PROGMEM = {..}; uint16_t y = 0; uint16_t x = 0; spalte1[x] =pgm_read_word(rawData[y]); Dann bekomme ich in spalte1[x] eig. nur Schrott. Wie muss ich die Variable y deklarieren? Mit dem ROM habt ihr natürlich recht, aber wohin kommt die dann? Gruss
Electronics'nStuff schrieb: > EDIT: > > sollte natürlich heissen: > > spalte1[x] =pgm_read_byte(rawData[y]); spalte1[x] =pgm_read_byte(rawData + y);
Electronics'nStuff schrieb: > spalte1[x] =pgm_read_byte(rawData[y]); pgm_read_byte braucht eine Adresse:
1 | spalte1[x] =pgm_read_byte(&rawData[y]) |
Bitte nochmal das hier: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29 durcharbeiten.
Quatschkopf schrieb: > spalte1[x] =pgm_read_byte(rawData + y); Wow, super, danke! Ehrlich gesagt habe ich aber keine Ahnung was das für ein Unterschied macht? Kann ich das irgendwo nachlesen? Diese Schreibweise habe ich nämlich noch nie gesehen. Gruss & nochmals Danke!
Electronics'nStuff schrieb: > Quatschkopf schrieb: >> spalte1[x] =pgm_read_byte(rawData + y); > > Wow, super, danke! > Ehrlich gesagt habe ich aber keine Ahnung was das für ein Unterschied > macht? > > Kann ich das irgendwo nachlesen? In jedem noch so grindigem C-Buch
Electronics'nStuff schrieb: > Quatschkopf schrieb: >> spalte1[x] =pgm_read_byte(rawData + y); > Kann ich das irgendwo nachlesen? Diese Schreibweise habe ich nämlich > noch nie gesehen. Dann wird's aber Zeit. Das heisst Pointerarithmetik.
Quatschkopf schrieb: > Das ist nicht richtig. Das ist zu 100% richtig. Das ist und bleibt ein ROM. Völlig unabhängig davon, ob man das mit irgendeinem Verfahren löschen und neu beschreiben kann. Funktioniert das: i++? Nein. Also Nur Lesen. mfg.
Electronics'nStuff schrieb: > Quatschkopf schrieb: >> spalte1[x] =pgm_read_byte(rawData + y); > > Wow, super, danke! > Ehrlich gesagt habe ich aber keine Ahnung was das für ein Unterschied > macht? der Name eines Arrays für sich alleine steht für seine Startadresse. D.h. du nimmst rawData die Startadresse von rawData im Speicher rawData + y und zählst da noch dazu, wieviele Array- Elemente die Adresse weiter gesetzt werden soll -> Ergebnis: du hast die Speicheradresse an der das y-te Element von rawData gespeichert ist. Und diese Adresse übergibst du an pgm_read_byte, welches das dort gespeicherte Byte besorgt und liefert. Die Indexoperation ist in C so definiert a[i] <==> *( a + i ) d.h. das unterscheidet sich nur dadurch, dass nach der Adressberechnung durch den * dann auch gleich noch der Wert geholt wird. Was ja auch sinnvoll ist, in j = a[i]; denn da will man ja den Wert haben und in j speichern. Nur bei dir geht das natürlich nicht, weil ja der * den Wert aus dem SRAM holen würde, deine Daten aber nicht im SRAM sind sondern im Flash. D.h. du musst die ganze Operation j = a[i]; 2-teilen. Da a[i] identisch ist zu *(a+i) und du den * durch einen Aufruf der Funktion pgm_read_byte ersetzen musst, ergibt sich ganz zwanglos j = pgm_read_byte( a + i ); Das pgm_read_byte übernimmt ganz einfach den Part der Dereferenzierung. Alternativ hätte man auch j = pgm_read_byte( &a[i] ); schreiben könnnen. Wenn man das auflöst, dann zeigt sich, dass auch das wieder auf dasselbe hinausläuft, denn & und * sind komplementäre Operationen. Ein &(*(a+i)) ist dasselbe wie a+i Wie gesagt: In jedem noch so grindigem C-Buch, wenn es um Arrays geht und wie die intern behandelt werden. Das ist nämlich wichtig, weil es auch reinspielt, wie eigentlich Arrays an Funktionen übergeben werden. Und natürlich hängt damit aufs Engste auch das ganze Kapitel Pointerarithmetik zusammen. wenn dir also bei const uint8_t a[20] PROGMEM = {...} j = pgm_read_byte( a + i ); nicht auf Anhieb klar ist, was bei den Funtkionsargumenten passiert, dann hast du ein enormes Defizit in deinem C-Sprachverständnis. Und das musst du beheben! Mit dem Durcharbeiten eines C-Buchs.
Thomas Eckmann schrieb: > Quatschkopf schrieb: >> Das ist nicht richtig. > Das ist zu 100% richtig. > Das ist und bleibt ein ROM. Völlig unabhängig davon, ob man das mit > irgendeinem Verfahren löschen und neu beschreiben kann. > Funktioniert das: i++? Nein. Also Nur Lesen. > > mfg. Du hast geschrieben: Zitat (siehe Beitrag "Re: PROGMEM Problem"): "Gar nicht." Und das ist falsch!
Quatschkopf schrieb: > Du hast geschrieben: Zitat (siehe > Beitrag "Re: PROGMEM Problem"): > > "Gar nicht." > > Und das ist falsch! Man kann auf fast allem solange auf Details rumreiten, bis die Erklärung niemandem mehr hilft. Für seine Zwecke, in seinem Programm, ist das Flash ein ROM und nicht beschreibbar. Lies dir mal das durch und sieh dir das Video an. http://scienceblogs.de/astrodicticum-simplex/2013/03/02/die-tyrannei-der-prazession-behindert-die-wissenschaftskommunikation/ In vielen, wenn nicht den meisten Fällen, ist einem Schüler mehr geholfen, wenn man erst mal mit einer vereinfachten Sicht der Dinge an das Problem rangeht. Selbst dann, wenn das nicht 100% präzise ist.
@ Karl Heinz, vielen Dank für deine sehr ausführliche Erklärung! Karl Heinz Buchegger schrieb: > a[i] <==> *( a + i ) Karl Heinz Buchegger schrieb: > rawData die Startadresse von rawData im Speicher Das sind die zwei Dinge, die ich einfach nicht wusste. Gruss
Quatschkopf schrieb: > Und das ist falsch! Ich habe dir doch schon mitgeteilt, daß es zu 100% richtig ist. Man kann im Flash keine Variablen überschreiben, sondern nur im RAM. 1. gibt es im Flash keine Variablen 2. muss die Speicherstelle erst gelöscht werden und kann dann neu beschrieben werden. Du versuchst hier Zusammenhänge herzustellen, die einfach nicht existieren. mfg.
Electronics'nStuff schrieb: > @ Karl Heinz, vielen Dank für deine sehr ausführliche Erklärung! > > Karl Heinz Buchegger schrieb: >> a[i] <==> *( a + i ) > > Karl Heinz Buchegger schrieb: >> rawData die Startadresse von rawData im Speicher > > Das sind die zwei Dinge, die ich einfach nicht wusste. Und genau das musst du abstellen. Denn das erste ist der Grund dafür, warum man in C schreiben kann
1 | int* a = malloc( anzahl * sizeof(int) ); |
2 | |
3 | a[i] = 5; // a[i] <--> *(a+i) a ist ein Pointer |
4 | // der Rest ist Pointerarithmetik (+)
|
5 | // bzw. Dereferenzierung (*)
|
und das zweite ist der Grund dafür, warum
1 | void foo( int* k ) |
2 | {
|
3 | k[0] = 8; |
4 | }
|
5 | |
6 | int main() |
7 | {
|
8 | int a[5]; |
9 | |
10 | foo( a ); // a ist die Startadresse des Arrays |
11 | // und foo will eine Adresse haben - passt also
|
12 | }
|
genau so funktioniert, wie es funktioniert. Das sind also ziemliche Basis-Dinge in C, sobald man mit Arrays arbeitet.
Karl Heinz Buchegger schrieb: > Das sind also ziemliche Basis-Dinge in C, sobald man mit Arrays arbeitet. Ich muss zugeben, ich habe Arrays bis jetzt nur sehr oberflächlich benutzt und noch nie für grössere Datenmengen. Bis jetzt habe ich sie eig. ausschliesslich für Ausmaskierungen etc. verwendet. Also zwei, drei Werte und gut ist. Ein gutes Buch wäre allerdings bestimmt nicht verkehrt!
Electronics'nStuff schrieb: > Ein gutes Buch wäre allerdings bestimmt nicht verkehrt! Allerdings. Denn das ist nur die Spitze des Eisbergs (wenn auch ein sehr wichtiger). Da wartet noch vieles darauf entdeckt zu werden.
@ Electronics'nStuff (Gast) >Ist es korrekt, dass der Zugriff auf's Flash vehältnismässig eeeewig >dauert? Nö. Beim Lesen 3 Takte, RAM-Zugriffe brauchen 2. Schreiben dauert natürlich eher lang, im Bereich von einigen Millisekunden pro Page.
Nö. Da im Flash auch das Programm liegt, wird darauf mit voller Prozessorgeschwindigkeit zugegriffen. Die avrlib Routinen (z.B. 'pgm_read_byte()') dauern ein klein wenig, aber kannste eigentlich vergessen. EEPROM ist eigentlich das langsamste wegen der ganzen Registervorbereitung.
Ob es wohl sonst einen Grund gibt, dass:
1 | int result; |
2 | result = spalte_nr/2; |
3 | y = y + result; |
4 | |
5 | while (spalte_position < 60) |
6 | {
|
7 | if(result*2 != spalte_nr) //ungerade zahlen |
8 | {
|
9 | zifferh = (pgm_read_byte(rawData + y)) % 16; |
10 | spalte[spalte_position] = zifferh; |
11 | }
|
12 | |
13 | if (result*2 == spalte_nr) //gerade zahlen |
14 | {
|
15 | spalte[spalte_position] = ((pgm_read_byte(rawData + y))-(zifferh)) /16; |
16 | }
|
17 | |
18 | spalte_position++; |
19 | y = y +128; |
20 | }
|
21 | |
22 | spalte_position= 0; |
knapp 220µs dauert bei einer Taktrate von 8Mhz?
@ Electronics'nStuff (Gast) >knapp 220µs dauert bei einer Taktrate von 8Mhz? Messfehler? DIV 8 Fuse gesetzt? AVR Fuses falsch eingestellt?
@ Matthias Sch. (Firma: Matzetronics) (mschoeldgen) >Prozessorgeschwindigkeit zugegriffen. Die avrlib Routinen (z.B. >'pgm_read_byte()') dauern ein klein wenig, Nö, das sind schon lange INLINE Funktionen.
Falk Brunner schrieb: > Messfehler? DIV 8 Fuse gesetzt? AVR Fuses falsch eingestellt? DIV 8 kann ich definitiv ausschliessen. Ist zwar der interne Oszillator aber der sollte ja wohl trotzdem so um die 8MHz haben. Messfehler? Hmm.. habe einfach einen Pin getoggelt am Anfang und am Ende des Programms.. mit DSO gemessen (das ist eig. ziemlich genau sonst). Gruss
@ Electronics'nStuff (Gast) >Hmm.. habe einfach einen Pin getoggelt am Anfang und am Ende des >Programms.. Togglen kann schief gehen, dann misst man Mist. Du must definert am Anfang setzen und am Ende löschen.
Jo, ist eingestellt. Das Array aus dem Flash habe ich über einen Header eingebunden, das sollte eig. keinen Einfluss haben nehme ich an?
> knapp 220µs dauert bei einer Taktrate von 8Mhz?
Welchen Wert hat "spalte_position"?
Electronics'nStuff schrieb: > Das Array aus dem Flash habe ich über einen Header eingebunden, das > sollte eig. keinen Einfluss haben nehme ich an? Das ist egal. Electronics'nStuff schrieb: > knapp 220µs dauert bei einer Taktrate von 8Mhz? Für die ganze Schleife? Ein Durchlauf ca. 30 Takte. Finde ich bei der Rechnerei da drin nicht so erstaunlich. mfg.
Harun schrieb: > Welchen Wert hat "spalte_position"? Wird von 0-60 heraufgezählt also ein 60 Durchläufe. Thomas Eckmann schrieb: > Ein Durchlauf ca. 30 Takte. Finde ich bei der Rechnerei da drin nicht so > erstaunlich. Dauert die echt so lange? Gibt es da noch was einfacheres? Ich will z.B. aus 0xBE zwei Variabeln kreieren -> 0x0B und 0x0E. Funktioniert auf diese Weise ohne Probleme aber geht es auch einfacher? Gruss
> Wird von 0-60 heraufgezählt also ein 60 Durchläufe. Kein Wunder. > Gibt es da noch was einfacheres? Da ungerade & gerade immer nacheinander folgen: Ja.
Harun schrieb: > Da ungerade & gerade immer nacheinander folgen: Ja. Tut mir leid, daraus werde ich nicht ganz schlau?
Electronics'nStuff schrieb: > Dauert die echt so lange? Das ist das, was du gemessen hast. Electronics'nStuff schrieb: > Ich will z.B. aus 0xBE zwei Variabeln kreieren -> 0x0B und 0x0E. Das verstehe ich jetzt nicht so ganz. mfg.
Naja.. ich habe in meinem Array (rawData) lauter 8-Bit "Worte" in hex gespeichert. Also irgendwie 0x45, 0xBE, 0x75 etc.. ich möchte diese nun umwandeln. Im Array spalte[] sollen die gleichen Werte vorkommen, allerdings "aufgeteilt". Also so: 0x45 -> 0x04 und 0x05 0xBE -> 0x0B und 0x0E 0x75 -> 0x07 und 0x05 Ich will quasi die 8-Bit Worte einfach auftrennen und dann in meinem Array unterbringen. Gruss
Electronics'nStuff schrieb: > Ich will quasi die 8-Bit Worte einfach auftrennen und dann in meinem > Array unterbringen. Also aus rawdata[0] = 0x45 soll spalte[0] = 0x04 und spalte[1] = 0x05 werden? mfg.
Electronics'nStuff schrieb: > Ich will quasi die 8-Bit Worte einfach auftrennen und dann in meinem > Array unterbringen. Dafür hast du dieses Monster PROGMEM aufgezogen? Glaub ich jetzt mal nicht.
1 | spalte[0] = (rawdata[0] >> 4) & 0x0f; |
2 | spalte[1] = rawdata[0] & 0x0f; |
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.