Struct Array in bestimmten Speicherbereich ablegen



  • Jackson0 schrieb:

    Ich programmiere einen MC der nur 8KB RAM hat, die Speicheradresse 0xDF0000-0xDf3FFF ist die vom interem EEProm.

    Gut, dann sollte der zweite Vorschlag funktionieren.



  • Direkt dort anlegen kannst du es nicht, aber über einen Zeiger darauf zugreifen (wie im Beispiel von dachschaden)

    Achte aber auf (mögliche) Füllbytes in der struct.

    Zudem solltest du eher Typen aus der stdint.h nehmen, da du damit die Hardware besser abbilden kannst.



  • Ok, aber ich verstehe noch nicht ganz wie ich dann Zugriff auf die einzelnen Arrays bekomme bzw. wo die Eckigen Klammern hin gehören. Im RAM sieht das ja so aus:

    Setup_PPG PPG[255];
    x=PPG[5].Period
    

    Du schreibst:

    Setup_PPG*PPG = (Setup_PPG*)0xDF4000;
    

    Wie kann ich dann z. B. das [5] oder [155] Array auslesen?

    Ein weiteres Problem, ich bin mir noch nicht sicher wie ich überhaupt mehr wie zwei Bytes auslesen kann (16Bit MC/EEprom). Normal wird es nur so ausgelesen:

    unsigned short read_eeprom(unsigned short adr)
    {
          return (*(__far unsigned int*) (0xDF4000 + adr * 2));
    }
    


  • Jackson0 schrieb:

    Ok, aber ich verstehe noch nicht ganz wie ich dann Zugriff auf die einzelnen Arrays bekomme bzw. wo die Eckigen Klammern hin gehören.

    Das sind absolute Grundlagen.
    Kapitel Arrays und Zeiger.

    Jackson0 schrieb:

    Wie kann ich dann z. B. das [5] oder [155] Array auslesen?

    x=PPG[5].Period
    

    Ja, es ist so einfach

    Jackson0 schrieb:

    Ein weiteres Problem, ich bin mir noch nicht sicher wie ich überhaupt mehr wie zwei Bytes auslesen kann (16Bit MC/EEprom). Normal wird es nur so ausgelesen:

    unsigned short read_eeprom(unsigned short adr)
    {
          return (*(__far unsigned int*) (0xDF4000 + adr * 2));
    }
    

    Was willst du genau machen?
    Bei dem Konstrukt wird erst die Adresse ausgerechnet und dann dem Zeiger zugewiesen.
    Da wird die Pointerarithmetik umgangen.

    Aber wenn du da das __far unsigned brauchst, wirst du das auch beim Zeiger auf die struct benötigen.



  • Sorry ich bin noch Anfänger...

    Am besten so wie wenn die Daten im RAM liegen würden, und Auslesen mit:

    Period=PPG[x].Period
    Duty100=PPG[x].Duty100
    usw.
    

    Ich bekomme das nicht hin, habe versucht:

    Setup_PPG* PPG =  (Setup_PPG*) *(__far unsigned char*) 0xDF4000;
    

    Compiler sagt: E4032C: initialization: constant expression is expected for file scope variable: `PPG'

    Habe versuch 'const' vor PPG einzubauen, aber gibt dann Syntax Fehler...



  • Jackson0 schrieb:

    Sorry ich bin noch Anfänger...

    Dann solltest du dich gar nicht erst mal an die Programmierung eines MC wagen. Da kann dir die MMU deine größten Patzer nicht abfangen.

    Jackson0 schrieb:

    Compiler sagt: E4032C: initialization: constant expression is expected for file scope variable: `PPG'

    Lern doch erst einmal, wie man ordentlich Zeiger verwendet.
    Du machst *(__far unsigned char*) 0xDF4000; - das Sternchen am Anfang ist eine Dereferenzierung, sprich, dass du den WERT haben willst, der an 0xDF4000 liegt, und nicht einfach nur die Adresse. Der Compiler weiß nicht, was an 0xDF4000; liegt, aber für globale Variablen (file scope) brauchst du einen Wert, der sich NICHT ändern kann.

    Lass das Sternchen also weg. Und noch viel wichtiger, lern erstmal C ohne MC.



  • Danke, ich bin ja dabei es zu lernen. (learning by doing 😉 )

    Ich habe es Compiliert bekommen, aber funktioniert leider noch nicht:

    init:

    typedef struct  PPG_Setup_Data {	
        short Period;
        short Duty100;
        short Duty50;
        short Duty1;
    } Setup_PPG;
    
    // Setup_PPG PPG[255];
    Setup_PPG* PPG = (Setup_PPG*) (__far unsigned char*) 0xDF4000;
    

    main:

    Uart_SendString(debugUart,"\nErgebnis EEprom read:\n");
    	for(z=0; z<10/2; z++) {
    		Uart_SendString(debugUart,"Period=");
    		Uart_SendBin2Asci(debugUart,PPG[z].Period , DEC, '0',5);
    		Uart_SendString(debugUart,", Duty100=");
    		Uart_SendBin2Asci(debugUart,PPG[z].Duty100 , DEC, '0',5);
    		Uart_SendString(debugUart,"\n");
    	}
    

    Ausgabe:

    Ergebnis EEprom read:
    Period=00000, Duty100=00000
    Period=00000, Duty100=00000
    Period=00000, Duty100=00000
    Period=00000, Duty100=00000
    Period=00000, Duty100=00000
    

    Testdaten sind im EEProm drin das habe ich überprüft und wenn keine drin wären würde eh alles 0xFF sein.



  • PPG sollte (so wie ich es verstehe) auch ein far-Pointer sein,

    __far Setup_PPG * PPG = (Setup_PPG*) (__far unsigned char*) 0xDF4000;
    


  • Habe ich geändert, leider bleibt die Ausgabe gleich.



  • Sollte das nicht eher:

    __far Setup_PPG *PPG = (__far Setup_PPG*)0xDF4000;
    

    sein? Kannst du dir mal im Programm PPG ausgeben lassen (printf)?



  • Jackson0 schrieb:

    Habe ich geändert, leider bleibt die Ausgabe gleich.

    Willst du interne Register der MCU ansprechen, oder hast du irgendeine Hardware an den Bus gebastelt? Im ersten Fall sollte es im SDK eine .h-Datei mit lauter typedefs geben, die man dafür benutzen kann.

    Um welchen Controller handelt es sich? Nenn mal bitte die Bezeichnung.



  • Der Code von Dachschaden funktioniert schon etwas (oder ich habe noch Fehler im schreiben/lesen vom EEPROM)

    Ich habe jetzt insgesamt 12 Bytes per Array (im Testarray und EEprom einfach von 0-107 befüllt)

    // Test EEProm Daten							1  2  3  4  5  6  7  8  9  10 11 12
    volatile const unsigned char Test[9][12] = {	0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10,11,
    												12,13,14,15,16,17,18,19,20,21,22,23,
    												24,25,26,27,28,29,30,31,32,33,34,35,
    												36,37,38,39,40,41,42,43,44,45,46,47,
    												48,49,50,51,52,53,54,55,56,57,58,59,
    												60,61,62,63,64,65,66,67,68,69,70,71,
    												72,73,74,75,76,77,78,79,80,81,82,83,
    												84,85,86,87,88,89,90,91,92,93,94,95,
    												96,97,98,99,100,101,102,103,104,105,106,107
    };
    

    main:

    Uart_SendString(debugUart,"\nErgebnis EEprom read:\n");
    	for(z=0; z<10; z++) {
    		Uart_SendString(debugUart,"Channel=");
    		Uart_SendBin2Asci(debugUart,PPG[z].Channel , DEC, '0',5);
    		Uart_SendString(debugUart,", Status=");
    		Uart_SendBin2Asci(debugUart,PPG[z].Status , DEC, '0',5);
    		Uart_SendString(debugUart,", Strom=");
    		Uart_SendBin2Asci(debugUart,PPG[z].Strom , DEC, '0',5);
    		Uart_SendString(debugUart,", Period=");
    		Uart_SendBin2Asci(debugUart,PPG[z].Period , DEC, '0',5);
    		Uart_SendString(debugUart,", Duty100=");
    		Uart_SendBin2Asci(debugUart,PPG[z].Duty100 , DEC, '0',5);
    		Uart_SendString(debugUart,", Duty50=");
    		Uart_SendBin2Asci(debugUart,PPG[z].Duty50 , DEC, '0',5);
    		Uart_SendString(debugUart,", Duty1=");
    		Uart_SendBin2Asci(debugUart,PPG[z].Duty1 , DEC, '0',5);
    		Uart_SendString(debugUart,"\n");
          }
    

    Ausgabe jetzt:

    Ergebnis EEprom read:
    Channel=00000, Status=00001, Strom=00770, Period=01284, Duty100=01798, Duty50=02312, Duty1=02826
    Channel=00012, Status=00013, Strom=03854, Period=04368, Duty100=04882, Duty50=05396, Duty1=05910
    Channel=00012, Status=00013, Strom=03854, Period=04368, Duty100=04882, Duty50=05396, Duty1=05910
    Channel=00024, Status=00025, Strom=06938, Period=07452, Duty100=07966, Duty50=08480, Duty1=08994
    Channel=00024, Status=00025, Strom=06938, Period=07452, Duty100=07966, Duty50=08480, Duty1=08994
    Channel=00036, Status=00037, Strom=10022, Period=10536, Duty100=11050, Duty50=11564, Duty1=12078
    Channel=00036, Status=00037, Strom=10022, Period=10536, Duty100=11050, Duty50=11564, Duty1=12078
    Channel=00048, Status=00049, Strom=13106, Period=13620, Duty100=14134, Duty50=14648, Duty1=15162
    Channel=00048, Status=00049, Strom=13106, Period=13620, Duty100=14134, Duty50=14648, Duty1=15162
    Channel=00060, Status=00061, Strom=16190, Period=16704, Duty100=17218, Duty50=17732, Duty1=18246
    

    Die Shortwerte sind jetzt natürlich schlecht zu lesen da glaube ich auch noch verdreht 03 + 02 HEX Ergibt 770

    Zeile 1 würde ich mal sagen stimmt,
    Zeile 2 auch, weil der erste Wert im nächsten Array ist 12
    aber warum steht in Zeile 3 wieder als erstes 12
    Zeile 4 wäre eigendlich Zeile 3 (also erstes Byte Zeile1=0 Z2=12,Z3=24,z4=36,z5=48,usw.)

    hier noch die Write_EEprom:

    for (z=0;z<9;z++) {
    			write_eeprom((0+z*12),12,&Test[z]);	// Testwerte speichern
    		}
    
    unsigned char write_eeprom(unsigned short adr, unsigned short len, unsigned short *data);
    


  • Andromeda schrieb:

    Willst du interne Register der MCU ansprechen, oder hast du irgendeine Hardware an den Bus gebastelt? Im ersten Fall sollte es im SDK eine .h-Datei mit lauter typedefs geben, die man dafür benutzen kann.

    Um welchen Controller handelt es sich? Nenn mal bitte die Bezeichnung.

    Nein das ist das ein Bereich des interene Flashs der für sowas zu gebrauchen ist (8K je Sektor) Fujitsu FX16 Serie. Für die Dinger gibt es leider keine SDK's...



  • Jackson0 schrieb:

    Fujitsu FX16 Serie. Für die Dinger gibt es leider keine SDK's...

    Muss es geben. Du hast doch bestimmt ein Eval Board, ne? Von dem du das gekauft hast bekommst du sicherlich auch ein SDK.

    Ansonsten mal dort nachfragen: https://www.mikrocontroller.net



  • Wo kommt plötzlich PPG[z].Strom her? Oder PPG[z].Channel Das Feld finde ich nicht in deiner Anfangsdeklaration. Kann es sein, dass du da mit den Feldern durcheinandergekommen bist? DirkB hat dich bereits gewarnt, dass Padding-Bytes eingefügt werden könnten, die willst du eventuell nicht haben.



  • Die war zum Besseren Verständnis recht einfach gehalten, zu Anfang waren es 9 Bytes jetzt sind es 12 Bytes. Das Ändert ja nichts am Prinzip. Und die ersten beiden Zeilen werden ja auch richtig übertragen je 12 Bytes.

    typedef struct  PPG_Setup_Data {	// Länge 12 Byte
    	char Channel;
        char Status;	
        short Strom;
        short Period;
        short Duty100;
        short Duty50;
        short Duty1;
    } Setup_PPG;
    


  • Also:
    Du schreibst in den EEPROM, und willst dann gleich wieder auslesen, was du so geschrieben hast.

    Hast du mal die gegenwärtige Adresse, auf die &PPG[z] zeigt, ausgegeben? Nur um sicherzugehen, dass er auch wirklich in 12-Byte-Schritten durchläuft.

    Wenn das Lesen funktioniert, vielleicht geht dann beim Schreiben was schief:

    for (z=0;z<9;z++) {
        write_eeprom((0+z*12),12,&Test[z]); // Testwerte speichern
    }
    

    (0+z*12) kann auch direkt z * sizeof(Test[z]) geschrieben werden. Ansonsten: da wir nicht wissen, was in write_eeprom passiert, können wir dir auch nicht sagen, was in write_eeprom passiert. Irgendwie logisch.

    Hast du dir mal ausgeben lassen, ob (0 + z * 12) wirklich die Position liefert, die du haben willst?



  • also die Daten im EEProm sind defintiv richtig:

    Uart_SendString(debugUart,"\nErgebnis EEprom read:\n");
    	for(z=0; z<108; z++) {
    		read_eeprom(z);
    		Uart_SendBin2Asci(debugUart,z, DEC, '0',3);
    		Uart_SendString(debugUart,",");
    	}
    	Uart_SendString(debugUart,"\n");
    

    Ergibt:

    Ergebnis EEprom read:
    000,001,002,003,004,005,006,007,008,009,010,011,012,013,014,015,016,017,018,019,020,021,022,023,024,025,026,027,028,029,030,031,032,033,034,035,036,037,038,039,040,041,042,043,044,045,046,047,048,049,050,051,052,053,054,055,056,057,058,059,060,061,062,063,064,065,066,067,068,069,070,071,072,073,074,075,076,077,078,079,080,081,082,083,084,085,086,087,088,089,090,091,092,093,094,095,096,097,098,099,100,101,102,103,104,105,106,107,
    

    Also funktioniert der Write-Befehl korrekt.

    Ich habe mir auch mal die Mühe gemacht:

    for(z=0; z<10; z++) { 
            Uart_SendString(debugUart,"Channel="); 
            Uart_SendBin2Asci(debugUart,PPG[z].Channel , DEC, '0',5); 
            Uart_SendString(debugUart,", Status="); 
            Uart_SendBin2Asci(debugUart,PPG[z].Status , DEC, '0',5); 
            Uart_SendString(debugUart,", Strom="); 
            Uart_SendBin2Asci(debugUart,PPG[z].Strom , DEC, '0',5); 
            Uart_SendString(debugUart,", Period="); 
            Uart_SendBin2Asci(debugUart,PPG[z].Period , DEC, '0',5); 
            Uart_SendString(debugUart,", Duty100="); 
            Uart_SendBin2Asci(debugUart,PPG[z].Duty100 , DEC, '0',5); 
            Uart_SendString(debugUart,", Duty50="); 
            Uart_SendBin2Asci(debugUart,PPG[z].Duty50 , DEC, '0',5); 
            Uart_SendString(debugUart,", Duty1="); 
            Uart_SendBin2Asci(debugUart,PPG[z].Duty1 , DEC, '0',5); 
            Uart_SendString(debugUart,"\n"); 
          }
    

    einmal mit und einmal ohne Schleife also 9 * hintereinander den ganzen Block geschrieben und für 'z' echte Zahlen in jeden Block geschrieben. Das Ergebnis ist das gleiche:

    Ergebnis EEprom read:
    z=00000 Channel=00000, Status=00001, Strom=00770, Period=01284, Duty100=01798, Duty50=02312, Duty1=02826
    z=00001 Channel=00012, Status=00013, Strom=03854, Period=04368, Duty100=04882, Duty50=05396, Duty1=05910
    z=00002 Channel=00012, Status=00013, Strom=03854, Period=04368, Duty100=04882, Duty50=05396, Duty1=05910
    z=00003 Channel=00024, Status=00025, Strom=06938, Period=07452, Duty100=07966, Duty50=08480, Duty1=08994
    z=00004 Channel=00024, Status=00025, Strom=06938, Period=07452, Duty100=07966, Duty50=08480, Duty1=08994
    z=00005 Channel=00036, Status=00037, Strom=10022, Period=10536, Duty100=11050, Duty50=11564, Duty1=12078
    z=00006 Channel=00036, Status=00037, Strom=10022, Period=10536, Duty100=11050, Duty50=11564, Duty1=12078
    z=00007 Channel=00048, Status=00049, Strom=13106, Period=13620, Duty100=14134, Duty50=14648, Duty1=15162
    z=00008 Channel=00048, Status=00049, Strom=13106, Period=13620, Duty100=14134, Duty50=14648, Duty1=15162
    

    Also müsste der Fehler doch irgendwo hier liegen:

    typedef struct  PPG_Setup_Data {	// Länge 12 Byte
    	char Channel;
        char Status;
        short Strom;
        short Period;
        short Duty100;
        short Duty50;
        short Duty1;
    } Setup_PPG;
    
    __far Setup_PPG *PPG = (__far Setup_PPG*)0xDF4000;
    


  • Du gibst z aus, aber:

    dachschaden schrieb:

    Hast du mal die gegenwärtige Adresse, auf die &PPG[z] zeigt, ausgegeben? Nur um sicherzugehen, dass er auch wirklich in 12-Byte-Schritten durchläuft.

    Mich beschleicht das Gefühl, dass du bei jedem zweiten Schritten vorwärts einen Schritt zurück machst.



  • Kann das was damit zu tun haben das __far nicht allein stehen darf sondern nur mit (__far unsigned int*) im EEProm Code gibt es nur __far mit unsigned int* nie alleine?

    unsigned short read_eeprom(unsigned short adr) 
    { 
          return (*(__far unsigned int*) (0xDF4000 + adr * 2)); 
    }
    

Anmelden zum Antworten