LCD without R/W pin

Hi,
I have a TFT display 2,8'', that (theorically) is driven by ILI3941 chip.
The problem is that every sample (and also library) I've seen use also a R/W pin that is not present on my LCD.
Pins are:

VDD
TFT_CS
SDI (SDA)
SDO
SCK (SCL)
RST
SD_CS
TFT_BL
GND

There isn't SD reader (altough in PCB I can see contacts).

I'm trying to use it with Arduino Mega 2560. Can you help me?
Thank you.

The pins you described are for a SERIAL interface (IIC or SPI), R/W is part of a PARALLEL interface, along with RS and E and D0-D7.

The ILI9341 is a 3.3V device. You must use level shifter with a 5V Mega2560.

There are plenty of SPI libraries for this display. e.g. Adafruit_ILI9341.h
However, these normally expect a TFT_DC pin.

Please post a link to your actual display.

David.

Hi,
thank you for your response :slight_smile:

The only link I can provide is this:

is a chinese sub-clone so you can imagine that there isn't any documentation (or it's well hidden).

For 3,3 V I've already setup a resistor grid of 220 - 330 ohm for having 3,3 V between resistors.

Maybe library UTFT can be used?

I think that D/C is useless because there isn't any SD card reader on the PCB so they used this strange SPI mode.

I hope these informations can help you to help me :slight_smile:

Marco

If your board looks exactly like the photo in your linked thread.

You have to provide 3.3V logic. The UTFT 9-bit SPI should work. As described in your linked thread

I suspect that it is not only 9-bit but with a bi-directional SDA pin.
So if you want to read the ID or GRAM, you have to do some other contortions.

I can post you a diagnostic test sketch that will handle all these "interfaces"
But only if you provide 3.3V logic. e.g. with series resistors

Incidentally, your pcb seems a little pointless without a microSD socket.
The only "good" point is the switchable Backlight.

David.

Thank you :slight_smile:
Please post me the code.
This evening I will try UTFT.

Seriously. If you connect the display with 5V logic, you will kill your controller.

Simple 2k2 series resistors will limit any currents. And be fairly safe.
The world is far simpler if you just use a proper 3.3V Arduino.

ST7735_readreg_diag.ino

// see if 4-line mode can read anything

#define TFT_MOSI 11
#define TFT_MISO 12
#define TFT_SCK  13
#define TFT_SS   10
#define TFT_DC  (9)     //DC=7 for HX8347
#define TFT_RESET (8)   //Backlight on HX8347
#define NINEBITS  (1<<0)
#define SDA_INPUT (1<<1)
#define HAS_MISO  (1<<2)
char *chip = "controller";
//char interface = 0;    //regular ST7735, ILI9163
//char interface = HAS_MISO;  //ILI9341 SPI
//char interface = NINEBITS;  //ILI9341 SPI with regular MISO 
char interface = NINEBITS | SDA_INPUT;  //ILI9341/ILI9481 9-bit SPI bidirectional

uint32_t readwrite8(uint8_t cmd, uint8_t bits, uint8_t dummy)
{
    digitalWrite(TFT_SS, LOW);
    write9(cmd, 0);
    uint32_t ret = read8(bits, dummy);
    digitalWrite(TFT_SS, HIGH);
    return ret;
}

void write9(uint8_t val, uint8_t dc)
{
    pinMode(TFT_MOSI, OUTPUT);
    digitalWrite(TFT_DC, dc);
    if (interface & NINEBITS) {
        digitalWrite(TFT_MOSI, dc);
        digitalWrite(TFT_SCK, HIGH);
        digitalWrite(TFT_SCK, LOW);
    }
    for (int i = 0; i < 8; i++) {   //send command
        digitalWrite(TFT_MOSI, (val & 0x80) != 0);
        digitalWrite(TFT_SCK, HIGH);
        digitalWrite(TFT_SCK, LOW);
        val <<= 1;
    }
}

