Kann keine Daten für 24c256 EEPROM schreiben?

Ich verwende den Pic24fj128ga202-Mikrocontroller und das 24c256-EEPROM und die ISL1208-RTC, die über den I2c-Bus verbunden sind. Das Problem ist, dass ich die Daten in EEPROM und RTC lesen und schreiben kann, aber auf einigen anderen Boards (mit demselben Design) kann ich die Daten nicht über den i2c-Bus lesen oder schreiben. Ich habe meinen Code und meinen Schaltplan gepostet. Bitte spricht mich jemand an, was ist das Problem? Ich habe kein Oszilloskop, um das zu überprüfen.

#include <stdio.h>
#include "C:\Program Files\Microchip\xc16\v1.24\support\PIC24F\h\p24FJ128GA202.h"
#include "uart.h"
// calculate baud rate of I2C
#define Fosc      32000000
#define Fcy       (Fosc/2)
#define Fsck      400000
#define I2C_BRG  ((Fcy/2/Fsck)-1)

int main()
{
    InitProcessor();
    Delayms();
    while(1)
    {
        I2c_Write(0xA0,1,'A');
        Delayms(5000);
        uart1tx(I2C_read(0xA0,1));
    }
}

void InitProcessor(void)
{
    // Oscillator    8mhz no pll
    OSCCON = 0x0011;
    CLKDIV = 0x0000; 

    // Configure Digital pins
    ANSA = 0x0003;
    ANSB = 0x0000;

    //  Assign  IO values for Ports
    PORTA = 0x0000;
    TRISA = 0x001B;
    TRISB = 0x468f;                   // 7 as receive and 8 as transmitter
    //PORTB = 0x0000;


    // Interrupt Bits 
    INTCON1 = 0x0000;                                               // Disable  Interrupts
    INTCON2 = 0x0000;

    // Init I2C
    I2C2CONL = 0x8000;
    I2C2CONH = 0x0000;
    I2C2STAT = 0x0000;
    I2C2BRG = I2C_BRG;
    //I2C2BRG = 79;

    Delayms(1000);
    Init_rtc();
}

void Init_rtc()
{
    I2c_Write(0xde, 0x07, 0x10);
    I2c_Write(0xde, 0x06, 0x00);
    Delayms(20);
}

void I2c_Write(unsigned char DeviceAddress,unsigned int Addr,unsigned char i2c_value)
{
    unsigned char i2c_exit=1,i2c_write=0;
    int I2creg = 0;
    IFS3 &= ~0x0004;
    I2C2CONL |= 0x0001;
    I2cTimer = 0;
    while(i2c_exit)
    {
        if(I2cTimer > 30){                                              // Exit routine
            i2c_exit = 0;
        }
        if(IFS3& 0x0004)
        {
            IFS3 &= ~0x0004;
            I2cTimer = 0;
            if(i2c_write == 0)
            {
                I2C2TRN = (DeviceAddress & 0xfe);
                if(DeviceAddress == 0xde)
                    i2c_write = 1;
            }
            else if(i2c_write == 1)
                I2C2TRN = Addr >> 8;
            else if(i2c_write == 2)
                I2C2TRN = Addr & 0xFF;
            else if(i2c_write == 3)
                I2C2TRN = i2c_value;
            else if(i2c_write == 4)
                I2C2CONL |= 0x04;
            else
            {
                i2c_write = 100;
                i2c_exit = 0;
            }
            i2c_write++;
        }
    }
    Delayms(5);
}

