CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

SPI: data received with 1 bit shift to the right [Solved]

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Donatello



Joined: 21 Oct 2016
Posts: 22

View user's profile Send private message

SPI: data received with 1 bit shift to the right [Solved]
PostPosted: Wed Mar 18, 2020 5:57 am     Reply with quote

Dear All,
I use DSPIC33EP16GS502 and AD7190 with a SPI communication.
In the AD7190 the SPI MODE is 3 because:
--> idle state for SPI clock is high (SPI clock polarity 1)
--> data is latched on the leading edge of SPI clock and data changes on trailing edge. (SPI clock phase 0)

Below my code:
Code:
include <33EP16GS502.h>
#device ADC=12
#include <string.h>
#fuses WDT                      // Watch Dog Timer
#fuses FRC_PLL
#fuses NOWRT                    // Program memory not write protected
#fuses NOPROTECT                //Code not protected from reading
#use delay(clock=120000000, internal)
#USE SPI (MASTER, SPI1, BAUD=1000000, DI=PIN_B0, DO=PIN_B9, CLK=PIN_B10, BITS=8, STREAM=AD7190, MODE=0)


Then my simple SPI routine:
Code:
char i = 0;
unsigned char receiveBuffer = 0;
 
//RESET AD7190
output_low(PIN_B3);
delay_ms(1);
spi_xfer(AD7190, 0x01);
for(i = 0; i < 6; i++)
   spi_xfer(AD7190, 0xFF);
delay_ms(1);
output_high(PIN_B3);
delay_ms(100);
//For test, I use the register constant, ID REGISTER, of the AD7190
while(1) {
   output_low(PIN_B3);
   spi_xfer(AD7190, 96);
   receiveBuffer = spi_xfer(AD7190, 0);
   delay_us(2);
   output_high(PIN_B3);
   delay_ms(10);
}


In the receiveBuffer there must be a value of 0x84 (b1010100), but instead the value is 0x42 (b0101010).
I lose a 1 bit, because there is 1 bit right shift.

If I use MODE = 2 or MODE = 3, the receiveBuffer is always the same. While if I use MODE = 1 the receiveBuffer is zero, so I don't receive anything.
Finally if I use MODE=0 and low baudrate, BAUD=500000, then I read the registers correctly. But in MODE=0 the clock polarity is wrong and I have to use a low speed.

Please, can someone help me?
Thank you very much

Regards,
Donatello


Last edited by Donatello on Fri Mar 20, 2020 11:22 am; edited 3 times in total
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 6:07 am     Reply with quote

SPI has 4 modes.... since mode 0 doesn't work, try mode 1 !!
Someone will probably post the 'code cheat' that lists the 4 modes as defines....I can't member stuff like that anymore,sigh.
Donatello



Joined: 21 Oct 2016
Posts: 22

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 6:14 am     Reply with quote

temtronic wrote:
SPI has 4 modes.... since mode 0 doesn't work, try mode 1 !!
Someone will probably post the 'code cheat' that lists the 4 modes as defines....I can't member stuff like that anymore,sigh.


Thanks temtronic for reply. While you were writing I edited my post with information on the other MODE (1 and 3).

I have tried all combinations even with different speeds.
MODE = 0 works only with low BAUD, but in the AD7190 datasheet it is clearly written that the idle state for SPI clock is high (in MODE 0 and 1 is low). I think that in MODE = 0 I have to use low speeds, because the communication is not working properly.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 6:23 am     Reply with quote

I downloaded the datasheet, max speed seems to be 4.8KHz, so I'd really slow down the SPI speed !
maybe try at 5,000 ??

I couldn't easily see the SPI mode in the datasheet...
Donatello



Joined: 21 Oct 2016
Posts: 22

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 6:41 am     Reply with quote

temtronic wrote:
I downloaded the datasheet, max speed seems to be 4.8KHz, so I'd really slow down the SPI speed !
maybe try at 5,000 ??

