Модуль ILI9327 - как включить последовательный интерфейс дисплея?

Всем привет. Есть модуль для ArduinoMega с дисплеем на контроллере ILI9327. Дисплей работает через параллельный 8-битный протокол. Вот так выглядит модуль:

Фотографии, извиняюсь за качество:


Контроллер позволяет работать через последовательный порт SPI, но, пока что, я не понял, возможно ли это сделать на данном модуле и, если возможно, то как. Количество резисторов на плате явно больше, чем используется сигналов в 8-битном режиме и не все контакты мне понятны по назначению. Если кто-нибудь использовал такой модуль в режиме SPI, помогите, пожалуйста.

Нужен даташит на дисплей. На ваших фото даже пины не подписаны, как вы предлагаете вам помочь?

Вопрос был адресован, в первую очередь, к тем, кто с таким модулем уже имел дело и у кого был вопрос, аналогичный моему и успешно решённый.
Вот даташит на дисплей: ILI9327.pdf — Яндекс Диск

У меня был, но с чуток другим дисплеем. Однако, такие вопросы решаются одинаково для любого дисплея и Вы можете решить его самостоятельно.

№1
Если у Вас всё работает с параллельным интерфейсом, то Вам надо открыть страницу 27 даташита и прочитать, что для последовательного интерфейса используются пины: CSX, SCL and SDA or DOUT

№2
Далее, надо определить где эти пины у Вас. Это легко определяется, т.к. они же используются и для параллельного интерфейса и можно просто посмотреть в библиотеке как они там называются.

№3
Теперь, когда Вы знаете где именно у Вас находятся нужные пины, осталось только аккуратно прописать работу через них (точно как описано в даташите).

Когда я это делал, у меня всё про всё заняло полдня. Думаю, у Вас тоже не займёт больше.

Производитель драйвера (странно, что Вы его сайт не изучили) даёт готовый пример использования дисплея с SPI, но я его не запускал и ничего сказать не могу. Попробуйте. Но, то, что я описал выше, сработает в любом случае.

Код на SPI от ILITEK
#include <SPI.h>  // We use this library, so it must be called here.
//#include <MCP23S17.h>         // Here is the new class to make using the MCP23S17 easy.
//Code modified from code I found on http://spikenzielabs.com/SpikenzieLabs/Project_64.html
//Purely to test if the hardware works, which it does.
// Code turns on and off each relay each second
//

// GPA port - these show which wires from the LCD are connected to which pins on the I/O expander

#define LCD_RST 0b00001000  // chip select 2  (pin 24)                            0x08
#define LCD_RD 0b00010000   // reset (pin 25)                                     0x10
#define LCD_WR 0b00100000   // 1xxxxxxx = data; 0xxxxxxx = instruction  (pin 26)  0x20
#define LCD_RS 0b01000000   // x1xxxxxx = read; x0xxxxxx = write  (pin 27)        0x40
#define LCD_CS 0b10000000   // enable by toggling high/low  (pin 28)                 0x80

#define MCP23S17 B01000000  // MCP23017 SPI Address

#define IOCON 0x0A  // MCP23017 Config Reg.

#define IODIRA 0x00  // MCP23017 address of I/O direction
#define IODIRB 0x01  // MCP23017 1=input

#define IPOLA 0x02  // MCP23017 address of I/O Polarity
#define IPOLB 0x03  // MCP23017 1= Inverted

#define GPIOA 0x12  // MCP23017 address of GP Value
#define GPIOB 0x13  // MCP23017 address of GP Value

#define GPINTENA 0x04  // MCP23017 IOC Enable
#define GPINTENB 0x05  // MCP23017 IOC Enable

#define INTCONA 0x08  // MCP23017 Interrupt Cont
#define INTCONB 0x09  // MCP23017 1= compair to DEFVAL(A or B) 0= change

#define DEFVALA 0x06  // MCP23017 IOC Default value
#define DEFVALB 0x07  // MCP23017 if INTCONA set then INT. if diff.

#define GPPUA 0x0C  // MCP23017 Weak Pull-Ups
#define GPPUB 0x0D  // MCP23017 1= Pulled HIgh via internal 100k

#define OLATA 0x14
#define OLATB 0x15

