Hallo allerseits, mal eine Frage bezüglich Datenloggern. Es sollen eine Menge Daten in einem Array aufgenommen werden. Dieses muss wohl, da die Daten durch 10bit AD-Wandlung gewonnen werden, Fächergrößen von 16 Bit haben, also uint16_t. Erzeugen würde ich es durch folgenden Code: #define SPEICHERGROSSE 1000 uint16_t *Speicher; uint16_t* Speicher_init() { Speicher = (uint16_t*) malloc(SPEICHERGROSSE* sizeof(uint16_t)); return *Speicher; } Ist es möglich, die übrigen 6 leeren Bits später dann noch zu belegen? Außerdem noch eine weitere Frage: Das Array soll Daten im RAM-Speicher aufnehmen. Das bedeutet doch, dass ich es zwangsläufig erst zur Laufzeit mittels malloc erzeugen darf, und ich nicht zu Beginn ein schön großes fixes Array anlegen kann, oder?
> Ist es möglich, die übrigen 6 leeren Bits später dann noch zu belegen? Ja. > Das bedeutet doch, dass ich es zwangsläufig erst zur Laufzeit mittels >malloc erzeugen darf Nein.
Wie stellst Du Dir das vor ? Ich würde eher die Gesamtgrösse verkleinern : ceil (1000 *16 /10) Und dann mit Modulo und Rest die benötigten bits aus den, dann meistens zwei uint16_t Werten herausmaskieren und verschieben. Du benötigst natürlich dann für lesen und schreiben in das array funktionen die die adresse und Wert entsprechend übersetzten.
Großes Fragezeichen schrieb: > ich es zwangsläufig erst zur Laufzeit mittels malloc erzeugen darf, und > ich nicht zu Beginn ein schön großes fixes Array anlegen kann, oder? Doch, genau das willst du tun: Ein schönes großes fixes Array benutzen. Denn: Du hast nur den Speicher den du hast. Da hilft dir auch malloc nichts. Maximal kriegst du also vom malloc auch nur den Speicher, den du in ein großes fixes Array buttern könntest. Im besten Fall. Im schlimmsten Fall kriegst du nämlich weniger, nämlich dann wenn der Speicher durch mehrere malloc fragmentiert ist. Und dann erhebt sich natürlich noch die Frage, was soll denn der Datenlogger machen, wenn er vom malloc keinen Speicher mehr kriegt? Da ist es besser für fixe Verhältnisse zu sorgen. Du dimensionierst dein Array auf 1000 Elemente und wenn die als ganzes in den Speicher passen, dann hast du auch 1000 Elemente.
Hallo, also zu deiner ersten Frage, ja es wäre noch möglich die restlichen 6 Bit zu belegen, aber dafür muss man ein wenig mehr aufwand betreiben. Kannst ja mal Google mit dem Stichwort Bitmaskierung bemühen. Ich weiss jetzt nicht wie der Speicher genau von einem Mikrocontroller verwaltet wird, aber den dynamischen Speicher nimmt man in der Regel wenn man dyanmischen Speicher brauch. Also wenn immer die selbe Menge an Daten anfallen oder dieser stark begrenzt ist nimm einen statischen Speicher. Als kleinen leckerbissen kann ich dir noch eine Funktion geben die ich mal geschrieben hatte. Sie funktionierte unter Visual Studio 6.0 wie es auf einem Mikrocontroller aussieht weiss ich nicht, kannst es ja mal versuchen. Ich möchte noch drauf hinweisen das in dieser Funktion mächtig getrickst wurde und man es normalerweise so nicht macht ;-) // erstellen und verändern eines 1 Dimensionalen Arrays void* onedimmem(void *array,int size) { void *arraytemp; // Freigeben des reservierten Speichers if(size==0) { free(array); return NULL; } arraytemp = (void *)realloc(array,size); if(arraytemp == NULL) { printf("Die Zuweisung des Speicherplatzes war nicht erfolgreich\n"); free(array); return NULL;; } array = arraytemp; return array; } Aufruf zum beispiel so: *pressure = NULL; //Deklaration pressure=(double*)onedimmem(pressure,3 * sizeof(double)); //speicher anlegen pressure=(double*)onedimmem(pressure,6 * sizeof(double)); //Grösse verändern, der Vorteil bei dieser Methode ist das der Speicherinhalt bestehen bleibt pressure=(double*)onedimmem(pressure,0); //Speicher Freigeben Hoffe dir ein wenig geholfen zu haben. Gruß BlabLa
Bei der Deklaration fehlt ein Double vor dem Variablen namen, also double *pressure = NULL; //Deklaration Gruß BlabLa
Karl heinz Buchegger schrieb: > Im schlimmsten Fall kriegst du nämlich weniger, nämlich dann wenn der > Speicher durch mehrere malloc fragmentiert ist. Das ist etwas missverständlich formuliert. Wenn du 1.000 Elemente anforderst, kriegst du die entweder komplett oder du kriegst garnichts (malloc retourniert 0). Dass du weniger als 1.000 Elemente bekommst - weil malloc vielleicht nur 389 Elemente zusammenkratzen konnte - das wird nicht passieren. Und wenn doch, dann ist es keine Standard-C-Lib.
Hi, verwende doch einfach Bit fields in einem struct. Mit dem struct kannst dann ein Array anlegen, und den 10 bit member dereferenzieren. Die restlichen 6 bits definierst Du entweder als anonym, oder belegst es gleich mit nem Namen - wie mit den 10 bits vorher. also etwa:
1 | struct sTest |
2 | {
|
3 | uint16_t adc : 10; |
4 | uint8_t rest: 6; |
5 | };
|
6 | |
7 | struct sTest saArray[32]; |
zum Zugreifen dann:
1 | b = saArray[n].adc |
Siehe http://en.wikipedia.org/wiki/C_syntax#Bit_fields Mfg Sascha Warner
swarner schrieb: > verwende doch einfach Bit fields in einem struct. Mit dem struct kannst > dann ein Array anlegen, und den 10 bit member dereferenzieren. Die > restlichen 6 bits definierst Du entweder als anonym, oder belegst es > gleich mit nem Namen - wie mit den 10 bits vorher. Das musst du mir jetzt erklären. Was versprichst du dir davon? Damit kriegst du in 1000 Array Elemente doch wieder nur 1000 Datensätze unter.
besucher schrieb: > Karl heinz Buchegger schrieb: >> Im schlimmsten Fall kriegst du nämlich weniger, nämlich dann wenn der >> Speicher durch mehrere malloc fragmentiert ist. > > Das ist etwas missverständlich formuliert. In der Tat. Danke für die Klarstellung
Du bekommst nur 1000 Datensaetze unter, kannst aber den .rest noch fuer was anderes verwenden, auch wenns nur 6 Bit sind. mit einer speziellen "Accessor" Funktion kannst da allerdings noch etwas dran rumbasteln, und 8 bits reinmappen (in entsprechend mehrere aufeinanderfolgende Arrayindizes). Das struct machts halt etwas einfacher auf die Elemente zuzugreifen. Das ist alles :)
swarner schrieb: > Du bekommst nur 1000 Datensaetze unter, kannst aber den .rest noch fuer > was anderes verwenden, auch wenns nur 6 Bit sind. Im Prinzip ja. Aber der TO hat ja nicht das Problem, dass er noch Zusatzinfo mit abspeichern muss. > mit einer speziellen > "Accessor" Funktion kannst da allerdings noch etwas dran rumbasteln, und > 8 bits reinmappen (in entsprechend mehrere aufeinanderfolgende > Arrayindizes). Das struct machts halt etwas einfacher auf die Elemente > zuzugreifen. Das ist alles :) In dem Fall, in dem du die 10 Bit aufeinanderfolgend ablegen willst, macht es die struct nicht wirklich einfacher. Eher komplizierter.
Sorry, ich dachte, es ginge darum, die restlichen 6 Bits doch noch fuer irgendwas nutzen zu koennen.
ok, erstmal sortieren... es ist also für mein Programm egal, ob ich schreibe: uint16_t *Speicher; uint16_t* Speicher_init() { Speicher = (uint16_t*) malloc(100*sizeof(uint16_t)); return *Speicher; } oder ob ich direkt folgendes tue: uint16_t Speicher[100]; Richtig ??? In beiden Varianten würde ich es ja durch eine Funktion der Art for(int i=0; i<100; i++) { Speicher[i]=ADC_Messung(); } beschreiben... ist es dann in beiden Varianten der RAM-Speicher, der gefüllt wird, obwohl der Mikrokontroller in Variante zwei fixen Speicher reserviert? mfg
>obwohl der Mikrokontroller in Variante zwei fixen Speicher reserviert?
Nein. In beiden Varianten wird Speicher im RAM reserviert.
Kein "fixer" Speicher. Damit könnte man sinngemäß etwa Speicher im
EEPROM oder Programmspeicher bezeichnen. Das aber ist hier nicht der
Fall.
Großes Fragezeichen schrieb: > ok, erstmal sortieren... > > es ist also für mein Programm egal, ob ich schreibe: > > uint16_t *Speicher; > uint16_t* Speicher_init() > { > Speicher = (uint16_t*) malloc(100*sizeof(uint16_t)); > return *Speicher; > } > > oder ob ich direkt folgendes tue: > > uint16_t Speicher[100]; > > Richtig ??? richtig. mit dem malloc riskierst du lediglich unvorhergesehen Probleme. Durch die statische Definition taucht der Platzbedarf für das Array in der Speicherstatistik des Compilers auf und du kannst abschätzen, ob du den Platz im Speicher überhaupt noch hast. Mit dem malloc weißt du nichts dergleichen. Da bügelst du dir einfach über den Stack drüber, ohne den geringsten Anhaltspunkt zu haben, warum dein Programm Amok läuft. > gefüllt wird, obwohl der Mikrokontroller in Variante zwei fixen Speicher > reserviert? In der Verwendung besteht kein Unterschied.
Warum nicht das Naheliegendste? Jeweils 4 Meßwerte entgegen nehmen (und in fünf unsigned char speichern). Von jedem der vier Meßwert die unteren 8 Bits in vier aufeinander folgende unsigned char speichern. Die jeweils oberen 2 Bit der vier Meßwerte schieben und in das fünfte unsigned char speichern. Fertig und jedes Bit genutzt!
Kann man das eventuel auch so mit struct machen?
1 | struct sTest |
2 | {
|
3 | uint16_t adc0 : 10; |
4 | uint16_t adc1 : 10; |
5 | uint16_t adc2 : 10; |
6 | uint16_t adc3 : 10; |
7 | };
|
8 | |
9 | struct sTest saArray[250]; |
Bastelmaus schrieb: > Kann man das eventuel auch so mit struct machen?struct sTest > { > uint16_t adc0 : 10; > uint16_t adc1 : 10; > uint16_t adc2 : 10; > uint16_t adc3 : 10; > }; > > struct sTest saArray[250]; Da wären ja bei jedem uin16 6bits nicht genutzt. Ich würde es wie einer da oben machen:
1 | struct ADC_DATA |
2 | {
|
3 | uint8_t data[5]; //Hier sind eigentlich nur 4 Werte gespeichert |
4 | void SetData(uint8_t index, uint16_t data); |
5 | uint16_t GetData(uint8_t index); |
6 | };
|
7 | |
8 | Das ist sogar relativ konfortabel. |
Ich finde ebenfalls Norberts Idee stark. Um spezielle Zugriffsfunktionen kommt man sowieso nicht rum. Aber Norberts Idee garantiert dir, dass du zumindest an das Low-Byte ohne Bitgefummel rankommst. Bitstrkturen. Da ist nur sehr wenig vorgegeben und der Compiler hat viele Freiheiten. Nicht vergessen sollte ausserdem, dass Bitfelder auch nur 'syntaktischer Zucker sind'. D.h. die C-Syntax sieht sauber aus. Unter der Haube muss der Prozessor aber nach wie vor das ganze Bitgefummel machen.
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.