MC9S08QG8 SPI Problem

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

MC9S08QG8 SPI Problem

1,030 Views
QG8dog
Contributor I
Hello,
I'm developing microcode for the MC9S08QG8 to act as a SPI slave device. I developed an extremely simple test application to test the robustness of my SPI communications (e.g. to see if communications break down at a particular baud rate). The test involves a MC9S08QG8 acting as a master and a MC9S08QG8 acting as a slave - connected appropriately.

Note that SSOE=1 and MODFEN=1, so /SS details are handled by the SPI module.

Code:
************************Problem Master Code******************************void setSPID( byte value ) {while ( !SPIS_SPTEF );SPID = value;}byte getSPID() {while ( !SPIS_SPRF );return SPID;}void main() {// setup for SCI here for serial port communication// setup SPI here; interrupts off// clear out anything in the slave bufferssetSPID( 0xff );getSPID();setSPID( 0xff );getSPID();setSPID( 0xff );getSPID();setSPID( 0x0a );getSPID();while ( true ) {byte i, b;do {SendMsg( "X" ); // SCI communicationsetSPID( 0x0a );b = getSPID(); // should always be a value between 1 and 6} while ( b == 0 );setSPID( 0x0 );b = getSPID(); // should always be a value between 1 and 6for ( i = 0; i != b; i++ ) {if ( i+1 == b )setSPID( 0xa );elsesetSPID( 0x0 );showVal( getSPID() ); // Should ALWAYS be 0. SCI communication.}// for pretty printingv[ 0 ] = '\r'; // SCISendMsg( v ); // SCIv[ 0 ] = '\n'; // SCISendMsg( v ); // SCI}}

 


Code:
************************Slave Code******************************void main() {byte z1=0;while ( 1 ) {byte val;WATCHDOG;val = getSPID();if ( val == 0xff ) continue; // ignore 0xff'sif ( val == 0x0 ) {setSPID( 0x0 );} else if ( val == 0xa ) {z1 = (z1 + 1) % 6;setSPID( z1 + 1 );} else {setSPID( val ); // this line never executes as a part of the test}} /* loop forever */}

 


******************************************************

To run the test, the master and slave are hooked together and a laptop is connected to th e serial port of the master. Hyperterminal is used on the laptop to display the SCI output from master. The master and slave should communicate back and forth indefinitely and the master should send SCI communication like:
X0
X000
X00000
X0
X000
etc..

What I found is that if I let this run for a few minutes, the master and slave get out of synch resulting in SCI communications like
XX10000
XX1000
XX...
etc.

The problem is that the master and slave are getting out of synch. The way the code is written, this should obviously never happen. What I eventually found was that when I altered the master's getSPID and setSPID to include a very small delay, the test no longer gets out of synch (even after hours).

Code:
**************************New Master getSID and setSPID*************void setSPID( byte value ) {byte x;while (!SPIS_SPTEF );SPID = value;// MINOR DELAYx = 0;do {x++;}while ( x != 20 );}byte getSPID() {byte x;while ( !SPIS_SPRF );// MINOR DELAYx = 0;do {x++;}while ( x != 20 );return SPID;}

 

This is obviously very concerning and I can find no reason in the documentation to expect that such a delay should be necessary. It happens at even the slowest baud rate. Any insight someone could provide would be greatly appreciated!

Message Edited by Alban on 2007-01-17 09:09 PM

Labels (1)
0 Kudos
1 Reply

219 Views
bigmac
Specialist III
Hello,
 
I suspect there might be a slight misunderstanding in the way that the SPI operates.
 
Whenever the master sends a byte to the slave, the slave will simultaneously return a byte to the master, and the byte value will be whatever was in the slave data register just prior to the transaction commencing.  If you need to obtain a return byte from the slave in response to the byte it has just received (as I suspect you do), you will need to commence a second transaction from the master in order to get the response, and this should be delayed by a sufficient amount for the slave to process the received byte, and to load a new value to its data register.
 
For the master I would generally prefer to emphasize that SPI is a two-way "transaction", so would combine the send and receive processes, for each byte, within a single function.  This might avoid some of the confusion.
 
byte SPItrans( byte value )
{
  // while ( !SPIS_SPTEF ); // Probably unnecessary for modified code
  SPID = value;
  while ( !SPIS_SPRF );
  return SPID;
}
This function will return the immediate value from the slave, not the response to the byte sent.  The function would be used in the following manner -
 
SPItrans( command1 );  // Ignore garbage return
// Wait for slave to process command
resp1 = SPItrans( command2 );  // Receive response to first command
// Wait for slave to process command
resp2 = SPItrans( command3 );  // Receive response to second command
// Wait for slave to process command
resp3 = SPItrans( 0 );         // Send dummy byte if no further data
 
For the slave end, receive and send should remain as individual functions.
 
Regards,
Mac
 
0 Kudos