#define INTFA 0x0E
#define INTFB 0x0F

#define INTCAPA 0x10
#define INTCAPB 0x11

// SPI
#define SS 10    // Pin mapping to Arduino = SELECT
#define MOSI 11  // Pin mapping to Arduino = Master Out Slave In
#define SCLK 13  // Pin mapping to Arduino = Serial clock
#define MISO 12  // Pin mapping to Arduino = Master IN slave OUT

int rx_data = 0;
int buttonPress = 0;
int error_flag = 0;
int COLUMN = 0;

void setup() {
  Serial.begin(9600);

  pinMode(SS, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(SCLK, OUTPUT);
  pinMode(MISO, INPUT);

  digitalWrite(SS, HIGH);
  digitalWrite(SCLK, LOW);
  digitalWrite(MOSI, LOW);
  // SPI.setClockDivider(SPI_CLOCK_DIV2);
  //  delay(100);                               // This delay seems important for the MCP23S17 power-up

  SPI_portexpanderinit();

  initft();
  //  LCD_Clear(0xf800);
  dis_color4(0xf800, 0x07e0, 0x001f, 0x07ff, 0xf81f, 0xffe0, 0x0000, 0xffff);  //8色间隔画面
  // clear (0,0,240,400,0xf800);
  //  clear (41,41,80,80,0xf800);
  //dis_color1(0xf800)   ;
}

void loop() {
  //Turns on and off each relay in turn
  // SPI_TX(MCP23S17,GPIOA,B10000000);
}

void SPI_portexpanderinit() {
  // --- Set I/O Direction
  SPI_TX(MCP23S17, IODIRB, B00000000);  // MCP23S17 port B = OUTPUT
  SPI_TX(MCP23S17, IODIRA, B00000000);  // MCP23S17 port A = OUTPUT

  //  --- Clear ALL Bits of GPIOA and GPIOB
  SPI_TX(MCP23S17, GPIOB, B00000000);  // MCP23S17 Clear port B
  SPI_TX(MCP23S17, GPIOA, B00000000);  // MCP23S17 Clear port A
}

void SPI_TX(int device, int regadd, int tx_data) {
  digitalWrite(SS, LOW);  // Select the Chip

  device = device & B11111110;  // Clear last bit for a write

  SPI8BITTXLOOP(device);  // SPI Device

  SPI8BITTXLOOP(regadd);  // SPI REGISTER ADDRESS

  SPI8BITTXLOOP(tx_data);  // Data

  digitalWrite(SS, HIGH);  // Done UN-Select the Chip
}

void SPI8BITTXLOOP(int data) {
  int i = 0;
  int temp = 0;

  for (i = 1; i < 9; i = i + 1) {
    temp = (data >> 7);  // Test bit 7 of DATA
    temp = temp & 1;
    if (temp == 0)  // SET or CLEAR MOSI
    {
      digitalWrite(MOSI, LOW);
    } else {
      digitalWrite(MOSI, HIGH);
    }
    digitalWrite(SCLK, HIGH);  // SET SCLK
    digitalWrite(SCLK, LOW);   // Clear Clock
    data = data << 1;          // Shift data LEFT by 1
  }
}

void initft() {
  SPI_TX(MCP23S17, GPIOA, LCD_RST);
  delay(50);
  SPI_TX(MCP23S17, GPIOA, 0);
  delay(10);
  SPI_TX(MCP23S17, GPIOA, LCD_RST);
  delay(50);
  cmd(0xE9);
  writeData(0x20);
  cmd(0x11);  //Exit Sleep
  //delay(100);
  cmd(0xD1);
  writeData(0x00);
  writeData(0x71);
  writeData(0x19);
  cmd(0xD0);
  writeData(0x07);
  writeData(0x01);
  writeData(0x08);
  cmd(0x36);
  writeData(0x48);
  cmd(0x3A);
  writeData(0x05);
  cmd(0xC1);
  writeData(0x10);
  writeData(0x10);
  writeData(0x02);
  writeData(0x02);
  cmd(0xC0);  //Set Default Gamma
  writeData(0x00);
  writeData(0x35);
  writeData(0x00);
  writeData(0x00);
  writeData(0x01);
  writeData(0x02);
  cmd(0xC5);  //Set frame rate
  writeData(0x04);
  cmd(0xD2);  //power setting
  writeData(0x01);
  writeData(0x44);
  cmd(0xC8);  //Set Gamma
  writeData(0x04);
  writeData(0x67);
  writeData(0x35);
  writeData(0x04);
  writeData(0x08);
  writeData(0x06);
  writeData(0x24);
  writeData(0x01);
  writeData(0x37);
  writeData(0x40);
  writeData(0x03);
  writeData(0x10);
  writeData(0x08);
  writeData(0x80);
  writeData(0x00);
  cmd(0x2A);
  writeData(0x00);
  writeData(0x00);
  writeData(0x00);
  writeData(0xeF);
  cmd(0x2B);
  writeData(0x00);
  writeData(0x00);
  writeData(0x01);
  writeData(0x8F);
  cmd(0x29);  //display on
  cmd(0x2C);  //display on
  //delay(100);
}
void setXY(int x1, int y1, int x2, int y2) {

  cmd(0x2a);
  writeData(x1 >> 8);
  writeData(x1);
  writeData(x2 >> 8);
  writeData(x2);
  cmd(0x2b);
  writeData(y1 >> 8);
  writeData(y1);
  writeData(y2 >> 8);
  writeData(y2);
  cmd(0x2c);
}
void clrXY() {

  setXY(0, 0, 240, 400);
}
void cmd(int dat) {
  SPI_TX(MCP23S17, GPIOB, dat);
  SPI_TX(MCP23S17, GPIOA, B00011000);
  SPI_TX(MCP23S17, GPIOA, B10111000);
}
void writeData(int dat) {
  SPI_TX(MCP23S17, GPIOB, dat);
  SPI_TX(MCP23S17, GPIOA, B01011000);
  SPI_TX(MCP23S17, GPIOA, B11111000);
}

void clear(const byte x1,  // start pixel
           const byte y1,
           const byte x2,  // end pixel
           const byte y2,
           const byte val)  // what to fill with
{
  char m, i;
  cmd(0x2a);
  writeData(x1 >> 8);
  writeData(x1);
  writeData(x2 >> 8);
  writeData(x2);
  cmd(0x2b);
  writeData(y1 >> 8);
  writeData(y1);
  writeData(y2 >> 8);
  writeData(y2);
  cmd(0x2c);

  for (i = 0; i < 400; i++)
    for (m = 0; m < 240; m++) {

      //SPI_TX(MCP23S17,GPIOA,LCD_RST|LCD_RD|LCD_RS);
      //SPI_TX(MCP23S17,GPIOB,val>>8);
      //SPI_TX(MCP23S17,GPIOA,LCD_RST|LCD_WR|LCD_RS|LCD_RD );
      SPI_TX(MCP23S17, GPIOA, LCD_RST | LCD_RD | LCD_RS);
      SPI_TX(MCP23S17, GPIOB, val);
      SPI_TX(MCP23S17, GPIOA, LCD_RST | LCD_WR | LCD_RS | LCD_RD);
    }
  digitalWrite(LCD_CS, HIGH);
}  // end of I2C_graphical_LCD_display::clear

//=================================单色画面======================================//
void dis_color1(unsigned int val) {
  unsigned int i, m;
  cmd(0x002c);
  for (i = 0; i < 400; i++)
    for (m = 0; m < 240; m++) {

      SPI_TX(MCP23S17, GPIOA, 0x58);  //LCD_RST|LCD_RD|LCD_RS
      SPI_TX(MCP23S17, GPIOB, val >> 8);
      SPI_TX(MCP23S17, GPIOA, 0x78);  //LCD_RST|LCD_WR|LCD_RS|LCD_RD
      SPI_TX(MCP23S17, GPIOA, 0x58);
      SPI_TX(MCP23S17, GPIOB, val);
      SPI_TX(MCP23S17, GPIOA, 0x78);
    }

  SPI_TX(MCP23S17, GPIOA, 0xf8);
}

void LCD_Clear(unsigned int j) {
  unsigned int i, m;
  cmd(0x02c);  //write_memory_start
  digitalWrite(LCD_RS, HIGH);
  digitalWrite(LCD_CS, LOW);
  Address_set(0, 0, 479, 399);

  for (i = 0; i < 480; i++)
    for (m = 0; m < 400; m++) {
      writeData(j);
    }
  digitalWrite(LCD_CS, HIGH);
}
/*void H_line(unsigned int x, unsigned int y, unsigned int l, unsigned int c)                   
{	
  unsigned int i,j;
  cmd(0x02c); //write_memory_start
  digitalWrite(LCD_RS,HIGH);
  digitalWrite(LCD_CS,LOW);
  l=l+x;
  Address_set(x,y,l,y);
  j=l*2;
  for(i=1;i<=j;i++)
  {
    Lcd_Write_Data(c);
  }
  digitalWrite(LCD_CS,HIGH);   
}
*/

void Address_set(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2) {
  cmd(0x2a);  // Set_column_address 4 parameters
  writeData(x1 >> 8);
  writeData(x1);
  writeData(x2 >> 8);
  writeData(x2);

  cmd(0x2b);  // Set_page_address 4 parameters
  writeData(y1 >> 8);
  writeData(y1);
  writeData(y2 >> 8);
  writeData(y2);

  cmd(0x2c);  // Write_memory_start
}
//=============================8色彩间隔画面======================================//
void dis_color4(unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f, unsigned int g, unsigned int h) {
  unsigned int i, m;
  cmd(0x002c);
  for (i = 0; i < 50; i++)
    for (m = 0; m < 240; m++) {

      SPI_TX(MCP23S17, GPIOA, 0x58);  //LCD_RST|LCD_RD|LCD_RS
      SPI_TX(MCP23S17, GPIOB, a >> 8);
      SPI_TX(MCP23S17, GPIOA, 0x78);  //LCD_RST|LCD_WR|LCD_RS|LCD_RD
      SPI_TX(MCP23S17, GPIOA, 0x58);
      SPI_TX(MCP23S17, GPIOB, a);
      SPI_TX(MCP23S17, GPIOA, 0x78);
    }

  SPI_TX(MCP23S17, GPIOA, 0xf8);
  for (i = 0; i < 50; i++)
    for (m = 0; m < 240; m++) {

      SPI_TX(MCP23S17, GPIOA, 0x58);  //LCD_RST|LCD_RD|LCD_RS
      SPI_TX(MCP23S17, GPIOB, b >> 8);
      SPI_TX(MCP23S17, GPIOA, 0x78);  //LCD_RST|LCD_WR|LCD_RS|LCD_RD
      SPI_TX(MCP23S17, GPIOA, 0x58);
      SPI_TX(MCP23S17, GPIOB, b);
      SPI_TX(MCP23S17, GPIOA, 0x78);
    }

  SPI_TX(MCP23S17, GPIOA, 0xf8);
  for (i = 0; i < 50; i++)
    for (m = 0; m < 240; m++) {

      SPI_TX(MCP23S17, GPIOA, 0x58);  //LCD_RST|LCD_RD|LCD_RS
      SPI_TX(MCP23S17, GPIOB, c >> 8);
      SPI_TX(MCP23S17, GPIOA, 0x78);  //LCD_RST|LCD_WR|LCD_RS|LCD_RD
      SPI_TX(MCP23S17, GPIOA, 0x58);
      SPI_TX(MCP23S17, GPIOB, c);
      SPI_TX(MCP23S17, GPIOA, 0x78);
    }

  SPI_TX(MCP23S17, GPIOA, 0xf8);
  for (i = 0; i < 50; i++)
    for (m = 0; m < 240; m++) {

      SPI_TX(MCP23S17, GPIOA, 0x58);  //LCD_RST|LCD_RD|LCD_RS
      SPI_TX(MCP23S17, GPIOB, d >> 8);
      SPI_TX(MCP23S17, GPIOA, 0x78);  //LCD_RST|LCD_WR|LCD_RS|LCD_RD
      SPI_TX(MCP23S17, GPIOA, 0x58);
      SPI_TX(MCP23S17, GPIOB, d);
      SPI_TX(MCP23S17, GPIOA, 0x78);
    }

  SPI_TX(MCP23S17, GPIOA, 0xf8);
  for (i = 0; i < 50; i++)
    for (m = 0; m < 240; m++) {

      SPI_TX(MCP23S17, GPIOA, 0x58);  //LCD_RST|LCD_RD|LCD_RS
      SPI_TX(MCP23S17, GPIOB, e >> 8);
      SPI_TX(MCP23S17, GPIOA, 0x78);  //LCD_RST|LCD_WR|LCD_RS|LCD_RD
      SPI_TX(MCP23S17, GPIOA, 0x58);
      SPI_TX(MCP23S17, GPIOB, e);
      SPI_TX(MCP23S17, GPIOA, 0x78);
    }

  SPI_TX(MCP23S17, GPIOA, 0xf8);
  for (i = 0; i < 50; i++)
    for (m = 0; m < 240; m++) {

      SPI_TX(MCP23S17, GPIOA, 0x58);  //LCD_RST|LCD_RD|LCD_RS
      SPI_TX(MCP23S17, GPIOB, f >> 8);
      SPI_TX(MCP23S17, GPIOA, 0x78);  //LCD_RST|LCD_WR|LCD_RS|LCD_RD
      SPI_TX(MCP23S17, GPIOA, 0x58);
      SPI_TX(MCP23S17, GPIOB, f);
      SPI_TX(MCP23S17, GPIOA, 0x78);
    }

  SPI_TX(MCP23S17, GPIOA, 0xf8);
  for (i = 0; i < 50; i++)
    for (m = 0; m < 240; m++) {

      SPI_TX(MCP23S17, GPIOA, 0x58);  //LCD_RST|LCD_RD|LCD_RS
      SPI_TX(MCP23S17, GPIOB, g >> 8);
      SPI_TX(MCP23S17, GPIOA, 0x78);  //LCD_RST|LCD_WR|LCD_RS|LCD_RD
      SPI_TX(MCP23S17, GPIOA, 0x58);
      SPI_TX(MCP23S17, GPIOB, g);
      SPI_TX(MCP23S17, GPIOA, 0x78);
    }

  SPI_TX(MCP23S17, GPIOA, 0xf8);
  for (i = 0; i < 50; i++)
    for (m = 0; m < 240; m++) {

      SPI_TX(MCP23S17, GPIOA, 0x58);  //LCD_RST|LCD_RD|LCD_RS
      SPI_TX(MCP23S17, GPIOB, h >> 8);
      SPI_TX(MCP23S17, GPIOA, 0x78);  //LCD_RST|LCD_WR|LCD_RS|LCD_RD
      SPI_TX(MCP23S17, GPIOA, 0x58);
      SPI_TX(MCP23S17, GPIOB, h);
      SPI_TX(MCP23S17, GPIOA, 0x78);
    }

  SPI_TX(MCP23S17, GPIOA, 0xf8);
}

(с показом кода какие-то проблемы, но кнопкой копирования он копируется полностью)

1 лайк

Большое спасибо за ответ!
На странице 27 я был и диаграммы видел. Но, используя дисплеи на других контроллерах (я имею ввиду именно контроллер дисплея) для переключения режимов интерфейса нужно было выполнять определённые коммутации выводов. Для ILI9327 я этой информации не нашёл. Может быть, плохо искал, может быть - ничего не нужно делать и достаточно просто начать работу по SPI. Хорошо, если сразу заработает, а если нет - где искать проблему? То ли в коде, то ли в том, что интерфейс принудительно не переведён в нужный режим. Сразу область поиска проблемы расширяется. Насчёт сайта - да, моё упущение, буду почитать. Ещё раз спасибо!

IM0, IM1, IM2 - тип интерфейса. Просмотрел, почему-то, хотя не в одном месте об этом написано в даташите. Теперь только их найти…

Пины №№ 64-66

Спасибо, это я видел. Найти бы нужные сигналы на 42-контактном шлейфе…


Белое - остатки двустороннего скотча. На шлейфе не видно посадочных мест под резисторы для IM0-2.

Не могу найти кнопки редактирования сообщений, приходится делать новый ответ. Можно как-нибудь редактировать свои сообщения?

Внизу справа - карандаш

image

Если у Вас нет, значит нет … тут многие возможности от стажа на форуме зависят.