Sunday, August 23, 2020

Using ATMega32 Internal EEPROM Memory

Overview

Beside program memory and data memory, the ATMega32 contains up to 1024 bytes of internal EEPROM for auxiliary storage. It can handle up to 100,000 Write/Erase cycles. However its access time is slower than SRAM. Each registers of EEPROM are 8-bit wide unlike the internal program memory that is 16-bit wide. Program memory space is quite larger than EEPROM memory space. In the case of the ATMega32 the program memory is 32K bytes.

It's important to store user's settings data in to this non-volatile memory to prevent data lost next time the MCU turns on, or power interruption. We can also store this type of data in internal program memory (Flash Memory).

Writing And Reading EEPROM Example

The AVR LibC contains the "eeprom.h" library allow us to read and write different kind of data types inside EEPROM such as byte, word, float, etc. Even it's 8-bit wide the library handle this task for the programmers. This library has the following routines,

  • eeprom_read_byte
  • eeprom_read_word
  • eeprom_read_dword
  • eeprom_read_float
  • eeprom_read_block

 

  • eeprom_write_byte
  • eeprom_write_word
  • eeprom_write_dword
  • eeprom_write_float
  • eeprom_write_block

and other update routine. For more detail you can see the header file.

For an introductory example, the program will write a set of data of 256 addresses, and read them back.

Using ATMega32 Internal EEPROM Memory
Writing and Reading EEPROM Example
I use AVR LibC in Microchip Studio.

  1. /*
  2.  * EepromEx1.c
  3.  *
  4.  * Created: 7/20/2023 6:53:22 PM
  5.  * Author : Admin
  6.  */
  7.  
  8. #include <avr/io.h>
  9.  
  10. #include <avr/eeprom.h>
  11.  
  12. #define F_CPU 8000000UL
  13. #include <util/delay.h>
  14.  
  15.  
  16. int main(void)
  17. {
  18. DDRC = 0xFF;
  19. for (uint8_t i= 0;i<0xFF;i++)
  20. eeprom_write_byte(i,i);
  21. while (1)
  22. {
  23. for (uint8_t i = 0; i<0xFF; i++)
  24. {
  25. PORTC = eeprom_read_byte(i);
  26. _delay_ms(250);
  27. }
  28.  
  29. }
  30. }
  31.  
  32.  

Click here to download its zip file.

Using the EEMEM attribute

EEMEM attribute allow us to declare data on EEPROM space. We can read or write the data using its address. In the following example, I declare a data array on EEPROM first, and then I read those data back.

  1. /*
  2.  * EepromEx2.c
  3.  *
  4.  * Created: 7/20/2023 9:16:24 PM
  5.  * Author : Admin
  6.  */
  7.  
  8. #include <avr/io.h>
  9.  
  10. #define F_CPU 8000000UL
  11. #include <util/delay.h>
  12.  
  13. #include <avr/eeprom.h>
  14.  
  15. const uint8_t myData[] EEMEM = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  16.  
  17. int main(void)
  18. {
  19. DDRC=0xFF;
  20. while (1)
  21. {
  22. for (int i =0;i<sizeof(myData);i++)
  23. {
  24. char temp = &myData[i];
  25. PORTC=eeprom_read_byte(temp);
  26. _delay_ms(1000);
  27. }
  28.  
  29. }
  30. }
  31.  
  32.  

Schematic Diagram

Using ATMega32 Internal EEPROM Memory
Using the EEMEM attribute
 

Click here to download its zip file.

Here's another example. I store constant 7-Segment data in EEPROM. The program will read them back and show it on display.

  1. /*
  2.  * EepromEx3.c
  3.  *
  4.  * Created: 7/20/2023 10:17:26 PM
  5.  * Author : Admin
  6.  */
  7.  
  8. #include <avr/io.h>
  9. #include <avr/eeprom.h>
  10.  
  11. #define F_CPU 8000000UL
  12. #include <util/delay.h>
  13.  
  14. /*Declare EEPROM Storage*/
  15. const uint8_t cCathode[] EEMEM = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
  16. 0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
  17. const uint8_t cAnode[] EEMEM = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,
  18. 0x90,0x88,0x83,0xC6,0xA1,
  19. 0x86,0x8E};
  20.  
  21. int main(void)
  22. {
  23. DDRC=0xFF;
  24. DDRD=0xFF;
  25. while (1)
  26. {
  27. for (int i=0;i<sizeof(cCathode);i++)
  28. {
  29. PORTD=eeprom_read_byte(&cCathode[i]);
  30. PORTC=eeprom_read_byte(&cAnode[i]);
  31. _delay_ms(500);
  32. }
  33. }
  34. }
  35.  
  36.  

 

 

