/* remember.c use EEPROM data */ // Arduino UNO R3 // AVR_ATmega328P #define F_CPU 16000000UL #include // register names/addresses and bit names/numbers #include // for the nop instruction #include // macros for strings in program memory void init_uart( void ); unsigned char getchar_uart( void ); void putchar_uart( unsigned char ); void string_in_uart( char * ); void string_out_uart( char * ); void dec_out_uart( unsigned int ); unsigned char EEPROM_read(unsigned int uiAddress); void EEPROM_write(unsigned int uiAddress, unsigned char ucData); void puts_eedata( unsigned int uiAddress, char * s ); void gets_eedata( unsigned int uiAddress, char * s ); #define MAX_STRING 11 int main(void) { unsigned char s[ MAX_STRING ]; init_uart(); string_out_uart("Using EEPROM\r\n"); // First we store an int in EEPROM at address 0,1 unsigned int a = 12345; // a gets this value EEPROM_write(0, a%256); // low byte EEPROM_write(1, a/256); // high byte // Now we recreate the int from EEPROM bytes string_out_uart("Stored 16 bit int is: "); a = EEPROM_read(1)*256 + EEPROM_read(0); // a gets value from EEPROM dec_out_uart( a ); // the free EEPROM Byte address is now 2 // we use it to store a string // the free EEPROM Byte address will then be 2 + MAX_STRING string_out_uart("\r\nI recall this text from my memory:\r\n"); // recall previous stored string from EEPROM gets_eedata( 2, s ); string_out_uart( s ); // prompt user for new input string_out_uart("\r\nWhat Do you want me to remember now: "); // get user input string string_in_uart( s ); // store new string in EEPROM puts_eedata( 2, s ); //propt user to finnish string_out_uart("\r\nNow disconnect the plug to turn off the power!\r\n"); string_out_uart("I will remember this until next time!\r\n"); while(1) { _NOP(); // will not be removed by compiler optimization } return 0; /* never reached */ } /* *********************************** */ /* FUNCTIONS */ /* *********************************** */ void init_uart( void ) { // Bits in UCSR0B register: "RXCIE0 TXCIE0 UDRIE0 RXEN0 TXEN0 UCSZ02 RXB80 TXB80" UCSR0B |= (1<<(RXEN0)) | (1<<(TXEN0)); // "----1---" // Bits in UCSR0C register: "UMSEL01 UMSEL00 UPM01 UPM00 USBS0 UCSZ01/UCPHA0 UCSZ01/UCPHA0 UCPOL0" UCSR0C |= (1<<(UCSZ01)) | (1<<(UCSZ00)); // "-----11-" UBRR0 = 103; // Baud prescaler 103 -> 9600 Baud } unsigned char getchar_uart( void ) { unsigned char ch; // Bits in UCSR0A register: "RXC0 TXC0 UDRE0 FE0 DOR0 UPE0 U2X0 MPCM0" // wait until a byte is ready to read while( ( UCSR0A & ( 1<<(RXC0) ) ) == 0 ){} // grab the byte from the serial port ch = UDR0; return ch; } void putchar_uart( unsigned char ch ) { // Bits in UCSR0A register: "RXC0 TXC0 UDRE0 FE0 DOR0 UPE0 U2X0 MPCM0" // wait until the port is ready to be written to while( ( UCSR0A & ( 1<<(UDRE0) ) ) == 0 ){} // write the byte to the serial port UDR0 = ch; } void string_out_uart( char * string ) // use for strings in RAM { while (* string != '\0') putchar_uart(*string ++); } void string_in_uart( char * string ) // Expects '\r' + '\n' to end input. Windows style. { unsigned char charCount, c; for( charCount = 0; ; charCount++ ) { c = getchar_uart( ); /* input 1 character */ string[charCount] = c; /* store the character */ putchar_uart( c ); /* echo the character */ if(c=='\r' ) charCount-- ; /* skip and wait for '\n' to end input */ if( c=='\n'){ string[charCount] = '\0'; return; } /* end of string and end of input */ if( charCount == (MAX_STRING-1)) charCount-- ; /* prevent buffer overflow */ } } void dec_out_uart( unsigned int number ) { unsigned char i; unsigned int divisor = 10000; for(i=0; ;i++) { putchar_uart( (unsigned char)(number/divisor) + '0' ); if( i==4 ) break; number %= divisor; divisor /= 10; } } /* *********************************** */ /* EEPROM FUNCTIONS */ /* *********************************** */ // ATmega328/P EEPROM (Bytes) address is a number between 0 - 1023 // char is 8 bit, one byte // int is 16 bit, two bytes, little endian void EEPROM_write(unsigned int uiAddress, unsigned char ucData) { /* Wait for completion of previous write */ // Bits in EECR register: "- - EEPM1 EEPM0 EERIE EEMPE EEPE EERE" while(EECR & (1<-|D00 >RXD A5|- | \/ | rxd -<-|D01 -(D01)-|03 PD1/TXD PC3 26|-(A3)- -|D04 A1|- -(D02)-|04 PD2/INT0 PC2 25|-(A2)- -|D05~ A0|- -(D03)-|05 PD3/INT1/PWM PC1 24|-(A1)- -|D06~ | Power: -(D04)-|06 PD4 PC0 23|-(A0)- -|D07 Vin|- +5V ---|07 VCC GND 22|--- Gnd | GND|- Gnd ---|08 GND AREF 21|--- Vin -|D08 GND|- Xtal |X|--|09 PB6/OSC1 AVCC 20|--- +5V -|D09~ +5V|- 16MHz |X|--|10 PB7/OSC2 SCK/PB5 19|-(D13)- -|D10~ +3.3V|- -(D05)-|11 PD5/PWM MISO/PB4 18|-(D12)- -|D11~ Res|- -(D06)-|12 PD6/PWM PWM/MOSI/PB3 17|-(D11)- -|D12 IOREF|- -(D07)-|13 PD7 PWM/SS'/PB2 16|-(D10)- -|D13 LED --- | -(D08)-|14 PB0 PWM/PB1 15|-(D09)- -|GND | |______________________________| -|AREF | -|SCL | -|SDA | |________________| */