Підключення дисплея DVD плеєра до мікроконтролера


 
Почну з передісторії, навіщо ж мені все це потрібно. Я задався метою зробити собі HTPC комп'ютер на базі корпусу від DVD плеєра Daewoo DV-500, зовні він мені подобається, і вільного місця в ньому досить для установки необхідного заліза всередину. Але крім всього, я задумав залишити рідний індикатор і задіяти його для відображення різної інформації. Про те, як я підключав дисплей до мікроконтролера і розшифровував протокол обміну цього дисплея, піде в цій статті.
 
Таку роботу треба починати з пошуку інформації, в першу чергу я знайшов схему плеєра, проблем з цим, на моє здивування, не виникло. За схемою я зміг зрозуміти з чим треба працювати, але знайти описи на контролер дисплея відразу не вийшло, тому що на схемі він підписаний неправильно. На жаль, документацію на контролер я знайшов в останній момент, випадково, але до цього часу я практично повністю розібрав протокол.
 
Отже, що ж ми маємо:
 
 
 
Ми маємо контролер VFD дисплея NEC D16312 (зверніть увагу як підписаний контролер на схемі, не дивно що я відразу не зміг знайти про нього інфу), з підключеними до нього VFD дисплеєм, клавіатурною матрицею і світлодіодом. З «зовнішнім світом» контролер під'єднаються через послідовний інтерфейс за допомогою роз'єму CN1.
 
Для перехоплення повідомлень від контролера основної плати в контролер дисплея я буду використовувати логічний аналізатор. Я, наприклад, користуюся китайським клоном USBee AX PRO, свої ф-ції він виконує на відмінно і коштує недорого.
 
Підключаємо висновки Data, Clk і Cs до будь трьох висновків логічного аналізатора, не забуваємо також з'єднати землю. Далі, з'єднуємо аналізатор по USB з комп'ютером і запускаємо USBee Suite (я опускаю процес установки драйверів і програмного забезпечення для логічного аналізатора, це виходить за рамки статті). У налаштуваннях Speed ​​and Samples ставимо следущие параметри: Sample Rate — 2Msps, Buffer Size — 10M samples. Цього буде достатньо щоб захопити кадр обміну розміром в 5 секунд.
 
Подальші мої дії такі, роблю одиничний захват (кнопка Capture Once) і відразу-ж включаю плеєр. Як тільки з'явилася перша інформація на екрані — вимикаю захоплення. Після того різання таких дій для різних варіантів тексту, що відображається, я став аналізувати отриману інформацію.
 
Отже, які ж є закономірності у всіх посилках команд. По-перше, що кинулося в очі відразу, це періодичність посилки команди з кодом 0x42 і трьома порожніми байтами після неї. Команда має строгу періодичність появи навіть коли відеоплеєр в стані спокою. Я припустив, що це команда опитування клавіатури, перевірити теорію дуже легко, затискаю будь-яку кнопку на плеєрі і роблю захоплення кадру в програмі.
 
 
 
Відразу ж після байта 0x42 з'явився не нульовий байт, а раніше був 0! Таким чином 0x42 — команда опитування клавіатури, яка відсилається контролером основної плати в контролер дисплея і у відповідь на цю команду контролер дисплея відповідає кодом натиснутоюклавіші (або 0 якщо не натиснута ні одна).
 
Наступною на черзі стала команда з кодом 0x40, вона з'являлася тільки коли на екран виводиться інформація. Після неї завжди йдуть два байти, перший байт завжди починається з 0xCX, де X змінюється значення. Третій байт має довільні значення, але головне що при першому включенні він завжди дорівнює 0
 
 
 
На цьому скріншоті видно що другий байт зростає з кожною посилкою групи 0x40, швидше за все він задає адресу символу і третім байтом записується значення символу. У даному випадку 0 очищає символ. Завжди після відсилання всіх груп з кодом 0x40 послідує два байти 0x02 0x8F.
 
 
 
Ну і останньою групою даних є команда, що починається з кодом 0x41 і наступним нульовим байтом після неї. Команда з'являється тільки при першому включенні відеоплеєра.
 
Аналіз даних вималював більш-менш зрозумілу картинку роботи контролера, залишилося тільки перевірити все на практиці. Я використовував отладочную хустці LPCXpresso, отримані мною «нахаляву» в рамках якогось конкурсу від NXP. Хустки оснащена простеньким 32х бітним контролером LPC1114. Т.к. контролер живиться напругою 3.3В, а контролер дисплея D16312 від 5ти вольт, то з'єднувати їх висновки безпосередньо я не наважився. Можливо, висновки мікроконтролера толерантні до напруги 5В, але у мене в наявності була хустки узгодження рівнів 3.3-5В і я використовував її.
 
 
 
Отже, з роз'єму, що йде до основної плати, витягаємо 3 дроти, що відповідають за Піни Data, Cs і Clk відповідно Піни 1, 2 і 3. До плати контролера діслея припаювати проводами до точок з'єднання Data, Clk і Cs, а також нам понядобятся висновки GND і +5 V VCC. На першому воемя, я приєднав витягнуті від основної плати три контакту з логічним аналізатором, щоб дебажіть передану інформацію.
 
 
 
Ось так у мене виглядає соденіеніе з отладочной хусткою
 
 
 
Вся залізна частина готова, пора приступати до софту. Для початку напишемо програму, яка буде повторювати отримані в ході аналізу, дані. Для LPCXpresso використовується однойменна LPCXpresso IDE на базі Eclipse. Запускаємо, вказуємо шлях до нашого нового робочому простору та імпорту в нього 2 стандартних бібліотеки CMSIS_CORE_LPC11xx і LPC11xx_cmsis2_Lib, вони нам знадобляться для розробки. Далі створимо новий проект File-> New-> C / C + + -> LPCXpresso C Project далі LPC11 / LPC12 -> LPC11xx /… -> C Project. Задаємо ім'я проекту і в наступному вікні вибираємо цільової контролер, в моєму випадку це LPC1114/302. На наступному кроці у списку вже повинна з'явитися бібліотека CMSIS_CORE_LPC11xx, т.к. ми її імпортували раніше. У вікні завдання DSP бібліотеки нічого не міняємо і на наступному кроці залишаємо все за умовчанням, тиснемо Finish.
 
Додаємо наступний код в сгенеренний файл <ім'я проекту>. C
 
#ifdef __USE_CMSIS
#include "LPC11xx.h"
#include "clkconfig.h"
#include "gpio.h"
#endif

#include <cr_section_macros.h>

void Delay(int32_t ticks);
void BeginCommand(uint8_t cmd, uint8_t isSingle);
void EndCommand();
void Clock();
void WriteData(uint8_t data);

#define PORT 3
#define DATA_BIT 2
#define CLK_BIT 0
#define CS_BIT 1

int main(void)
{
	GPIOInit();

	// Set pins to output
	GPIOSetDir(PORT, CLK_BIT, 1);
	GPIOSetDir(PORT, CS_BIT, 1);
	GPIOSetDir(PORT, DATA_BIT, 1);

    while(1)
    {
    	BeginCommand(0x40, 1);
    	BeginCommand(0xC0, 0);
    	WriteData(0xFF);
    	EndCommand();

    	BeginCommand(0x02, 1);
    	BeginCommand(0x8F, 1);

    	Delay(3000000);
    }
    return 0 ;
}

void Delay(int32_t ticks)
{
	volatile int32_t i = ticks;
	while(i--);
}

void BeginCommand(uint8_t cmd, uint8_t isSingle)
{
	GPIOSetValue(PORT, CLK_BIT, 1);
	GPIOSetValue(PORT, CS_BIT, 0);
	Delay(10);

	WriteData(cmd);

	if (isSingle)
	{
		EndCommand();
	}
}

void EndCommand()
{
	GPIOSetValue(PORT, CLK_BIT, 1);
	GPIOSetValue(PORT, CS_BIT, 1);
	Delay(10);
}

void Clock()
{
	Delay(10);
	GPIOSetValue(PORT, CLK_BIT, 0);
	Delay(10);
	GPIOSetValue(PORT, CLK_BIT, 1);
}

void WriteData(uint8_t data)
{
	GPIOSetDir(PORT, DATA_BIT, 1);

	uint8_t i = 0;
	for (i = 0; i < 8; ++i)
	{
		uint8_t isSet = (data & 0x01);
		GPIOSetValue(PORT, DATA_BIT, isSet);

		Clock();

		data = data >> 1;
	}
}

Тут бачимо кілька ф-цій для роботи з послідовним портом. У самому верху файлу задаються настройки порту і пинов для даних, синхронізації і стрибає. У моєму випадку все висить на порту 3, пін 2 відповідає за сигнал Data, 0 — синхронізацію і 1 — стробирование.
 
Ф-ція BeginCommand відсилає команду в порт, у цієї ф-ції є другий цікавий параметр. Якщо придивитися на графіки сигналів вище, то можна побачити що сигнал стробування, виставляється в активний (низький) рівень, перед посилкою даних, і змінюється між двома незалежними командами. Але не перемикається, якщо після відправлення команди повинні передаватися дані
 
 
 
Так от, другий параметр каже що команда є атомарної якщо isSingle == 1. Для випадку неатомарних команд призначена ф-ція EndCommand, яку слід викликати після відсилання даних.
 
Відсилання ж даних виконується в ф-ції WriteData, по черзі, біт-за-бітом, починаючи з молодшого, передаємо в пін Data інформацію. Кожне виставлення даних супроводжується сигналом синхронізації, ф-ція Clock генерує його.
 
У ф-ції main спочатку инициализируем роботу з входами введення / виведення, далі виставляємо Піни Data, Clk і Cs на висновок. У нескінченному циклі імітуємо команди, які були отримані раніше на етапі аналізу даних. Т.ч. ми відправили в контролер дисплея послідовність даних 0x40 0xC0 0xFF 0x02 0x8F, а контролер відповів висновком _8
 
 
 
Т.ч. було встановлено що команда:
 - 0x42 — відповідає за обробку клавіатури. Після її відправки в контролер дисплея потрібно виставити порт Data на вхід і прочитати з нього дані, попередньо синхронізувавши сигналом Clk
 - 0x40 — команда запису даних в дисплей, після неї повинна записуватися команда вказівки адреси символу, а після вказівки адреси записуються дані
 - 0x41 — це команда для управління світлодіодом, після неї йде байт з даними якої світлодіод повинен бути включений чи ні
Більш детальну інформацію ви можете знайти в керівництві по даному контролеру дисплея D16312, там розписані як повинні формуватися команди. Ну, а я оформив всю роботу в невелику бібліотечку, яка лежить на гітхабе . Бібліотека дозволяє відображати текст, управляти спецсимволами, заповнювати символ диска в процентному співвідношенні, читати клавіатуру, міняти яскравість відображення і управляти світлодіодом. На цьому все, сподіваюся комусь це чтиво буде корисним і цікавим. А на закуску я залишу відео, з демонстрацією роботи бібліотеки
 
 
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.