9S08AW60  SPI 4Kb EERPOM   X5043/X5045

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

9S08AW60  SPI 4Kb EERPOM   X5043/X5045

3,538 Views
harlenChen
Contributor I
Hello,
I am using 9s08AW60 ' SPI module to connect with X5043 EEPROM.
But I can read anything from the EEPROM device?
The following is the Read Devide code:
#define CS PTED_PTED4
Void SPIInit(void)
{  
  SPI1C1 = 0x00;                     
  SPI1C2 = 0x00;       //clear the control register                               
  SPI1BR = 0x04;   // set the Speed
  SPIS;                   //clear the status register
  SPI1C1 = 0x50;   //set the control register                                   
}
 
unsigned char ReadByte(unsigned char ADD)
{
unsigned char Temp;
CS=0;
while(! SPI1S_SPTEF ); SPI1D =0x03;     //send the Read command
while(! SPI1S_SPTEF ); SPI1D = ADD;   //send the address
while(!SPI1S_SPRF);  Temp = SPI1D;    // feedback the data of  address
CS = 1;
return Temp;
}
 
 
Very thank for your reply.
Labels (1)
0 Kudos
12 Replies

1,071 Views
harlenChen
Contributor I
Now , it;s OK
 
Thanks every one
0 Kudos

1,071 Views
harlenChen
Contributor I
Thanks for veryone's reply.
 
I have try to use your offering method, however, can not read EEPROM..
 
I have attached the X5045 PDF.
 
According the spec. SI and SO have different edge.
So how to set the SPOL and SPHA ?
Message Edited by t.dowe on 2009-08-31 04:25 PM
0 Kudos

1,071 Views
bigmac
Specialist III
Hello,
 
Your original setup had CPHA=0 and CPOL=0.  For the EEPROM device, I would suspect that the setting should be altered to CPHA=1.
 
You need to compare the waveforms shown in the MCU data sheet with those shown for the EEPROM.  The clue is whether the MSB of the data is captured, for both the MCU and the EEPROM, on the first or second edge of the clock waveform.  For CPHA=1, it is the second edge.  For CPOL=0, this edge is negative.
 
The point at which an output changes state (MOSI for MCU, SO for EEPROM) and the point at which an input is read (MISO for MCU, SI for EEPROM), will always be on different edges of the clock.  This allows about one half cycle for the data output to settle, before it is read.
 
Regards,
Mac
 
0 Kudos

1,071 Views
peg
Senior Contributor IV
Hi harlen Chen,
 
Without knowing the details of this memory device, I think what you need to do is send a dummy byte after the address for the response to "ride back" on.
 
Try chaging your routine to this:
unsigned char ReadByte(unsigned char ADD)
{
unsigned char Temp;
CS=0;
while(! SPI1S_SPTEF ); SPI1D =0x03;     //send the Read command
while(! SPI1S_SPTEF ); SPI1D = ADD;   //send the address
while(! SPI1S_SPTEF ); SPI1D = 0x00;   //send dummy to enable response to come in
while(!SPI1S_SPRF);  Temp = SPI1D;    // feedback the data of  address
CS = 1;
return Temp;
}
 
All transfers must be intiated by the master and the memory cannot reply until it has the address, so you need to sent something/anything to read the response data in.
 
I am presuming a one byte response.
 
0 Kudos

1,071 Views
bigmac
Specialist III
Hello,
 
I can see two problems with your code . . .
 
As Peg has already said, to read a single byte value from the EEPROM, you need to send three bytes, (and receive three bytes) over the SPI.
1st byte:  send READ command, receive garbage
2nd byte:  send ADDRESS, receive garbage
3rd byte:  send dummy value (say zero), receive value from EEPROM
 
The second problem is that receive overrun will be occurring, since the SPRF flag is not cleared for the first two bytes sent. This will cause loss of the later received bytes, i.e. the second garbage byte and the real EEPROM value.  The flag must be cleared after both the first and second send bytes, even though the returned data is not used.  You would wait until SPRF is set, and then read SPI1D, as is already done for the third byte.
 
