Обсуждаем контроллеры компании Atmel.
Ответить

Нужна библиотека для CVAVR ILI9341 3.2 inch TFT LCD module

Пн дек 17, 2018 16:18:20

Купил себе дисплейчик вот такой: 3.2 inch TFT LCD Module with Touch Panel ILI9341 Drive IC 240(RGB)*320 SPI Interface (9 IO) 240*320 Touch ic XPT2046 SPI port
очень хочется заюзать
Если кто нить запускал такой, поделитесь библой для CVAVR
Вложения
TFT LCD ILI9341 spi 3.2inch.jpg
(91.94 KiB) Скачиваний: 744

Re: Нужна библиотека для CVAVR ILI9341 3.2 inch TFT LCD modu

Вт дек 25, 2018 11:29:33

Если есть опыт портрирования , то реализция авр но с исспользованием дуруины . https://github.com/marekburiak/ILI9341_due

Re: Нужна библиотека для CVAVR ILI9341 3.2 inch TFT LCD modu

Вт дек 25, 2018 15:41:18

Спасибо за ссылку! :beer: Уже что то.
Не ужели ни кто в CVAVR не юзал такой дисплей?
очень странно... :shock:

Re: Нужна библиотека для CVAVR ILI9341 3.2 inch TFT LCD modu

Вт янв 15, 2019 12:58:40

Давайте сначала определимся, какие требования к библиотеке должны быть ?
Поскольку работа с дисплеем делится на три части:
1. Физическая работа с дисплеем - это подключение дисплея к АВРке, отправка байта в дисплей, управление выводами CS, RS и RST
2. базовая работа с дисплеем (низкоуровневая графика) - включение/выключение, инициализация, спящий режим, определение области вывода, отправка данных в дисплей
3. Работа с графикой на более высоком уровне - процедуры рисования линии, прямоуголника, окружности, вывода текста

По большому счету - эти три части - это три разных уровня, которые не зависят друг от друга.

И Аппаратно-зависимый - только первый уровень, где описано физическое подключение дисплея к МК.

Я в свое время делал изделие с таким дисплеем, под него выписал первую и вторую части. Третья часть - графика - у меня была написана ранее.

Все написано на чистом С (файлы *.h, *.c) - поэтому не важно, по большому счету, в какой оболочкне писать - в Авр Студии, Атмел Студии или в ЦВАРе... Или в блокноте. для avr gcc не имеет разницы, где написан с-код.

Если вопрос еще актуален - напишите, что нужно - я выложу.

Добавлено after 21 minute 5 seconds:
Re: Нужна библиотека для CVAVR ILI9341 3.2 inch TFT LCD module
Единственное что - у меня дисплей с параллельным интерфейсом - соответственно, у меня 2 порта полностью заняты 16битной шиной данных.
У вас SPI - вам проще подключать.

Re: Нужна библиотека для CVAVR ILI9341 3.2 inch TFT LCD modu

Вт янв 15, 2019 13:16:43

Не ужели ни кто в CVAVR не юзал такой дисплей?
очень странно... :shock:

Если посчитать с какой скорость AVR сможет его обновлять, то не очень и странно.

Re: Нужна библиотека для CVAVR ILI9341 3.2 inch TFT LCD modu

Вт янв 15, 2019 13:46:47

Reflector писал(а):Если посчитать с какой скорость AVR сможет его обновлять, то не очень и странно.


У меня по параллельному интерфейсу заливка дисплея - кадров 4-5 в секунду при тестировании железа была. Мега32 16 мгц.
Отрисовка всего дисплея (вывод текста, распаковка RLE-битмапов) - нуууу, навскидку менее секунды на всё....
У меня реализованы часики с календарем - на дисплее большие цифры времени и ниже календарь на месяц. И термометр в верхнем углу.

Но по СПИ будет медленнее.... Но увы, топикстартер уже купил СПИ-дисплей....

Re: Нужна библиотека для CVAVR ILI9341 3.2 inch TFT LCD modu

