View previous topic :: View next topic |
Author |
Message |
sdkilde
Joined: 19 Dec 2009 Posts: 4 Location: Wisconsin
|
SPI Read problem on 25LC256 |
Posted: Tue May 18, 2010 6:50 am |
|
|
I am seeing a problem with reading data from a 25LC256. Specifically what is happening is there is a right-shift by one bit to the data (eg receiving 3F instead of the actual 7E). The code below writes the data correctly (I verified by pulling chip after a write and reading it with a EEPROM programmer that the data sent was correct). However the read is bit shifted and I don't see why it would be. Any help would be appreciated.
Code: |
#define EEPROM_SELECT PIN_H4
#define EEPROM_DI PIN_C4
#define EEPROM_DO PIN_C5
#define EEPROM_ADDRESS long int
#define EEPROM_SIZE 32768 //32Kb x 8
#define READ 0b00000011
#define WRITE 0b00000010
#define WRDI 0b00000100
#define WREN 0b00000110
#define RDSR 0b00000101
#define WRSR 0b00000001
void init_ext_eeprom()
{
output_high(EEPROM_WP);
output_high(EEPROM_HOLD);
output_high(EEPROM_SELECT);
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16 );
return;
}
//--------------------------------
int1 ext_eeprom_ready(void)
{
BYTE data;
output_low(EEPROM_SELECT);
spi_write(RDSR);
data = spi_read(0);
output_high(EEPROM_SELECT);
return(!bit_test(data, 0));
}
//--------------------------------
void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data)
{
while(!ext_eeprom_ready());
output_low(EEPROM_SELECT);
spi_write(WREN);
output_high(EEPROM_SELECT);
output_low(EEPROM_SELECT);
spi_write(WRITE);
spi_write(address >> 8);
spi_write(address);
spi_write(data);
output_high(EEPROM_SELECT);
return;
}
//--------------------------------
BYTE read_ext_eeprom(EEPROM_ADDRESS address)
{
BYTE data;
while(!ext_eeprom_ready());
output_low(EEPROM_SELECT);
spi_write(READ);
spi_write(address >> 8);
spi_write(address);
data = spi_read(0);
output_high(EEPROM_SELECT);
return(data);
}
|
I am using CCS version 4.103. The project is using a PIC18F97J60 at 25MHZ with #define INTERNAL_CLOCK 0.16 statement in the main program prior to doing any SPI actions. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 18, 2010 12:25 pm |
|
|
If you have a problem where your SPI data is "off by one bit", it's
usually caused by selecting the wrong SPI mode. The mode is critical
for correct operation in SPI.
The first thing is to determine the SPI mode used by your slave device.
In Microchip data sheets, they very nicely give the mode in the timing
diagrams for the chip. Look at the timing diagrams on page 5 of
the 25LC256 data sheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/21822F.pdf
You'll see that they use Mode 0,0 or 1,1. (That's in binary).
You can also call these Mode 0 and Mode 3.
Now you need some way to specify the mode in CCS. This information
is available in the forum archives. You just sort of have to know it's there:
Code: |
// SPI mode definitions.
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
|
Here's your SPI statement:
Quote: |
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16 );
|
We can see that you're using Mode 2, which is not correct. That's likely
the cause of your "shifted by 1" problem.
The solution is to add those 4 #define statements above main(), and
then edit your setup_spi() statement to use the proper mode:
Code: |
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_16 );
|
Notice how that line is now self-documenting. You can see the SPI mode
just by looking at it. |
|
|
sdkilde
Joined: 19 Dec 2009 Posts: 4 Location: Wisconsin
|
|
Posted: Tue May 18, 2010 12:47 pm |
|
|
Thanks that was the problem |
|
|
|