A final comment - the MISO line will be high-Z during the sending of the first two bytes, and when the EEPROM device is not enabled.  If the SPI master is to remain continuously active, there should be an external pull-up (or pull-down) resistor connected to this line to prevent the input to the MCU causing excessive current draw when at an intermediate voltage level.
 
Alternatively, if the SPI module is disabled when not in use, the underlying GPIO associated with all three SPI pins should be set for output.
 
Regards,
Mac
 


Message Edited by bigmac on 2007-07-17 03:09 AM
0 Kudos

1,071 Views
bigmac
Specialist III
Hello,
 
The following code demonstrates what I alluded to in my previous post.  The SPI_trans() function would be common to all SPI operations, whatever the SPI slave device.
 
unsigned char ReadByte(unsigned char ADDR)
{
   unsigned char Temp;
 
   CS = 0;                  /* Enable EEPROM device */
   Temp = SPI_trans(READ);  /* Send READ command */
   Temp = SPI_trans(ADDR);  /* Send address value */
   Temp = SPI_trans(0);     /* Send dummy value, receive data */
   CS = 1;                  /* Disable EEPROM device */
   return Temp;
}
 
unsigned char SPI_trans(unsigned char val)
{
   while (!SPI1S_SPTEF);
   SPI1D = val;            /* Send byte value */
   while (!SPI1S_SPRF);
   return SPI1D;           /* Return received value, clear flag */
}
 
I also notice that you have CPHA = 0, within SPI1C1 register.  I suspect the correct setting should be CPHA = 1 for the X5043, i.e.  SPI1C1 = 0x54;
 
Is there a reason you initially set SPI1C1 to zero, and then changed the value at the end of the initialisation function?  Why not set SPI1C1 to the required value first up?
 
Regards,
Mac


Message Edited by bigmac on 2007-07-17 04:10 AM
0 Kudos

1,071 Views
peg
Senior Contributor IV
Hello,
 
Woops! perhaps I should read my own posts:smileyhappy:
 
Here is another way to do it:
 
unsigned char ReadByte(unsigned char ADD)
{
unsigned char Temp;
CS=0;
while(!SPI1S_SPTEF ); SPI1D =0x03;    //send the Read command
while(!SPI1S_SPTEF ); SPI1D = ADD;   //send the address - use double buffer
while(!SPI1S_SPRF);  Temp = SPI1D;    //strip out first garbage return
SPID = 0x00                           //send a dummy byte to get the address
while(!SPI1S_SPRF);  Temp = SPI1D;    //strip out second garbage return
while(!SPI1S_SPRF);  Temp = SPI1D;    //feedback the data at the address
CS = 1;
return Temp;
}
0 Kudos

1,071 Views
bigmac
Specialist III
Hello Peg,

peg wrote:
Here is another way to do it:
 
unsigned char ReadByte(unsigned char ADD)
{
unsigned char Temp;
CS=0;
while(!SPI1S_SPTEF); SPI1D = 0x03; //send Read command
while(!SPI1S_SPTEF); SPI1D = ADD; //send address - double buffer
while(!SPI1S_SPRF); Temp = SPI1D; //strip out first garbage return
SPID = 0x00                       //send dummy byte to get address
while(!SPI1S_SPRF); Temp = SPI1D; //strip out second garbage return
while(!SPI1S_SPRF); Temp = SPI1D; //feedback data at address
CS = 1;
return Temp;
}

I think your code may be a little risky, certainly when using a fast SPI clock rate.  Consider the scenario where an interrupt (any interrupt) occurs after the address has been sent, but prior to SPTEF being tested.  Since the ISR delay is very likely to exceed the SPI transmission period, overrun would occur and the second garbage return would be lost.
 
