cancel
Showing results for 
Search instead for 
Did you mean: 

SPI communication with 3 wire display

Danny0007
Senior

Hi community,

I have a display, which has only CLK, DI and CS pin for SPI communication. It uses TI protocol.

The original driver is only working with raspberry pi, I try to import it into my custom STM32 MCU board, the CLK and CS signals seem okay,  Only the MOSI signal is always low. it seems no data is really sent to the display. 

here is the signal capture from logic analyzer. 

The whole write sequence: 

Danny0007_1-1708464524960.png

zoom in, single byte write:

Danny0007_2-1708464622941.png

what could be the reason? Thanks in advance.

 

 

32 REPLIES 32

Sounds like, you make progress. Cool.
What was the issue with MOSI?

Based on my experiences with SPI (I saw such issue, "CS signal toggles, has 'spike'", recently one a setup as well):

  • it can be cross-talk:
    esp. when using long wires (or long parallel traces on PCB) - the SCLK signal can "cross-talk" to other signals.
    My solution was: "shield" the SCLK signal (like a coax cable, good EMI design on PCB)
  • it can be a scope issue:
    I use the same Logic tool and scope. If voltage is set wrong (e.g. to 1V8 but 3V3 signals) - you could see such effect.
    You can try to use also a glitch filter: this might "eliminate" the "glitches" (but there is for sure still "cross-talk").
  • You can try if a pull-up/pull-down on SCS signal helps: because it is a high-active logic - you might use a pull-down (pull-up/pull-down always for the "inactive" level)
  • you can add 33R..47R resistors in series, in all of the signals (SCLK, MOSI, SCS). It acts like a "serial termination" and avoids "ringing" on wires/signals.
  • You can also play with the "drive strength" or "speed" setting of the SPI signals: make it with slower speed, lower drive strength (to avoid EMI, cross-talk issues).
    This solved my similar problem recently.

Hi @tjaekel 

yes, some progress:) 

If I set the logic tool to 1.8V, the signals look much better, but the MOSI signal is still not correct. Also tried with low speed.

Danny0007_1-1708793283520.png

Maybe you´re right, cross-talk could be the reason. Because the pin orders on the chip and the display connector are different, the SPI traces are not always parallel and a little long, it´s about 40mm, at some point I have to cross the clock and MOSI traces on PCB.

Danny0007_0-1708793244912.png

I will try to make a new PCB, after that I will come back and give a update again. 

thanks a lot for all replies! :folded_hands:

 

 

 

"not always in parallel" - not really good to have parallel traces with high speed clocks on it (without "shielding").

Have a "pour GND" along all the SPI signals: fill all empty areas with "pour GND", so that all SPI signals are separated with a ground plane (not a "free space" between traces).
Keep signals apart from each other, esp. from high speed signals, e.g. clock signals, MCU OSC signals.

Add (optional) 33R series resistors in all driven lines, e.g. SCLK, SCS, MOSI. Place these resistors close to the output (driver): you can solder 0R or 33R later. 33R is there for "serial termination", to match the impedance of the trace (e.g. as resulting 50 Ohm), to avoid reflections ("ringing") and they also reduce "cross talk".

Have you tried to "play" with drive strength and speed setting on SPI signals? It might solve already your issue (e.g. slower speed, to avoid "cross talk" (EMI)).

When you go from header pins via "flying wires" to an external device: use double row headers: one row is got signals, the other is all GND. When you would use later a "ribbon cable": every second gauge is GND: it acts as shielding, to separate two signals with a GND wire between both signals.

Consider an option to have pull-ups (or pull-downs) on all signals: they can act  a bit as "parallel termination", also helpful to deal with "impedance mismatch" etc.

Good luck.

 

Ok, I see,  you mean parallel traces cause the cross-talk, understood.

I tried with different speed: HIGH, MEDIUM and LOW, got same results. 

what do you mean with "drive strength"? 

 

this is how the SPI traces look like, at some place SCK and MOSI are parallel and too close to each other, even without "pour GND"

Danny0007_1-1708839470661.png

 

 

 

Danny0007
Senior

@tjaekel 

I made a new PCB, but the result is the same.

The same SPI2 settings I tested on IDB011V2 and also get the same result.

So I think the issue is not caused by hardware design, could you please also test SPI2(PA4/PA5/PA6) on a IDB011V2 board and confirm it?

