|
|
View previous topic :: View next topic |
Author |
Message |
Donatello
Joined: 21 Oct 2016 Posts: 22
|
SPI: data received with 1 bit shift to the right [Solved] |
Posted: Wed Mar 18, 2020 5:57 am |
|
|
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: 9245 Location: Greensville,Ontario
|
|
Posted: Wed Mar 18, 2020 6:07 am |
|
|
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
|
|
Posted: Wed Mar 18, 2020 6:14 am |
|
|
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: 9245 Location: Greensville,Ontario
|
|
Posted: Wed Mar 18, 2020 6:23 am |
|
|
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
|
|
Posted: Wed Mar 18, 2020 6:41 am |
|
|
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: 9245 Location: Greensville,Ontario
|
|
Posted: Wed Mar 18, 2020 7:20 am |
|
|
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: 19545
|
|
Posted: Wed Mar 18, 2020 8:02 am |
|
|
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
|
|
Posted: Wed Mar 18, 2020 10:14 am |
|
|
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: 9245 Location: Greensville,Ontario
|
|
Posted: Wed Mar 18, 2020 10:45 am |
|
|
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
|
|
Posted: Wed Mar 18, 2020 11:22 am |
|
|
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!
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: 19545
|
|
Posted: Wed Mar 18, 2020 2:35 pm |
|
|
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
|
|
Posted: Wed Mar 18, 2020 3:21 pm |
|
|
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: 19545
|
|
Posted: Thu Mar 19, 2020 1:02 am |
|
|
Quite a lot of errata do apply to other similar chips or in undocumented
states. Looks as if you have found one....
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.
Have you really managed to run at 10MHz?. Your setup line only shows
1MHz.
Have fun. |
|
|
|
|
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
|