2017-08-08 82 views
0

我已經使用以下代碼,用於訪問EEPROM:數據沒有得到存儲在EEPROM中

void EEPROM_write(unsigned int uiAddress,unsigned char ucData) 
{ 
  while(EECR & (1<<EEWE)) 
   { 
       //do nothing 
   } 

   while(SPMCR & (1<<SPMEN)); 
  EEAR = uiAddress; 
   EEDR = ucData; 
   EECR |= (1<<EEMWE); 
   EECR |= (1<<EEWE); 
} 

char EEPROM_read(unsigned int uiAddress) 
{ 
    while(EECR & (1<<EEWE)) 
   { 
       //do nothing 
   } 

  EEAR = uiAddress; 
   EECR |=(1<<EERE); 
   return EEDR; 
} 

void EEPROM_write_str(unsigned int uiAddress,unsigned char* string,unsigned int size) 
{ 
    int i; 
   for(i=0;i<size;i++) 
  { 
       EEPROM_write(uiAddress+i,string[i]); 
   } 
} 

void EEPROM_read_str(unsigned int uiAddress,unsigned char* string,unsigned int size) 
{ 
    int i; 
  for(i=0;i<size;i++) 
   { 
       string[i] = EEPROM_read(uiAddress+i); 
   } 
} 

char str[]="hello "; 
char str2[20]; 

int main() 
{ 
    usart_init(12); 
  //EEPROM_write_str(0,str,6); 
   EEPROM_read_str(0,str2,6); 
   usart_puts(str2,6); 
} 

在上面的代碼中,我第一評論的EEPROM_read_str和usart_puts,...閃蒸它然後評論的EEPROM_write_str功能和刪除了另外兩個人的評論,然後再次閃現。儘管如此,數據並未被存儲,並且終端中顯示的輸出爲yyyyy(十六進制FF)。 這裏有什麼問題? (這裏USART_puts以第二個參數作爲字符數發送字符串)

+0

在地址0有eeprom嗎?在寫入之前在哪裏擦除eeprom? – Lundin

+0

@Lundin它是在地址爲0到1023的EEPROM我猜 – user102958

+0

@Lundin AVR-s是Hardvare架構,所有存儲器都有獨立的地址空間。 AVR可以在寫入期間選擇它。單元格被擦除並一次寫入。它被atmel稱爲「原子eeprom寫」 –

回答

0

我的舊avr項目的工作代碼。我不使用他們多年來如此規定的,正如我不記得位的確切含義,現在

void EEPROM_write(uint8_t addr, uint8_t value) { 
    while(EECR & (1 << EEPE)) ;    //wait for write enable bit to clear 
    EECR &= ~((1 << EEPM1) | (1 << EEPM0)); // (erase & write in one operation) 
    EEARL = addr;       // set the address 
    EEDR = value;       // set value to be written 
    EECR |= (1 << EEMPE);      // set EEPROM Master Write Enable 
    EECR |= (1 << EEPE);      // set EEPROM Master Write Enable 
} 

uint8_t EEPROM_read(uint8_t addr) { 
    while(EECR & (1 << EEPE)) ;    
    EEARL = addr;       // set the address 
    EECR |= (1 << EERE); 
    return EEDR; 
} 
+0

問題不存在....當我一次執行寫操作和讀操作時,數據返回相同,但是,重置控制器會導致擦除數據... – user102958

+0

此代碼用於售出十萬臺設備 - 並始終保持其價值。第一個字節非常複雜 - 有時在某些系列的uC上被破壞(不同的批次可以不行),所以要避免第一個字節,並記住關於功耗的問題。 –

+0

嘗試我的一個奇怪的話然後 –

0

這是從源代碼配套文件爲AVR103 AVR EEPROM Application Note,從設備製造商的權威刊物。

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. 
} 
+0

我的編譯器(atmel studio 7)將EEMPE顯示爲錯誤....它理解較早的命令(EEMWE) – user102958

+0

該文檔很早以前就已經寫入,並且一些寄存器名稱在較新的AVR部分中可能略有更改。請檢查您的零件數據表以瞭解當前的註冊名稱。但請放心,算法保持不變。 – TomServo