Danny0007
Senior
This is I´m using:
*****************************************************
void BSP_SPI2_Init(void)
{
  /* Initialize the GPIOs associated to the SPI port */
  
  BSP_SPI2_MISO_GPIO_CLK_ENABLE();
  LL_GPIO_SetPinMode(BSP_SPI2_MISO_GPIO_PORT, BSP_SPI2_MISO_PIN, LL_GPIO_MODE_ALTERNATE);
  LL_GPIO_SetPinSpeed(BSP_SPI2_MISO_GPIO_PORT, BSP_SPI2_MISO_PIN, LL_GPIO_SPEED_FREQ_HIGH);
  LL_GPIO_SetPinOutputType(BSP_SPI2_MISO_GPIO_PORT, BSP_SPI2_MISO_PIN, LL_GPIO_OUTPUT_PUSHPULL);
  LL_GPIO_SetPinPull(BSP_SPI2_MISO_GPIO_PORT, BSP_SPI2_MISO_PIN, LL_GPIO_PULL_NO);
  BSP_SPI2_MISO_GPIO_AF();
  
  BSP_SPI2_MOSI_GPIO_CLK_ENABLE();
  LL_GPIO_SetPinMode(BSP_SPI2_MOSI_GPIO_PORT, BSP_SPI2_MOSI_PIN, LL_GPIO_MODE_ALTERNATE);
  LL_GPIO_SetPinSpeed(BSP_SPI2_MOSI_GPIO_PORT, BSP_SPI2_MOSI_PIN, LL_GPIO_SPEED_FREQ_HIGH);
  LL_GPIO_SetPinOutputType(BSP_SPI2_MOSI_GPIO_PORT, BSP_SPI2_MOSI_PIN, LL_GPIO_OUTPUT_PUSHPULL);
  LL_GPIO_SetPinPull(BSP_SPI2_MOSI_GPIO_PORT, BSP_SPI2_MOSI_PIN, LL_GPIO_PULL_DOWN);
  BSP_SPI2_MOSI_GPIO_AF();

  BSP_SPI2_SCK_GPIO_CLK_ENABLE();
  LL_GPIO_SetPinMode(BSP_SPI2_SCK_GPIO_PORT, BSP_SPI2_SCK_PIN, LL_GPIO_MODE_ALTERNATE);
  LL_GPIO_SetPinSpeed(BSP_SPI2_SCK_GPIO_PORT, BSP_SPI2_SCK_PIN, LL_GPIO_SPEED_FREQ_HIGH);
  LL_GPIO_SetPinOutputType(BSP_SPI2_SCK_GPIO_PORT, BSP_SPI2_SCK_PIN, LL_GPIO_OUTPUT_PUSHPULL);
  LL_GPIO_SetPinPull(BSP_SPI2_SCK_GPIO_PORT, BSP_SPI2_SCK_PIN, LL_GPIO_PULL_DOWN);
  BSP_SPI2_SCK_GPIO_AF();

  BSP_SPI2_CS_DISPLAY_GPIO_CLK_ENABLE();
  LL_GPIO_SetPinMode(BSP_SPI2_CS_DISPLAY_GPIO_PORT, BSP_SPI2_CS_DISPLAY_PIN, LL_GPIO_MODE_OUTPUT); //LL_GPIO_MODE_ALTERNATE    
  LL_GPIO_SetPinSpeed(BSP_SPI2_CS_DISPLAY_GPIO_PORT, BSP_SPI2_CS_DISPLAY_PIN, LL_GPIO_SPEED_FREQ_HIGH); //  
  LL_GPIO_SetPinOutputType(BSP_SPI2_CS_DISPLAY_GPIO_PORT, BSP_SPI2_CS_DISPLAY_PIN, LL_GPIO_OUTPUT_PUSHPULL);
  LL_GPIO_SetPinPull(BSP_SPI2_CS_DISPLAY_GPIO_PORT, BSP_SPI2_CS_DISPLAY_PIN, LL_GPIO_PULL_DOWN);
  LL_GPIO_ResetOutputPin(BSP_SPI2_CS_DISPLAY_GPIO_PORT, BSP_SPI2_CS_DISPLAY_PIN);
  //BSP_SPI2_CS_GPIO_AF();  


  /* Initialize the SPI clock */
  BSP_SPI2_CLK_ENABLE();

  /* SPI parameter configuration*/
  LL_SPI_SetMode(BSP_SPI2, LL_SPI_MODE_MASTER);
  LL_SPI_SetStandard(BSP_SPI2, LL_SPI_PROTOCOL_TI); //      LL_SPI_PROTOCOL_MOTOROLA
  LL_SPI_SetTransferDirection(BSP_SPI2, LL_SPI_FULL_DUPLEX); //   LL_SPI_HALF_DUPLEX_TX
  LL_SPI_SetClockPolarity(BSP_SPI2, LL_SPI_POLARITY_LOW); // LL_SPI_POLARITY_HIGH
  LL_SPI_SetClockPhase(BSP_SPI2, LL_SPI_PHASE_1EDGE); // BSP_SPI2_CLK_PHASE
  LL_SPI_SetNSSMode(BSP_SPI2, LL_SPI_NSS_SOFT);// 
  LL_SPI_SetDataWidth(BSP_SPI2, LL_SPI_DATAWIDTH_8BIT);
  LL_SPI_SetTransferBitOrder(BSP_SPI2, LL_SPI_MSB_FIRST);
  LL_SPI_DisableCRC(BSP_SPI2);
  LL_SPI_DisableNSSPulseMgt(BSP_SPI2);
  LL_SPI_SetBaudRatePrescaler(BSP_SPI2, LL_SPI_BAUDRATEPRESCALER_DIV8); /* 8 MHz */

  /* Configure the SPI RX FIFO threshold to 1 byte */
  LL_SPI_SetRxFIFOThreshold(BSP_SPI2, LL_SPI_RX_FIFO_TH_QUARTER);

  /* Enable the SPI */
  LL_SPI_Enable(BSP_SPI2);

}
Danny0007
Senior

