GT16A SPI

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

GT16A SPI

843 Views
woohoo
Contributor I

Hi,

 

I am trying to get two GT16A MCUs to communicate via SPI, however I am not succeeding. The master is configured as shown below(SPI_Initialise), with the data sending being done in the laserComm function where Data[] is an array of unsigned char. Finally, the slave is configured as initSPI shows with the receiving done in the receiveSPI function. Any help would be appreciated!

 

void SPI_Initialise (void){      SPIBR = 0x00; // SPI baud rate = 9.437184MHz    SPIC1_SPIE  = 1;   SPIC1_SPE   = 1;   SPIC1_SPTIE = 0;    SPIC1_MSTR  = 1;   SPIC1_CPOL  = 0;   SPIC1_CPHA  = 1;   SPIC1_SSOE  = 0;   SPIC1_LSBFE = 0;     //SPIC2 = 0x00; // SPI control register 2 setup   SPIC2_MODFEN = 0;   SPIC2_BIDIROE = 0;   SPIC2_SPISWAI = 0;    SPIC2_SPC0 = 0; } void laserComm(char Data[]){   int i;   PTCD_PTCD6 = 0; //Pull low to select slave   PTCD_PTCD5 = 0; //Pull low to select slave   PTCD_PTCD4 = 0; //Pull low to select slave   PTCD_PTCD3 = 0; //Pull low to select slave    for(i = 0; i<=dataSize; i++){//send data   while(!SPIS_SPTEF)   SPID = Data[i++];   }   PTCD_PTCD6 = 1;   PTCD_PTCD5 = 1;   PTCD_PTCD4 = 1;   PTCD_PTCD3 = 1; }  ///////// SLAVE //////////////// void initSPI (void){    SPIC1_SPIE = 1;   // SPI control register 1 setup   SPIC1_SPE = 1;    // SPI enable   SPIC1_SPTIE = 0;  // Transmit interrupt enable   SPIC1_MSTR = 0;   // Slave select   SPIC1_CPOL = 0;   // Clock polarity   SPIC1_CPHA = 1;   // Clock phase   SPIC1_SSOE = 0;   // Slave select output enable   SPIC1_LSBFE = 0;  // LSB first disabled      //SPIC2 = 0x00; // SPI control register 2 setup   SPIC2_MODFEN = 0;   SPIC2_BIDIROE = 0;   SPIC2_SPISWAI = 0;    SPIC2_SPC0 = 0; }  interrupt 15  // SPI receive interrupt   void receiveSPI (void){   int i;     for (i = 0; i<=dataSize; i++)   while(!SPIS_SPRF) SPIdataIn[i] = SPID;  // Wait for receive buffer flag, read data        SPIdataReceived = 1;     }

 

 

Labels (1)
0 Kudos
6 Replies

624 Views
Monica
Senior Contributor III

Oliver, how is the project going?

Please let us know! :smileywink:

Regards!

0 Kudos

624 Views
bigmac
Specialist III

Hello Oliver,

There seems to be a couple of issues with your master function.

void laserComm( char Data[])

  int i;

  PTCD_PTCD6 = 0; // Pull low to select slave

  PTCD_PTCD5 = 0; // Pull low to select slave

  PTCD_PTCD4 = 0; // Pull low to select slave

  PTCD_PTCD3 = 0; // Pull low to select slave

  for( i = 0; i <= dataSize; i++) { // send data

    while( !SPIS_SPTEF)  SPID = Data[i++];

  }

  PTCD_PTCD6 = 1;

  PTCD_PTCD5 = 1;

  PTCD_PTCD4 = 1;

  PTCD_PTCD3 = 1;

}


The state of the flag SPIS_SPTEF is high when ready to send data, and goes low whenever the buffer is full.  You are attempting to send the data when the flag is low.  This condition can never occur within your code.  The second problem is that you are potentially going to set the SS signals high before final byte tranfer has finished.  To determine completion of transfer, you need to wait until the SPIS_SPRF flag is set. The corrected code follows -

void laserComm( char Data[])

{  

  int i;

 

  PTCD_PTCD6 = 0; // Pull low to select slave

  PTCD_PTCD5 = 0; // Pull low to select slave

  PTCD_PTCD4 = 0; // Pull low to select slave

  PTCD_PTCD3 = 0; // Pull low to select slave

 

  for( i = 0; i <= dataSize; i++) {

    while( !SPIS_SPTEF);     // Wait until ready to send

    SPID = Data[i++];        // send data byte

    while( !SPIS_SPRF);      // Wait until transfer is complete

    (void)SPID;              // Clear flag

  }

 

  PTCD_PTCD6 = 1;

  PTCD_PTCD5 = 1;

  PTCD_PTCD4 = 1;

  PTCD_PTCD3 = 1;

}

The slave function also has some issues.  I notice that you have a wait condition within your ISR code while you attempt to receive multiple bytes.  It is normal to process only a single byte for each interrupt, to keep the ISR duration as short as possible.

