1 Reply Latest reply on Apr 13, 2017 11:09 AM by e.pratt_1639216

    3-Wire SPI, Bidirectional, Half-Duplex Issue

    adam.carlson

      I am having an issue with an attempt to get 3-Wire SPI working.  First the vitals:

         

      uC: CYBC4247LQI-BL483

         

      IDE: PSoC Creator v4.0 Update 1 (4.0.0.432)

         

      SPI Component: SPIM_1 created with the SPI Master Bidirecional mode Macro (v 2.50)

         

      Device being communicated with: STMicro LSM303C (Datasheet)

         

       

         

      Issue:

         

      After I use SPIM_1_TxDisable() to disable the SPI output from the PSoC device sdat line, I then call a dummy write to generate the required clock cycles to cause the slave device to shift its information out of its registers while also maintaining the CS line low.  What I am finding when I watch the signal buss with a logic analyzer is that the dummy write that I do is actually not just generating a dummy value, but seems to be being sent to the RX buffer when I call SPIM_1_ReadRxData() to pull the returned data out of the read buffer it actually seems to be pulling the value from 2 previous reads (still, though being the dummy value).

         

      I have checked this with two different logic analyzers to confirm what is going on.  When I use the logic analyzer I see that actually the value that is being transmitted back appears to be just a repeat of what ever the dummy write byte is.  For tracking purposes, I am using just a repeat of the register value that I was trying to read.  So on the logic analyzer, I am getting a straight 1 for 1 correlation to the register that I am trying to read being pinged back to me as the "read" value, but when I am using the debugging register view, I see that what I pull from the register as the read value was the register of the slave device that I was trying to read two reads ago. 

         

      In trying to solve this, I though that perhaps in the 4 byte min sided buffer that some values were behaving strangely, so I call both SPIM_1_ClearRxBuffer() and SPIM_1_ClearFIFO().  These did not change the behavior of what was happening.  I currently cannot upload the entire project, but I will see if I can extract the key parts into a new project and then upload it.  I have inserted some of the code that I am using that is causing the issue as well as a screen shot of the logic analyzer capture.

         

      I have also uploaded screen shots of the SPIM component configuration for clarity till I can break this out into a separate project that I can upload.

         

       

         

      for(;;)
      {

         

          AccelRead();
          CyDelay(1);

         

      }

         

       

         

      uint8_t ReadSPI(uint8_t regValue)
      {
          uint8_t returnVal;
          
          SPIM_1_ClearRxBuffer();
          SPIM_1_ClearTxBuffer();
          SPIM_1_TxEnable();
          SPIM_1_WriteTxData((regValue | 0b10000000));
         

         

          //Begin the read process by disabling the Transmit, but write dummy value to cycle the clock

         

          SPIM_1_TxDisable();
          SPIM_1_ClearRxBuffer();
          SPIM_1_ClearFIFO();
          SPIM_1_WriteTxData((regValue | 0b10000000));
          returnVal = SPIM_1_ReadRxData();
          SPIM_1_TxEnable();
           
          return returnVal;
      }

         

       

         

      double AccelRead(void)
      {
          volatile int16_t valueX;
          volatile int16_t valueY;
          volatile int16_t valueZ;
          volatile double magnitude;
          volatile uint8_t whoAmI;
          
          //TODO Need to add register information and function definitions
          valueX = ReadSPI(0x28);
          CyDelay(1);
          valueX = valueX << 8 | ReadSPI(0x29);
          CyDelay(1);
          
          valueY = ReadSPI(0x2A);
          CyDelay(1);
          valueY = valueY << 8 | ReadSPI(0x2B);
          CyDelay(1);
          
          valueZ = ReadSPI(0x2C);
          CyDelay(1);
          valueZ = valueZ << 8 | ReadSPI(0x2D);
          CyDelay(1);
          
          whoAmI = ReadSPI(0b00001111);
          
          magnitude = sqrt(valueX * valueX + valueY * valueY + valueZ * valueZ);
          return 0;
      }

        • 1. Re: 3-Wire SPI, Bidirectional, Half-Duplex Issue
          e.pratt_1639216

          I ran into a similar issue when setting up the SPI component to communicate with a Microchip SPI device; I ran into the issue where the data was delayed by several bytes being sent/received for an echo-test program I wrote. It seems like the SPI component has an internal FIFO buffer for both input and output, which could be why you are having a delay between seeing the byte on the physical line, and seeing it in the RX buffer in the component. I ended up rewriting my communications protocol to be ignorant of timing by introducing start/end of data sequences that allow me to merely send a data message and ignore all data until a response comes in. This allowed a more or less polling of the data until the next message start sequence.