3

The SSD1803 is a controller which is used to control an LCD-Display. I'm using SPI to communicate with the controller, which works fine for normal instructions: I can print text onto the display, clearing the display, storing my custom characters in the RAM, setting the cursor, etc.
But now I want to read the Busy Flag (BF), which isn't working properly-> The byte which contains the BF always returns 0.

Command Table

Instruction RE RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 Execution Time
Clear Display X 0 0 0 0 0 0 0 0 0 0 1.53ms
Ready busy flag and address/part ID X 0 1 BF AC6/ID6 AC5/ID5 AC4/ID4 AC3/ID3 AC2/ID2 AC1/ID1 AC0/ID0 0us

BF = 1: busy state
BF = 0: ready state

SSD1803 Datasheet p. 29


Timing Diagram

Timing_Diagram

SSD1803 Datasheet p. 27


IOC Config File

IOC_File

The clock frequency is 312.5kHz which is in the external clock range of the controller:

External_Clock

SSD1803 Datasheet p. 57


Code

   int LCDInstrHandler(void)
   {
     // Clear Display
•    HAL_GPIO_WritePin(SPI_LCD_NSS_GPIO_Port, SPI_LCD_NSS_Pin, GPIO_PIN_RESET);

     uint8_t tDataClear[3] = {0b11111000, 0b10000000, 0b00000000};
     HAL_StatusTypeDef tClearState = HAL_SPI_Transmit(&SPI_LCD, tDataClear, 3, 1000);

     HAL_GPIO_WritePin(SPI_LCD_NSS_GPIO_Port, SPI_LCD_NSS_Pin, GPIO_PIN_SET);
     
     // Read Busy Flag
     uint8_t tDataBF[2] = {0b11111100, 0x00};
     uint8_t tRecBuf[2];

     HAL_GPIO_WritePin(SPI_LCD_NSS_GPIO_Port, SPI_LCD_NSS_Pin, GPIO_PIN_RESET);
     HAL_StatusTypeDef tBFState = HAL_SPI_TransmitReceive(&SPI_LCD, tDataBF, tRecBuf, 2, 1000);
     HAL_GPIO_WritePin(SPI_LCD_NSS_GPIO_Port, SPI_LCD_NSS_Pin, GPIO_PIN_SET);

•    return 0;
   }

= Breakpoint

By default, there's a text on the display, which gets printed after the initialization. After that the function LCDInstrHandler gets called.
As you can see in the IOC Config file, I set the First Bit to MSB First. Means the left bit is sent first and when I receive a byte, the left bit is the first bit the slave sent.

To test if the busy flag works, I send the clear display instruction, which takes 1.53ms. This works: My display is cleared. After that, I send the start byte with RS = 0 and R/W = 1, which tells the SSD1803 controller to return me a byte containing the BF in DB7 (see Command Table).

The time between the first breakpoint and the second breakpoint is 150us (measured with oscilloscope). Means that the BF instruction gets executed in time, so that the BF should be 1 since the SSD1803 controller is still executing the clear display instruction.

What I get:

  • tRecBuf: {0, 0}
  • tClearState, tBFState: HAL_OK

What I expect

  • tRecBuf: {0, 0bxxxxxxx1}
    • 1: BF (DB7) as LSB
    • xxxxxxx: AC0-AC6


Attachments

puncher
  • 1,570
  • 4
  • 15
  • 38
  • 1
    Why do you think that the flag should be `1`? – 0___________ Feb 21 '23 at 10:53
  • @0___________ Because the SSD1803 is processing the `Clear Display` instruction which dues 1.53ms and I'm reading the `BF` within these 1.53ms. – puncher Feb 21 '23 at 11:21
  • What's "CPHA 2 Edge" even supposed to mean? SPI has two clock phase settings, CPHA=0 meaning clock edge happens half a bit length inside the data, CPHA=1 meaning data and clock edges are aligned. CPHA=2 means... what? – Lundin Feb 21 '23 at 12:04
  • 1
    Do you have a 2 channel scope? Trigger on /CS falling edge and check if the actual data contains the 1 or not. – Lundin Feb 21 '23 at 12:13
  • @Lundin "2 Edge" is `CPHA = 1` in code . Because I have a `HIGH` Polarity clock (if it doesn't clock, the clock line is on `HIGH`) and, as you can see in the timing diagram, the data should be clocked out on rising edge, I have to set the Clock Phase on "2 Edge". – puncher Feb 21 '23 at 12:48
  • Busy flag is transmitted with some other bits - `ACx/IDx`. Since these are received as zeros two, it looks like data reception doesn't work at all. Try to make an external loopback - disconnect the SSD1803 and connect MOSI to MISO directly. This way the mcu should receive it's own data with `HAL_SPI_TransmitReceive` function. If it still receives zero - then SPI or MISO pin is not configured correctly. – Flexz Feb 21 '23 at 19:10
  • @Flexz Would be nice approach. The problem is, the SSD1803 is soldered on a bought LCD-Display and I can't reach the controller because it has thermal paste on it. Thanks though for you comment! – puncher Feb 22 '23 at 14:13
  • Are you saying that you cannot disconnect the MCU from the display? – the busybee Feb 23 '23 at 21:21
  • Did you try to receive 2 bytes, as the second one will tell you the ID of the LCD controller? -- Please record the actual transmission, as Lundin suggested, and add it to your question. – the busybee Feb 23 '23 at 21:26
  • OT: Why did you swap the bits of the bytes? The diagrams of the LCD controller show that LSBit is transmitted first. You will need to mirror all values in your program, compared to common notation. – the busybee Feb 23 '23 at 21:27
  • @thebusybee Not the MCU. I can't reach the controller (SSD1803) of the LCD Display. Also, I measured the transmission. The CS is in time and the clock looks fine (same as in the timing diagram). The data line is on 0V (same as the data I receive). – puncher Feb 23 '23 at 22:31
  • @thebusybee I set in the IOC the first bit to MSB. Since the SSD1803 uses LSB, I swapped the bytes. – puncher Feb 23 '23 at 22:32
  • Concerning the MSB/LSB: Do want you want, I just wondered why you make life harder than necessary. -- The suggestion of Flexz was to separate the MCU from the LCD and to connect MOSI to MISO to check that on the MCU's side transmission works correctly. -- You might want to add your scope/analyzer recordings of the write/read cycles. – the busybee Feb 24 '23 at 06:45

0 Answers0