Пт янв 25, 2019 17:24:29

Подключение дисплея.
Диспллей с SPI - последовательным интерфейсом.

SCK - тактирование, данные с линии SDA защелкиваются по нарастающему фронту
SDA - Данные для записи в дисплей (биты передаются от старшего к младшему)
RES(RST) - Сброс, активный уровень низкий
RS(A0) - низкий уровень - команда, высокий уровень - данные
CS - выбор дисплея (chip select), активный уровень низкий

SCK дисплея - к SCK контроллера
SDA дисплея - к MOSI контроллера.

RES, RS, CS - к любым портам контроллера.

Инициализация железа.
Спойлервсе 5 линий настраиваем на выход, на линии CS и RES выводим 1.

Так же настраиваем SPI на максимальную скорость:
SPCR = 1<<SPE | 1<<MSTR | 0<<SPR1 | 0<<SPR0;
SPSR |= (1<<SPI2X);


Теперь процедуры низкоуровневого общения с дисплеем.
СпойлерУ нас 4 процедуры :
процедура отправки байта по СПИ и три процедуры управления сигналами RST, RS, CS.

определение, куда у нас подключен выводы RST, RS и CS дисплея
Код:
#define LCD_RST_PORT      B
#define LCD_RST_BITVAL      (1<<PORTB4)
#define LCD_RS_PORT         D
#define LCD_RS_BITVAL      (1<<PORTD5)
#define LCD_CS_PORT         D
#define LCD_CS_BITVAL      (1<<PORTD3)


и процедуры управления выводами этими:
Код:
   // Управление битом RST - Сброс, активный уровень низкий
   void setResetPinILI9341(unsigned char resetLevel){
      if (resetLevel) __OUTPORT(LCD_RST_PORT) |= LCD_RST_BITVAL; else __OUTPORT(LCD_RST_PORT) &= ~LCD_RST_BITVAL;
   }

   // Управление битом RS(A0) - выбор данные/команда
   void setRsLevelILI9341(unsigned char rsLevel){
      if (rsLevel) __OUTPORT(LCD_RS_PORT) |= LCD_RS_BITVAL; else __OUTPORT(LCD_RS_PORT) &= ~LCD_RS_BITVAL;
   }

   // Управление битом CS - выбор дисплея
   void setСsLevelILI9341(unsigned char сsLevel){
      if (сsLevel) __OUTPORT(LCD_СS_PORT) |= LCD_СS_BITVAL; else __OUTPORT(LCD_СS_PORT) &= ~LCD_СS_BITVAL;
   }

И процедура отправки 2 байт в дисплей
Код:
   // отправка 2 байт в дисплей по SPI
   void sendWordILI9341(unsigned int wordToSend) {
      setСsLevelILI9341(0);
      SPDR = wordToSend >> 8;
      while((SPSR & (1<<SPIF)) == 0);
      SPDR = wordToSend & 0xFF;
      while((SPSR & (1<<SPIF)) == 0);
      setСsLevelILI9341(1);
   }

Всё. с железной частью разобрались.

теперь библиотека дисплея.
Спойлер
Код:
/*
 * ILI9341.h
 *
 * Created: 25.09.2018 19:58:27
 *  Author: GoldenAndy
 */


#ifndef ILI9341_H_
#define ILI9341_H_

// физическое разрешение матрицы
#define DISPLAY_ILI9341_WIDTH   240
#define DISPLAY_ILI9341_HEIGHT   320

#define ILI9341_MADCTL_MY   0x80
#define ILI9341_MADCTL_MX   0x40
#define ILI9341_MADCTL_MV   0x20
#define ILI9341_MADCTL_RGB   0x00
#define ILI9341_MADCTL_BGR   0x08
#define ILI9341_MADCTL_ML   0x10
#define ILI9341_MADCTL_MH   0x04

#define ILI9341_RGB444      0x03
#define ILI9341_RGB565      0x05
#define ILI9341_RGB666      0x06



