mc9s12dp512 SPI interfacing problems

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

mc9s12dp512 SPI interfacing problems

Jump to solution
2,043 Views
Franklin
Contributor I

Hi,

I am trying to use the processor expert SPI bean to help establish communication between my MCU and a sensor. I know very little about how SPI works, and am having difficulty trouble-shooting the problem. Does the hcs12 store any data being sent from the slave in a buffer, which can then be read at a later time using the RecvChar command?

 

A potential problem is that the hcs12 only seems to run the clock (SCLK) signal while it is sending data, and I can't figure out how to get it to run during the time when it is supposed to be receiving a signal. Also, I don't see a way to modify or pick the clock speed. I have attached the document which describes the SPI  interface on my sensor, and posted my code below.

/* Including used modules for compiling procedure */
#include "Cpu.h"
#include "Events.h"
#include "SPI3.h"
#include "Inhr1.h"
#include "Inhr2.h"
#include "Inhr3.h"
#include "SRREADY.h"
#include "PORTP0.h"
#include "PORTP1.h"
#include "PORTP2.h"
#include "PORTP3.h"
/* Include shared modules, which are used for whole project */
#include "PE_Types.h"
#include "PE_Error.h"
#include "PE_Const.h"
#include "IO_Map.h"

//constants
int SPI_DELAY = 100;

//vars
int response=0;

int skipperoo=0;
   byte recvd1=0;
  byte recvd2=0;
  int reply=0;

int SPIcommand(byte command, byte operand)
{


  PORTP0_SetVal();
  PORTP1_ClrVal();
  
  SPI3_SendChar(command);
  SPI3_SendChar(operand);

  PORTP0_ClrVal();
  PORTP1_SetVal();
 
  //while(!SRREADY_GetVal());
//  while(!PORTP2_GetVal());
  Cpu_Delay100US(SPI_DELAY);

  PORTP0_SetVal();
  PORTP1_ClrVal();

  SPI3_RecvChar(&recvd1);
  SPI3_RecvChar(&recvd2);

  reply = recvd1;
  reply <<= 8;
  reply += recvd2;

  return reply;
}

