This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

EEPROM Read/Write AT89C51AC3

Hello,

I have the following code for writing/reading EEPROM of this device.

unsigned char eepromWrite (const unsigned int Address, unsigned char Data) {
    bit oldEA;
    unsigned char DataReadBack;

    if (Address <= 0x07ff)
    {
        oldEA = EA;
        EA = 0;

        EECON |= 0x02; // Enable EEPROM memory space
        XBYTE[Address] = Data;
        EECON &= 0xFD; // Disable EEPROM memory space
        EA = oldEA;

        EECON = 0x50; EECON = 0xA0;     // Programming...

        // wait programming...
        while(EECON & b00000001);

        // Byte re-read
        oldEA = EA;
        EA = 0;
        EECON |= 0x02; // Enable EEPROM memory space
        DataReadBack = XBYTE[Address];
        EECON &= 0xFD; // Disable EEPROM memory space
        EA = oldEA;
        if (DataReadBack != Data)
        {
            return(2);
        }
        return(0);
    }
    else
    {
        return(1);
    }
}

unsigned char eepromRead (const unsigned int Address, unsigned char* Data) {
bit oldEA;
	if (Address <= 0x07ff) {
	    oldEA = EA;
	    EA = 0;
		while(EECON & b00000001); //EEbusy
	    EECON |= 0x02; // Enable EEPROM memory space
	    *Data = XBYTE[Address];
	    EECON &= 0xFD; // Disable EEPROM memory space
	    EA = oldEA;
		return (0);
	}
    else
    {
        *Data = 0;
        return(1);
    }
}

Then I write the following code for write/read multiple byte (or structure)

void write_to_EEPROM (unsigned int EEPROM_address, void *buffer, unsigned char buffer_len) {
unsigned char *bp;
for (bp = buffer; buffer_len; buffer_len--, bp++, EEPROM_address++)
  {
	eepromWrite(EEPROM_address, *bp);
  }
  Wait20ms();
}

void read_from_EEPROM (unsigned int EEPROM_address, void *buffer, unsigned char buffer_len) {
unsigned char *bp;

for (bp=buffer; buffer_len; buffer_len--, bp++, EEPROM_address++)
  {
	eepromRead(EEPROM_address, bp);
  }
}

Most of the time it works. For example I could write/read a struct:
typedef struct    {
                     uchar       MotorMin;
		     uchar       MotorKnee;
                     uchar       MotorMax;
                  }  Blower_TYP;

//////////

write_to_EEPROM (FAN_ADDR, &BlowerNew, sizeof (Blower_TYP));

void readMotorConf (void) {
 Blower_TYP temp;
 read_from_EEPROM(FAN_ADDR, &temp, sizeof(Blower_TYP));
 Blower = temp;
}
}


Only sometime the read function give wrong reading of the blower. What could be the problem on above code? Thanks for advise!

  • hi,

    Only sometime the read function give wrong reading.

    How do you determine this? Do you find difference between twice reading or between writting and reading?

    By the way, the datasheet says:

    Note: The sequence 5xh and Axh must be executed without instructions between then otherwise the programming is aborted.

    So I think you should keep interrupts disabled during launching programming by writing the control sequence.

    Regards,
    Oleg

  • Hai, thanks for feedback about disabling interrupt.

    Back to the read function. It is from several reading, I test with this function.

    void BlowerTest(void) {
    Blower_TYP xdata BlowerNew;
    bit OldET0;
    			BlowerNew = Blower;
    			OldET0 = ET0;
    			ET0 = 0;
    			readMotorConf(); // Read Blower from eeprom
    			ET0 = OldET0;
    			if (Blower.MotorMin != BlowerNew.MotorMin ||
    				    Blower.MotorKnee != BlowerNew.MotorKnee ||
    				    Blower.MotorMax != BlowerNew.MotorMax) {
    
    
                                        DisplayText (2,1, "Diff!");
    			}
    }
    

  • Can you have a look at the assembly code the compiler generates, especially for the

    EECON |= 0x02; // Enable EEPROM memory space
    DataReadBack = XBYTE[Address];
    EECON &= 0xFD; // Disable EEPROM memory space
    

    part of the eeprom_read function ?

  • BlowerNew = Blower;
    

    What is this line of code supposed to do ?

  • Also, just as general advice, you might want to review your use of pointers here. On the '51 architecture, the use of pointers is generally fairly inefficient, and most locations are known at compile time. This is quite different from, say, programming in C on a PC.

  •                                            ; SOURCE LINE # 45
    0030 43D202            ORL     EECON,#02H
                                               ; SOURCE LINE # 46
    0033 8F82              MOV     DPL,R7
    0035 8E83              MOV     DPH,R6
    0037 E0                MOVX    A,@DPTR
    ;---- Variable 'DataReadBack' assigned to Register 'R7' ----
                                               ; SOURCE LINE # 47
    0038 53D2FD            ANL     EECON,#0FDH
    

  • Blower = temp;

    Ok, I missed this line before.

    What are you trying to accomplish with this line ? If this is supposed to do an element-by-element copy, like

    Blower.MotorMin = temp.MotorMin;
    Blower.MotorKnee = temp.MotorKnee;
    Blower.MotorMax = temp.MotorMax;
    

    ... that's not going to work.

  • Hallo all,
    There were mistakes on my test. It might other bugs. So, that

    BlowerNew = Blower;
    
    Can be different from the ones stored previously in eeprom. I just tried to make another test solely just read the eeprom, and the values always correct. I am sorry for that, and thanks for all your advises. Kind Regards