#define ILI9341_NOP         0x00
#define ILI9341_SWRESET      0x01
//#define ILI9341_RDDID      0x04
//#define ILI9341_RDDST      0x09

#define ILI9341_SLPIN      0x10
#define ILI9341_SLPOUT      0x11
#define ILI9341_PTLON      0x12
#define ILI9341_NORON      0x13

#define ILI9341_INVOFF      0x20
#define ILI9341_INVON      0x21
#define ILI9341_DISPOFF      0x28
#define ILI9341_DISPON      0x29
#define ILI9341_CASET      0x2A
#define ILI9341_RASET      0x2B
#define ILI9341_RAMWR      0x2C
#define ILI9341_RGBSET      0x2D
//#define ILI9341_RAMRD      0x2E

#define ILI9341_PTLAR      0x30
#define ILI9341_COLMOD      0x3A
#define ILI9341_MADCTL      0x36

/*******/
#define RED_565     0xF800
#define ORANGE_565   0xFC00
#define YELLOW_565  0xFFE0
#define LIME_565   0x7FE0
#define GREEN_565   0x07E0
#define CYAN_565   0x07FF
#define BLUE_565    0x001F
#define MAGENTA_565   0xF81F
#define WHITE_565   0xFFFF
#define BLACK_565   0x0000
#define GRAY0_565   0xEF7D
#define GRAY1_565   0x8410
#define GRAY2_565   0x4208

//----------
//-- Внешние процедуры физического общения с дисплеем ----------
//----------

// Управление пином сброса дисплея.
extern void setResetPinILI9341(unsigned char resetLevel);

// Управление битом RS(A0) - выбор данные/команда
extern void setRsLevelILI9341(unsigned char rsLevel);

// Отправка слова в дисплей
// процедура должна прижать CS дисплея к 0, отправить слово в дисплей,
// подождать окончания отправки данных и, по окончании отправки, отпустить CS
extern void sendWordILI9341(unsigned int wordToSend);


//----------
//-- Основные процедуры работы с дисплеем ----------
//----------
// инициализация
void initDisplayILI9341(void);

// спящий режим
void sleepModeILI9341(unsigned char isSleep);

// включение/выключение дисплея
void powerModeILI9341(unsigned char isPowerOn);

// аппаратная инверсия изображения
void inversionModeILI9341(unsigned char isInversionOn);

// управление записью данных в видеопамять дисплея (регистр MADCTL).
// параметр - комбинация флагов ILI9341_MADCTL_хх.
//
// направление записи данных в видеопамять - флаги ILI9341_MADCTL_MY, ILI9341_MADCTL_MX, ILI9341_MADCTL_MV
//   ILI9341_MADCTL_MX - X-mirror
//   ILI9341_MADCTL_MY - Y-mirror
//   ILI9341_MADCTL_MV - X-Y axis exchange (влияет на верхнюю границу RASET/CASET)
//   [MV:MX:MY] = 000, start left top,     draw left to right, then top to bottom
//   [MV:MX:MY] = 001, start left bottom,  draw left to right, then bottom to top
//   [MV:MX:MY] = 010, start right top,    draw right to left, then top to bottom
//   [MV:MX:MY] = 011, start right bottom, draw right to left, then bottom to top
//   [MV:MX:MY] = 100, start left top,     draw top to bottom, then left to right
//   [MV:MX:MY] = 101, start left bottom,  draw bottom to top, then left to right
//   [MV:MX:MY] = 110, start right top,    draw top to bottom, then right to left
//   [MV:MX:MY] = 111, start right bottom, draw bottom to top, then right to left
//
// Режим отображения цвета из видеопамяти на матрице дисплея:
//   ILI9341_MADCTL_RGB : RGB data - RGB-данные отображаются как есть
//   ILI9341_MADCTL_BGR : BGR data - при отображении RGB-данных меняются R- и B-компоненты
void setMemoryWriteModeILI9341(unsigned char madctlFlags);   