new findings:

with this setting 

 LL_SPI_SetDataWidth(BSP_SPI2, LL_SPI_DATAWIDTH_8BIT);

the data is actually 9 bits

Danny0007_2-1710283656800.png

 

"hmmm", for me, I would be suspicious, something wrong...:

  • You have one CLK edge, before the bursts with always 9 clocks - why is this CLK edge there and would it "confuse" your slave device?
    (it comes at the same time as nCS gets active high
  • At the end is always a clock edge, together with nCS right to go inactive (back to low here). Your slave device might still see the "spurious" clock edges. I would try to figure out why and how to get rid of it.
  • All data as ones - looks clean, but all as zero? Why do you have high pulses there? Even they might not be considered as "one" (outside the sampling clock edge) - but why and what is driving the data line in between?
    Are there pull-ups? Is the data line floating in between? (I cannot imagine).
  • Here, I would also try to understand what causes the high pulses when data line should be constant zero.
    It could be "cross-talk" (again) because: it corelates with the rising edge of CLK signal, not always, but when - the high pulses on data line are "in sync" with the CLK signal. A scope, sampling and rounding up to logic level 0 or 1 could look like this. You might need to use scope in analog mode and see the real waveform of the data line: potentially, you will see everywhere "when CLK goes high - there is also a pulse on data line".
  • Have you "played" with drive strengths or speed setting of the SPI pin signals? (the pin signal config)? Try to use "slow speed", e.g. on CLK signal... "Fast speed" can cause more EMI and cross-talk issues.
  • You could also try to add pull-up or pull-down on data line - hoping to get rid of the "wrong pulses".
  • Try to "get rid" of these "wrong pulses". Otherwise, any other data line bit pattern can be affected by this (and would be wrong).

BTW: when I see your PCB layout: why to keep the SPI signals parallel for such a long distance? You have enough space to separate the 3 traces much more, with a ground pour between them. To route the high speed SPI traces for such a long distance together, without a "shielding" between them, is not the best approach to avoiding cross-talk.

Danny0007
Senior

Hi @tjaekel 

Thanks for reply.

the first byte is 0xC0, which will be sent to display.

this is capture on Raspberry Pi, it also has a peak, but it doesn´t matter.

Danny0007_0-1710329273073.png

these are the captures on my board, the data will be recognised as 0xE0 or 0x60. Of course, it has more peaks, but it doesn´t affect the data. 

Danny0007_2-1710329542457.png

Danny0007_3-1710330432663.png

 

the biggst difference between the captures is the timing of MOSI signal, as you can see the MOSI signal on Pi board is already high, before the first clock signal comes. 

which settings can affect the timing?

 

 

 

 

Danny0007
Senior

just found the peaks can be eliminated by set the pin speed to LOW

Danny0007_0-1710368094316.png

the data should be 0xC0 and 0x80, but both are recognised as 0xE0...