Under these circumstances, the first read of SPI1D would return the first garbage byte, and the second read, after the dummy byte is sent, would return the wanted byte.  The function would then wait indefinitely for SPIF to become set again.
 
An attempt to single step the code would likely cause a similar problem.
 
I think it is much safer to wait for SPIF to become set after each byte is sent.
 
Regards,
Mac
 


Message Edited by bigmac on 2007-07-17 12:30 PM
0 Kudos

1,071 Views
peg
Senior Contributor IV
Hi Mac,
 
I was well aware of this limitation. I put it out there because I am struggling to understand how to make use of the buffered nature of the SPI. The way you are doing it, and the way I would normally do it, would work with a totally unbuffered SPI.
What is the benefit of having the buffers? It seems nearly impossible to maintain the required co-ordination to enable their use.
If the recieve buffers could hold two full values like the transmit then my proposal would work.
Perhaps the manual is misleading here and the byte in the shifter will wait for the buffer read?
I might try this later.
 
0 Kudos

1,071 Views
rocco
Senior Contributor II
Hi Peg,

peg wrote:

What is the benefit of having the buffers? It seems nearly impossible to maintain the required co-ordination to enable their use.

I see the purpose of the buffers as a way to allow a continuous stream of bits greater than eight (although always a multiple of eight). The buffer on the transmitter allows the next byte to start shifting without any interuption of the clock. The buffer on the receiver does the same, by giving the shift register someplace to put the received byte, so that it could continue to receive another byte.

When the SPI is a master, this may not be all that useful. Although I have made use of the continuous clock to drive sequencers external to the MCU, if the clock paused every eight bits, it probably wouldn't be the end of the world.

But as a slave, when the MCU does not control the clock, the ability to transfer more than eight bits at a time is what makes the SPI usable. Hook your SPI up to a codec that sends 24 bits at a time, word after word continuously, and you see how necessary that buffering can be.

When trying to talk to a simple EEPROM, the buffers just get in the way.
0 Kudos

1,071 Views
bigmac
Specialist III
Hello Rocco and Peg,
 
It would seem that, in about 95% of cases, the posts to this forum about SPI concern the MCU as a master.  Very very rarely is the MCU used as a slave.  The only instances I can think of were about MCU to MCU communications, possibly in a multi-master situation.
 
However, I agree with Rocco that the situation of the slave will be substantially different than that of the master -
  1. Use of the SPI interrupts would generally be necessary for a slave MCU, in order to read each incoming byte, and then process the byte in a timely manner.
  2. The byte value to be returned to the master must be loaded to the send buffer prior to the arrival of the first clock pulse of the next incoming byte, or prior to SS reactivating, depending on CPHA mode.  So, as Rocco said, it makes total sense to be able to queue two bytes in the send buffer of a slave.
This will mean that, when an incoming byte is received, the send buffer will always be immediately ready to accept the next byte value to be returned, presumably done within the ISR.  Without the double buffer, there would be a delay of one transmission period before this could occur.
 
This probably explains Peg's query to why there is additional buffering for send, compared with the receive buffering.  For the SPI master, I don't think there is anything at all to be gained by attempting to utilize the double send buffering, especially at high clock rates.
 
Regards,
Mac
 
0 Kudos

1,071 Views
peg
Senior Contributor IV
Yep!
 
I just came to the same conclusion.
 
Double buffering (or single buffering of the shifter I would call it) helps a great deal in both directions in a slave.
 
It is totally useless in a master, but poses no problem as it is virtually transparent as the bytes fall straight through (almost).
 
Well totally useless if you care about the returned bytes, you could keep an output only going full tilt easily with the buffer.
 
I just did some testing and just like the datasheet says if that second byte gets all the way in before you read the first one out of the buffer it vaporises, never sets SPRF again and if you just read again anyway you get the first byte again. While it works at full speed you would not want to rely on it.
 
So its probably better to not even think about those buffers while you programming bidirectional master SPI comms.
 
 
0 Kudos