void main(void)
{
  /*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
  PE_low_level_init();
  /*** End of Processor Expert internal initialization.                    ***/



  for(;;)
  {
       response = SPIcommand(4,0);

    PORTP3_NegVal();

    //Cpu_Delay100US(1*SPI_DELAY);
  }
  /*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
  for(;;){}
  /*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

 


 

Message Edited by Franklin on 2009-11-12 06:41 PM
Message Edited by t.dowe on 2009-11-13 09:49 AM
Labels (1)
0 Kudos
1 Solution
649 Views
bigmac
Specialist III

Hello,

 

I think that the main problem with your code is that you have not met the SPI data format requirements of the slave device, as detailed in its datasheet.

 

You do not say, but am I correct in assuming that "PORTP0" represents the signal SEN0, and "PORTP1" the signal SEN1?  It would appear that SEN0 should remain inactive high for the whole period of a command sequence.  Similarly SEN1 should remain inactive high for the whole period of an event interface sequence.

 

Additionally, a command may have either no operand, or a single 16-bit (word) operand.  Your code does not currently allow for either of these alternatives.  So we appear to require either a total transmission of 8-bits for no operand, or alternatively a total of 24-bits.

 

It would appear that you may need a separate function for each case, or a special "invalid" operand value that is outside the normal operand range.  A value of 0xFFFF might be such a value.  Perhaps something like the following untested code would work -

 

word SPIcommand( byte command, word operand)
{
  byte recvd1;
  byte recvd2;

  PORTP0_SetVal();  // Ensure SEN0 event interface disabled
  PORTP1_ClrVal();  // Enable SEN1 command interface
  
  SPI3_SendChar(command);
  if (operand < 0xFFFF) {                 // Test for operand present
    SPI3_SendChar((byte)(operand / 256)); // High operand byte
    SPI3_SendChar((byte)(operand % 256)); // Low operand byte
  }  PORTP1_SetVal();            // Set SEN1 inactive 
  while (!SRREADY_GetVal());  // Wait until ready for data return

  PORTP1_ClrVal();            // Re-enable SEN1 command interface
  SPI3_RecvChar(&recvd1);     // High return byte
  SPI3_RecvChar(&recvd2);     // Low return byte
  PORTP1_SetVal();            // Set SEN1 inactive
  return (recvd1 * 256 + recvd2);
}

 

Regards,

Mac 

View solution in original post

0 Kudos
5 Replies
649 Views
Franklin
Contributor I
Thanks guys,

I think I have my issues worked out, for the most part. It was a combination of things, as usually happens.

I misread the documentation on the slave spi (my sensor device) and thought the two spi select signals mixed up. I thought SEN0 was for the command interface, and SEN1 for the  event interface. The other big problem was that my codewarrior seems to be highly unreliable. In a fit of frustration, I recreated my project, replicated my beans, and copy/pasted my code into the new project. It gave me a link error because I forgot to enable a bean method. When I enabled it and tried to compile, again I got the link error. After synch. modification dates, it compiled and the SPI seemed to work, though. The lesson seems to be: When in doubt, create a replica of your project and try again.

Oh, and RTFM of course.
0 Kudos
649 Views
Franklin
Contributor I

Actually, I will take that back. Things don't work.

 

The signal SRDY, which is supposed to go low-high when the slave is ready to transmit a response, is not doing anything, ever. Yet somehow, there is a signal appearing on SDO. Now, my question is, since the master controls the clock, how does the master know when to run the SCK signal for receiving information? It can't possibly, unless reading the signal from SRDY, right? Only, that signal is not transitioning, and somehow the slave device is still sending something out. I am so confused... 

0 Kudos
649 Views
Lundin
Senior Contributor IV
The SPI data register is a shift register. When you clock out data from the master on MOSI, you clock in data from the slave on MISO simultaneously.

Note that SPI flags are cleared in a very dumb way on Freescale micros: you clear by reading. This will make the debugger destroy these flags in case the SPI status register is shown in memory maps, watch variables etc. This is a common cause of flag clearing issues and deadlock while debugging Freescale micros with SPI.
0 Kudos
649 Views
Lundin
Senior Contributor IV
If you know very little about SPI, the SPI manual might be good reading... Processor Expert is no replacement for engineering knowledge.

Yes the HCS12 stores the data in the same register that is used to send data. As for SPI clock, why would you need it to be active when there is no data communication? If the device is a ADC or similar clocked device, you should clock it from a real oscillator.

The most common problem with SPI is "clock skew", which means that the master & slave either trigger on different slopes of the clock, or that the master sends the clock with 0,5 bits offset. You can set both of these options in the SPI registers. You need to read the datasheets of the slave device carefully before doing so.
0 Kudos
650 Views
bigmac
Specialist III

Hello,

 

I think that the main problem with your code is that you have not met the SPI data format requirements of the slave device, as detailed in its datasheet.

 

You do not say, but am I correct in assuming that "PORTP0" represents the signal SEN0, and "PORTP1" the signal SEN1?  It would appear that SEN0 should remain inactive high for the whole period of a command sequence.  Similarly SEN1 should remain inactive high for the whole period of an event interface sequence.

 

Additionally, a command may have either no operand, or a single 16-bit (word) operand.  Your code does not currently allow for either of these alternatives.  So we appear to require either a total transmission of 8-bits for no operand, or alternatively a total of 24-bits.

 

It would appear that you may need a separate function for each case, or a special "invalid" operand value that is outside the normal operand range.  A value of 0xFFFF might be such a value.  Perhaps something like the following untested code would work -

 

word SPIcommand( byte command, word operand)
{
  byte recvd1;
  byte recvd2;

  PORTP0_SetVal();  // Ensure SEN0 event interface disabled
  PORTP1_ClrVal();  // Enable SEN1 command interface
  
  SPI3_SendChar(command);
  if (operand < 0xFFFF) {                 // Test for operand present
    SPI3_SendChar((byte)(operand / 256)); // High operand byte
    SPI3_SendChar((byte)(operand % 256)); // Low operand byte
  }  PORTP1_SetVal();            // Set SEN1 inactive 
  while (!SRREADY_GetVal());  // Wait until ready for data return

  PORTP1_ClrVal();            // Re-enable SEN1 command interface
  SPI3_RecvChar(&recvd1);     // High return byte
  SPI3_RecvChar(&recvd2);     // Low return byte
  PORTP1_SetVal();            // Set SEN1 inactive
  return (recvd1 * 256 + recvd2);
}

 

Regards,

Mac 

0 Kudos