📄 eeprom.c
字号:
// This file has been prepared for Doxygen automatic documentation generation.
/*! \file ********************************************************************
*
* Atmel Corporation
*
* \li File: eeprom.c
* \li Compiler: IAR EWAAVR 3.10c
* \li Support mail: avr@atmel.com
*
* \li Supported devices: All devices with split EEPROM erase/write
* capabilities can be used.
* The example is written for ATmega48.
*
* \li AppNote: AVR103 - Using the EEPROM Programming Modes.
*
* \li Description: Example on how to use the split EEPROM erase/write
* capabilities in e.g. ATmega48. All EEPROM
* programming modes are tested, i.e. Erase+Write,
* Erase-only and Write-only.
*
* $Revision: 1.6 $
* $Date: Friday, February 11, 2005 07:16:44 UTC $
****************************************************************************/
#include <ioavr.h>
#include <inavr.h>
/* These EEPROM bits have different names on different devices. */
#ifndef EEPE
#define EEPE EEWE //!< EEPROM program/write enable.
#define EEMPE EEMWE //!< EEPROM master program/write enable.
#endif
/* These two are unfortunately not defined in the device include files. */
#define EEPM1 5 //!< EEPROM Programming Mode Bit 1.
#define EEPM0 4 //!< EEPROM Programming Mode Bit 0.
/* Define to reduce code size. */
#define EEPROM_IGNORE_SELFPROG //!< Remove SPM flag polling.
/*! \brief Read byte from EEPROM.
*
* This function reads one byte from a given EEPROM address.
*
* \note The CPU is halted for 4 clock cycles during EEPROM read.
*
* \param addr EEPROM address to read from.
* \return The byte read from the EEPROM address.
*/
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.
}
/*! \brief Write byte to EEPROM.
*
* This function writes one byte to a given EEPROM address.
* The differences between the existing byte and the new value is used
* to select the most efficient EEPROM programming mode.
*
* \note The CPU is halted for 2 clock cycles during EEPROM programming.
*
* \note When this function returns, the new EEPROM value is not available
* until the EEPROM programming time has passed. The EEPE bit in EECR
* should be polled to check whether the programming is finished.
*
* \note The EEPROM_GetChar() function checks the EEPE bit automatically.
*
* \param addr EEPROM address to write to.
* \param new_value New EEPROM value.
*/
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.
}
/*! \brief Execution starts here.
*
* The main() function tests the EEPROM_GetChar() and EEPROM_PutChar()
* functions. The values written to EEPROM are chosen so that all the
* EEPROM programming modes are tested.
*/
__C_task 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.
}
// end of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -