Searching \ for '[PIC]: SPI problem on dsPIC33FJ64GS610' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: techref.massmind.org/techref/microchip/ios.htm?key=spi
Search entire site for: 'SPI problem on dsPIC33FJ64GS610'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: SPI problem on dsPIC33FJ64GS610'
2011\09\24@212037 by Sean Breheny

face picon face
O great piclist,

I must once again approach you with a request for help :)

I have a project where a dsPIC33FJ64GS610 communicates with an AD5060
16-bit DAC using SPI. This is a uni-directional transfer, so the data
received by the PIC is discarded and the SDI pin on the PIC is left
floating and its TRIS bit is cleared. I do not know whether it remains
an output when the SPI module is enabled.

The problem I am having is this: in this three byte transfer, the
first byte is always 00, the second is the MSByte of the commanded
codeword, and the third is the LSByte of the commanded codeword. The
transfer always works fine if I hardcode delays (longer than 1 byte
time) between each line of code which loads the next byte into the
SPI2BUF register. However, if I try to use the SPI status bits to
complete the transfer as efficiently as possible (i.e., use the fact
that I can be loading the next byte while it is transferring the
first), then sometimes, seemingly randomly, the MSbit of the middle
byte will get set. There are certain codewords where this never
happens and then others where it happens about 50% of the time. It
seems that the MSbit of the third byte is what determines whether this
problem can happen. If the MSbit of the third byte is 0, then the
problem never seems to happen. If it is 1, then it sometimes happens -
almost as if the third byte's MSbit is being copied to the middle
byte's MSbit.

I checked the errata for this part and there doesn't seem to be any
errata for the simple SPI master mode that I am using. Interestingly,
some other PICs in the dsPIC family have an erratum for the SPI port
where certain values get transmitted as a 0x80, which sounds
suspiciously like this problem.

On my scope, I can see that, when this problem happens, it is caused
by a narrow glitch on the SDO line from the PIC. In the SPI mode I am
using, data should change on the rising edge of the clock and get
sampled by the DAC on the falling edge. This glitch happens right
before the falling edge of the 9th bit of the 24-bit transfer. The
falling edge of the glitch seems to happen simultaneously to the
falling edge of the clock. As I say, this glitch only happens for
certain codewords and even then, only about half the time.

To see scope screen shots of this, please see:

http://www.cheapgalvis.com/D001.BMP
http://www.cheapgalvis.com/D002.BMP

The bottom two traces are zoomed-in versions of the top two. The clock
is the trace with the regular transitions. The glitch is most easily
visible in the bottom-most trace (zoomed-in version of the SDO line).
The D001 shot is zoomed out further to see the beginning of the
transfer and the D002 is zoomed in enough to show the width of the
glitch.

For those who are kind enough to really look into this problem with
me, please see the initialization code and actual SPI transfer
function below. It is written in C, and I am compiling this using
MPLAB X beta 7.01 with the included free version of the C30 compiler,
and programming it into the PIC using a PICkit 3.

Thank you!

Sean



Here is the initialization code:

#include <p33FJ64GS610.h>
// 7372800 MHz Fosc
// div by 2 to get Fcy=
#define FCY 3686400
#include <libpic30.h>
#include <adc.h>
#include <stdio.h>