I couldn't easily see the SPI mode in the datasheet...


The AD7190 is a 24bit Sigma-Delta ADC converter, the 4.8kHz is the ADC output datarate. For SPI communication, the maximum SCLK frequency specified for AD7190 is 5MHz, please read the answer in analog forum:
https://ez.analog.com/data_converters/precision_adcs/f/q-a/24417/ad7190-looses-clock/141423

On the oscilloscope, I see the response message from the AD7190 to dsPIC with BAUD up to 2Mbps. But the dsPIC only in MODE 2 or 3 can receive the message by losing a bit (right shift). With high BAUD and in MODE 0 or 1, the dsPIC cannot decode any data.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 7:20 am     Reply with quote

hmm, that answer says it's prone to noise at high frequencies.(5MHz is 'high' ?..sigh...
I'd still try subMHz , at least to get the proper data THEN increase the speed.

OK, finally found this...

#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)

might help with the 'modes'

Also check the listing to confirm it's not a 'bug' that's setting the wrong bits....
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 8:02 am     Reply with quote

The datasheet says that the clock should idle high (CPOL=1), and the data
should be read on the rising edge of the clock (CPHA=1). This is SPI
mode 3. However there is also t1, which says you must pause for at least
80nSec between dropping CS, and actually starting sending the clock.
The clock has 100nSec high and low minima, so 5MHz max clock rate.
So you need a tiny delay between the output_low(PIN_B3), and the
spi_xfer.
delay_cycles(5) (4.8 is the minimum required). The clock dropping straight
away after the CS, is why you are getting the bit shift. It is actually missing
the first clock. Remember your chip executes an instruction in just 16nSec.
Donatello



Joined: 21 Oct 2016
Posts: 22

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 10:14 am     Reply with quote

Ttelmah wrote:
The datasheet says that the clock should idle high (CPOL=1), and the data
should be read on the rising edge of the clock (CPHA=1). This is SPI
mode 3. However there is also t1, which says you must pause for at least
80nSec between dropping CS, and actually starting sending the clock.
The clock has 100nSec high and low minima, so 5MHz max clock rate.
So you need a tiny delay between the output_low(PIN_B3), and the
spi_xfer.
delay_cycles(5) (4.8 is the minimum required). The clock dropping straight
away after the CS, is why you are getting the bit shift. It is actually missing
the first clock. Remember your chip executes an instruction in just 16nSec.


I tried to add a delay but the behavior doesn't change. However, as an oscilloscope, the AD7190 response is perfect and follows the clock. The dsPIC and/or CCS does not take the last bit.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 10:45 am     Reply with quote

OK, I don't use that PIC but 3 things I can think of...

1) check the listing to confirm the hardware SPI peripheral is being used....

2) check the compiler version for 'bugs'

3) check the PIC for 'erratas'

If none of these are the problem, well you've elimintated them as 'possibles'...
Donatello



Joined: 21 Oct 2016
Posts: 22

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 11:22 am     Reply with quote

temtronic wrote:
OK, I don't use that PIC but 3 things I can think of...

1) check the listing to confirm the hardware SPI peripheral is being used....

2) check the compiler version for 'bugs'

3) check the PIC for 'erratas'

If none of these are the problem, well you've elimintated them as 'possibles'...


I use CCS compiler 5.091 and dsPIC33EP16GS502 with AD7190 in SPI Communication. In the dsPIC33EP16GS502 Silicon Errata issue #39 (page 18) :
In Master mode, the SPI device reads the data on
the SDIx line incorrectly; data are shifted by one bit
(e.g., if 0x37 is transmitted, it is read as 0x1B).

The issue occurs for the following configuration:
SMP = x, CKE = 0 and CKP = 1

In my case, for MODE=3, the CKE = 0 and CKP = 1, then I have the problem! Sad