Using ATMega32 Internal EEPROM Memory
Displaying 7-Segment Data From EEPROM

 Click here to download its zip file.

Reading/Writing With Switches and a 7-Segment Display

In this example I use two DIP switches, one for input address while another one for input data that will write data into EEPROM. Input data is between 0 and 0x0F.

Using ATMega32 Internal EEPROM Memory
Reading/Writing With Switches and a 7-Segment Display
One the SW2 push button is pressed, it will write data from input DSW2 DIP switch with a given address from DSW1 DIP switch.

With any input address change from DSW1, it will read the data from new given address.

  1. /*
  2.  * EepromEx4.c
  3.  *
  4.  * Created: 7/21/2023 9:21:18 AM
  5.  * Author : Admin
  6.  */
  7.  
  8. #include <avr/io.h>
  9.  
  10. #define F_CPU 8000000UL
  11. #include <util/delay.h>
  12.  
  13. #include <avr/eeprom.h>
  14.  
  15. #define Write (PIND&0x08)==0
  16. #define LED 7
  17.  
  18. /*Declare EEPROM Storage*/
  19. uint8_t Edata[256] EEMEM;
  20.  
  21. const uint8_t cAnode[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
  22. 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
  23.  
  24. int main(void)
  25. {
  26. uint8_t oldAddr=1,newAddr=0,segment=0,inputData;
  27. DDRA=0x00;
  28. PINA=0xFF;
  29. DDRC=0xFF;
  30. PORTC=0xFF;
  31. DDRD=0x07;
  32. PORTD=0xF8;
  33. while (1)
  34. {
  35. /*Check Address Change*/
  36. if (newAddr!=oldAddr)
  37. {
  38. segment = eeprom_read_byte(&Edata[newAddr]);
  39. oldAddr = newAddr;
  40. }
  41. PORTC = cAnode[segment];
  42. newAddr = PINA;
  43. if (Write)
  44. {
  45. PORTC&=~(1<<LED);
  46. inputData = (PIND&0xF0)>>4;
  47. eeprom_write_byte(&Edata[newAddr],inputData);
  48. while(Write);
  49. segment = eeprom_read_byte(&Edata[newAddr]);
  50. PORTC|=(1<<LED);
  51. }
  52. }
  53. }
  54.  
  55.  

Click here to download source file. 

The example above use the 7-Segment data that store in SRAM. We can also store and read it from EEPROM.

  1. /*
  2.  * EepromEx5.c
  3.  *
  4.  * Created: 7/21/2023 3:11:48 PM
  5.  * Author : Admin
  6.  */
  7.  
  8. #include <avr/io.h>
  9.  
  10. #define F_CPU 8000000UL
  11. #include <util/delay.h>
  12.  
  13. #include <avr/eeprom.h>
  14.  
  15. #define Write (PIND&0x08)==0
  16. #define LED 7
  17.  
  18. /*Declare EEPROM Storage*/
  19. uint8_t Edata[256] EEMEM;
  20.  
  21. uint8_t cAnode[] EEMEM = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
  22. 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
  23.  
  24. int main(void)
  25. {
  26. uint8_t oldAddr=1,newAddr=0,segment=0,inputData,DisplayData=0;
  27. DDRA=0x00;
  28. PINA=0xFF;
  29. DDRC=0xFF;
  30. PORTC=0xFF;
  31. DDRD=0x07;
  32. PORTD=0xF8;
  33. while (1)
  34. {
  35. /*Check Address Change*/
  36. if (newAddr!=oldAddr)
  37. {
  38. segment = eeprom_read_byte(&Edata[newAddr]);
  39. DisplayData = eeprom_read_byte(&cAnode[segment]);
  40. oldAddr = newAddr;
  41. }
  42. PORTC = DisplayData;
  43. newAddr = PINA;
  44. if (Write)
  45. {
  46. PORTC&=~(1<<LED);
  47. inputData = (PIND&0xF0)>>4;
  48. eeprom_write_byte(&Edata[newAddr],inputData);
  49. while(Write);
  50. segment = eeprom_read_byte(&Edata[newAddr]);
  51. DisplayData = eeprom_read_byte(&cAnode[segment]);
  52. PORTC|=(1<<LED);
  53. }
  54. }
  55. }
  56.  
  57.  
  58.  

Click here to download its source file.

No comments:

Post a Comment