EB006 with PIC16F88 - EEPROM issue.

For E-blocks user to discuss using E-blocks and programming for them.

Moderators: Benj, Mods

Post Reply
Phaenix
Posts: 13
Joined: Tue Apr 10, 2012 3:39 pm
Has thanked: 4 times

EB006 with PIC16F88 - EEPROM issue.

Post by Phaenix »

I'm trying to write a value to the EEPROM, received from button inputs (see my other thread about the Keypad).

For now I'm doing it with a switch board...

Code: Select all

#include <system.h>

void setup_hardware(void)
{
	trisb = 0xff;
	trisa = 0xe0;
	
	porta = 0x00;
}

void write_eeprom(unsigned char address, unsigned char data)
{
	while (eecon1 & WR);
	
	eeadr = address;
	eedata = data;
	
	clear_bit(eecon1, EEPGD);
	
	set_bit(eecon1, WREN);
	
	clear_bit(intcon, GIE);
	
	eecon2 = 0x55;
	eecon2 = 0xAA;
	
	set_bit(eecon1, WR);
	
	set_bit(intcon, GIE);
	
	clear_bit(eecon1, WREN);
}

unsigned char read_eeprom(unsigned char address)
{
	unsigned char data = 0;
	
	eeadr = address;
	
	clear_bit(eecon1, EEPGD);
	
	set_bit(eecon1, RD);
	
	data = eedata;
	
	return data;
}

int read_eeprom_int(unsigned char address)
{
	unsigned char high, low;
	int data;
	
	low = read_eeprom(address);
	high = read_eeprom(address+1);
	
	data = high * 256;
	data = data + low;
	
	return data;
}

void write_eeprom_int(unsigned char address, int data)
{
	unsigned char high, low;
	
	low = data % 256;
	high = data / 256;
	
	write_eeprom(address, low);
	write_eeprom(address+1, high);
}

unsigned char get_digit(void)
{
	unsigned char count = 0;
	unsigned char oldv, newv;
	oldv = portb ^ 0x00;
	while(count < 20)
	{
		newv = portb ^ 0x00;
		if (oldv == newv)
		{
			count++;
		}
		else
		{
			count = 0;
			oldv = newv;
		}
	}
	return oldv;
}

int get_value(void)
{
	int total = 0, x;
	unsigned char i, k;
	
	for(i=0;i<4;i++)
	{
		while(get_digit() == 0);
		k = get_digit();
		total = total * 10;
		total = total + k;
		for(x=0;x<16000;x++);
	}
	return total;
}

void main(void)
{
	setup_hardware();
	
	int key, attempt, v;
	
	write_eeprom_int(1, 1536);
	
	key = read_eeprom_int(1);

	if (key == 1536)
	{
		porta = 0x01;
	}
}
The following code is ought to write 1536 (split up into two 8-bit numbers) to a place in the EEPROM (1 and 2, here) and then get it back. I put a simple check in it to see if it was succesful. It wasn't. The first LED on porta does not lit up.

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Re: EB006 with PIC16F88 - EEPROM issue.

Post by Benj »

Have you tried with bytes to see if the problem is with the EEPROM functions or the Int to Byte functions.

Phaenix
Posts: 13
Joined: Tue Apr 10, 2012 3:39 pm
Has thanked: 4 times

Re: EB006 with PIC16F88 - EEPROM issue.

Post by Phaenix »

The problem is with the splitting up of the large number. The write_eeprom and read_eeprom functions work.

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Re: EB006 with PIC16F88 - EEPROM issue.

Post by Benj »

Hello,

Yes I see the problem now.

In your write function this code.

Code: Select all

   low = data % 256;
   high = data / 256;
Should look like this.

Code: Select all

   low = data & 0xFF;
   high = data >> 8;
And your read function should also maybe look something like this for better efficiency.

Code: Select all

   data = high << 8;
   data = data + low;
Because the address is always in a power of 2 I would multiply the address by 2 in both the read and write 16-bit int functions before you pass to the byte functions so that you are simply addressing using 0,1, 2 etc instead of 0, 2, 4.

Phaenix
Posts: 13
Joined: Tue Apr 10, 2012 3:39 pm
Has thanked: 4 times

Re: EB006 with PIC16F88 - EEPROM issue.

Post by Phaenix »

I changed it, but I think I found a different problem. When I write several things to the EEPROM using the write_eeprom function, it only writes the first... for example if I did:

Code: Select all

write_eeprom(0, 205);
write_eeprom(1, 6);
write_eeprom(2, 16);
write_eeprom(3, 25);
etc...
only write_eeprom(0, 205); gets done

Phaenix
Posts: 13
Joined: Tue Apr 10, 2012 3:39 pm
Has thanked: 4 times

Re: EB006 with PIC16F88 - EEPROM issue.

Post by Phaenix »

Does anyone know why it does that?

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Re: EB006 with PIC16F88 - EEPROM issue.

Post by Benj »

Hello,

Try changing your write function to look like this.

Code: Select all

void write_eeprom(unsigned char address, unsigned char data)
{
   char intsave = test_bit(intcon, GIE);

   while (test_bit(eecon1, WR));
   
   eeadr = address;
   eedata = data;
   
   clear_bit(eecon1, EEPGD);
   
   set_bit(eecon1, WREN);
   
   clear_bit(intcon, GIE);
   
   eecon2 = 0x55;
   eecon2 = 0xAA;
   
   set_bit(eecon1, WR);
   while (test_bit(eecon1, WR));

   if (intsave)
       set_bit(intcon, GIE);
   
   clear_bit(eecon1, WREN);
}

Phaenix
Posts: 13
Joined: Tue Apr 10, 2012 3:39 pm
Has thanked: 4 times

Re: EB006 with PIC16F88 - EEPROM issue.

Post by Phaenix »

It works now, thank you!

Do you mind explaining why those 'checks' for lack of a better term are necessary? Or rather, why mine wouldn't work for more than one write every time I ran the program?

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Re: EB006 with PIC16F88 - EEPROM issue.

Post by Benj »

Hello,

I think one of the main problems you had was this line.

Code: Select all

while (eecon1 & WR);
This syntax is not correct and not doing what you expect. This code would have worked.

Code: Select all

while (eecon1 & (1<<WR));
i.e. WR is the bit number and not a mask, shifting 1 by the bit number produces a mask we can use. I like the test_bit function instead as it looks slightly cleaner and does pretty much the same thing.

The second check I added at the end of the function waits for the write to complete before clearing the WREN bit. This could also have been causing issues if the write functionality was switched off before the data had gone into the memory.

Post Reply