Подключение цветного LCD с сенсорным экраном к микроконтроллеру

в 9:06, , рубрики: diy или сделай сам, lcd, микроконтроллеры, Программинг микроконтроллеров, электроника, Электроника для начинающих, метки: , ,

Добрый день. Сегодня я хотел бы поделиться некоторым опытом, касающимся подключения цветных LCD-индикаторов к микроконтроллеру. Эта тема уже поднималась на хабре (http://habrahabr.ru/post/139384/), поэтому данный пост может рассматриваться как дополнение к уже написанному моими уважаемыми коллегами.
Подключение цветного LCD с сенсорным экраном к микроконтроллеру

В посте, на который приведена ссылка в начале, рассматриваются LCD-индикаторы, подключаемые с помощью интерфейса SPI. Такой способ подключения является простым, но не единственным. Множество индикаторов имеют «на борту» лишь упрощенный контроллер, не имеющий памяти для хранения изображения, и в силу этого, требующий непрерывного обновления изображения. Такие индикаторы применяются повсеместно в электронных гаджетах, и для их функционирования необходим специальный контроллер LCD, встроенный в микроконтроллер. Примером такого индикатора может служить MI0350CT-3 производства фирмы Multi-Inno Technology. Это достаточно типичный представитель цветных LCD, имеющий разрешение 320*240 и резистивный сенсор.
Итак, у нас появляется некоторая проблема. Пусть каждый пиксел представлен в памяти 32-битным значением (из них используется только 24, но данные выровнены по 4-байтным границам). Итого, под одну видеостраницу нам понадобится 320*240*4 = 307200 байт = 300 кбайт RAM. Не в каждом микроконтроллере есть такое количество памяти. Поэтому, как правило, для работы LCD нужна внешняя память, а значит, и контроллер внешней памяти на кристалле микроконтроллера.
Справедливости ради нужно заметить, что требования к объему памяти можно снизить, если использовать не 24-бита на пиксел, а меньшую глубину цвета, но, с другой стороны, мы можем захотеть разместить в памяти системы несколько видеостраниц, чтобы иметь возможность быстрого переключения между ними. Позже мы вернемся к этой теме.
Для примера рассмотрим подключение LCD к микроконтроллеру LPC2478. Это немного устаревший представитель микроконтроллеров фирмы NXP (на ядре ARM7, а не на современном Cortex M3), но для наших целей это несущественно. Этот микроконтроллер содержит всё необходимое: контроллер внешней памяти (с возможностью подключения как SRAM, так и SDRAM), и контроллер LCD с возможностью очень гибкой настройки.
Для экспериментов я использовал плату SK-MLPC2478 имеющую, помимо микроконтроллера LPC2478, микросхему статической памяти (CMOS SRAM) K6R4008V1D-TI10 объемом 512Kx8 bit. К плате подключен вышеупомянутый индикатор MI0350CT-3.
Есть еще один подводный камень: данный индикатор требует для питания подсветки источник с выходным током 20 мА при напряжении около 20 В. В качестве такого источника можно использовать, например, импульсный повышающий преобразователь, который питается входным напряжением +5В, и питает нагрузку стабилизированным током 20 мА. Если нагрузка не подключена, то преобразователь работает в режиме стабилизации выходного напряжения (U вых = 20 В). Схема преобразователя приведена на рис 1. Принцип действия и расчет повышающего преобразователя здесь рассматриваться не будет, интересующиеся этой темой могут обратиться к документации на микросхему MC34063A.

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 1. Преобразователь напряжения.

Рассмотрим вкратце подключение и работу LCD такого типа. LCD использует 24 сигнала для информации о цвете, сигнал CLK для пиксельной синхронизации, сигналы HSINK и VSINC для импульсов горизонтальной и вертикальной синхронизации. Помимо этого, индикатор имеет интерфейс SPI для настройки вспомогательных регистров, сигнал #RESET и сигнал DEN (data enable). Интерфейс SPI в данном случае предназначен не для передачи изображения в контроллер дисплея, а для конфигурирования вспомогательных регистров. Эти регистры позволяют выбрать режим работы индикатора, регулировать яркость, контрастность и другие параметры. Однако регистры управления индикатора по умолчанию устанавливаются в нужное нам состояние, и, если мы не собираемся их изменять, сигналы SPI можно просто проигнорировать. Сигнал #RESET можно просто установить в неактивное (единичное) состояние. В дальнейшем он нам не понадобится.
Итак, основными сигналами, необходимыми для работы данного типа индикатора, являются: сигналы данных, несущие информацию о текущем цвете пиксела в формате RGB, сигнал тактирования CLK, сигналы вертикальной и горизонтальной синхронизации, а также сигнал разрешения данных. Рассмотрим временные диаграммы.

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 2. Временная диаграмма передачи данных в LCD.

На рис. 2 показана самая «крупномасштабная» временная диаграмма передачи данных, изображающая передачу данных одной строки изображения. Передача происходит по фронту сигнала CLK, и сопровождается высоким уровнем сигнала разрешения данных DEN. Передача происходит в формате RGB, при этом биты Data0 — Data7 соответствуют синему цвету, Data8 — Data15 — зеленому, Data16-Data23 — красному.
Перед передачей данных строки и после передачи данных вставляются «пустые», не несущие информации импульсы CLK. Передача строки предваряется импульсом горизонтальной синхронизации HSYNC (LCD_LP).
Тактовая частота индикатора составляет 6,4 МГц (её можно уменьшить, но тогда становится заметным мерцание кадров).

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 3. Временная диаграмма передачи кадра в LCD

Временная диаграмма передачи полного кадра в LCD показана на рис. 3. Передача кадра начинается с 13 «пустых» строк, далее следуют 240 строк с изображением, после которых опять идут «пустые» строки. Передача кадра начинается с импульса вертикальной синхронизации.
Также подключим к микроконтроллеру резистивный сенсор. Описание этого подключения будет приведено ниже.
Полную схему подключения индикатора к микроконтроллеру я приводить не буду, в силу ее очевидности, приведу лишь таблицу соответствия выводов индикатора и пинов контроллера.

Таблица 1. Соответствие сигналов LCD и выводов контроллера

Сигнал SK-MLPC2478 (connector X6) LCD pin Порт микроконтроллера Примечание
GND 1 53, 54 земля
+5V 2 - не используется
DATA6 3 18 данные
+3.3 V 4 41, 42 питание
LCD CLK IN 5 - не используется
DATA 7 6 19 данные
DATA 19 7 31 данные
DATA 18 8 30 данные
DATA 22 9 34 данные
DATA 23 10 35 данные
DATA 20 11 32 данные
DATA 21 12 33 данные
DATA 14 13 26 данные
DATA 15 14 27 данные
DATA 12 15 24 данные
DATA 13 16 25 данные
DATA 11 17 23 данные
DATA 10 18 22 данные
DATA 1 19 13 данные
DATA 0 20 12 данные
DATA 9 21 21 данные
DATA 8 22 20 данные
DATA 17 23 29 данные
DATA 16 24 28 данные
LCD LE 25 - не используется
LCD PWR 26 - не используется
LCD FP 27 37 Вертикальная синхронизация
LCD CLK 28 38 Тактирование индикатора
LCD LP 29 36 Горизонтальная синхронизация
LCD ENAB 30 52 Разрешение данных
DATA 5 31 17 данные
DATA 4 32 16 данные
DATA 3 33 15 данные
DATA 2 34 14 данные
SPENA 35 43 P0.20 интерфейс SPI, serial port data enable
- 36 - Не используется
#RESET 37 6 P0.19 сброс
- 38 - Не используется
SPCK 39 49 P0.17 интерфейс SPI, serial port clock
SPDA 40 50 P0.18 интерфейс SPI, serial data
YU Connector X7.15 8 AD0/P0.23 Резистивный сенсор
XR Connector X7.13 9 AD1/P0.24 Резистивный сенсор
YD Connector X7.10 10 P0.26 Резистивный сенсор
XL Connector X7.12 11 P0.25 Резистивный сенсор

Собираем макет устройства (рис. 4 — 6):

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 4. Платы макета устройства

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 5. Макет устройства (частично собран)

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 6. Макет устройства в сборе

Теперь, когда всё подключено, можно приступить к написанию кода. Первое, что нужно сделать, это сконфигурировать и протестировать внешнюю SRAM память:

// Init SDRAM controller
  // Enable EMC clock
  PCONP_bit.PCEMC    = 1;

  EMCSTATICWAITRD0   = 0x00000001;
  EMCSTATICWAITPG0   = 0x00000000;
  EMCSTATICWAITWR0   = 0x00000000;
  EMCSTATICWAITTURN0 = 0x00000000;
  
  EMCCONTROL      = 1;         // enable EMC

Тест SRAM:

char SRAM_Test(void)
{
// 32 bits access
  for (Int32U i = 0; i < 0x80000; i+=sizeof(Int32U))
  {
    *(Int32U*)(((Int32U)SRAM_BASE_ADDR)+i) = i;
  }

  for (Int32U i = 0; i < 0x80000; i+=sizeof(Int32U))
  {
    if (*(Int32U*)(((Int32U)SRAM_BASE_ADDR)+i) != i)
    {
      printf("Verification error on address : 0x%xn",(Int32U)SRAM_BASE_ADDR+i);
      return(FALSE);
    }
  }

  return TRUE;
}

Следует понимать, что быстродействие внешней памяти является важным фактором. В самом деле, поток данных в нашем случае составляет Fclk * N, где Fclk — тактовая частота индикатора, N — количество байт в памяти, отведенных под 1 пиксел. Итого получаем 6.4*10^6 * 4 = 25.6 Мбайт/с. Для памяти с 8-битным интерфейсом это означает максимально допустимое время доступа 39 нс. Требования к быстродействию памяти можно снизить, если использовать память с 16 или 32-битным интерфейсом и/или уменьшить используемую глубину цвета.
Конфигурируем LCD в, выставляя длительности сигналов в соответствии с документацией индикатора:

// Init GLCD cotroller
  PCONP_bit.PCLCD = 1;      // enable LCD controller clock
  CRSR_CTRL_bit.CrsrOn = 0; // Disable cursor
  LCD_CTRL_bit.LcdEn = 0;   // disable GLCD controller
  LCD_CTRL_bit.LcdBpp= 5;  //2bpp // 24 bpp
  
  LCD_CTRL_bit.LcdTFT= 1;   // TFT panel
  LCD_CTRL_bit.LcdDual=0;   // single panel
  LCD_CTRL_bit.BGR   = 0;   // normal output
  LCD_CTRL_bit.BEBO  = 0;   // little endian byte order
  LCD_CTRL_bit.BEPO  = 0;   // little endian pix order
  LCD_CTRL_bit.LcdPwr= 0;   // disable power
  
  // init pixel clock
  LCD_CFG_bit.CLKDIV = SYS_GetFsclk() / (Int32U)C_GLCD_PIX_CLK;
  LCD_POL_bit.BCD    = 1;   // bypass inrenal clk divider
  LCD_POL_bit.CLKSEL = 0;   // clock source for the LCD block is HCLK
  LCD_POL_bit.IVS    = 1;   // LCDFP pin is active LOW and inactive HIGH
  LCD_POL_bit.IHS    = 1;   // LCDLP pin is active LOW and inactive HIGH
 // LCD_POL_bit.IPC    = 1;   // data is driven out into the LCD on the falling edge
  LCD_POL_bit.IPC    = 0;   // data is driven out into the LCD on the rising edge
  
  LCD_POL_bit.PCD_HI = 0;  //  //
  LCD_POL_bit.PCD_LO = 0;  //

  LCD_POL_bit.IOE    = 0;   // active high
  LCD_POL_bit.CPL    = C_GLCD_H_SIZE-1;
  // init Horizontal Timing
  LCD_TIMH_bit.HBP   =  C_GLCD_H_BACK_PORCH - 1;
  LCD_TIMH_bit.HFP   =  C_GLCD_H_FRONT_PORCH - 1;
  LCD_TIMH_bit.HSW   =  C_GLCD_H_PULSE - 1;
  LCD_TIMH_bit.PPL   = (C_GLCD_H_SIZE/16) - 1;
  // init Vertical Timing
  LCD_TIMV_bit.VBP   =  C_GLCD_V_BACK_PORCH;
  LCD_TIMV_bit.VFP   =  C_GLCD_V_FRONT_PORCH;
  LCD_TIMV_bit.VSW   =  C_GLCD_V_PULSE;
  LCD_TIMV_bit.LPP   =  C_GLCD_V_SIZE - 1;
  // Frame Base Address doubleword aligned
  LCD_UPBASE         =  (Int32U)GetVramAddr()  & ~7UL;

Теперь записываем в ROM тестовую картинку и копируем ее в RAM:

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис 7. Тестовая картинка

Картинка записывается в виде массива unsigned int [240][320], и копируется по базовому адресу внешней памяти (0x80000000).
Работа встроенного в микроконтроллер механизма поддержки LCD заключается в том, что данные считываются из RAM контроллером DMA, и подаются на контроллер LCD, где накладывается изображение курсора и данные подаются на вход LCD. Также контроллер LCD может обеспечивать поддержку палитры для режимов от 1 до 8 бит на пиксел. Палитра реализована в микроконтроллере как 256 16-битных регистров и, таким образом, обеспечивает отображение 8-битного цвета в 16-битный (5 бит/цвет + 1 бит общей интенсивности).
Курсор имеет отдельную палитру из двух 32-битных регистров, она обеспечивает отображение монохромного изображения курсора в 24-битное цветовое пространство. Курсор может быть размером 64x64 пиксела либо 32х32 пиксела, и содержит как само изображение курсора, так и маску инверсии изображения.
Теперь можно запустить тестовою программу и посмотреть на результат.

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 8. Результат работы.

Подключение резистивного сенсора

Принцип действия резистивного сенсора широко известен (те, кому он неизвестен, могут ознакомиться с ним, например, здесь http://ru.wikipedia.org/wiki/Сенсорный экран ). Поэтому перейдем сразу к описанию подключения сенсора к микроконтроллеру. В данном устройстве используется сенсор с четырехпроводной схемой подключения. Схема подключения показана на рис. 9.
Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 9. Схема подключения резистивного сенсора к микроконтроллеру.

Идея, лежащая в основе такого подключения, состоит в следующем. Каждый вывод микроконтроллера может находиться в одном из следующих состояний: выход с логическим 0, выход с лог. 1, вход (т. е., фактически, неподключенный вывод), и вход, подтянутый к напряжению питания через резистор. Выводы YU и XL могут также служить входами АЦП.
Вся процедура определения координат нажатия может быть условно разделена на три фазы. В первой фазе выводы, к которым подключен сенсор, находятся в следующем состоянии: (рис. 10).

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 10. Определение координат нажатия. Фаза 1.

При замыкании пленок сенсора на вход микроконтроллера поступает сигнал лог. 0, и программа переходит к фазе 2, определению x-координаты нажатия (рис. 11). Затем следует фаза 3, определение y-координаты. (рис. 12).

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 11. Определение х-координаты нажатия.

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 12. Определение y-координаты нажатия.

Разумеется, алгоритм вычисления координат нажатия должен включать в себя подавление дребезга «контактов» (плёнок сенсора).
При однократном измерении точность определения координат будет слишком низкая, шумы измерений приведут к тому, что курсор будет сильно колебаться в окрестностях точки касания. Поэтому весьма желательным является применение какого-либо алгоритма фильтрации, например медианного фильтра (http://ru.wikipedia.org/wiki/Медианный_фильтр).
После получения результата в кодах АЦП он пересчитывается в координаты экрана с помощью обычных линейных преобразований (ax + b), где коэффициенты a и b должны быть найдены путем калибровки сенсора и сохранены в энергонезависимой памяти контроллера. На рис. 13. приведен пример экран калибровки.

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 13. Экран калибровки.

Подключение цветного LCD с сенсорным экраном к микроконтроллеру

Рис. 14. Экран калибровки на LCD.

Возможна также реализация подключения сенсорного экрана с помощью внешнего контроллера, например, XPT2046.
Полный исходный код примера программы можно скачать отсюда: https://bitbucket.org/arktur04/lcd-demo (среда разработки IAR).

Ссылки на упомянутую в посте документацию:
1.Дисплей Multi-Inno MI0350CT-3 http://www.displayfuture.com/engineering/specs/TFT/MI0350CT-3.pdf
2.Импульсный преобразователь напряжения MC34063A http://www.fairchildsemi.com/ds/MC/MC33063A.pdf
3.Микроконтроллер LPC2478 http://www.ru.nxp.com/products/microcontrollers/arm7/lpc2400/LPC2478.html
4.Контроллер резистивного сенсора XPT2046 http://www.dzsc.com/uploadfile/company/785710/20111014212155973.pdf

Автор: 32bit_me

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js