S12X SPI Protocol Issues

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

S12X SPI Protocol Issues

Jump to solution
2,850 Views
cbhavi
Contributor III

Hello,

 

I am using a S12X (MC9S12XS256) controller with CodeWarrior v5.9.0.

I am using the SPI port to communicate with a DSP(ADAU1701).

My SPI runs in the single byte mode with CPHA = 0 and CPOL = 0 and is the Master device.

After much trouble I have finally managed to init the DSP in SPI mode and write a couple of bytes to the Core Register. (i verified this by using an external debugger for the DSP)

 

My issue is that I have been having trouble in reading from the DSP.

In order to read, the DSP expects 3 bytes of input data to start with; 1st byte is a 7-bit chip address + a single bit read/write command (0-write and 1-read; this bit is the LSB), 2nd byte is the higher byte of the register address and 3rd byte is the lower byte of the register address. After it receives these bytes, the DSP should transmit the content of the register.

I however read only 0xFFs on the controller!!

 

After a thorough look into the reference manual for the controller in question, i found the below statement...

"During an SPI transmission, data is transmitted (shifted out serially) and received (shifted in serially)

simultaneously. The serial clock (SCK) synchronizes shifting and sampling of the information on the two

serial data lines."

I have also seen several similar explanations in different threads in the forum.

 

Does this mean that I have to read as soon as I send bytes to the slave device since it is simultaneous transmission?

But this wont work, since the DSP needs the 3 bytes in order to send anything. Even if the DSP is ready to send the content of the register (or any data for that matter) after it has received the address, it cannot do so since the SCK stops after all the bytes are transmitted (because of simultaneous transmission) and so all that I would read is junk!

..and so I am stuck!

 

Request someone to clarify and help me out this.

 

Thanks in advance.

- Bhavya

Labels (1)
0 Kudos
1 Solution
1,738 Views
kef2
Senior Contributor IV

Well. I have no idea why I can't post normally whole reply. Trying to break it into single or few lines replies:

    //while(!(SPI0SR & SPI0SR_SPIF_MASK)); //Commented because the control gets stuck here.


This ^^is required code! Wasn't it that you single stepped in debugger over txrx routine while debugger memory window was pointing at SPI registers? Memory window contents refresh may read SPISR and SPID, which is a SPIF clearing sequence.

View solution in original post

0 Kudos
15 Replies
1,738 Views
kef2
Senior Contributor IV

What ADAU1701 tells about SPI format? Is it really CPOL=CPHA=0?

ADAU datasheet tels you this:

"The CCLK signal latches CDATA during a low-to-high transition. COUT data is shifted out of the ADAU1701 on the falling edge of CCLK and should be clocked into a receiving device, such as a microcontroller, on the CCLK rising edge"

It sounds little fuzzy, but between lines I read that data is shifted out of ADAU on the falling edge, and only then is should be sampled by MCU and clock in on rising edge. I think it is CPOL=CPHA=1 format. Both 0-0 and 1-1 formats don't affect sending data to ADAU, but will affect proper reading of data to MCU. Though t doesn't explain reading 0xFF's.

About simultaneous transmission. Figure 27 clearly shows that you need to write 3 bytes over spi, and then read 2 bytes. But as you may know, to read from SPI you need to send something.

unsigned char SPIIO(char data)

{

char tmp;

  tmp=SPISR; // read flags followed by write to SPIDR, as required to clear flag

  SPIDR = data;

  while(!(SPISR & SPISR_SPIF_MASK))

  {

  }

  return SPIDR;

}

...

   set CLATCH low

    SPIIO( 1st byte to ADAU);

    SPIIO( 2nd byte to ADAU);

   SPIIO(3rd byte to ADAU);

   1st byte from ADAU = SPIIO(0);

   2nd byte from ADAU = SPIIO(0);

  set CLATCH high

0 Kudos
1,738 Views
cbhavi
Contributor III

An update...

I was able to read the core register of the DSP but I dont understand how or why.

I removed the while loop wait in the function, and instead of transmitting 2 dummy bytes after the first 3 address data, I transmitted 3 dummy bytes and voila, I got the data I was looking for.

So altogether, for having transmitted 6 bytes, the MCU received 0xFF in the first four transmissions and valid data in the last two transmissions.

For the all the above transmissions the MCU still requires a 12.5us delay after each byte to work.

Any idea why it is like this?

0 Kudos
1,738 Views
kef2
Senior Contributor IV

Something wrong must be in your code. Since it is very secret, I can't help further.

0 Kudos
1,738 Views
cbhavi
Contributor III

Its no secret, its just very similar to what you've mentioned.

Below is the code I am using,

void Init_SPI(void) {  

  SPI0CR1 = 0x00;  

  SPI0CR2 = 0x02;   // 8-bit data format; Stop SPI clock when in wait mode                     

  SPI0BR  = 0x23;   // Baudrate = 625kbps ; fs= 30MHz

  SPI0CR1 = 0x50;   // CPOL=CPHA=0; Transmit MSB first; Enable SPI in master mode

}

