Страница 1 из 1

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

Добавлено: Пн дек 17, 2018 16:18:20
CAT86
Купил себе дисплейчик вот такой: 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

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

Добавлено: Вт дек 25, 2018 11:29:33
7seg
Если есть опыт портрирования , то реализция авр но с исспользованием дуруины . https://github.com/marekburiak/ILI9341_due

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

Добавлено: Вт дек 25, 2018 15:41:18
CAT86
Спасибо за ссылку! :beer: Уже что то.
Не ужели ни кто в CVAVR не юзал такой дисплей?
очень странно... :shock:

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

Добавлено: Вт янв 15, 2019 12:58:40
GoldenAndy
Давайте сначала определимся, какие требования к библиотеке должны быть ?
Поскольку работа с дисплеем делится на три части:
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
Reflector
[uquote="CAT86",url="/forum/viewtopic.php?p=3534730#p3534730"]Не ужели ни кто в CVAVR не юзал такой дисплей?
очень странно... :shock:[/uquote]
Если посчитать с какой скорость AVR сможет его обновлять, то не очень и странно.

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

Добавлено: Вт янв 15, 2019 13:46:47
GoldenAndy
Reflector писал(а):Если посчитать с какой скорость AVR сможет его обновлять, то не очень и странно.
У меня по параллельному интерфейсу заливка дисплея - кадров 4-5 в секунду при тестировании железа была. Мега32 16 мгц.
Отрисовка всего дисплея (вывод текста, распаковка RLE-битмапов) - нуууу, навскидку менее секунды на всё....
У меня реализованы часики с календарем - на дисплее большие цифры времени и ниже календарь на месяц. И термометр в верхнем углу.

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

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

Добавлено: Пт янв 25, 2019 17:24:29
GoldenAndy
Подключение дисплея.
Диспллей с 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 вольта
В том дисплее, что у меня - управление подсветкой - это логический вход, т.е. им можно управлять без всяких резисторов и транзисторов прямо с ноги контроллера.
Читайте описание вашего дисплея, что бы убедиться, что у вас так же.
Или смотрите по плате - куда и как идут дорожки подсветки.