STM32f030C8 I2C EEPROM - keine Daten empfangen, wenn nach einem Schreibvorgang gelesen wird

Ich entwickle eine Bibliothek für I2C eeprom at24c04 mit stm32f030c8 . Meine Lese- und Schreibfunktionen funktionieren, aber wenn ich versuche, unmittelbar nach einem Schreibvorgang in das Eeprom zu lesen, gibt das Eeprom keine Daten zurück. aber ich könnte sofort hintereinander schreiben. Das Problem tritt nur auf, wenn ich nach einer Schreibanweisung lese. Ich habe versucht, das I2C-Aktivierungsbit zu aktivieren und zu deaktivieren, aber das Problem besteht weiterhin. Kann mir jemand sagen, was das Problem ist.

void main()
{
   Configure_GPIO_I2C2();
   Configure_I2C2_Master(0xA0,1);

    I2C_WriteByte(5,'k');
    charr= I2C_ReadByte(5);//the program get stuck here because no byte is 
                            //received from eeprom
    UART_Send_String(1,&charr);

}

void I2C_WriteByte(uint8_t addr,uint8_t bytetowrite)
            {
                I2C2->ISR=0x01;
                I2C2_StartWrite(2);//start

                I2C2->TXDR = addr;//write addr
                while(!(I2C2->ISR & I2C_ISR_TXE));

                //I2C2_StartWrite(1);

                I2C2->TXDR = bytetowrite;
                while(!(I2C2->ISR & I2C_ISR_TXE));

                I2C2->CR2 |= I2C_CR2_STOP;//stop
                while(I2C2->CR2 & I2C_CR2_STOP);

            }

            uint8_t I2C_ReadByte(uint8_t byteToRead)
            {
                I2C2->ISR=0x01;
                I2C2_StartWrite(1);

                I2C2->TXDR = byteToRead;
                while(!(I2C2->ISR & I2C_ISR_TXE));

                I2C2_StartRead(1);  
                while(!(I2C2->ISR & I2C_ISR_RXNE));
                UART_Send_String(1,"r strt");
                uint8_t recv_data=I2C2->RXDR;   


                I2C2->CR2 |= I2C_CR2_STOP;
                while(I2C2->CR2 & I2C_CR2_STOP);

                return recv_data;

            }


            /////////////////////////////////////////////////////////
            /////////////////////////////////////////////////////////
            void Configure_GPIO_I2C2(void)
            {

                RCC->AHBENR |= RCC_AHBENR_GPIOFEN;  
                GPIOF->MODER |= (2<<12) | (2<<14);  
                GPIOF->OTYPER |= GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7; 

                GPIOF->OSPEEDR &=  ~(1<<12);
                GPIOF->OSPEEDR &=  ~(1<<14);

                GPIOF->PUPDR &= ~(1<<12);
                GPIOF->PUPDR &= ~(1<<12);
            }

        void Configure_I2C2_Master(uint8_t slave_addr,uint8_t no_of_bytes)
            {

                RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;

                /* (1) Timing register value is computed with the AN4235 xls file,
                 fast Mode @400kHz with I2CCLK = 48MHz, rise time = 140ns, fall time = 40ns */  
                I2C2->CR1 &= ~I2C_CR1_PE;
                I2C2->TIMINGR |= (uint32_t)0x00B01A4B; /* (1) */
                I2C2->CR2 |= (uint8_t)slave_addr;
                I2C2->CR2 |= no_of_bytes<<16;   
                I2C2->CR1 |= I2C_CR1_PE;
                //NVIC_SetPriority(I2C2_IRQn, 0); /* (7) */
                //NVIC_EnableIRQ(I2C2_IRQn); /* (8) */
            }

    void I2C2_StartWrite(int bytesToWrite)
            {

                I2C2->CR2 &= ~I2C_CR2_RD_WRN;

                I2C2->CR2 |= bytesToWrite<<16;

                I2C2->CR2 |= I2C_CR2_START;
                while(I2C2->CR2 & I2C_CR2_START);
            }



            void I2C2_StartRead(int bytesToRead)
            {
            I2C2->CR2 |= I2C_CR2_RD_WRN;

                I2C2->CR2 |= bytesToRead<<16;

                I2C2->CR2 |= I2C_CR2_START;
                while(I2C2->CR2 & I2C_CR2_START);
            }