In Errata documents:
Work around
When CKE = 0 and CKP = 1, use the following
sequence to initiate SPI communication:
1. Set the Slave select line to the Idle state.
2. Set the SCKx pin high.
3. Enable Master mode.
4. Enable the module.
5. Assert the Slave select line.
If the SPI Slave device does not use the SSx line,
the SPI Slave should be enabled only after the
master clock line is made high.


Now, in my code:
Code:
#PIN_SELECT SDO1 = PIN_B9
#PIN_SELECT SCK1OUT = PIN_B10
#PIN_SELECT SDI1 = PIN_B0
#define SPI1_DI          PIN_B0
#define SPI1_DO          PIN_B9 
#define SPI1_CLK         PIN_B10
#define AD7190_SS        PIN_B3
#byte SPI1CON1x = getenv("SPI1CON1")
#byte SPI1STATx = getenv("SPI1STAT")


Then in the main:
Quote:
output_high(AD7190_SS); // 1. Set the Slave select line to the Idle state.
output_high(SPI1_CLK); // 2. Set the SCKx pin high.
bit_set(SPI1CON1x, 1); // 3. Enable Master mode.
bit_set(SPI1STATx, 15); // 4. Enable the module.
output_low(SPI1_CLK); // 5. Assert the Slave select line.
delay_ms(1);
output_high(SPI1_CLK);

setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_112|SPI_SCK_IDLE_HIGH);

But the problem has not been solved.

Please, can you help me in these steps?
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 2:35 pm     Reply with quote

Simple answer, use software SPI. Seriously at 120MHz, your PIC can generate
SPI at almost the 5MHz rate using software.
Just get rid of the #pin select lines for the SPI, specify the pins in the
#USE statement, and it'll use software,
No disadvantage at all.

For hardware, it sounds as if the erratum applies in other modes.

The correct work round in the SPI, is:
Code:

#PIN_SELECT SDO1 = PIN_B9
#PIN_SELECT SCK1OUT = PIN_B10
#PIN_SELECT SDI1 = PIN_B0
#USE SPI (MASTER, SPI1, BAUD=1000000, BITS=8, STREAM=AD7190, MODE=3, NOINIT)

//Then at the start of the main code:

output_high(PIN_B10); //raise the clock line
spi_init(AD7190,TRUE); //now init the SPI



You are not using the SPI SS line.
Donatello



Joined: 21 Oct 2016
Posts: 22

View user's profile Send private message

PostPosted: Wed Mar 18, 2020 3:21 pm     Reply with quote

Dear Ttelmah, thank you very much!
This is the right work around for the dsPIC33EPXXGS50X family. I just added the output_high on the clock pin.

I report your code here with this setting, maybe it can help someone else.

Code:
#define SPI1_CLK    PIN_B10
#PIN_SELECT SDO1 = PIN_B9
#PIN_SELECT SCK1OUT = SPI1_CLK
#PIN_SELECT SDI1 = PIN_B0
#USE SPI (MASTER, SPI1, BAUD=1000000, BITS=8, STREAM=AD7190, MODE=3, NOINIT)

//Then at the start of the main code:

output_high(AD7190_SS);     // 1. Set the Slave select line to the Idle state.
output_high(SPI1_CLK);      // 2. Set the SCKx pin high.
spi_init(AD7190, TRUE);     // 3. Enable Master mode. /  4. Enable the module.


These days I will do better tests. Out of curiosity, I set a speed of 10M without losing any information from the AD7190.
Thanks again!

Donatello
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Mar 19, 2020 1:02 am     Reply with quote

Quite a lot of errata do apply to other similar chips or in undocumented
states. Looks as if you have found one.... Sad

Glad the fix works. One of those 'often missed' features of the CCS
compiler, that you have the choice of the initialisation being done
'secretly' at the start of the code, or you being able to trigger it when
'you want' in the code. In this case it allows you to raise the clock line,
then initialise. Very Happy

Have you really managed to run at 10MHz?. Your setup line only shows
1MHz.

Have fun.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group