// определение области вывода на дисплее.
// установка позиции вывода графических данных в стартовый угол, данные будут
// последовательно выводиться согласно MADCTL-регистра (см. setMemoryWriteModeILI9341)
// условие: x1<=x2, y1<=y2
// после задания области вывода дисплей переводится в режим записи цветовых данных
void setOutputAreaILI9341(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);

// команда включения режима записи цветовых данных в определенную область вывода.
// после данной команды в дисплей можно отправлять неограниченное количество цветовых данных,
// данные будут запиываться в заданную область вывода согласно MADCTL-регистра, после достижения
// конечного угла области вывода запись продолжится снова со стартового угла.
void setColorWriteModeILI9341(void);

// отправка слова данных о цвете в дисплей, должна выполняться после включения резима записи цветовых данных.
// Формат цвета RGB565 или BGR565 (см. MADCTL)
// Физически - команда отправляет в дисплей одно слово данных, сначала старший байт, потом младший.
void sendColorDataILI9341(unsigned int colorData);

// отправка произвольной команды в дисплей
void sendCommandILI9341(unsigned char displayCommand);

// отправка произвольного слова данных в дисплей
void sendDataILI9341(unsigned int displayData);

//----------
//-- Графические примитивы ----------
//----------

// очистка дисплея (заполнение черным цветом)
void clearDisplayILI9341(void);

// заполнение дисплея заданным цветом
void fillDisplayILI9341(unsigned int fillColor);

// заполнение заданным цветом прямоугольной области на дисплее
// условие: x1<=x2, y1<=y2
void fillAreaILI9341(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int fillColor);

// отрисовка пикселя заданным цветом
void putPixelILI9341(unsigned int x, unsigned int y, unsigned int pixelColor);

#endif /* ILI9341_H_ */



Код:
/*
 * ILI9341.c
 *
 * Created: 25.09.2018 19:59:12
 *  Author: GoldenAndy
 */


#include "ILI9341.h"
#include <util/delay.h>

static unsigned char isSwapCoordinates = 0;