void writeblock(uint8_t cmd, uint8_t *block, int8_t N)
{
    uint8_t val = cmd;
    digitalWrite(TFT_SS, LOW);
    write9(cmd, 0);
    while (N-- > 0) write9(*block++, 1);
    digitalWrite(TFT_SS, HIGH);
}

uint32_t read8(uint8_t bits, uint8_t dummy)
{
    uint32_t ret = 0;
    uint8_t SDA = (interface & HAS_MISO) ? TFT_MISO : TFT_MOSI;
    pinMode(SDA, INPUT_PULLUP);
    digitalWrite(TFT_DC, HIGH);
    for (int i = 0; i < dummy; i++) {  //any dummy clocks
        digitalWrite(TFT_SCK, HIGH);
        digitalWrite(TFT_SCK, LOW);
    }
    for (int i = 0; i < bits; i++) {  // read results
        ret <<= 1;
        if (digitalRead(SDA)) ret |= 1;;
        digitalWrite(TFT_SCK, HIGH);
        digitalWrite(TFT_SCK, LOW);
    }
    return ret;
}

void showreg(uint8_t reg, uint8_t bits, uint8_t dummy)
{
    uint32_t val, mask = 0x10000000;
    for (uint8_t wid = 32; wid > bits; wid -= 4) mask >>= 4;
    writeblock(0x01, NULL, 0);   //software reset first
    delay(100);
    uint8_t d[4];
    if (interface & SDA_INPUT) {
        d[0] = 0x00;
        writeblock(0xB0, d, 1);  //UNLOCK
        d[0] = 0x80;
        writeblock(0xC6, d, 1);  //enable SDA as input
    }
    // works for an ILI9341 in 4-wire SPI mode
    if ((interface & HAS_MISO) && ((reg >= 0xB0 && reg < 0xF0)) ) {
        val = 0;
        d[0] = 0x10;
        while (bits > 0) {
            writeblock(0xD9, d, 1);       // CS sequence
            val <<= 8;
            val |= readwrite8(reg, 8, 0); // CS sequence
            bits -= 8;
            d[0]++;
        }
    }
    else val = readwrite8(reg, bits, dummy);

    Serial.print(chip);
    Serial.print(" reg(0x");
    if (reg < 0x10) Serial.print("0");
    Serial.print(reg , HEX);
    Serial.print(") = 0x");
    while (val < mask) Serial.print("0"), mask >>= 4;
    if (val) Serial.println(val, HEX);
    else Serial.println();

}

void setup() {
    // put your setup code here, to run once:
    uint32_t ID = 0;
    Serial.begin(9600);
    while (!Serial) ;
    if (interface & HAS_MISO)
        Serial.println("Read registers 8-bit SPI with MISO (+ DC)");
    else if (interface & NINEBITS)
        Serial.println("Bi-directional Read registers 9-bit SPI");
    else
        Serial.println("Bi-directional Read registers SDA (+ DC)");
    digitalWrite(TFT_SS, HIGH);
    //    digitalWrite(TFT_SCK, HIGH);
    pinMode(TFT_SS, OUTPUT);
    pinMode(TFT_SCK, OUTPUT);
    pinMode(TFT_MOSI, OUTPUT);
    pinMode(TFT_MISO, INPUT);
    pinMode(TFT_DC, OUTPUT);
    pinMode(TFT_RESET, OUTPUT);
    digitalWrite(TFT_RESET, HIGH);
    digitalWrite(TFT_RESET, LOW);   //Hardware Reset
    delay(50);
    digitalWrite(TFT_RESET, HIGH);
    writeblock(0x01, NULL, 0);            //Software Reset
    delay(100);
    ID = readwrite8(0x04, 24, 1);
    if (ID == 0x7C89F0uL) chip = "ST7735S";
    if (ID == 0x548066uL) chip = "ILI9163C";
    ID &= 0xFF0000;
    if (ID == 0x5C0000) chip = "ST7735";
/*
    Serial.println("Scan all registers for any response");
    for (uint8_t reg = 0; reg < 0xFF; reg++) {
        if (readwrite8(reg, 32, 0) != 0xFFFFFFFF)
            showreg(reg, 32, 0);
    }
*/
    Serial.println("data sheet specific calls");
    showreg(0x04, 24, 1);  //RDDID
    showreg(0x09, 32, 1);  //RDDSTATUS
    showreg(0x0A, 8, 0);
    showreg(0x0B, 8, 0);   //RDDMADCTL
    showreg(0x0C, 8, 0);   //RDDCOLMOD
    showreg(0x0D, 8, 0);
    showreg(0x0E, 8, 0);
    showreg(0x0F, 8, 0);
    showreg(0x2E, 24, 8);  //readGRAM
    showreg(0xA1, 32, 1);  //ILI9481 DDB_Start
    showreg(0xBF, 32, 1);  //ILI9481 ID
    showreg(0xD3, 32, 1);  //RDID4 according to data sheet
    showreg(0xDA, 8, 0);   //RDID1
    showreg(0xDB, 8, 0);   //RDID2
    showreg(0xDC, 8, 0);   //RDID3
}