/* Function to Read and return a data through I2C  */
unsigned char I2C_read(unsigned char DeviceAddress,unsigned int Addr)
{   unsigned char db, ReadState=0,I2CFlag;
    ReadState = 0;
    IFS3 &= ~0x0004;                                                        // Master I2C interrupt flag
    I2CFlag = 1;
    I2C2CONL |= 0x0001;         // SEN = 1;
    I2cTimer = 0;
    while(I2CFlag){
        if(I2cTimer > 30){                                              // Exit routine
            I2CFlag = 0;

            //ModemDiagnostics(64,1);
        }
        //uart1tx('r');
        if(IFS3 & 0x0004)
        {       
            I2cTimer = 0;
            IFS3 &= ~0x0004;
            if(ReadState == 0)
            {
                I2C2TRN = (DeviceAddress & 0xfe);
                if(DeviceAddress == 0xde)
                    ReadState = 1;
            }
            else if(ReadState == 1)
                I2C2TRN = Addr >> 8;
            else if(ReadState == 2)
                I2C2TRN = Addr & 0xff;
            else if(ReadState == 3)I2C2CONL |= 0x0002;  
            else if(ReadState == 4)I2C2TRN = (DeviceAddress | 0x01);
            else if(ReadState == 5){
                I2C2CONL |= 0x0008;                             // RCEN = 1, Enable data receive
                db = I2C2RCV;
            }
            else if(ReadState == 6){
                db = I2C2RCV;                                                       // Read Data
                I2C2CONL |= 0x0020;                                                 // ACKDT = 1, Set Acknowledge bit (No Acknowledge)
                Delayms(5);
                I2C2CONL |= 0x0010;                                                 // ACKEN = 1
            }
            else if(ReadState == 7)I2C2CONL |= 0x04;                                // PEN = 1, Stop enable bit forI2C
            else{ReadState = 100; I2CFlag = 0;}                                     
            ReadState++;
        }
    }
    if(db)
        return db;
    else
        return 0;
}

I2c-Bild

Ohne zu viel zu graben, vermute ich, dass die Pullup-Widerstände (R41 und R42) einen zu hohen Wert haben (die Gesamtkapazität der Schaltung kann ich nicht kennen). Versuchen Sie, sie durch 4,7 KB oder vielleicht 2,2 KB zu ersetzen

Antworten (2)

Die Berechnung des maximalen Pull-Ups bei 400 kHz lautet:

R M A X = 300 N S C B u S ; durch Umstellen erhalten wir:

C B u S ( M A X ) = 300 N S 10 k Ω für Ihren Fall ergibt sich 30 pF.

Die Pin-Kapazitäten des EEPROM und des RTC liegen wahrscheinlich beide in der Größenordnung von 10 pF; Fügen Sie die Pin-Kapazität des PIC hinzu, und Sie nähern sich bereits 30 pF und setzen das Design auf eine haarige Kante (um den gebräuchlichen Begriff zu verwenden), wo es möglicherweise ordnungsgemäß funktioniert oder nicht, was genau das ist, was Sie erleben.

Es ist nicht schwierig, eine Streukapazität von 10 pF oder mehr zu erreichen, und dies würde die Anforderung für die maximale Pull-up-Größe verletzen, was zu beschädigten I2C-Daten führen würde.

Wenn Sie diese Teile durch 4,7 k ersetzen, dürfen Sie fast 64 pF Buskapazität haben, was das Problem sehr wahrscheinlich lösen wird.

Wie bereits erwähnt, wenn Sie die Busgeschwindigkeit reduzieren und sie ordnungsgemäß funktioniert, ist dies ein klarer Hinweis darauf, dass dies das Problem ist.

Danke @ Peter Smith. Ich freue mich darauf, das Problem anzugehen. Und manchmal startet der Mikrocontroller neu. Gibt es dadurch ein Problem?
Ob der Controller neu startet, hängt von vielen Dingen ab, einschließlich davon, ob nicht behandelte Kommunikationsfehler Nebenwirkungen haben. Ich habe die Details des Controllers nicht gelesen.

Da es in einem anderen Board wie gewünscht funktioniert, gehe ich davon aus, dass die Probleme von der Hardware herrühren (auch wenn eine schlechte Software es verschlimmern kann). Dafür sehe ich 2 Gründe:

  • Einer der Pins Ihres IC ist nicht richtig angeschlossen. Führen Sie mit einem Multimeter Durchgangstests zwischen den Pins verschiedener ICs durch, um zu überprüfen, ob sie richtig miteinander verbunden sind
  • Aus irgendeinem Grund liegt einer Ihrer elektrischen Parameter außerhalb der Grenzen der Datenblätter. Dies kann dazu führen, dass einige Boards funktionieren, während andere dies nicht tun würden.
+1 Neben Opens sind auch Shorts möglich