//-- Основные процедуры работы с дисплеем ----------
// инициализация
void initDisplayILI9341(void){
   setResetPinILI9341(0);
   _delay_ms(50);
   setResetPinILI9341(1);
   _delay_ms(10);

   sendCommandILI9341(ILI9341_SWRESET);
   _delay_ms(120);
   

   sendCommandILI9341(0xCB);   //ILI9341_POWERA
   sendDataILI9341(0x39);
   sendDataILI9341(0x2C);
   sendDataILI9341(0x00);
   sendDataILI9341(0x34);
   sendDataILI9341(0x02);
   sendCommandILI9341(0xCF);   //ILI9341_POWERB
   sendDataILI9341(0x00);
   sendDataILI9341(0xC1);
   sendDataILI9341(0x30);
   sendCommandILI9341(0xE8);   //ILI9341_DTCA
   sendDataILI9341(0x85);
   sendDataILI9341(0x00);
   sendDataILI9341(0x78);
   sendCommandILI9341(0xEA);   //ILI9341_DTCB
   sendDataILI9341(0x00);
   sendDataILI9341(0x00);
   sendCommandILI9341(0xED);   //ILI9341_POWER_SEQ
   sendDataILI9341(0x64);
   sendDataILI9341(0x03);
   sendDataILI9341(0x12);
   sendDataILI9341(0x81);
   sendCommandILI9341(0xF7);   //ILI9341_PRC
   sendDataILI9341(0x20);
   sendCommandILI9341(0xC0);   //ILI9341_POWER1
   sendDataILI9341(0x23);
   sendCommandILI9341(0xC1);   //ILI9341_POWER2
   sendDataILI9341(0x10);
   sendCommandILI9341(0xC5);   //ILI9341_VCOM1
   sendDataILI9341(0x3E);
   sendDataILI9341(0x28);
   sendCommandILI9341(0xC7);   //ILI9341_VCOM2
   sendDataILI9341(0x86);
   sendCommandILI9341(0x36);   //ILI9341_MAC
   sendDataILI9341(0x48);
   sendCommandILI9341(0x3A);   //ILI9341_PIXEL_FORMAT
   sendDataILI9341(0x55);
   sendCommandILI9341(0xB1);   //ILI9341_FRC
   sendDataILI9341(0x00);
   sendDataILI9341(0x18);
   sendCommandILI9341(0xB6);   //ILI9341_DFC
   sendDataILI9341(0x08);
   sendDataILI9341(0x82);
   sendDataILI9341(0x27);
   sendCommandILI9341(0xF2);   //ILI9341_3GAMMA_EN
   sendDataILI9341(0x00);
   sendCommandILI9341(ILI9341_CASET);//ILI9341_COLUMN_ADDR
   sendDataILI9341(0x00);
   sendDataILI9341(0x00);
   sendDataILI9341(0x00);
   sendDataILI9341(0xEF);
   sendCommandILI9341(ILI9341_RASET);//ILI9341_PAGE_ADDR
   sendDataILI9341(0x00);
   sendDataILI9341(0x00);
   sendDataILI9341(0x01);
   sendDataILI9341(0x3F);
   sendCommandILI9341(0x26);   //ILI9341_GAMMA
   sendDataILI9341(0x01);
   sendCommandILI9341(0xE0);   //ILI9341_PGAMMA
   sendDataILI9341(0x0F);
   sendDataILI9341(0x31);
   sendDataILI9341(0x2B);
   sendDataILI9341(0x0C);
   sendDataILI9341(0x0E);
   sendDataILI9341(0x08);
   sendDataILI9341(0x4E);
   sendDataILI9341(0xF1);
   sendDataILI9341(0x37);
   sendDataILI9341(0x07);
   sendDataILI9341(0x10);
   sendDataILI9341(0x03);
   sendDataILI9341(0x0E);
   sendDataILI9341(0x09);
   sendDataILI9341(0x00);
   sendCommandILI9341(0xE1);   //ILI9341_NGAMMA
   sendDataILI9341(0x00);
   sendDataILI9341(0x0E);
   sendDataILI9341(0x14);
   sendDataILI9341(0x03);
   sendDataILI9341(0x11);
   sendDataILI9341(0x07);
   sendDataILI9341(0x31);
   sendDataILI9341(0xC1);
   sendDataILI9341(0x48);
   sendDataILI9341(0x08);
   sendDataILI9341(0x0F);
   sendDataILI9341(0x0C);
   sendDataILI9341(0x31);
   sendDataILI9341(0x36);
   sendDataILI9341(0x0F);
   
   sleepModeILI9341(0);   //   ILI9341_SLPOUT
   _delay_ms(120);

   powerModeILI9341(1);   //   ILI9341_DISPON
   _delay_us(150);
   
   
   sendCommandILI9341(ILI9341_COLMOD);
   sendDataILI9341(ILI9341_RGB565);

   setMemoryWriteModeILI9341(ILI9341_MADCTL_RGB);   //   ILI9341_MADCTL
   /*
   unsigned char i=0;
   sendCommandILI9341(ILI9341_RGBSET);  //Look up table
   for(i=0;i<32;i++)
      sendDataILI9341(2*i); //Red
   for(i=0;i<64;i++)
      sendDataILI9341(1*i); //Green
   for(i=0;i<32;i++)
      sendDataILI9341(2*i); //Blue     */
}

// спящий режим
void sleepModeILI9341(unsigned char isSleep){
   if (isSleep) sendCommandILI9341(ILI9341_SLPIN);
   else sendCommandILI9341(ILI9341_SLPOUT);
}

// включение/выключение дисплея
void powerModeILI9341(unsigned char isPowerOn){
   if (isPowerOn) sendCommandILI9341(ILI9341_DISPON);
   else sendCommandILI9341(ILI9341_DISPOFF);
}