You are also attempting to read the data when the flag is clear, and the transfer is incomplete.  The interrupt will occur when the flag becomes set.  You must clear the flag before exiting the ISR.  There does seem to be a misunderstanding about the functionality of the flags.

The byte counter will need to be a static or global variable defined outside of the ISR function, and this will need to be initialised prior to each sequence.  You will probably need to sense the state of the SS signal to determine when initialisation should occur.

Regards,

Mac

0 Kudos

624 Views
bigmac
Specialist III

Hello Oliver,

The following untested code provides an example of the SPI slave process, using interrupts.  I have assumed that the GPIO pin PTCD4 is paralleled with the SS pin (PTE2), for sensing the SS state.

#define SS_sig  PTCD_PTCD4    // Additional input pin paralleled with SS

// Static variables:
static byte SPIdataIn[dataSize];
static byte count = 0;

byte Wait_for_SPIdata( void)
{
   byte c;
  
   if (SS_sig)  return 0;     // No data transfer yet
   while (!SS_sig);           // Wait for completion of transfer sequence
   c = count;                 // Number of bytes transferred
   count = 0;                 // Ready for next sequence
   return c;
}

// SPI receive interrupt
interrupt 15 void receiveSPI( void)
{  
  (void)SPIS;                 // Commence clear flag
  SPIdataIn[count++] = SPID;  // Read data
}

Regards,

Mac


0 Kudos

624 Views
AntiGeri
Contributor II

Hi,

First of all, at leaving reset all pins are GPIO IN, w/o pullups. The chip-select signals need to be outputs.

If it is so, then the problem seems to be with the topology used. If I understand correctly, as you pull 4 chipselects at the same time, you 're sending data to multiple slaves. they should have the MOSI pins connected parallel, not in the daisy chain fashion, like jtag chains.If it is so, then we need further examination of the software.

624 Views
woohoo
Contributor I

Hi, The code I posted above is a snippet from the main body, so the initialisation of the GPIO's isn't shown. The MOSI pins are connected in parallel and still I have no luck receiving data at the slave.

One thing I did notice when running the debugger is the interrupt for the slave is not triggered. Is the vector number for the interrupt correct?

0 Kudos

624 Views
AntiGeri
Contributor II

Hi,

One more idea, when you do the write operations on the SPIC1, and SPIC2, in your code, you do it bit by bit, and the datasheet suggests, that this would be done bytewise, in other words, something like SPIC1 |= SPIE | SPE ...

...anyway...

I have set up an SPI master once, to receive , (I'm not a sw-expert, so please don't laugh, but) master controls look like this:

    /*Some Init code for the peripherals*/
  SOPT = 2;       //Disable WD
  ICGC2 = 0x08;     //10MHz Crystal -> 40MHz Core, 20MHz Bus
  ICGC1 = 0xFE;
     
  PTCDD = 0x08;     //PTC3 -> INT_ENAn(Out), PTC2 -> DIR_SEL(In)
  PTDDD = 0x08;     //PTD3 -> PWM(Out)
  PTEDD = 0x04;     //PTE2 -> SSn(Out)

  PTCD = 0x08;     //Disable IRQ
  PTDD = 0x08;      //PWM is active low, so off
  PTED = 0x04;      //SSn is active low, so off

  SPIC1 =0x54;      //Enable,Master Mode,CPHA=1
  SPIC2 =0x00;
  SPIBR =0x40;      //CLK = (BUSCLK / 5) / 2 = 1MHz

  TPM1SC = 0x48;    //TPM1 will produce timing INT (int on every 1mS)(1kHz)
  TPM1MODH = 0x4E;  //Set the Modulo to be 20000
  TPM1MODL = 0x20;  //wich is req'd for 1kHz
  TPM1C0VH = 0;     //just to start up the timer
  TPM1C0VL = 0;     //Same reason
  TPM1C0SC = TPM1C1SC =  0x00;

  TPM2SC = 0x08;    //TPM2 will be free-running PWM generator
  TPM2MODH = 0x3F;  //Set the Modulo to be 16383
  TPM2MODL = 0xFF;  //wich is req'd for 14bit res
  TPM2C0SC = 0x24;  //Low True Pulses 
  TPM2C0VH = 0;     //Off for now...
  TPM2C0VL = 0;
  EnableInterrupts; /* enable interrupts */

...and in the interrupt routine, i give dummy bytes to the spi, to start transfer, but I only need the received bytes, anyway I suppose the sent bytes are out also...

...

PTED = 0x00;   //Set SSn low,
for (aB = 0; aB < 2; aB++){ //Do it twice...
  SPID = 0xFF;  //  Put 0xFF to SPID

  bB = 0;//  Wait for transfer to end
  while (!(bB)) bB = (SPIS & 0x80);

  SPIDataW = SPIDataW << 8;
  SPIDataW += SPID; //  Get the data from the SPID
};//...Until this line
PTED |= 0x04;   //Set SSn high

...

This is how I handled the master, without irq unfortunately, but show some things...

Another question:

Could you confirm with an oscilloscope, that during transmission, data, and clk lines are toggling, or they are idle?

this can guide us towards finding the problem.