void loop() {
    // put your main code here, to run repeatedly:

}

#if defined(USE_SPI)
// use SPI mode #0
uint8_t spi(uint8_t c)
{
    SPDR = c;
    while ((SPSR & 0x80) == 0) ;
    return SPDR;
}

uint32_t readwrite8(uint8_t cmd, uint8_t bits, uint8_t dummy)
{
    uint32_t ret = 0;
    uint8_t val = cmd;
    int cnt = 8;
    digitalWrite(TFT_SS, LOW);
    SPSR = (0 << SPI2X);
    SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); //1MHz
    digitalWrite(TFT_DC, LOW);
    pinMode(TFT_MOSI, OUTPUT);
    spi(cmd);
    if (bits) {
        digitalWrite(TFT_DC, HIGH);
        pinMode(TFT_MOSI, INPUT);
        while (bits) {
            ret <<= 8;
            ret |= spi(0x00);
            bits -= 8;
        }
        ret >>= dummy;
    }
    digitalWrite(TFT_SS, HIGH);
    return ret;
}
#endif

Note that this sketch is a bit universal. You need to connect your pins like this:

#define TFT_MOSI 11     //SDA
#define TFT_MISO 12     //SDO
#define TFT_SCK  13     //SCL
#define TFT_SS   10     //TFT_CS
#define TFT_DC  (9)     //TFT_BL
#define TFT_RESET (8)   //RST

I have only used this particular “interface” with an ILI9481. It should work with an ILI9341. Please let me know.

David.

Hi,
Bad news. I think that IC is broken, because yesterday I used 5V without the resistor array.
I've connected everything to an Arduino DUE, I've compiled your sketch but it returns only lot of 0xFF.
Thank you for your time... I think that I will buy a parallel LCD display.

If you look in the ILI9341 datasheet, there are several IM# modes.

IM#5 is 3-wire 9-bit data serial interface with SCL,SDA,CSX
IM#13 is 3-wire 9-bit data serial interface with SCL,SDI,SDO,CSX

The ILI9341 does not appear to have the SPI_READ_EN bit in reg(0xC6) that ILI9481 has.
Or reg(0xFB) that the ILI9486/88 have.

You could just try:

        writeblock(0xC6, d, 1);  //enable SDA as input 
        d[0] = 0xF0;         //enable SPI_READ_EN i.e. bidirectional
        writeblock(0xFB, d, 1);  //write to 0xFB for ILI9486/8

You could also just try:

char interface = NINEBITS;  //ILI9341 SPI with regular MISO
//char interface = NINEBITS | SDA_INPUT;  //ILI9341/ILI9481 9-bit SPI bidirectional

It is probably wise to just buy a 8-bit parallel (or 16-bit parallel) or 8-bit SPI display.
They are plentiful and cheap. The 8-bit parallel Mcufriend ones already come as a shield with 3.3V level converters.

David.