Search code examples
avreeprom

AVR EEPROM issue in proteus


When I'm using Proteus to simulate following program, The EEPROM will not change, and Also the EEPE will not set when I add EECR to watch, The whole program is here:

#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

void writeEEPROM(unsigned char address,char data){
   while(EECR & (1<<EEPE)); //wait for previus writing;
   EECR = ((0<<EEPM1)|(0<<EEPM0)); 
   //EECR=0;
   EEAR = address; //set address to eeprom address register
   EEDR = data;
   cli();
   EECR |= (1<<EEMPE);
   EECR |= (1<<EEPE);
   while(EECR & (1<<EEPE)); //wait for previus writing;
   EECR |= (1<<EEMPE);
   EECR |= (1<<EEPE);
   sei();
}

char readEEPROM(unsigned char address){
   while(EECR & (1<<EEPE)); //wait for previous write operation
   EEAR=0;
   EEAR |= address;
   EECR=0;
   EECR |= 1; //set bit0
   return EEDR;
}

int main()
 { 
   // Write your code here
   char ret=0;
   writeEEPROM(1,9);
   _delay_ms(100);
   ret=readEEPROM(1);
   if(ret==9){
   DDRB=0xff;
   PORTB=0xff;
   }
  while (1)
     ;
  return 0;
}

On calling writeEEPROM data will not store to the eeprom.


Solution

  • This is from the source code companion fileset to AVR103 AVR EEPROM Application Note, authoritative publication from the device manufacturer.

    char EEPROM_GetChar( unsigned int addr )
    {
        do {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.
        EEAR = addr; // Set EEPROM address register.
        EECR = (1<<EERE); // Start EEPROM read operation.
        return EEDR; // Return the byte read from EEPROM.
    }
    
    
    void EEPROM_PutChar( unsigned int addr, char new_value )
    {
        char old_value; // Old EEPROM value.
        char diff_mask; // Difference mask, i.e. old value XOR new value.
    
        unsigned char old_interrupt; // Stores interrupt flag while programming.
        old_interrupt = __save_interrupt(); // Save interrupt flag state.
        __disable_interrupt(); // Ensure atomic operation for the write operation.
    
        do {} while( EECR & (1<<EEPE) ); // Wait for completion of previous write.
        #ifndef EEPROM_IGNORE_SELFPROG
        do {} while( SPMCSR & (1<<SELFPRGEN) ); // Wait for completion of SPM.
        #endif
    
        EEAR = addr; // Set EEPROM address register.
        EECR = (1<<EERE); // Start EEPROM read operation.
        old_value = EEDR; // Get old EEPROM value.
        diff_mask = old_value ^ new_value; // Get bit differences.
    
        // Check if any bits are changed to '1' in the new value.
        if( diff_mask & new_value ) {
            // Now we know that _some_ bits need to be erased to '1'.
    
            // Check if any bits in the new value are '0'.
            if( new_value != 0xff ) {
                // Now we know that some bits need to be programmed to '0' also.
    
                EEDR = new_value; // Set EEPROM data register.
                EECR = (1<<EEMPE) | // Set Master Write Enable bit...
                       (0<<EEPM1) | (0<<EEPM0); // ...and Erase+Write mode.
                EECR |= (1<<EEPE);  // Start Erase+Write operation.
            } else {
                // Now we know that all bits should be erased.
    
                EECR = (1<<EEMPE) | // Set Master Write Enable bit...
                       (1<<EEPM0);  // ...and Erase-only mode.
                EECR |= (1<<EEPE);  // Start Erase-only operation.
            }
        } else {
            // Now we know that _no_ bits need to be erased to '1'.
    
            // Check if any bits are changed from '1' in the old value.
            if( diff_mask ) {
                // Now we know that _some_ bits need to the programmed to '0'.
    
                EEDR = new_value;   // Set EEPROM data register.
                EECR = (1<<EEMPE) | // Set Master Write Enable bit...
                       (1<<EEPM1);  // ...and Write-only mode.
                EECR |= (1<<EEPE);  // Start Write-only operation.
            }
        }
    
        __restore_interrupt( old_interrupt ); // Restore interrupt flag state.
    }
    
    
    void main()
    {
        char t; // Temporary byte.
        unsigned int addr = 0x10; // EEPROM address to use.
    
        // Test the EEPROM_GetChar() function.
        t = EEPROM_GetChar( addr );
    
        // Try erasing the whole byte.
        EEPROM_PutChar( addr, 0xff );
    
        // Try changing a few bits to '0'.
        EEPROM_PutChar( addr, 0x0f );
    
        // Try changing bits both ways.
        EEPROM_PutChar( addr, 0xf0 );
    
        // Try changing nothing.
        EEPROM_PutChar( addr, 0xf0 );
    
        // Restore old value.
        EEPROM_PutChar( addr, t );
    
        for(;;); // Loop forever.
    }