unsigned char SPI_TxRx(unsigned char data) {

  unsigned char temp = SPI0SR,

                       i = 0;

  SPI0DRL = data;

  for (i=0; i<0x60; i++);                                     //This delay required here; only then values written correctly to the DSP

// while(!(SPI0SR & SPI0SR_SPIF_MASK));    //Commented because the control gets stuck here.

  return SPI0DRL;

}

void main (void){

unsigned char rxdata[5] = {0};

Init_SPI();

//Init DSP in SPI mode by pulling CLATCH low three times.

CLATCH_LOW;

CLATCH_HIGH;

CLATCH_LOW;

CLATCH_HIGH;

CLATCH_LOW;

CLATCH_HIGH;

//read core-register

CLATCH_LOW;

rxdata[0] = SPI_TxRx(0x01);   //7bit chip address + read command

rxdata[1] = SPI_TxRx(0x08);  // 1st address byte

rxdata[2] = SPI_TxRx(0x1C);  // 2nd address byte

rxdata[3] = SPI_TxRx(0x00);  //Transmitting dummy bytes

rxdata[4] = SPI_TxRx(0x00);

rxdata[5] = SPI_TxRx(0x00);

CLATCH_HIGH;

}

When I run the above code, rxdata gets filled as,

rxdata[0] = 0xFF

rxdata[1] = 0xFF

rxdata[2] = 0xFF

rxdata[3] = 0xFF

rxdata[4] = 0x00

rxdata[5] = 0x1A


The last two bytes are the correct data from the DSP core-register.

Is something wrong/right here?!

0 Kudos
1,738 Views
kef2
Senior Contributor IV

For some reason forums engine doesn't allow to reply

0 Kudos
1,739 Views
kef2
Senior Contributor IV

Well. I have no idea why I can't post normally whole reply. Trying to break it into single or few lines replies:

    //while(!(SPI0SR & SPI0SR_SPIF_MASK)); //Commented because the control gets stuck here.


This ^^is required code! Wasn't it that you single stepped in debugger over txrx routine while debugger memory window was pointing at SPI registers? Memory window contents refresh may read SPISR and SPID, which is a SPIF clearing sequence.

0 Kudos
1,738 Views
kef2
Senior Contributor IV

Above one werked, continue:

Since you broke good code, you had to workaround it inserting "wonderful" for loop. BTW 12.5us is close to 8 SPI clock pulses (12.8us @ 625kbps). Doesn't it explain why there's such a delay between bytes?


You can't use 6th rxdata element (rxdata[5]), your array size is only 5 bytes.

0 Kudos
1,738 Views
kef2
Senior Contributor IV

Above one had to be shortened like you see ^^. Continue:


0 Kudos
1,738 Views
kef2
Senior Contributor IV

6 bytes

0 Kudos
1,738 Views
kef2
Senior Contributor IV

v s 5 b y t e s  m a y  b e   c a u s e d   b y

0 Kudos
1,738 Views
kef2
Senior Contributor IV

- wrong CPOL/CPHA, DSP may get confused somehow


- for loop instead of proper read SPIF flag clearing sequence (read SPISR and then read SPID). Maybe 12.5us is not enough for such broken code.


If above doesn't help, then maybe this will. I saw many versions of SPI modules, starting from one in old HC11. Some of them required required read of SPISR before configuring control registers. I've used following sequence to init SPI in master mode since old HC12 days:


1)read SPISR

2)setup baud rate register

3)cpol, cpha, MSTR=1, SPE=1


Hope it helps

0 Kudos
1,738 Views
kef2
Senior Contributor IV

Sorry. It was driving me crazy. No matter, IE10, IE8, Opera, the same crazy error message

0 Kudos
1,738 Views
cbhavi
Contributor III

Edward, It was the debug window!

Since my code is running only in the debug mode currently, the Function register window is always open. But when I close all the Function Register windows (not allowing unwanted reads from the SPI control registers), the SPI read and write seems to work fine and does not require any additional delays (I agree the 'for' loop is a bad idea!).

Thank you very much for your help!

0 Kudos
1,738 Views
kef2
Senior Contributor IV

I'm glad it helped.

0 Kudos
1,738 Views
cbhavi
Contributor III

Thank you Edward, but unfortunately what you suggested didn't work.

When I implemented the above routine in my project, the processor gets stuck at the while loop in the function waiting for the SPIF bit to get set (and it doesnt seem to happen).

Also I should mention that the write to the DSP registers happens only when I provide a delay of about 12.5us between transfer of every byte (I had given a simple for-loop to test if it works, and it does but it doesnt seem like a good implementation). If I remove the delay, nothing gets written.

When CPOL=CPHA=1, data only gets written with SPIBR=0x21 (2.5Mbps) but not with 0x23(which is the setting I need for 625kbps). But with CPOL=CPHA=0, I can write data at both SPIBR = 0x21 and 0x23. But, data read doesnt happen under any condition!  :smileysad:

0 Kudos