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 : john@jscontrols.co.za Web: www.jscontrols.co.za ----- Original Message ----- From: "Sean Breheny" To: "Microcontroller discussion list - Public." Sent: Friday, October 07, 2011 4:25 AM Subject: Re: [PIC]: SPI problem on dsPIC33FJ64GS610 > 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 > wrote: >>> 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 >> >> Joe >> -- >> http://www.piclist.com PIC/SX FAQ & list archive >> View/change your membership options at >> http://mailman.mit.edu/mailman/listinfo/piclist >> > > > 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 > // 7372800 MHz Fosc > // div by 2 to get Fcy=3D > #define FCY 3686400 > #include > #include > #include > > > _FOSCSEL (FNOSC_PRI) > _FOSC(POSCMD_HS & OSCIOFNC_OFF & FCKSM_CSDCMD) > _FWDT(FWDTEN_OFF) > > TRISGbits.TRISG0=3D0; // unused > TRISGbits.TRISG1=3D0; // unused > TRISGbits.TRISG2=3D0; // unused > TRISGbits.TRISG3=3D0; // unused > // TRISG4,TRISG5 do not exist > TRISGbits.TRISG6=3D1; // -- SCK2 - DAC_SCLK > TRISGbits.TRISG7=3D0; // unused > TRISGbits.TRISG8=3D1; // -- SDO2 - DAC_SDATA > TRISGbits.TRISG9=3D0; // unused > // TRISG10,TRISG11 do not exist > TRISGbits.TRISG12=3D0; // unused > TRISGbits.TRISG13=3D0; // unused > TRISGbits.TRISG14=3D0; // unused > TRISGbits.TRISG15=3D0; // unused > > // Configure SPI2 for DAC > SPI2CON1bits.MSTEN=3D1; // Enable master mode > SPI2CON1bits.CKP=3D1; // Idle CLK state is high > SPI2CON1bits.CKE=3D1; // Data changes on transition from active to > idle > SPI2CON1bits.DISSCK=3D0; // Do not disable the SCK pin > SPI2CON1bits.DISSDO=3D0; // Do not disable the SDO pin > SPI2CON1bits.MODE16=3D0; // 8 bit wide > SPI2CON1bits.SMP=3D0; // Unused since we do not read any result from > DACs > SPI2CON1bits.SPRE=3D0; // three bits long, 000 sets to 8:1 prescale > SPI2CON1bits.PPRE=3D2; // two bits long, 10 sets to 4:1 prescale > // SCK will be FCY/32 > SPI2CON2=3D0; // We do not use framing features > > SPI2STATbits.SPISIDL=3D0; // Do not stop in idle mode > SPI2STATbits.SPIEN=3D1; // Enable module > SPI2STATbits.SPIROV=3D0; > > > 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=3DSPI2BUF; > // Clear RX overflow bit > SPI2STATbits.SPIROV=3D0; > LATDbits.LATD8=3D1; // 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=3D0; // Begin transfer > __delay_us(2); > SPI2BUF=3D0x00; // 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=3D(pin_word>>8)&0x00FF; // Load next byte into buffer > while (!SPI2STATbits.SPIRBF); // Wait for 1st transfer to complete > dac_spi_rx_byte=3DSPI2BUF; // 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=3Dpin_word&0x00FF; // Load last byte into buffer > while (!SPI2STATbits.SPIRBF); // Wait for 2nd transfer to complete > dac_spi_rx_byte=3DSPI2BUF; // 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=3DSPI2BUF; // Read result to clear RX buffer > __delay_us(2); > LATDbits.LATD8=3D1; // End transfer > -- > http://www.piclist.com PIC/SX FAQ & list archive > View/change your membership options at > http://mailman.mit.edu/mailman/listinfo/piclist -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .