Подключение дисплея Nokia 1616 на примере LPC1343

Что за зверь

Как я уже писал в прошлом посте, дисплей с подсветкой, имеет разрешение 128х160 пикселей и глубину цвета 18 бит. Размеры примерно 28х36мм. шлейф имеет 12 контактных площадок (1-я и 12-я не подключены) с шагом 0.5мм. Логика вся работает от 3.3В и лучше не завышать. От 5В скорее всего сгорит. На подсветку надо около 7В.
UPD: По правильному на питание цифровой схемы надо подать 1.8В и на аналоговую 2.7В, но всё прекрасно работает и от одного источника 3.3В (уже пол года не сгорело ничего), по даташитам это напряжение в пределах допустимого. Так же в комментариях отмечено что появились дисплеи с 3В подсветкой, мне на днях похоже такой же попался, имейте это ввиду.
Работа с дисплеем аналогична работе с Nokia 6100 (статей на эту тему предостаточно) по тому глубоко вдваться не стану, а сконцентрируюсь на различиях.
Отмечу что мне попадалось 2 разновидности дисплеев, но оба работают с данным кодом. Различить их можно по форме шлейфа. Шлейф в форме буквы T — хороший дисплей, верх будет со стороны шлейфа. Если же шлейф просто прямоугольный выходит, то со стороны шлейфа у вас будет низ и ужасно тусклая подстветка. Не знаю, то ли мне бракованный дисплей попался, толи они все такие. На счет подсветки и качества соврал. Промывал от канифоли плату спиртом, в итоге просто слои рассеивателей и поляризаторов разошлись. Не давайте спиртного дисплею, он спиваетса быстро! :)


Как подключить

В моём варианте работает следующая схема включения:
Схема подключения дисплея Nokia 1616
Важно! на данной схеме учтены только «подключенные» выводы, крайние в счет не берутся. Таким образом 1-й вывод на схеме соответствует 2-му на дисплее. 10 вывод схемы — 11-му на дисплее.

Взаимодействие

Данный дисплей, как и большенство других цветных Nokia, для взаимодействия использует интерфейс SPI 9 бит. Возможно взаимодействие в режимах 0 и 3 (если память не изменяет). Успешно работает на скоростях 4Мб/с и 9Мб/с, больше проверять не стал. Линия данных на самом деле у дисплея двунаправленная и по ней можно считать такую информацию как ID контроллера в дисплее, но мы её быдем использовать только для записи.
Старший бит является признаком данных: для команды он равен 0, для данных 1. младшие 8 бит содержат либо сами данные, либо код команды.
Ну и естественно перед работой с дисплеем его надо сбросить. делаеся это выбором дисплея и подачей на вывод Reset низкого уровня в моём случае на 100мс. После снятия сброса надо так же выдержать паузу, что бы дисплей успел инициализироваться.
Перечислять команды дисплея не буду, поскольку сам их не знаю. Но большенство команд едины для разных моделей дисплеев и при желании сможете разобраться сами.
И так, получается следующий набор функций (для LPC1343)

void SPI_init() {	// Раздел 13.2 UM10375
    // Reset SSP (пункт 4)
    LPC_SYSCON->PRESETCTRL &= ~(1<<0);	// "маска" сброса SSP
    LPC_SYSCON->PRESETCTRL |= (1<<0);	// 1 в бит RST_SSP_0

    // Enable AHB clock to the SSP domain. (пункт 2)
    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11);

    // Divide by 1 (SSPCLKDIV also enables to SSP CLK) (пункт 3)
    LPC_SSP->CPSR = 0;	// отключим тактирование (а то мало ли)

    // Set P0.9 to SSP MOSI
    LPC_IOCON->PIO0_9	&= ~(7<<0);
    LPC_IOCON->PIO0_9	|= (1<<0);	// использовать как вывод MOSI
    LPC_IOCON->PIO0_9	|= IOCON_COMMON_MODE_PULLUP;

    // Set 2.11 to SSP SCK (0.6 and 0.10 can also be used)
    LPC_IOCON->SCKLOC	= 1;	// SCK на вывод 2.11
    LPC_IOCON->PIO2_11	&= ~(7<<0);	// сброс текущей функции порта ввода-вывода
    LPC_IOCON->PIO2_11	|= (1<<0);	// использовать как вывод SCK
    LPC_IOCON->PIO2_11	|= IOCON_COMMON_MODE_PULLUP;

    // Set P0.2/SSEL to GPIO output and high
    LPC_IOCON->PIO0_2	&= ~(7<<0);	// сброс текущей функции порта ввода-вывода
    LPC_IOCON->PIO0_2	|= (1<<0);	// использовать как вывод SSEL	(можно обычным GPIO как 0)
    LPC_IOCON->PIO0_2	|= IOCON_COMMON_MODE_PULLUP;
    LPC_GPIO0->DIR	|= 1<<2;
    LPC_GPIO0->DATA	|= 1<<2;

    // If SSP0CLKDIV = DIV1 -- (PCLK / (CPSDVSR X [SCR+1])) = (72,000,000 / (2 x [3 + 1])) = 9.0 MHz
    LPC_SSP->CR0	= ( (8<<0)	// Размер данных 1000 - 9 бит
					  | (0<<4)	// Формат фрейма 00 - SPI
					  | (0<<6)	// Полярность 0 - низкий уровень между фреймами
					  | (0<<7)	// Фаза 0 - по нарастанию
					  | (3<<8)	// Делитель частоты шины на бит
					  ) ;

    // Clock prescale register must be even and at least 2 in master mode
    LPC_SSP->CPSR = 2;	// пердделитель 2-254 (кратно 2)

    // Enable device and set it to master mode, no loopback (разрешаем работу)
    LPC_SSP->CR1	= ( (0<<0)	// 0 - Loop Back Mode Normal
					  | (1<<1)	// Разрешение работы 1 - разрешено
					  | (0<<2)	// Режим ведущий-ведомый 0 - мастер
					  );
}

void SPI_send(uint16_t value) {
	while ((LPC_SSP->SR & ((1<<1) | (1<<4))) != (1<<1));	// если буффер передачи не переполнен и устройство не занято
	LPC_SSP->DR = value;
}

// Вспомогательные макросы
#define LCD_send(x)	SPI_send(x)
#define LCD_command(cmd)	LCD_send(cmd)
#define LCD_data(data) LCD_send(0x0100|(uint8_t)(data))

void LCD_reset(void) {
	// Настройка для вывода Reset дисплея
	LPC_IOCON->PIO0_8	&= ~(7<<0);	// сброс текущей функции порта ввода-вывода
	LPC_IOCON->PIO0_8	|= IOCON_COMMON_MODE_PULLUP;
	LPC_GPIO0->DIR	|= 1<<8;
	LPC_GPIO0->DATA	|= 1<<8;
	// Настройка для вывода Select
	LPC_IOCON->PIO0_2	&= ~(7<<0);	// Временно отключаем спецфункцию вывода выбора SPI
	delayms(100);
	// Сброс дисплея
	LPC_GPIO0->DATA	&= ~(1<<2);	// ncs = 0
	LPC_GPIO0->DATA	&= ~(1<<8);	// nrst = 0
	delayms(100);
	LPC_GPIO0->DATA	|= 1<<8;	// nrst = 1
	LPC_GPIO0->DATA	|= 1<<2;	// ncs = 1
	delayms(100);
	// Возврат спецфункции
	LPC_IOCON->PIO0_2	|= (1<<0);	// использовать как вывод SSEL
}

В этих функциях по сути собран весь аппаратно-зависимый код. именно по этой причине функция LCD_reset включена сюда, хотя правильнее её описать в следующем разделе. Я использовал «фоновый вывод данных», так функция SPI_send сначала ожидает окончания вывода предидущего байта (9 бит), затем помещает очередной байт (9 бит) на вывод и возвращается не ожидая завершения операции вывода.
Важно: Линию выбора дисплея CS обязательно надо периодически освобождать, иначе вывода никакого не будет, получите просто белый экран. У меня используется полностью аппаратный контроль.

Инициализация дисплея

Идем по пути найменьшего сопротивления, и одалживаем у тов. Rossum'а код для работы с дисплеями Nokia из проекта NokiaSuperBreakout. Не беда что нашего дисплея нет в перечислении, берём тот что соответствует диспею 132х160 контроллер SPFD54124B.
Данный код настраивает дисплей на 16-битный индексный режим вывода, в итоге получаем формат BGR 5-6-5. по биту глубины на R и B мы теряем, но зато получаем возможность передавать только 2 бата на один пиксель, взамен 3-х в 18битном режиме.
Перед инициализацией надо не забыть сбросить дисплей (иногда критично).

const uint16_t init_lcd1616ph[] = {
		0xBA, 0x107, 0x115,	// Data Order
		0x25, 0x13F,		// Contrast
		0x11,				// Sleep Out
		0x13,				// Display Normal mode

		0x37,0x100,			// VSCROLL ADDR
		0x3A,0x105,			// COLMOD pixel format 4=12,5=16,6=18
		0x29,				// DISPON
		0x20,				// INVOFF
		0x13				// NORON
};

void LCD_init()
{
	const uint16_t *data = &init_lcd1616ph[0];
	uint16_t size = sizeof(init_lcd1616ph)/sizeof(init_lcd1616ph[0]);
	while(size--) {
		LCD_send(*data++);
	}
	LCD_command(0x2D);
	int i;
	for (i = 0; i < 32; i++)
		LCD_data(i<<1);
	for (i = 0; i < 64; i++)
		LCD_data(i);
	for (i = 0; i < 32; i++)
		LCD_data(i<<1);
	delay(100);
	m_lcdResetClip();
	EndDraw();
	SetFont(0);
}

Про m_lcdResetClip, EndDraw и SetFont потом.
Но, одной инициализацией сыт не будешь. максимум чего ей можно добиться, это случайноразбросанных по дисплею цветных точек.

Вывод графики

Принцип вывода у всех встреченных мной дисплеев один. Вначале передается команда выбора диапазона строк, затем диапазона столбцов, после чего попиксельно выводятся пиксели в получившееся окно. Таким образом для вывода изображения в области [ x1:y1, x2:y2 ] надо передать следующую последовательность:
[PASET] [y1] [y2] [CASET] [x1] [x2] [RAMWR] [pixel_1] [pixel_2]… [pixel_N]
Однако, в отличии от 6100 дисплей для 1616 каждая из величин координат (x1, x1, y1, y2) имеет 2-хбайтовый размер, не смотря на то, что старший байт всегда нулевой. Контроллер дисплея сам будет переносить «курсор» вывода в окне на следующую строку вывода, при достижении правой границ окна. Направление заполнения слева-направо, сверху вниз. Удобно. Ну и немаловажный фактор: левый верхний угол имеет координату x:y = 2:1.
Таким образом получаем что на операцию вывода требуется передать 11 служебных байт плюс 2хN байт данных. Естественно получаем что выгоднее выводить прямогольными областями по несколько пикселей за раз.
Ну а теперь к ложке дегтя. К сожалению при передаче координат «вне экрана» предсказать поведение дисплея нельзя. Он вроде как и «закольцован» на размер в 256 байт, но артефакты попадаются порой очень странные. По этому у вас есть выбор: либо не передавать координаты вне экрана, либо делать програмное отсечение. Я выбрал второй вариант и вот что из этого получилось:

// Nokia1616
#define displayOffsetX	2
#define displayOffsetY	1
#define displayWidth	128
#define displayHeight	160

#define	RGB(r, g, b)	(((uint32_t)(R))|((uint32_t)(g)<<8)|((uint32_t)(b)<<16))
#define RECT_set(rect, l, t, r, b) { (rect).left = (l); (rect).top = (t); (rect).right = (R); (rect).bottom = (b); }

// Описание переменных
RECT	m_lcdBound;		// Установленная для вывода область
POINT	m_lcdOutput;		// Очередная позиция для вывода
RECT	m_lcdClip;		// Размеры области отсечения
uint8_t	m_lcdClipOutput;	// Активны ли отсечения в текущей итерации вывода

uint32_t BeginDraw(int16_t left, int16_t top, uint16_t width, uint16_t height)
{
	int16_t right = left + width - 1;
	int16_t bottom = top + height - 1;
	if( left >= m_lcdClip.left && top >= m_lcdClip.top && right <= m_lcdClip.right && bottom <= m_lcdClip.bottom ) {	// RectInRect
		// область вывода полностью видима, используем "быстрый" вывод без проверок отсечения
		m_lcdClipOutput = 0;
	} else {
		// область вывода частично либо полностью невидима на дисплее, используем вывод с проверкой отсечений
		m_lcdClipOutput = 1;
		m_lcdOutput.x = left;
		m_lcdOutput.y = top;
		RECT_set(m_lcdBound, left, top, right, bottom);
		if(left < m_lcdClip.left) left = m_lcdClip.left;	// ClipRect
		if(top < m_lcdClip.top) top = m_lcdClip.top;
		if(right > m_lcdClip.right) right = m_lcdClip.right;
		if(bottom > m_lcdClip.bottom) bottom = m_lcdClip.bottom;
	}
	if( left > right || top > bottom ) {	// IsRectValid
		// область не видна на дисплее, завершаем вывод
		EndDraw();
		return 0;
	}
	uint32_t count;
	// Устанавливаем "виртуальные" границы вывода
	LCD_command(0x2A);	//LCD_command(CASETP);
	count	 = right - left + 1;
	left	+= displayOffsetX;
	right	+= displayOffsetX;
	LCD_data(left>>8);
	LCD_data(left);
	LCD_data(right>>8);
	LCD_data(right);
	// Диапозон строк
	LCD_command(0x2B);	//LCD_command(PASETP);
	count	*= (bottom - top + 1);
	top		+= displayOffsetY;
	bottom	+= displayOffsetY;
	LCD_data(top>>8);
	LCD_data(top);
	LCD_data(bottom>>8);
	LCD_data(bottom);
	LCD_command(0x2C);	//LCD_command(RAMWR);
	// Возвращаем количество видимых пикселей
	return count;
}

void EndDraw()
{
	m_lcdClipOutput = 1;
	m_lcdBound.right = m_lcdBound.left - 1;	// SetRect
}

void NextPoint(uint32_t color)
{
	// Надо ли проверять отсечения при выводе
	if( m_lcdClipOutput ) {
		int16_t x = m_lcdOutput.x;
		int16_t y = m_lcdOutput.y;
		// учит.отсеч.
		//if(!m_lcdClip.width /* || !m_lcdClip.height */) return;
		if(m_lcdBound.right < m_lcdBound.left) { // IsRectValid вывод недоступен
			return;
		}
		// Смещение на следующую позицию вывода
		if( m_lcdOutput.x >= m_lcdBound.right ) {
			// Если в конце строки - переходим на следующую
			m_lcdOutput.x = m_lcdBound.left;
			if( m_lcdOutput.y >= m_lcdBound.bottom ) {
				// Если последняя точка, переходим в начало (или можно завершить вывод вызовом EndDraw)
				m_lcdOutput.y = m_lcdBound.top;
			} else {
				m_lcdOutput.y++;
			}
		} else {
			m_lcdOutput.x++;
		}
		if(!(x >= m_lcdClip.left && x <= m_lcdClip.right && y >= m_lcdClip.top && y <= m_lcdClip.bottom) ) {	// PtInRect
			return;
		}
	}
	// точка будет видимой
	uint8_t r = color;
	uint8_t g = color>>8;
	uint8_t b = color>>16;
	LCD_data((r&0xF8)|(g>>5));
	LCD_data(((g<<3)&0xE0)|(b>>3));
}

Данные функции являются «дисплей ориентированными» и могут быть изменены для работы с другим дисплеем (естественно не забыв и про функцию инифиализации).
Код получился громадным исключительно из-за наличия програмного отсечения, без него всё получается в разы меньше и просто сводится к последовательному вызову функций записи комманд и данных.
В функции настройки отображения я прибавляю смещение начала координат, что позволяет мне не запоминать с каким именно дисплеем я работаю. С той же целью для цвета используется 32-битное значение, по 8 бит на компоненту, и 8 бит прозапас и для выравнивания.
Функция вывода очередной точки NextPoint должна выполнить некоторые проверки и расчеты, тут нам позволит хорошо ускорить процесс использование фонового вывода на дисплей: пока по SPI передаются данные, мы проводим свои проверки для следующей точки.
Ну а функция завершения вывода просто задает недействительную область. При желании и этого можно было не делать, но вдруг появится дисплей, которому требуется что-либо сказать по окончании? Не переписывать же потом весь код.
Ну и для завершения картины средства для работы с отсечениями:

typedef struct _tagPOINT {
	int16_t x;
	int16_t y;
} POINT, *PPOINT;

typedef struct _tagRECT {
	int16_t left;
	int16_t top;
	int16_t right;
	int16_t bottom;
} RECT, *PRECT;

void m_lcdSetClip(const RECT *r)
{
	// Проверяем на видимость отсечения
	RECT_set(m_lcdClip, r->left, r->top, r->right, r->bottom);
	// Устанавливаем "абсолютное" ограничение для вывода c усечением до границ дисплея
	if(m_lcdClip.left	< 0) m_lcdClip.left = 0;	// ClipRect
	if(m_lcdClip.top	< 0) m_lcdClip.top = 0;
	if(m_lcdClip.right	>= displayWidth) m_lcdClip.right = displayWidth - 1;
	if(m_lcdClip.bottom	>= displayHeight) m_lcdClip.bottom = displayHeight - 1;
	// Is clip valid
	if(m_lcdClip.bottom < m_lcdClip.top || m_lcdClip.right < m_lcdClip.left) {	// IsRectValid
		// invalid clip region
		RECT_set(m_lcdClip, 0, 0, -1, -1);
	}
}

void m_lcdResetClip()
{
	RECT_set(m_lcdClip, 0, 0, displayWidth - 1, displayHeight - 1);
}


Примитивы

Самое простое пожалуй это закрасить область одним цветом.

void Fill(int16_t left, int16_t top, uint16_t width, uint16_t height, uint32_t color)
{
	uint32_t count;
	count = BeginDraw(left, top, width, height);	// Функция возвращает количество видивых пикселей в установленной области вывода.
	m_lcdClipOutput = 0;	// Принудительно меняем функцию вывода, выводим только необходимое количество пикселей
	while(count--) {
		NextPoint(color);
	}
	EndDraw();
}

void Clear(uint32_t color)
{
	Fill(0, 0, displayWidth, displayHeight, color);
}

void Pixel(int16_t x, int16_t y, uint32_t color)
{
	Fill(x, y, 1, 1, color);
}

А проверяется всё это дело так:

	SPI_init();
	LCD_reset();
	LCD_init();
	Clear(0x00000000);
	Fill(10, 20, 30, 40, 0x00FF00FF);


P.S.

Позже добавлю про вывод «упакованных» картинок и текста.
  • +6
  • 02 августа 2011, 00:35
  • angel5a
  • 1
Файлы в топике: usbdisplay_2011_07_27.zip

Комментарии (114)

RSS свернуть / развернуть
скучно без картинок
-2
Картинки и видео, которые есть, были в предидущих постах. Делать новые не хочется, во-первых потому как надо будет пересобирать макетку (а она уже в другой проект подготовлена), во-вторых, для макетки остался только тот «бракованный» дисплей, а яркости ему явно нехватает, да и на части он начал распадаться после моих издевательств :)
Данная статья написана путём выдерания кода из готового устройства.
0
Да, народ требует хлеба и зрелищ!
Алсо, валяется у меня половина экспрессы с этим LPC. Надо-бы из неё че-нибудь сделать…
0
Халявные экспрессы с LPC1114 идут, код возможно прийдется доработать.
0
Нет, на моей 1343. Но половина.
0
кусок схемы нокии 1616 (LCD)
Piccy.info - Free Image Hosting
0
  • avatar
  • Resp
  • 02 августа 2011, 08:48
Угу, с сервис-мануала распиновку и узнавал :)
0
В самом начале поста приведена схема, из которой видна распиновка дисплея как SPI, а в куске из сервис-мануала показано, как I2C.
Это как правильно понять? Как то, что дисплей (его контроллер) может работать с интерфейсом как I2C, так и SPI?
Просто тоже планирую его заюзать, вот и хотелось бы гадать поменьше.
0
В сервисмануале тоже SPI. У шины I2C нет сигналов выбора (LCD_CS) только с объединеннами MOSI и MISO поскольку линия данных (LCD_SDA) двунаправленная у дисплея. Читать можно, но так же можно и только писать (что делаю я) не беспокойтесь, ничего не замкнёт, дисплей перехожит на вывод только по запросу от контроллера. Но при желании можете и резюки поставить на время эксперементов.
0
Спасибо :)
А есть ли где-то datasheet на контроллер, или просто описание команд, чтобы не надо было перекапывать исходники?
0
Перенес в блог по LPC1xxx
0
Пост больше планировался про дисплей, нежели про арм. но в принципе без разницы.
0
Вначале передается команда выбора диапазона строк, затем диапазона столбцов, после чего попиксельно выводятся пиксели в получившееся окно.
А как они вводятся? Слева направо-сверху вниз?

Таким образом для вывода изображения в области [ x1:y1, x2:y2 ] надо передать следующую последовательность:
… Однако, в отличии от 6100 дисплей для 1616 каждая из величин
Кажется куда то делась последовательность.
0
Да, дополнил пост.
А в последовательности использовал угловые скобки не подумав. Но не смотря на это блокнот рулит :)
0
Счет ног идет со стороны дисплея? Шлейф короткий,
металлизация с 2-х сторон, и с каждого края цифра «1» :)

И что на 10-м пине?
0
  • avatar
  • valio
  • 03 августа 2011, 13:20
На самом шлейфике 1 и 12 выводы подписаны, не ошибетесь. шлейф 7мм в длину где-то, для того что бы перекинуть на обратную сторону плты и нормально припаять хватает. Метализация на шлейфе с 2-х сторон. Шлейф терпим к пайке, минут 5 пайки пережил без повреждений на 270 градусах.
0
Точно, двойка после единички смазалась, не разглядел.

А какое мин/макс напряжение и ток на 10 пине
по даташиту (контроллера?) и в рабочей схемке?
На схемке в статье понижающий импульсный стаб,
а в комментария — повышающий показан.
Так что же там должно быть?

Может видео работы есть? для дисплея с коротким
кабелем и тусклой подстветкой?
0
Даташита дисплея и его контроллера у меня нет. Потребление контроллера как-то не смотрел, у меня армина по даташиту потребляет 50мА, и преобразователь подсветки столько же, по томы 1мА будет контроллер кушать или 10, мне не принципиально было. В теории должно быть мелким, ибо в телефонах они долго работают.
На схеме и в статье повышающие, просто на схеме подсветка «замкнута» на разрядку индуктивности. Подсветке как писал надо 6-8В где-то, потребление будет ~5-20мА. Преобразователь можете повесить любой, хоть на mc34063 хоть как я на транзисторе простом, хоть драйвер светодиода.
Видео сделать не смогу, плата уже в другой схеме включена.
P.S.: у меня сейчас в отличие от схемы в статье диод D1 и конденсатор C6 удалены, и включен диод в обратном направлении между базой транзистора и землёй. Он помогает кондеру C7 быстрее разрядится. В итоге яркость повысилась.
0
Подскажите, сильно ли отличается подсветка при питании от 5В и от 7В? Имеет ли смысл заводить на плату 7В…
0
  • avatar
  • Kino
  • 08 августа 2011, 13:01
При 5В она просто не работает.
0
Подключил 7В на подсветку — дала дуба. Может и весь ЖКИ накрылся. Там что, резисторов на светодиоды даже нет?
0
Нету. Вот буквально вчера подобный дисплей разобрал — только светодиоды и все.
0
Я тоже уже разобрал. Какие-то кондеры с резюками есть. Но сам факт, что при 7В без ограниченя тока — горит.
0
Вот еще хотел уточнить фразу «CS надо переодически освобождать»… Как правильно эта линия должна работать?
0
На время передачи данных линия CS садится на землю, в паузах между посылками устанавливается в единицу. Если в 1 периодически не ставить, то дисплей просто белый будет весь.
0
6100 имел резюки, 1616 не разбирал, не знаю.
0
Ура, запустил. И сразу назрел вопрос, может кто видел примеры подключения дисплеев побольше, например от КПК? И так, чтобы цена не кусалась. Вот цена 1616 действительно привлекательная, по карману не бъет.
0
  • avatar
  • Kino
  • 01 сентября 2011, 15:38
Как раз с КПК все довольно просто. Голый TFT, только распиновку найди (или реверсни, если в КПК хотя бы контроллер TFT стартует). Ну правда чтобы его поднять нужен МК с контроллером TFT (хотя некоторые МК, скажем STM32F, позволяют подключить дисплейчик через имеющийся контроллер памяти, но производительность будет хуже).
0
  • avatar
  • Vga
  • 01 сентября 2011, 15:49
В дисплеях от КПК/фотоаппаратов есть тольо драйвер дисплея, без памяти. Данные в них гнать надо постоянно. Для этих целей надо брать контроллер со свтроенной поддержкой дисплеев. Иначе будет довольно много ресурсов отнимать у контроллера.
Есть проект с подключением их к атмеге но с дополнительной микрухой памяти и регистром. Есть проект с только текстоым монохромным выводом на меге. Ссылки я уже где-то давал, не помню где.
0
Линию выбора дисплея CS обязательно надо периодически освобождать
А можно чуть подробнее? В смысле освобождать? Переводить в 0, 1 или вообще вывод МК переводить в High-Z?
0
Снимать активный уровень. Т.е. переводить в единичку. Пока кристалл контроллера выбран — обновлять изображение на экране он не будет.
0
  • avatar
  • Vga
  • 12 сентября 2011, 07:07
да, так оно и есть. Совершенно не ожидал такого поведения. Ладно уж лишний вывод, это не такая и проблема для 48 выводной микрухи. Но плохо, что данные нельза без устали слать, в фоновую задачу вывод не пошлёшь.
0
А чего в фоновую задачу не пошлёшь? Выводом дёргать по надобности, в начале и в конце посылки. Фоновая задача вполне справится.
0
какраз таки фоновая аппаратный контроль и подразумевает. Я отдал данные на вывод и пошел дальше своими делами заниматься, без ожидания завершения передачи. Ожидаю только перед отдычей. Но т.к. очередные данные приходят всегда до завершения вывода, получается что вывод ssel не отпускается.
Можно правда добавить проверку на полное завершение отправки (с освобождением выбора), что то раньше не подумал об этом.
0
Ага, спасибо. Значит всё правильно делаю.
0
А можно попросить куда-то выложить рабочий код? И, если есть USBee, лог общения с индикатором?
А то пишу код для STM32, и что-то «не входит каменный цветок» :(
И SPI 9-битный уже добился от USART, и вроде по шине всё правильно, и согласуется со статьёй. А всё равно не хочет работать. Белый экран и всё тут.
А код из проекта NokiaSuperBreakout каким-то унылым показался. Буду его потрошить уже если ничего больше не останется.
0
Код выложу сюда попозже. С собой нету.
Белый экран может быть если SSEL не отпускать в единицу, я об этом писал.
А у Россума код может и унылый, зато сделан с поддержкой сразу многих дисплеев. Что иногда очень полезно. Да и выбрать оттуда своё не проблема.
0
SSEL — имеется в виду 3-й вывод дисплея, здесь на схеме 2-й? Правильно?
Я его пробовал отпускать/«передёргивать» как после каждого байта, так и в начале большой посылки «опускать» в 0, а в конце — поднимать в 1.
Результат, увы, один: белый экран. Может ещё как-то надо?
0
Попробуйте пошагово пройти. после подачи питания, снятия ресета и вывода команд инициализции на дисплее должен появится мусор. Если мусора нет, перемишите на битбанг мускай килогерцовый даже, и повторите деяние.
Может у вас просто дисплей мертвый, или контроллер неизвестый науке, ну или подключение неправильное :)
0
В общем, так. Ранее у меня уже был мусор на экране. Но затем обнаружил, что SPI как-то неправильно работает и выдаёт наружу совсем не те данные, которые туда засылаются. В том числе и что-то с синхронизацией было. Когда поправил и дописал код, шум на экране пропал.
Сейчас взял и по-памяти закомментировал изменения и сделал многое как раньше.
в общем, теперь у меня весь экран в мусоре, а поверх выводится небольшой розовый прямоугольник. Так — правильно?
Зато теперь есть, куда дальше копать, спасибо. И надо будет «повертеть» настройки протоколирования SPI у USBee.
0
Это уже лучше. значит какие-то из «исправлений» оказались на самом деле неправильными.
Розовый прямоугольник наверника был выведен раньше вами (но раньше дисплей был просто выключен) и когда пришна нормальная команда включить дисплей (DISPON) вы и увидили все. После отключения питания на несколько секунд он снова станет мусором.
0
Я изучаю STM32, но дисплея 1616 у меня нет и его в Тольятти не продают. Писать библиотеку буду для монохромных дисплеев 1100, 2100 (Nokia). Про SPI 9-bit через синхронизированный USART: я так понимаю линии D/C и CS управляются программно как простые выводы GPIO?
0
Ага. MISO, MOSI, SCK — аппаратные, а CS у меня программный. Да, и при отправке через такой «SPI via USART» надо переворачивать биты в отправляемом 9-битном слове. Тогда они уйдут правильно. Переворачивать биты STM рекомендуют такой вот процедурой, которая лежит в core_cm3.c:
/**
 * @brief  Reverse bit order of value
 *
 * @param  value  value to reverse
 * @return        reversed value
 *
 * Reverse bit order of value
 */
uint32_t __RBIT(uint32_t value)
{
  __ASM("rbit r0, r0");
  __ASM("bx lr");
}

Если надо код класса, работающего с 9-битным SPI для STM32, могу куда-то или выложить, или выслать. Но код — чисто ООП-ный, на плюсах. На будущее, для универсальности. Если такое не надо, придётся переделывать.
0
Нее, я свой напишу. Без плюсов и без классов :)
0
Выложи в виде статьи, очевидно же.
0
  • avatar
  • Vga
  • 14 сентября 2011, 19:53
Очевидно-не-очевидно. И на статью тут никак не потянет. Разве что в блоге немного. И то надо будет допилить код приёма. Это уже скорее всего на выходных. Завтра — будем с отдыха возвращаться, а в пятницу — весь день уже распланирован в разъездах.
0
Я и собираюсь выложить. На статью вполне потянет. Распишу принципы работы с такими дисплеями и свою реализацию.

«Ядро» библиотеки написал, уже вывожу пиксели на экран :) Единственное, что насторожило — не проще было бы тупым bit-bang'ом (полностью программно) дёргать ножками SCLK и SDA. Скорости большие (115200 бит/с), экран заполняется мгновенно и профита от работы на прерываниях никакого нет, а раз прерывания не используем, следовательно, и от аппаратного USART или SPI тоже профита нет. Зря я радовался 9-битному USART'у — он мне, чую, уже не пригодится.
0
Прикрепил
0
А позволите ли предложить такой кастыль:
int count = 0;
unsigned short buff = 0;
void fake_spi9(unsigned int val) {
	if(count < 7) {
		buff |= val << (7 - count);
	} else {
		buff |= val >> (count - 7);
		real_spi16(buff);
		buff = val << (16 + 7 - count); 
	}
	count += 9;
	count &= 0x0F;
}
void start() {
	CS_SELECT;
}
void stop() {
	while(count)
		fake_spi9(0);
	CS_UNSELECT;
}

Да код не оптимален и время вывода постоянно для групп 1-16, 17-32, 33-48,… вызовов за сеанс.
Важным моментом является что сдвиг на несколько бит должен выполняться за то же время что и на 1 бит. Иначе лучше побитово задвигать данные.
0
По-моему, проще i/o ногами вручную дёргать. Всё равно же во время работы аппаратного SPI ЦПУ не занимается другими делами.
0
Ан нет :)
У меня NextPoint выполняется пока идет вывод, прочии вызовы функциий. При выводе картинок извлечение очередной точки помещается в это время.
У меня ожидание завершения вывода идет перед посылкой очередного байта на вывод и сразу после этово возврат. Это позволяет мне подготовить очередной байт, пока железка выводит данные.
Так что если вся эта перепаковка займет времени меньше чем вывод, то смысл есть. Но это надо проверять :)
Да и задать частоту SPI проще чем в битбанге в условиях конвеера.
0
подскажите в чем может быть глюк, при управлении яркостью светодиода с помощью ШИМ от него идут помехи на сигналы управления. короче мусор лепит. это можно вылечит?
0
  • avatar
  • Kino
  • 21 сентября 2011, 12:23
Раздельное питание, либо правильно составить схему (кондеры где надо, разводка). У меня тоже подсветка на шиме и ниче, норм всё.
Ву 3 вольта от куда берёте? может имеет смысл питание на подсветку брать перед стабилизатором?
0
я даже не понял в чем дело было. поставил ШИМ 8 бит, вместо 9 и все стабилизировалось. Питание ЖКИ от отдельного стабилизатора 3.3В. ШИМ на подсветку 5В прямо с ноги МК через резистор 150 Ом.
0
в смысле прямо с ноги? без ключа что-ли? :)

P.S.: при включении питания выводы LPC1343 находятся в состоянии «на ввод» с включенной подтяжкой. По этому ключ может быть (частично) открыт. Я кондер ставил что-бы убрать постоянную составляющую, яркость чуть падает, зато ничего не спалишь.
0
С ключем была такая-же фигня. Тем более нога контроллера вполне вытягивает 20 мА. у меня авр.
0
а кто-нить знает какой в этом дисплее контроллер стоит?
0
  • avatar
  • fin
  • 26 сентября 2011, 14:00
Вопрос к счастливым обладателям дисплея
-Не моли бы Вы измерить ширину, длину, высоту, размер видимой области и длину шлейфа дисплея.
Рисую элемент для библиотеки Altium Designer, а под рукой на данный момент нет LCD.
Заранее благодарен!
0
размеры видимой области в описании телефона глянуть можно. На данный момент дисплея нет под рукой, измерить не смогу. За шлейвы сразу скажу что есть покороче, а есть подлиннее, ориентируйтесь на 7мм.
0
36х29 мм
0
Подскажите, а преобразователь питания из вышеприведённой схемы подойдёт для подсветки дисплея от 6100?
0
Да, вполне.
0
какое все-таки у этого дисплея напряжение питания подсветки?
0
внутри имеется резистор, так что точно не скажу. Яподбираю на глазок, что бы яркость меня устроила и ток не был выше 20мА, а сколько там вольт не так и важно для меня.
0
Нет там резистора (по крайней мере, у тех, что у меня). Подбирай резистор для ~20 мА от твоего напряжения.
0
Дали 3 вида дисплеев на пробу, во всех на подсветке 2 параллельный светодиода. Соединяю через 10 ом на +3.3, как раз 20ma. Тестировал на LPC1114 без переделки программы.
0
А вот это уже интересно. у меня во всех цветных дисплеях последовательно светики были включены.
0
Сам был приятно удивлен, не надо лепить преобразователь.
0
Опа, попал. Привезли еще 5 дисплеев, подсветка 7В, но самое интересное — не запускаются, белый экран. Пошел менять.
0
у них же шлейф под пайку, а такие вроде не меняют же?
Форма шлейфа случаем не поменялась?
0
Нет, все один в один. Возит их мне знакомый ремонтник сотовых, так он сказал, что есть несовместимые модификации.
0
Возможно контроллер другой. Считай ID и поправь код соответсвенно ему.
0
Уже отдал на замену. Мне не подходит подсветка 7-ми вольтовая, платы развел на 3.3В. Остался один паянный, будет свободное время позанимаюсь им ради спортивного интереса.
0
Добрый день. Купил дисплей nokia 1616, на шлейфе не подписаны номера контактов, кто может подсказать как распознать первую ножку.
0
  • avatar
  • sprut
  • 26 декабря 2011, 10:34
Смотрите на лицо дисплея, шлейф вверху: счет слева на право. В схеме их статьи предполагается что крайние неподключенные выводы не считаются (первый вывод на схеме соответствует второму на шлейфе).
Проверить так же возможно мультимтром в режиме прозвонки диодов. у подсветки не будет контактов с питанием, у сигланьных же выводов есть защитные диоды на питание.
0
Спасибо. Подсветку вызвонил тестером, она даже зажигается на режиме прозвонки. А кто ни будь подскажет какие разъемы подходят для подключения, а то сходу не нашел.
0
Если от мультика светит, то вам явно будет много 7 вольт. похоже у мас тоже 3в подсветка. Мне аж интерестно стало, надо сходить прикупить ещё дисп, посмотреть какая у него подсветка.

в качестве разъема — просто паяетесь к шлейфу. он выдерживает пайку. Можно проводками а можно к плате, а можно и то и то. Разъема для них не предусмотрено, на сколько мне известно, так как они в мобилке припаяны.
0
У меня кстати тоже подсветка от прозвонки светит. Шлейф Т-образный, но никакой маркировки на нем нет (но контакты отсчитываются также слева на право). И еще вопрос, почему 6 и 7 нога посажены на 3,3В? Просто в схеме сервис мануала одна из них (6) идет на нечто под названием V1V8 (я так понимаю это 1.8В), а другая (7) на VAUX (что это хрен знает). Или дисплей себя нормально чувствует и при 3,3?
0
1V8 это питание цифровой схемы от 1.8В, но дисплей нормально себя чувствует и от 3.3В (проверено, и в даташитах на контроллеры разные оно допустимо). AUX это питание аналоговой части, для самого жк, туда дают 2.7В обычно, но так же от 3В пока ничего не погорело. вообже можете питание разнести (даже лучше будет), но я не вижу свмысла делать отдельное питание 1.8В и потом ещё и уровни согласовывать.
Другое дело если вы питаете МК от 1.8В (что актуально для снижения энергопотребления системы), то и цифровую часть дисплея так же лучше запитать от них же, и не надо согласовывать уровни. Так напримар при питание схемы скажем от 3-х вольтовой батарейки, можно мк и цифру диспа питать напряпую (типа сохраняет работоспособность до полного разряда батарейки), а вот на аналоговую ногу диспа прийдется по идеи ставить преобразователь для поддержания 2.7В (вам же не надо что бы от разряда батарейки менялся угол обзора дисплея).
0
А дисплей у вас оказался как на фотке с девушкой или как на фотке чуть ниже (где надпись Download datasheet (click here), Product Description)? Вопрос в том, чистый ли дисплей или с иконками (домик, письмо, и т.д.)? Я брал у другого продавца, но у него тоже одна фотка с иконками, другая без, а прислал с иконками, мать его.
Вот теперь думаю, как их отковырять, сохранив работоспособность тача, а также сохранив эстетичный вид дисплея после моих манипуляций.
0
Блин, не туда. Просьба к модераторам перенести коммент в этот топик: we.easyelectronics.ru/angel5a/displey-pobolshe-s-lpc1343.html
0
Чистый: в следующем посте есть фотка.
0
Повезло значит) Зато я 15 баксов всего отдал ))
0
Добрый день. Использую следующий код:
для инициализации USART на STM32:

USART1->CR2 = USART_CR2_STOP_0|USART_CR2_CLKEN|USART_CR2_CPOL|USART_CR2_CPHA|USART_CR2_LBCL; 
USART1->CR1 = USART_CR1_OVER8|USART_CR1_M|USART_CR1_TE|USART_CR1_UE; 

отправка байта:

void USART1_send (uint16_t data)
    {
    uint32_t temp;
    temp  = __RBIT (data) >> 23;
    while (!(USART1->SR & USART_SR_TXE))
        {}
    USART1->DR = temp; 
    }

Остальной код из статьи с добавлением дрыганья CS, однако ноль эффекта.
Смотрел лог. анализатором вроде бы все данные отсылаются правильно.
Что может быть не так?
0
А почему не SPI? даже при наличие 8-митного устройства можно их запарралелить. Просто при выборе устройства переключаете ещё и между 8/9 бит.
0
Дык STM32 не умеет 9-битный SPI…
Нашел код с чистым ногодрыгом — работает, правда там инициализация немного другая.
Разобраться бы теперь, как USART правильно настроить…
0
перенесите чистый ногодрыг с его инициализацией на уарт. Как настроит сам уарт можно найти тут. Если не заработает, скорее всего лажа в монтаже.
С стм32 я не работаю ещё.
0
Запустил и через UART…
Но по результатам забега по граблям обнаружились следующие отличия от приведенного в статье:
1)Последовательность инициализации другая
2)Хоть шлейф и T-образный, но верх с противоположной стороны.
3)Развертка идет по столбцам, а не по строкам(при выводе иконки оказались повернуты на 90 градусов, а вместо шрифтов, вообще, крякозябры) пришлось переупаковывать.
Сейчас свожу и пречесываю все в единую библиотечку, как доделаю — выложу.
Дисплеи покупались в СПб «Профи» у Сенной.
Шли как "Дисплей Nokia 1661/5030/1616/1800/1662"
Nokia1616
0
Раскурил такую же штуку из Сириуса…
1. Инициализация что та что та работает, причина различий — нежелание( неимение) читать описание контроллера.
2. Развертка переключается командой 0х36 как необходимо плюс зеркалирование по осям, что позволяет перевернуть картинку как требуется.
3. Разрешение 128 на 160.
+1
Кстати развертку ты сам перевернутую задал при инициализации :-)
0
а как реализовать 9 битный SPI на atmege16 или 32
где можно почитать об этом
в инете везде на STM
0
или поделитесь кодом под АВР
нужно выводить только текст и иконки
Спасибо
0
Нашел неточность — для указаного типа контроллера команда инициализации
0xBA, 0x107, 0x115,     // Data Order

не имеет смысла, ее нет в ДШ.
На реальном дисплее ее отсутствие тоже не сказывается.
0
  • avatar
  • Flash
  • 24 августа 2012, 11:39
То же самое и для
0x25, 0x13F,		// Contrast
0
Вполне возможно. Как я писал, код инициализации взят от другого дисплея.
Однако следует учесть что в дисплеях попадаются разные контроллеры, и для другого данный код может быть нужным.
0
это да, как говорят — «лучше перебдеть, чем недо...».
Еще момент нашел —
0x13, // Display Normal mode
в самом начале не нужна, при включении и сбросе дисплей сам входит в этот режим.

Сейчас занимаюсь этим диспом. Управляю PIC-ом. Пока выжал 10 кадров/сек.
0
10 кадров на чем? просто заливка или текст/изображения?
Пики умеют хардварно 9 бит? Дисп 9МГц тянет, 24fps на заливке простой можно выжимать.
0
На заливке.
Нет, не умеют. Софт+хард.
Частота у пика всего-лишь 12 мгц…
0
подскажите порядок расположения пинов для дисплея от 1616 пожалуста!?
0
  • avatar
  • Amigo
  • 24 августа 2012, 15:56
а что это дисплей?
0
А что это за дисплей, Amigo?
0
Вроде такой же как и 1661
0
это не тот, который такой же, как и 6116?
0
Нет, нокиа 1616 и 1661. Про китайцев речи не идет!
0
ДЫ тот же нокия 1616, там я просто не пойму на шлейфе где начало, где конец, ничего не указано. Т-образный шлейф, стеклом ко мне лежит… откуда считать то? И какие выводы?
0
  • avatar
  • Amigo
  • 24 августа 2012, 16:48
Если стеклом, то слева направо — 12...1
0
А названия выводов, если не затруднит, пожалуйста)
0
  • avatar
  • Amigo
  • 24 августа 2012, 17:46
Схема с названиями выводов в статье есть и в комментах.
0
ааа, точно, я бестолоч)))
0
  • avatar
  • Amigo
  • 24 августа 2012, 18:27
Вопрос вот тут такой назрел: формат общения соответствует SPI, с хитростью: линия данных двунаправленная. А кто-нибудь пробовал на I2C подключить и так поработать — суть-то будет примерно та…
0
Не пойдет. Тут 9 бит данных, на I2C это бит подтверждения, и вдобавок направление передачи при его трансляции изменяется (1-8 бит мастер -> слейв, 9 бит слейв -> мастер).
А двунаправленная линия дисплея вполне соответствует SPI, да и то не требуется. Читать из дисплея надо только ID, и только при инициализации, только если требуется иметь возможность работать с несколькими дисплеями. Можно и ногодрыгом, но в большенстве случаев стоит просто забить на чтение.
0
Да подключить можно, если режим открытого коллектора, MISO с MOSI объединяются, для чтения отправляем единички, если пришёл 0 — записан был ноль или ацк. Некоторые контроллеры поддерживают разные длины байта в спи — вон, стм32 от 4 до 16 бит. Но зачем, если есть аппаратный и2ц?
+1
Купил в профи два таких дисплея, шаг оказался 0,6, подсветка 3В. Везде указано что шаг 0,5?? Есть дисплей от nokia x1-01 и там шаг 0,6.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.