problem on reading eeprom content

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi;

I have written a program to toggle PB0 and PB1 by sending '1' and '2' and read portB state by sending '3';

and save portB state to eeprom.

data is saved to eeprom correctly and when uC is powered off and on the LED's that are connected to PB0 and PB1 show that the last portB state is loaded correctly.

but when i want to read portbB state by sending '3' i receive incorrect data.

for example when both PB0 and PB1 are low and LED's are off I receive 98 and 98 instead of 0 and 0 when I send '3'.

here is the code:



#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>

volatile int state0,state1;
const uint8_t *state0_address,*state1_address,*data_address; 
void usart_init();

int main(void)
{
    usart_init();
	DDRB=(1<<DDB0)|(1<<DDB1);//set PB0 and PB1 as output
	state0=eeprom_read_byte(state0_address);//read state0(PB0 state) and state1(PB1 state) from eeprom 
	state1=eeprom_read_byte(state1_address);
	PORTB=eeprom_read_byte(data_address);//read previous portB state	
	sei();
    while (1);
}

ISR (USART_RXC_vect)
{
	
	char data=UDR;
	if (data=='1') {
		PORTB^=(1<<PB0);//toggle PB0 if '1' received
		asm ("nop");//nop to update pinB  state
		if(bit_is_clear(PINB,PB0))
		state0=0;
		else state0=1;			
	}
	if (data=='2') {
		PORTB^=(1<<PB1);//toggle PB1 if '2' received
		asm ("nop");
		if(bit_is_clear(PINB,PB1))
		state1=0;
		else state1=1;
	}
	if (data=='3') {
		while( !( UCSRA & (1<<UDRE)) );//send PB0 and PB1 state via USART if '3' received
		UDR=state0;
		while( !( UCSRA & (1<<UDRE)) );
		UDR=state1;
			}
	
	uint8_t data1=PORTB;
	eeprom_write_byte((uint8_t*)data_address,(uint8_t) data1);//save portB state to eeprom
		
}

void usart_init(){
	UCSRB=(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);//enable recieve & interrupt
	UCSRC=(1<<UCSZ0)|(1<<UCSZ1);//8N1
	UBRRH=0;
	UBRRL=12;//BAUD 38400
}

 

This topic has a solution.
Last Edited: Sun. Nov 5, 2017 - 06:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

reza_mslm wrote:
i receive incorrect data.

So what data, exactly, do you receiev?

 

and what were you expecting to receive?

 

Your 'state' variables seem to contain just 0 or 1, and you just send these directly to the UART.

 

If you were expecting to see these as '0' or '1' on a terminal - that won't work!

You would need to send the character '0' or the character '1' for that - not just the binary values ...

 

https://en.wikipedia.org/wiki/ASCII

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Curious use of pointers. Oh and I'll mention EESAVE while I'm at it as EEPROM is involved.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Curious use of pointers. 

Indeed.

 

​And, apparently, uninitialised ...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

 

So what data, exactly, do you receiev?

 

and what were you expecting to receive?

 

 

as I sayed "for example when both PB0 and PB1 are low and LED's are off I receive 98 and 98 instead of 0 and 0 when I send '3'."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

 

So what data, exactly, do you receiev?

 

and what were you expecting to receive?

 

 

as I sayed "for example when both PB0 and PB1 are low and LED's are off I receive 98 and 98 instead of 0 and 0 when I send '3'."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

reza_mslm wrote:
I receive 98 and 98 instead of 0 and 0 when I send '3'.

The 98 is very likely the saved PORTB state. All three EEPROM pointers are 0, therefore you read here

	state0=eeprom_read_byte(state0_address);//read state0(PB0 state) and state1(PB1 state) from eeprom
	state1=eeprom_read_byte(state1_address);
	PORTB=eeprom_read_byte(data_address);//read previous portB state	

in all three cases from the very same location (0) the very same data, which is the saved PORTB state.

(state0 and state1 are never saved to EEPROM anyway)

Stefan Ernst

Last Edited: Sat. Nov 4, 2017 - 05:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sternst wrote:

The 98 is very likely the saved PORTB state. All three EEPROM pointers are 0, therefore you read here

	state0=eeprom_read_byte(state0_address);//read state0(PB0 state) and state1(PB1 state) from eeprom
	state1=eeprom_read_byte(state1_address);
	PORTB=eeprom_read_byte(data_address);//read previous portB state	

in all three cases from the very same location (0) the very same data, which is the saved PORTB state.

(state0 and state1 are never saved to EEPROM anyway)

 

I added 

	eeprom_write_byte((uint8_t*)state0_address,(int) state0);
	eeprom_write_byte((uint8_t*)state1_address,(int) state1);

to ISR but didn't solved.

how can I save my state variables in eeprom and read them correctly?

I can not find my fault

Last Edited: Sun. Nov 5, 2017 - 07:31 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

reza_mslm wrote:
how can I save my state variables in eeprom and read them correctly?

http://www.avrfreaks.net/forum/tut-c-using-eeprom-memory-avr-gcc

 

reza_mslm wrote:
I can not find my fault

As already said, you are writing/reading all three variables to/from one and the same location in EEPROM.

Stefan Ernst

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

how can I save my state variables in eeprom and read them correctly?

Try 

 

const uint16_t state0_address = 10;
const uint16_t state1_address = 11;
const uint16_t data_address   = 12;

uint8_t data1 = PORTB;

eeprom_write_byte((uint8_t*)data_address, data1)   // save portB state to eeprom
PORTB = eeprom_read_byte((uint8_t*)data_address);  // read previous portB state

 

Last Edited: Sun. Nov 5, 2017 - 02:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thank you

Solved

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Still quite wrong. Do you have some aversion to using EEMEM properly?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have no aversion

just don't know how to use it

Last Edited: Tue. Nov 7, 2017 - 09:07 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2
#include <avr/eeprom.h>

int nEE EEMEM = 1234;

int main(void) {
    int nRAM;
    
    nRAM = eeprom_read_word(&nEE);
    eeprom_update_word(&nEE, nRAM + 1);
}

This creates a variable "nEE" in EEPROM and gives it an initial value of 1234. When this program is built both a .hex file for the code and a .eep file for the initial EEPROM data will be created. You use ISP to put the .hex into flash and the .eepm into the EEPROM.

 

When the AVR is powered on it will read the current (1234) value from the nEE location into a variable in RAM called nRAM. It will then write back that value + 1 into the nEE location in the EEPROM.

 

The key thing in all this is that the EEPROM variable is created using "EEMEM" and in the eeprom_do_something() functions you reference it by address using the & (address of) operator. THAT is how you provide the pointer that eeprom_*() functions are looking to use.

 

You will never know the actual address of "nEE" in the EEPROM (just as you probably never know the address of the nRAM variable in RAM either). The linker will assign addresses (that importantly cannot overlap!) to all the variables in your program so you don't have to use things like:

const uint16_t state0_address = 10;
const uint16_t state1_address = 11;
const uint16_t data_address   = 12;

where you take charge of the 10/11/12 in this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0