// аппаратная инверсия изображения
void inversionModeILI9341(unsigned char isInversionOn){
   if (isInversionOn) sendCommandILI9341(ILI9341_INVON);
   else sendCommandILI9341(ILI9341_INVOFF);
}

// управление записью данных в видеопамять дисплея (регистр MADCTL).
void setMemoryWriteModeILI9341(unsigned char madctlFlags){
   sendCommandILI9341(ILI9341_MADCTL);
   sendDataILI9341(madctlFlags);
   isSwapCoordinates = madctlFlags & ILI9341_MADCTL_MV;
}

// определение области вывода на дисплее.
void setOutputAreaILI9341(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2){
   sendCommandILI9341(ILI9341_CASET);
   sendDataILI9341(HI(x1));
   sendDataILI9341(LO(x1));
   sendDataILI9341(HI(x2));
   sendDataILI9341(LO(x2));
   sendCommandILI9341(ILI9341_RASET);
   sendDataILI9341(HI(y1));
   sendDataILI9341(LO(y1));
   sendDataILI9341(HI(y2));
   sendDataILI9341(LO(y2));
   setColorWriteModeILI9341();
}

// команда включения режима записи цветовых данных в определенную область вывода.
void setColorWriteModeILI9341(void){
   sendCommandILI9341(ILI9341_RAMWR);
}

// отправка двух слова данных о цвете в дисплей, должна выполняться после включения режима записи цветовых данных.
void sendColorDataILI9341(unsigned int colorData){
   sendDataILI9341( colorData );
}

// отправка произвольной команды в дисплей
void sendCommandILI9341(unsigned char displayCommand){
   setRsLevelILI9341(0);
   sendWordILI9341(displayCommand);
}

// отправка произвольного слова данных в дисплей
void sendDataILI9341(unsigned int displayData){
   setRsLevelILI9341(1);
   sendWordILI9341(displayData);
}

//-- Графические примитивы ----------

// очистка дисплея (заполнение черным цветом)
void clearDisplayILI9341(void){
   fillDisplayILI9341(0x0000);
}

// заполнение дисплея заданным цветом
void fillDisplayILI9341(unsigned int fillColor){
   if (isSwapCoordinates) fillAreaILI9341(0,0,DISPLAY_ILI9341_HEIGHT-1,DISPLAY_ILI9341_WIDTH-1,fillColor);
   else fillAreaILI9341(0,0,DISPLAY_ILI9341_WIDTH-1,DISPLAY_ILI9341_HEIGHT-1,fillColor);
}

// заполнение заданным цветом прямоугольной области на дисплее
// условие: x1<=x2, y1<=y2
void fillAreaILI9341(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int fillColor){
   setOutputAreaILI9341(x1,y1,x2,y2);
   unsigned int i=x1;
   while(1) {
      unsigned int j=y1;
      while(2) {
         sendColorDataILI9341(fillColor);
         if (j==y2) break;
         j++;
      }
      if (i==x2) break;
      i++;
   }
}

// отрисовка пикселя заданным цветом
void putPixelILI9341(unsigned int x, unsigned int y, unsigned int pixelColor){
   fillAreaILI9341(x,y,x,y,pixelColor);
}



Как пользоваться.

1. Проинициализировать интерфейс СПИ и выводы управления дисплеем.
2. вызвать initDisplayILI9341();
3. Рисовать.

И да, я тут не рассматривал вопросы питания и подсветки.
Хоть контроллер ILI9341 и толерастен к 5 вольтам питания, входная логика исключительно 3.3 вольта. Соответственно, на 5 линий интерфейса надо 5 делителей, или питать контроллер от источника 3,3 вольта
В том дисплее, что у меня - управление подсветкой - это логический вход, т.е. им можно управлять без всяких резисторов и транзисторов прямо с ноги контроллера.
Читайте описание вашего дисплея, что бы убедиться, что у вас так же.
Или смотрите по плате - куда и как идут дорожки подсветки.
Ответить