Home > Atmel AVR > USART and EEPROM on AVR ATMega8515

USART and EEPROM on AVR ATMega8515

Using the EEPROM for text storage on ATMega8515
By 09/11/10 [Last Edited by Joseph 09/11/10]
BOOKMARK
LOGIN
REGISTER
Playing around with interrupt driven USART code, and reading/writing to EEPROM. Made a little bit of code for the AVR, and VB6 app that allows you to store a string of text to the AVR over RS232, and retrieve it. As it the string is stored in the EEPROM, it won't be lost when the power is removed. Probably not the best code ever, just a really quick thing I was working on which I thought I would share.



Tested on ATMega8515 on STK500. Compiled in AVR Studio 4 (WinAVR)

{You can download the sources for both the AVR and VB6 programs, including the compiled binaries from here: EEPROMWriter}

Note:

The code can only handle up to address 255 of the EEPROM, even though there is 512 bytes of EEPROM on the ATMega8515. May work around this later.

Strings are stored from address 1, with address 0 being a byte indicating how long the string is. The string is stored much like a byte array

// Include library files
#include <avr/io.h>
#include <stdlib.h>
#define F_CPU 3680000UL //Define crystal/RC osc frequency
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>

//Definitions
#define CMD_PING 3
#define CMD_READ_EEPROM 4
#define CMD_WRITE_EEPROM 5

#define ACK_OK 100
#define ACK_ERROR 99

// Prototypes
void init_usart(unsigned int baud);
void init_io(void);
void txbyte(unsigned char data);
unsigned char rxbyte(void);
void startup_tasks(void);
void out_debug(unsigned char output);
void out(unsigned char output);
unsigned char out_state(void);


// Let's go

int main(void) 
{
	startup_tasks(); //Boot procedure for microcontroller
	while(1)
	{ //Infinite loop, let ISRs do all the hard work from now on

	}
}

void startup_tasks(void) 
{
	init_usart(23); //Init the USART (Serial) for 3.68Mhz clock at 9600 Baud
	init_io();
	sei(); //Enable interrupts
}

void out_debug(unsigned char output) 
{
	//Procedure to output byte to 'debug' port
	PORTA = output;
}

void out(unsigned char output) 
{
	//Procedure to output byte to output port
	PORTB = output;
}

unsigned char out_state(void) 
{
	//Procedure to get the current output state
	return PORTB;
}

void init_usart(unsigned int baud) 
{
	// Setup serial I/O for communication
	UBRRH = (unsigned char)(baud>>8);
	UBRRL = (unsigned char)baud;                           
	UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
	UCSRC = (1 << URSEL) | (3 << UCSZ0);
}

SIGNAL (SIG_UART_RECV) 
{ 
	//USART RX interrupt service routine
	switch(UDR) 
	{
		case(CMD_PING):
			txbyte(ACK_OK);
			break;
		case CMD_READ_EEPROM:
			txbyte((unsigned char)eeprom_read_byte((uint8_t*)rxbyte()));
			break;
		case CMD_WRITE_EEPROM:
			eeprom_write_byte ((uint8_t*)rxbyte(), (uint8_t)rxbyte());
			txbyte(ACK_OK);
			break;
		default:
			txbyte(ACK_ERROR);
			break;
	}
	
}

void init_io(void) 
{
	DDRB = 255; //Set PORTB for output (Relay Outputs)
	DDRA = 255; //Set PORTA for output (Debug Output)
}

void txbyte(unsigned char data) 
{
	while ( !( UCSRA & (1<<UDRE)) ); //Wait for empty slot to send data
	UDR = data; //Send it

}

unsigned char rxbyte (void) 
{
	while ( !(UCSRA & (1<<RXC)) ); //Wait until there is a byte to be read from RX buffer
	return UDR; //Get it

}

And here's the VB6 app. Just make a textbox with the name txtMem, and the MSComm object with the name serial. Make two buttons, btnRead and btnWrite.

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Sub btnRead_Click()
    txtMem.Text = ""
    Dim i As Byte
    For i = 1 To getMem(0)
        txtMem.Text = txtMem.Text & Chr$(getMem(i))
    Next
End Sub

Private Sub btnWrite_Click()
    writeMem 0, Chr$(Len(txtMem.Text))
    delay
    Dim i As Byte
    For i = 1 To Len(txtMem.Text)
        writeMem i, Mid(txtMem.Text, i, 1)
        delay
    Next
End Sub

Sub Form_Load()
    serial.CommPort = 2
    serial.InBufferSize = 1
    serial.InputMode = comInputModeBinary
    serial.PortOpen = True
End Sub

Sub writeMem(ByVal byLoc As Byte, ByVal szData As String)
    serial.Output = Chr$(5)
    serial.Output = Chr$(byLoc)
    serial.Output = szData
End Sub

Function getMem(ByVal byLoc As Byte) As Byte
    serial.Output = Chr$(4)
    serial.Output = Chr$(byLoc)
    getMem = getByte
End Function

Private Function getByte() As Byte
    Sleep (10) 'Wait a bit for the microcontroller to get into the swing of things
    Dim byInData() As Byte
    Dim i As Byte
    byInData = serial.Input 'Get the COM port buffer into byte array
    If UBound(byInData) > -1 Then 'Check we actually have something in the buffer
        For i = 0 To UBound(byInData)
            getByte = byInData(i)
        Next
    Else
        getByte = 0
    End If
End Function

Sub delay()
    Sleep (10)
End Sub