_FOSCSEL (FNOSC_PRI)
_FOSC(POSCMD_HS & OSCIOFNC_OFF & FCKSM_CSDCMD)
_FWDT(FWDTEN_OFF)

   TRISGbits.TRISG0=0; // unused
   TRISGbits.TRISG1=0; // unused
   TRISGbits.TRISG2=0; // unused
   TRISGbits.TRISG3=0; // unused
   // TRISG4,TRISG5 do not exist
   TRISGbits.TRISG6=1; // -- SCK2 - DAC_SCLK
   TRISGbits.TRISG7=0; // unused
   TRISGbits.TRISG8=1; // -- SDO2 - DAC_SDATA
   TRISGbits.TRISG9=0; // unused
   // TRISG10,TRISG11 do not exist
   TRISGbits.TRISG12=0; // unused
   TRISGbits.TRISG13=0; // unused
   TRISGbits.TRISG14=0; // unused
   TRISGbits.TRISG15=0; // unused

   // Configure SPI2 for DAC
   SPI2CON1bits.MSTEN=1; // Enable master mode
   SPI2CON1bits.CKP=1; // Idle CLK state is high
   SPI2CON1bits.CKE=1; // Data changes on transition from active to idle
   SPI2CON1bits.DISSCK=0; // Do not disable the SCK pin
   SPI2CON1bits.DISSDO=0; // Do not disable the SDO pin
   SPI2CON1bits.MODE16=0; // 8 bit wide
   SPI2CON1bits.SMP=0; // Unused since we do not read any result from DACs
   SPI2CON1bits.SPRE=0; // three bits long, 000 sets to 8:1 prescale
   SPI2CON1bits.PPRE=2; // two bits long, 10 sets to 4:1 prescale
   // SCK will be FCY/32
   SPI2CON2=0; // We do not use framing features

   SPI2STATbits.SPISIDL=0; // Do not stop in idle mode
   SPI2STATbits.SPIEN=1; // Enable module
   SPI2STATbits.SPIROV=0;


Here is the actual transmit function:

void set_pin_dac ( unsigned int pin_word )
{
   unsigned char dac_spi_rx_byte;

   // Clear receive buffer full bit
   if (SPI2STATbits.SPIRBF) dac_spi_rx_byte=SPI2BUF;
   // Clear RX overflow bit
   SPI2STATbits.SPIROV=0;
   LATDbits.LATD8=1; // Reset DAC's SPI module
   while(SPI2STATbits.SPITBF); // Wait for register to be empty
   __delay_us(200); // Wait for more than 1 byte time to ensure
   // that SPI2 system is idle

   LATDbits.LATD8=0; // Begin transfer
   __delay_us(2);
   SPI2BUF=0x00;   // Load first byte into buffer
   while(SPI2STATbits.SPITBF); // Wait for TX buffer to be empty
   // Should happen almost right away because system was idle when we
   // loaded 1st byte.
   SPI2BUF=(pin_word>>8)&0x00FF; // Load next byte into buffer
   while (!SPI2STATbits.SPIRBF); // Wait for 1st transfer to complete
   dac_spi_rx_byte=SPI2BUF; // Read result to clear RX buffer
   while(SPI2STATbits.SPITBF); // Wait for register to be empty
   // Should happen almost right away because we already waited for RX
   // buffer to be loaded
   SPI2BUF=pin_word&0x00FF; // Load last byte into buffer
   while (!SPI2STATbits.SPIRBF); // Wait for 2nd transfer to complete
   dac_spi_rx_byte=SPI2BUF; // Read result to clear RX buffer
   while(SPI2STATbits.SPITBF); // Wait for register to be empty
   // Should happen almost right away because we already waited for RX
   // buffer to be loaded
   while (!SPI2STATbits.SPIRBF); // Wait for 3rd transfer to complete
   dac_spi_rx_byte=SPI2BUF; // Read result to clear RX buffer
   __delay_us(2);
   LATDbits.LATD8=1; // End transfer

2011\09\24@221359 by IVP

face picon face
> the SDI pin on the PIC is left floating and its TRIS bit is
> cleared. I do not know whether it remains an output when
> the SPI module is enabled

Sean, I don't believe you can disable SDI if SPI is enabled, for the
dsPICs I use anyway. SDO and SCLK you can. If that's true for
the 610 then SDI will be a floating input and a accident waiting to
'appen

Look at the control bits in SPIxCON1

Jo


'[PIC]: SPI problem on dsPIC33FJ64GS610'
2011\10\06@222502 by Sean Breheny
face picon face
This thread is old by now, but I just had a chance to try your
suggestion, Joe. I agree that it appears that you cannot disable SDI.
So, I tied it high, set it as an input, and then reverted back to the
old method of using SPI (stream the next byte into the buffer as soon
as it says that the buffer is not full rather than waiting for the
entire byte transfer to finish before loading the next byte) and the
problem is still there. It is good practice to tie SDI to some level
and not let it float, but the problem still exists.

Any more ideas?

I have copied my original message below Joe's reply for reference.

Thanks,

Sean




On Sat, Sep 24, 2011 at 10:13 PM, IVP <spam_OUTjoecolquittTakeThisOuTspamclear.net.nz> wrote:
{Quote hidden}

>

2011\10\20@082811 by John Sanderson

flavicon
face
Hello Sean & PIC.ers,

I am chiming in late to this thread..  but this might be relevant.

I have a long series of products in the field using the 18Fxxx and
AD7715 adc. The SPI i/f is driven in s/w by the 18F and the data
comes out the adc on SDO to a pic pin (can't remember which but
it is not in portb).
I had *assumed* that the adc SDO line would act like an output always
should, low impedance etc. all the time as it is a hardware function
of the adc.
It was a big surprise to find that node floating at the end of
transfers, the pic i/o pin was trised for input so it was always
hi-Z as well.

Result:
The node floats all over the show when there is no activity on the bus.

It was undoubtedly the cause of a lot of unexplained uC
lock-up behaviour:-
Most units never reported any trouble.
Some did sometimes on Mondays but never Thursdays, occasionally the moon
was indicted as a possible perpetrator.
Others created havoc at the client's premises but nowhere else that they
were powered-up.
Some worked well with certain operators, but gave endless trouble with
other guys.

Almost always (but not _always_) the lockups disappeared at my shop.


Finally I got fed up a while back, hacked in with a scope
and discovered this.
It is not covered anywhere in the AD datasheet/s, that I could find.

Fix:
Hang a 10k pull-down on the node. Clean signal & no more spurious futz,
all units so far modified have reported no subsequent trouble.





   best regards,    John

eMail from John Sanderson's desk.
JS Controls cc. Manufacturer & purveyor of laboratory force testing
apparatus.
PO Box 1887, Boksburg 1460, Rep. of S. Africa
Tel: +27 (0) 11 023 1412
Fax: +27 (0) 86 516 9725
Cell: +27 (0) 82 741 6275
eMail : .....johnKILLspamspam@spam@jscontrols.co.za
Web: http://www.jscontrols.co.za




{Original Message removed}

2011\10\20@105643 by Michael Rigby-Jones

flavicon
face


> -----Original Message-----
> From: piclist-bouncesspamKILLspammit.edu [.....piclist-bouncesKILLspamspam.....mit.edu] On
Behalf
{Quote hidden}

It should come as no surprise to see the data output pin of an SPI slave
device in a high impedance state after de-asserting the chip select (or
possibly after the last bit transferred in a frame on some devices).  If
this were not the case, you would be unable to connect multiple slaves
to the same SPI bus, since there would be a conflict between slaves
trying to assert different levels.

Regards

Mike

=======================================================================
This e-mail is intended for the person it is addressed to only. The
information contained in it may be confidential and/or protected by
law. If you are not the intended recipient of this message, you must
not make any use of this information, or copy or show it to any
person. Please contact us immediately to tell us that you have
received this e-mail, and return the original to us. Any use,
forwarding, printing or copying of this message is strictly prohibited.
No part of this message can be considered a request for goods or
services.
=======================================================================

2011\10\20@140004 by John Sanderson

flavicon
face
Hello Mike, Sean, etc,,

----- Original Message ----- From: "Michael Rigby-Jones" <EraseMEMichael.Rigby-Jonesspam_OUTspamTakeThisOuToclaro.com>
To: "Microcontroller discussion list - Public." <piclistspamspam_OUTmit.edu>
Sent: Thursday, October 20, 2011 4:56 PM
Subject: RE: [PIC]: SPI problem on dsPIC33FJ64GS610


>
>
>> {Original Message removed}

2011\10\20@213910 by speff

picon face
Quoting John Sanderson <@spam@johnKILLspamspamjscontrols.co.za>:


>
> sure, that's right. The thing is that the adc was the only SPI part
> in the system and the /cs line was asserted (LO) all the time.
> Thus, hi-Z was never expected.
> It would have been nice if AD had actually explicitly described this
> in their datasheet then it would have been easy to avoid.

Of course it's implicit in figure 8 and the t9 bus relinquish timing  specification (the bus is shown in fig 8 going High-Z at t9 nanoseconds
from the SCLK rising edge), but if you're not looking carefully at
figure 8 etc. you might not notice it.

--sp

More... (looser matching)
- Last day of these posts
- In 2011 , 2012 only
- Today
- New search...