Führen Sie irgendeine Art von Überprüfung durch, um sicherzustellen, dass der Schreibvorgang abgeschlossen ist, bevor Sie ihn so bald lesen?
Ich habe eine Bestätigungsabfrage versucht, wie im Datenblatt erwähnt. und sogar eine Verzögerung. aber das Ergebnis ist das gleiche
Was macht I2C2_StartWrite? Ist Ihnen der genaue Ablauf des Schreibens und Lesens mit I2C bekannt? Es sollte wie die Wellenformen auf Seite 11 des Datenblatts aussehen. Dann wissen Sie, wie ein Lesevorgang durchgeführt wird? Auch hier stehen Details auf dem Datenblatt. Was zeigt Ihr Umfang, was tatsächlich passiert, im Gegensatz zu dem, was Ihrer Meinung nach passieren sollte?
Ich habe die Funktionen I2C2_StartWrite und I2C2_StartRead hinzugefügt. Ich habe den Code aus dem Tutorial und aus dem Datenblatt entwickelt. Ich glaube, ich folge der richtigen Methode, weil ich individuell schreiben und lesen konnte. Ich folge dem im Datenblatt gezeigten i2c-Zyklus. @DiBosco
Zunächst möchte ich wiederholen: Was zeigt Ihr Umfang? Ich hoffe, ich liege falsch, aber ich vermute, weil Sie dieser Frage ausgewichen sind, haben Sie sie noch nicht verwendet. Zweitens sehe ich nicht genügend Zugriffe auf TXDR. Mein Verdacht ist, dass Sie nicht ganz verstehen, wie Sie die Hardwareadresse, dann die interne Adresse und dann die Daten schreiben müssen. Das Auslesen von Daten ist noch komplizierter. I2C ist sehr gewöhnungsbedürftig, es ist eine ziemliche Kopfsache, wenn Sie es zum ersten Mal ausprobieren. Dieses Tutorial ist IMHO gut: robot-electronics.co.uk/i2c-tutorial
Ich konnte noch keinen Bereich bekommen, ich versuche es. Über den TXDR. Ich habe das folgende Tutorial befolgt. und ich hatte den Eindruck, dass der stm32 i2c die Slave-Adresse schreibt, die während der Konfiguration angegeben wurde, und ich die Slave-Adresse nicht extra angeben muss. danke für den link. @DiBosco ( youtube.com/… )
Sieht so aus, als hätten Sie Recht mit der Hardwareadresse. Haben Sie A0, A1 und A2 auf dem EE alle auf 0 gesetzt? Ich habe dieses lange Tutorial jedoch nicht vollständig befolgt und Ihren Code nicht mit seinem verglichen, daher gibt es möglicherweise eine Zeile, die Sie verpasst haben. Ich finde ein Oszilloskop oder einen I2C-Analysator unerlässlich, wenn ich solche Sachen mache, es lässt mich oft erkennen, dass ich irgendwo einen dummen Fehler gemacht habe.
Ja, die A0, A1 und A2 sind alle geerdet. Was mich stört, ist, dass beide Funktionen einzeln funktionieren und wenn ich nach dem Lesen schreibe, gibt es kein Problem. Das Problem tritt nur auf, wenn ich nach dem Schreiben einen Lesevorgang durchführe. Ich folge dem I2C-Fluss, wie im Datenblatt erwähnt. Ich überprüfe den Umfang.

Antworten (2)

Meine Lese- und Schreibfunktionen funktionieren, aber wenn ich versuche, sofort nach einem Schreibvorgang in das Eeprom zu lesen, gibt das Eeprom keine Daten zurück. aber ich könnte sofort hintereinander schreiben.

Das riecht, als ob Sie nicht darauf warten, dass das EEPROM den Schreibvorgang beendet. Ich habe mir Ihr EEPROM nicht angesehen, aber bei allen, die ich jemals verwendet habe, startet eine Schreib- oder Löschsequenz nur die Aktion. Das EEPROM ist dann noch einige Zeit beschäftigt.

Die meisten EEPROMs haben so etwas wie ein Statusregister, in dem Sie ein wenig abfragen können, ob es beschäftigt ist. Diese Leseaktion kann durchgeführt werden, ob besetzt oder nicht.

Die allgemeinste Softwarearchitektur fragt immer das Busy-Bit ab, bevor sie versucht, irgendetwas zu tun. Wenn das EEPROM beschäftigt ist, fährt es mit der Abfrage fort, bis dies nicht mehr der Fall ist, und fährt dann mit der angeforderten Aktion fort. Anspruchsvollere Implementierungen setzen beim Schreiben und Löschen ein Flag, das anzeigt, dass das EEPROM möglicherweise beschäftigt ist. Die Besetztprüfung wird nur durchgeführt, wenn dieses Flag gesetzt ist. Naive Implementierungen warten immer nur nach einem Löschen oder Schreiben.

Sehen Sie sich Ihren Code genau an, insbesondere was genau an das EEPROM gesendet wird, wenn auf einen Schreibvorgang unmittelbar ein Lesevorgang folgt. Meine Vermutung ist, dass die Besetztprüfung in diesem Fall irgendwie übersprungen wird.

Ich habe die Lesefunktion in zwei Zyklen geändert, einen Schreibvorgang zum Laden der Leseadresse und einen Lesevorgang für die aktuelle Adresse. Es funktioniert jetzt. Ich bin mir jedoch nicht sicher, warum der im Datenblatt erwähnte Lesezyklus für zufällige Adressen nicht funktioniert.

Ich vermute, Sie haben die Startsequenz vorher nicht erneut übertragen. Wenn ich wetten müsste, würde ich sagen, dass Sie vorher nicht wirklich dem zufälligen Leseverfahren gefolgt sind und jetzt sind Sie es. Ich vermute, Sie haben geschrieben und gelesen, ohne diese Startsequenz erneut zu senden. Der Tutorial-Link, den ich gesendet habe, ist sehr gut darin, das klar zu erklären. Die I2C-Analysatoren wie der Beagle sind auch großartig darin, diese Dinge sofort aufzuzeigen. Tools wie diese sparen viel Zeit und sind es wert, das Geld dafür auszugeben, besonders am Anfang IMHO.
@DiBosco Ich habe die Startanweisung zuvor gesendet, wie Sie im Code sehen können. Aber jetzt habe ich eine Stoppbedingung zwischen den beiden Startzyklen hinzugefügt. Das ist die einzige Änderung, die ich vorgenommen habe. Ich werde in ein Analysegerät investieren