Как подключить дисплей от телефона к stm32

Обновлено: 07.07.2024

Завалялся у меня TFT LCD дисплей 2.4 дюйма с сенсорным экраном. Никакой информации о нем я не знал. На модуле есть слот для sd карты, стабилизатор напряжения и пара LVC245A.

На дисплее есть резистивный сенсор. Управление по 4 проводам. Выводы подключены к выводам передачи данных. X+ на LCD_D1, X- на LCD_CS, Y+ на LCD_RS и Y- на LCD_D0. Я так понимаю этот модуль рассчитан на Arduino Uno. Это совершено не удобно, нужно использовать ногу где есть АЦП. А еще это большая потеря скорости отдачи данных на дисплей.

Я отпаял шлейф сенсора и подключил отдельно, но об этом в отдельной статье.

На МК STM32F103C8T6 нет FSMC. Я советую использовать подряд идущие пины одного порта, например A0-A7 для передачи данных на экран. Можно и не с нулевого пина, просто при записи делать побитовый сдвиг.

В моем случае я сделал плату для соединения экрана и модуля с МК STM32F103C8T6 по этому подключение будет таким.

То есть B8 - B15 я подключил к портам LCD_D0 - LCD_D7. Выводы RST, CS, RS, WR я подключил к A9-A12. Вывод RD я не использую, так как читать с экрана данные мне не нужно, по этому я подключил его к питанию 3.3В.

Команды, которые нам пригодятся для теста дисплея

Вспомогательные функции для задержки

Обмен данными с дисплеем на базе ILI9341 и инициализация

Таблица настроек вывода пикселя

Функции вывода пикселей на экран

Команда CASET (Column Address Set) - принимает два байта, номер первого пикселя в строке, по оси X и два байта номер последнего.

Команда PASET (Page Address Set) аналогично принимает принимает по Y.

Для удобства вместо номера конечного пикселя в качестве аргумента функции TFTRect я использую ширину и высоту, а уже в самой функции перевожу в адрес пикселя.

Команда RAMWR это запись наших пикселей. Если взять ширину 5 пикселей а высоту 2, то всего нужно будет передать 2 * 5 = 10 пикселей по 2 байта.

Некоторые цвета для теста

Или можно воспользоваться макросом для вычисления цвета из RGB

Остается настроить тактовую частоту и порты на вывод с подтяжкой к питанию

И можно что то выводить на дисплей

ILI9341 вывод с STM32

Комментарии к статье: Подключение сенсорного дисплея на ILI9341 (R61520, SPFD5408) к STM32

Здравствуйте! Интересно, но жалко не описана работа с резистивной панелью. Планируется ли в дальнейшем?

Я пользовался двумя статьями с easyelectronics.ru. Первая описывает как опрашивать экран, называется "Работа с резистивным сенсорным экраном". Вторая как откалибровать "Освоение STM32F103VE + TFT LCD + touch screen (часть 4)".

Сайт не дает ссылки запостить, по этому пишу названия. В гуле по названиям и имени сайта они легко находятся.


ЖК-матрица от Nokia 3310 имеет размеры 84 × 48 пикселей, что позволяет комфортно отображать 14 разборчивых буквенно-цифровых символов в 6 строках. По сравнению с возможностями популярных буквенно-цифровых дисплеев (обычно 2 × 16 или 2 × 20 символов), это большой объем информации.

Рис. 1. Внешний вид дисплейного модуля от телефона Nokia 3310

Внешний вид дисплейного модуля от телефона Nokia 3310

Доступное в интернете описание дисплеев телефона Nokia 3310 указывают на то, что он имеет встроенный драйвер типа PCD8544 производства NXP (Philips).

Кратко напомним конструкцию и способ управления контроллером PCD8544. Его структура включает в себя:

  • Матричный драйвер ЖК-дисплея, включающий в себя систему подачи напряжения матрицы и систему компенсации контрастности в зависимости от температуры,
  • Память изображений SRAM
  • Интерфейс связи функционально аналогичен интерфейсу SPI.

На рис. 2 показан временная диаграмма при отправке байта данных или команды на контроллер дисплея.


Рис. 2. Способ отправки байта на контроллер PCD8544


Обновленная версия, мощность: 600 Вт, расход воздуха: 240 л/час.

Передача начинается с активации линии nSCE (установка на низкий уровень). Данные из линии SDIN вводятся в регистр контроллера с нарастающими фронтами тактового сигнала SCLK. В примере, показанном на рис. 2, после ввода одного байта линия nSCE становится неактивной. Контроллер допускает ввод блока байтов с активным nSCE (без необходимости устанавливать 1 по этой линии после каждого переданного байта), что в свою очередь ускоряет передачу данных.

Расположение выводов модуля дисплея от телефона Nokia 3310


Контактный номер 1 2 3 4 5 6 7 8
функция Vdd SCLK SDIN D/C SCE GND Vout RES

На рис. 3 показана принципиальная схема, иллюстрирующая подключение модуля дисплея к микроконтроллеру.


Рис. 3. Схема подключения дисплейного модуля от Nokia 3310 к микроконтроллеру

Память изображения

Содержимое памяти SRAM, встроенной в контроллер PCD8544, можно изменить, введя данные в контроллер, когда линия D/nC находится в высоком состоянии. ЖК-матрица может отображать 48 строк, каждая из которых имеет 84 пикселя.

Память SRAM организована в 6 банков по 84 байта. Эта организация обеспечивает логическое разделение поля отображения на 6 строк по 84 столбца (рис. 4). Строки пронумерованы от 0 до 5, столбцы от 0 до 83.


Рис. 4. Организация памяти SRAM в контроллере PCD8544

При вводе данных в память изображений сначала укажите номер банка памяти (переменная Y на рис. 4), затем номер байта в строке (переменная X на рис. 4). Сохранение всего банка эквивалентно отображению одной строки дисплея (линейки).

Каждый байт оперативной памяти отображается в виде вертикальной полосы размером 8 пикселей. Старший пиксель в строке соответствует младшему значащему биту, а самый низкий пиксель соответствует старшему значащему биту памяти. В стандартном режиме отображения установка бита в байте памяти соответствует отображению черного пикселя, а обнуление соответствует его отключению.

Адресация памяти


Рис. 5. Вертикальная адресация памяти изображений в контроллере PCD8544

Каждый раз, когда байт сохраняется, он увеличивается на один ряд строк. Когда достигается максимальное число строк, счетчик строк сбрасывается, а счетчик столбцов увеличивается на 1. При отправке 6 байтов 0xFF, начиная с номера строки, равного нулю, в первом левом столбце дисплея будет отображаться вертикальная полоса по всей высоте дисплея. Режим вертикальной адресации (рис. 6) можно использовать при сохранении полноэкранного растрового изображения.


Рис. 6. Горизонтальная адресация памяти изображений в контроллере PCD8544

После сохранения каждого байта счетчик столбцов увеличивается. При достижении максимального числа столбцов счетчик столбцов сбрасывается, а счетчик строк увеличивается на 1. Режим горизонтальной адресации очень удобен при работе в текстовом режиме. Режимы адресации могут свободно переключаться во время нормальной работы дисплея, и это не влияет на отображаемую информацию.

Команды драйвера PCD8544

Контроллер принимает два набора команд: стандартную и расширенную, их описания перечислены в табл. 1 .

Табл . 1. Команды контроллера PCD8544 (согласно документации NXP)

Описание параметров из таблицы 1.

Все сегменты освещены.

VLCD температурный коэффициент 1

VLCD температурный коэффициент 2 (стандарт)

Команда Function Set предназначена для программного переключения дисплея в режим пониженного энергопотребления, обращения к памяти RAM и установки набора команд (обычный или расширенный).

Контрастность дисплея зависит от напряжения, подаваемого на ЖК-матрицу, и устанавливается командой Set Vop. Можно установить 128 значений, но используемый диапазон регулировки составляет от 30 до 90.

Команда «Контроль температуры» позволяет установить одну из 4 предопределенных характеристик компенсации контрастной температуры. Коэффициент 2 (TC1 = 1, TC0 = 0) может использоваться для большинства приложений. Для дисплея телефона Nokia 3310 значение параметра BIAS должно быть 3.

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Последние посетители 0 пользователей онлайн

Rede RED

так мне не нужен, на ИРисках 44 "завёлся" "с пол оборота", ни чего не перекашивает, по нижнему немного ТП, но пусть попробуют и покажут что у них на Дубовых и Линеральных, тем более на соответствие открывания (вольта на затворах в даташит) и какой ТП нужен. Можно сказать класс "В", ТП от 80мА: С12 для моста, 47пФ. Кг 0005 до предклиппа (может и меньше, не хочу ждать) Х.З. что не так когда литералы, может модельки - фейк. Quad 44 2.ms14 Кз нет, может есть перегрузка. R804, R805 целые? Так у них и номинал вдвое больше. ТС, покажите нам напряжение со всех концов R804, R806. И ток через них.

ZLOdeyB@sil@

И на кой они нужны? Напрасная трата времени и жизненных иллюзий. "Бастуйте, не бастуйте -денег нет". не работает и уволиться всей бригадой, всем пох что нормальные рабы за дёшево работать не будут - набирают ПТУ шинков (детей которые ничего не умеют), криминальных, алкошню и тп.

Rede RED

Интересно, а почему R804, R805 на схеме 2 ваттные. а R806, К 807 = 1 ваттные

Soundoverlord

Стали дешевле. Старый человек не раритет, а старая развалюха.

Dr. West



Двухканальный осциллограф-планшет Fnirsi 1013D 100МГц

Похожий контент

Добрый день всем! Столкнулся с проблемой, над решением которой бьюсь уже месяц - суть в том, что при пересылке аудио данных с контроллера в внешний цап на выходе цапа звучит белый шум(именно когда летят данные). Уже перепробовал разные конфигурации и параметры, да даже другой цап ставил - всё равно та же самая проблема. Может кто сталкивался, или у кого есть идеи почему так происходит?
Контроллер stm32f407ve китайский, но вроде как рабочий, цап - pcm1606, вытащенный из двд-плеера.

код инициализации i2s
RCC_PLLI2SCmd(DISABLE); RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S); RCC_PLLI2SConfig(200,5); RCC_PLLI2SCmd(ENABLE); while(RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY) == RESET)<>; //WS - word clock output GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_SPI2); GPIO_StructInit(&gpioInit); gpioInit.GPIO_Pin = GPIO_Pin_9; gpioInit.GPIO_Mode = GPIO_Mode_AF; gpioInit.GPIO_OType = GPIO_OType_PP; gpioInit.GPIO_PuPd = GPIO_PuPd_NOPULL; gpioInit.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOB, &gpioInit); //BCLK - shift clock output GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_SPI2); gpioInit.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOB, &gpioInit); //SD - serial audio data GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_SPI2); gpioInit.GPIO_Pin = GPIO_Pin_3; GPIO_Init(GPIOC, &gpioInit); //MCO - master clock output GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_SPI2); gpioInit.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOC, &gpioInit); I2S_StructInit(&i2sInit); i2sInit.I2S_CPOL = I2S_CPOL_Low; i2sInit.I2S_Mode = I2S_Mode_MasterTx; i2sInit.I2S_MCLKOutput = I2S_MCLKOutput_Enable; i2sInit.I2S_Standard = I2S_Standard_Phillips; i2sInit.I2S_AudioFreq = I2S_AudioFreq_48k; i2sInit.I2S_DataFormat = I2S_DataFormat_24b; I2S_Init(SPI2, &i2sInit); SPI2->I2SPR = (uint16_t)((uint16_t)512 | (uint16_t)12 | (uint16_t)1); //for 48k Fs SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); I2S_Cmd(SPI2, ENABLE);
код инициализации dma
DMA_InitTypeDef dmaInit; NVIC_InitTypeDef nvicInit; DMA_DeInit(DMA1_Stream4); DMA_Cmd(DMA1_Stream4, DISABLE); while(DMA_GetCmdStatus(DMA1_Stream4) == ENABLE)<>; __ISB(); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); //To dmaInit.DMA_PeripheralBaseAddr = (uint32_t) &(SPI2->DR); //From dmaInit.DMA_Memory0BaseAddr = (uint32_t)&AUDIO_SAMPLE; dmaInit.DMA_BufferSize = 20480; dmaInit.DMA_Channel = DMA_Channel_0; dmaInit.DMA_DIR = DMA_DIR_MemoryToPeripheral; dmaInit.DMA_PeripheralInc = DMA_PeripheralInc_Disable; dmaInit.DMA_MemoryInc = DMA_MemoryInc_Enable; dmaInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; dmaInit.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; dmaInit.DMA_Mode = DMA_Mode_Circular; dmaInit.DMA_Priority = DMA_Priority_High; dmaInit.DMA_FIFOMode = DMA_FIFOMode_Enable; dmaInit.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; dmaInit.DMA_MemoryBurst = DMA_MemoryBurst_Single; dmaInit.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; while(DMA_GetCmdStatus(DMA1_Stream4) == ENABLE); DMA_Init(DMA1_Stream4, &dmaInit); DMA_ITConfig(DMA1_Stream4, DMA_IT_TC | DMA_IT_HT, ENABLE); //configure interrupt nvicInit.NVIC_IRQChannel = DMA1_Stream4_IRQn; nvicInit.NVIC_IRQChannelPreemptionPriority = 0; nvicInit.NVIC_IRQChannelSubPriority = 0; nvicInit.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvicInit); DMA_Cmd(DMA1_Stream4, ENABLE); while(DMA_GetCmdStatus(DMA1_Stream4) != ENABLE)<>; AUDIO_SAMPLE просто wav скопированный через hex редактор и живущий в памяти контроллера, крутиться по кругу. Вроде как, в теории всё должно работать(снизу скрин из pulseview - снято логическим анализатором), к сожалению осциллограф пока что не приобрёл, так что проверить правильность частот не представляется возможнымб но всё же всё вроде как красиво.
Формат i2s на контроллере совпадает с форматом на цапе - первый бит передаётся через 1 тик sck после смены ws

П.С. подозреваю сразу вопросы про MSB/LSB - wav файл сам по себе little-endian, собственно как и контроллер, то есть тут не должно быть проблем, а i2s стандарт передаёт MSB первым, соответственно если у меня в памяти записано 0x64, 0x61, 0x61, 0x66, 0x02, 0x00, 0x85. то, судя по скрину всё передаётся правильно? или я что то не понимаю в этом всём? Но не в этом суть - в один момент тоже подумал что порядок не тот, но, к сожалению, попытки свапать байты местами(и побайтово, и по словам) не дали ни какого результата

Вливаюсь в среду программирования MBED OS с платой STM32F429I-DISC1 и вот что заметил:
1) Почему-то PWM у меня нормально заработал только на ножке PF_6. Я перебрал, конечно, не все порты, которые поддерживают работу с PWM, но другие, которые я попробовал, не заработали.
2) Пытался сконфигурировать некоторые порты в качестве цифрового выходи и тоже фигушки. Нормально заработали только те, что подключены к зеленому и красному светодиодам (PG_13 и PG_14). На некоторых ножках был какой-то неведомый мне меандр, какие-то не захотели переходить в низкоомное состояние.

В качестве базы я использовал код DISCO-F429ZI_LCDTS_demo (это из примеров по этой плате с работой ЖК индикатора и тачскрина).

Что может быть не так? Может быть какие-нибудь библиотеки, подключаемые при работе тачскрина и/или дисплея занимают большую часть портов и не позволяют их использовать по усмотрению программиста? Или я еще что-то не понимаю в архитектуре ARM? (Сам я прихожу из AVR-ов)


По SPI данные передаются байтами бит за битом, это обычный способ передачи данных, такой же как у USART'а или I2C. То есть для передачи одного бита нужен один условный такт, соответственно чтоб передать байт нужно сделать восемь тактов. В отличии от SPI, параллельная шина может «закидавать» в дисплей все восемь бит за один условный такт, где каждый бит «летит» по своему проводу. Такой способ подразумевает более высокую скорость передачи данных, но требует значительно большее количество пинов микроконтроллера.

Обычно эти дисплеи оснащаются ещё и тач-панелью, которая тоже работает по SPI. За работу «тача» отвечает отдельный чип, чаще всего это что-то вроде TSC2046 (буквы могут быть другие). И вот тут есть интересный момент.

Суть заключается в том, что в дисплей нам нужно передавать данные как можно быстрее (чтоб картинка быстрее отрисовывалась) , поэтому мы указываем максимально возможную скорость SPI (для BluePill это 18Мбит/с, какую максимальную скорость поддерживает сам дисплей я не знаю, вроде как до 50Мбит/с) . Тач-панель мы можем подключить к этому же SPI, а пинами CS (Chip Select) выбирать с чем мы сейчас работаем, с дисплеем или «тачем». Однако драйвер «тача» корректно работает только на скорости 1-2Мбит/с, если указать больше, то начинаются проблемы. Соответственно, если мы подключаем дисплей и «тач» к одному SPI, то нам нужно будет переключать скорость SPI прямо «на лету».

Другой вариант, это подключить дисплей и «тач» на разные SPI. С одной стороны кажется что так проще, но с другой, вам может понадобится флешка (подразумевается отдельный чип флеш-памяти) или SD карта для хранения изображений, и обе эти штуки тоже работают по SPI, а у BLuePill всего два таких интерфейса.

Чтоб было понятно, картинка в 16-ти битном цвете, размером во весь экран (320х240) весит 153600 байта. То есть ни о каком хранении её внутри простенького микроконтроллера и речи быть не может.

Следуя из выше сказанного, лучше всего подключить дисплей и «тач» на один SPI, так как они прекрасно уживаются вместе и не мешают друг другу при правильной организации программы, а второй SPI оставить для хранилища (флешка или SD карта), или ещё для чего-то.


Теперь к вопросу почему не стоит вешать на один SPI дисплей и хранилище. Дело в том, что процесс вычитывания с флешки/карты и вывод на дисплей занимают определённое время. Считывать данные из хранилища нужно по кусочкам, создав промежуточный буфер, например 10Кб (при условии что у BluePill всего 20Кб RAM, и какая-то часть из них нужна самой программе) , и сначала вычитывать в этот буфер данные, а потом отправлять его в дисплей. То есть со всеми накладными расходами, картинка на весь экран будет выводиться около 200мс, а это как вы понимаете 5 FPS

Исходя из выше сказанного, чтоб вывести данные хранящиеся в SPI-флешке на экран как можно быстрее, нужно во-первых, подключать хранилище и дисплей к разным интерфейсам, и во-вторых использовать DMA таким образом чтоб данные одновременно читались из флешки и отправлялись в дисплей. То есть заполняем половину буфера и начинаем её отправлять, пока первая половина отправляется, вторая заполняется, и т.д. В результате мы сможем получить максимально возможную скорость — картинка на весь экран будет выводится за

70 мс, что равно 14 FPS. Это относится к SPI-флешке, работа с SD-картой будет происходить дольше так как там используется FATFS, которая требует дополнительного времени.

Расчёты для работы с SPI-флешкой: при скорости SPI 18Мбит/с, за 1 мс можно передать 2250 байт, соответственно 153600 байт передастся за 68 мс (153600 / 2250 = 68), плюс 2 мс на накладные расходы. Ну и 1000мс / 70мс = 14 FPS.

Если картинка не на весь экран, то естественно она будет считываться и выводится быстрее, а значит мы получим больше FPS. Вот пример…


Зацикленный вывод тринадцати картинок размером 200х214. Каждая картинка выводится за 41 мс, то есть 24 FPS. Размер экрана 2.4".


Работа с флешкой или SD-картой будет описана не в этой статье, а в следующей. Всё выше сказанное сделано для того, чтоб объяснить как и почему нужно использовать интерфейсы SPI.

Подключение

У всех дисплеи разные поэтому перечислю те контакты дисплея, к которым будем подключаться. SPI (MOSI, MISO, CLK). CS (Chip Select) подача низкого уровня на этот контакт говорит о том, что мы собираемся работать с дисплеем (к шине SPI можно подключать множество устройств, и у каждого из них есть свой CS с помощью которого мы выбираем с кем собираемся общаться) . DC подача низкого уровня на этот контакт говорит о том, что мы собираемся отправлять в дисплей команду, а подача высокого уровня означает что мы будем слать данные. RST (RESET) сброс дисплея (всё это библиотека делает сама).

Помимо этого нужно конечно же подать питание, и включить подсветку. Подсветку можно сделать постоянную, а можно организовать регулируемую, через транзистор с помощью таймера в режиме ШИМ. Питание и подсветку я подавал от отдельного источника питания, то есть не от самой платы.


Тачскрин будем подключать к тому же SPI что и дисплей. У него есть свой CS, и контакт (называется что-то типа IRQ) на котором появляется низкий уровень во время нажатия. Этот контакт мы будем опрашивать в бесконечном цикле.

Конфигурация



Устанавливаем максимальную скорость SPI (18.0 MBits/s). Это для системной частоты 72Мгц. Если ваш камень допускает большую частоту, то можно попробовать увеличить скорость SPI, но сначала протестируйте на этой.


Если у вас нет тачскрина, тогда TOUCH_CS и IRQ не нужны. Пин IRQ настраиваем как GPIO_Input , остальные (кроме SPI) как GPIO_Output . Эти контакты можете назначить на удобные вам ножки, а названия нужно дать такие как нарисовано, тогда в библиотеке ничего не надо будет менять.

Названия вводятся в разделе GPIO…



User Label


И настраиваем USART для вывода инфы.

Подключаем всё, и если подсветка работает то переходим к кодингу.

Программа

Скачиваем библиотеку и добавляем в проект файлы:

ILI9341_GFX.c
xpt2046_touch.c
fonts.c

ILI9341_GFX.h
xpt2046_touch.h
fonts.h
img.h

Если тача нет, то xpt2046_touch.c и xpt2046_touch.h не нужны.

Номер SPI и пины задефайнены в файлах ILI9341_GFX.h и xpt2046_touch.h .


В main.c инклюдим…


Далее перед бесконечным циклом добавляем следующий код…


Всё это есть в примере, но тем не менее продублирую.

Здесь перечислены и прокомментированы все пользовательские функции, которые нужны для вывода текста, различных фигур, и картинок из внутренней памяти микроконтроллера.


Условимся что сейчас будем пользоваться экраном в горизонтальном положении. Если будете использовать экран в вертикальном положении, тогда нужно поменять местами значения ширины и высоты в файле ILI9341_GFX.h …

В этом же файле задефайнены другие цвета, и указан ресурс для создания своих.


В самом начале программы мы задали ориентацию зкрана…


Аргумент этой функции указывает от какого угла ведётся отсчёт начальных координат. В примере, в самом конце, это демонстрируется — начальные координаты у картинки и текста везде одинаковые, а угол от которого они начинаются меняется.



Собственно можно прошивать и смотреть что получилось. Если дошло до моего логотипа значит всё

Теперь по поводу функции вывода картинок из массива…

Она используется для вывода картинок хранящихся во внутренней памяти МК в виде массива. В частности мой логотип лежит в файле img.h и «весит» 12800 байт. Если вам не нужно много больших картинок, то можно создать их столько, сколько позволит объём флеш-памяти микроконтроллера, и обойтись без внешнего хранилища.

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


Конвертер

Чтобы из ваших картинок создавать массивы правильного формата, можно воспользоваться специальным онлайн-ресурсом…




Выберите файл, укажите Code format и Used for как на иллюстрации, и нажмите кнопку Get C string . Полученный массив вставьте в файл img.h вместо моего, впишите в функцию ширину и высоту вашего рисунка и пробуйте. Ширина и высота изображения будет написана там же на ресурсе, внизу.

Чтоб прикинуть размер будущей картинки, умножьте ширину на высоту, и умножьте это на 2 (картинка 16-ти битная, то есть на каждый пиксель два байта). На примере моего логотипа это выглядит так: 80 * 80 * 2 = 12800 байт.

Другие изображения можно так же добавлять в этот файл, только имена массивов меняйте.


Там же внизу можно скачать файл в бинарном виде — Download data will save the converted data as binary file. Этот файл можно использовать при работе с SD картой.


На тот случай, если ресурс окажется не рабочим, я создал свой онлайн-конвертер. Работает очень просто — выбираете файл, загружаете, и если всё хорошо, через несколько секунд (нужно время на обработку) появится кнопка «скачать». В скаченом архиве будут лежать бинарник, и заголовочный файл с массивом.

Так же в библиотеке есть папка Converter, в которой лежит PHP-скрипт для использования на своём компе (понадобиться установленный php7+). Пример использования…


После выполнения появятся описанные выше файлы.


Тачскрин

Тачскрин будем опрашивать в бесконечном цикле, точнее не тачскрин, а пин IRQ, который сигнализирует о нажатии. Перед бесконечным циклом добавьте несколько переменных…


А в цикл добавляем вот такой код…

Когда условие «если нажат тачскрин» сработает (пин IRQ выдаст низкий уровень), SPI переключится на меньшую скорость, функция ILI9341_TouchGetCoordinates(&x, &y) прочитает данные полученные от тачскрина, после чего SPI вернётся к изначальной скорости.

Важно! Если у вас какой-то другой камень, то посмотрите в Кубе какие нужно прописать делители — SPI_BAUDRATEPRESCALER_х .

Теперь можно прошить и потыкать в экран.


В USART и на экран будут выведены координаты нажатия. Это отладочная инфа, в дальнейшем её можно закомментировать. Там же приведён пример как пользоваться этими координатами. То есть, допустим вы рисуете какую-то кнопку на экране, тыкаете по углам этой кнопки, получаете координаты области, и прописываете их в условии — «если больше и меньше по Х, и больше и меньше по Y, тогда что-то делаем».

Условие «задержка до следующего нажатия» нужно чтоб данные не сыпались как сумасшедшие, типа защита от типа «дребезга».

Ну и «удержание кнопки» говорит само за себя, время удержания можно установить какое нужно. При этом ничего в цикле не тормозится. Короткое нажатие на эту кнопку ничего не делает. То есть это сделано не для того чтоб было два варианта действий на одной кнопке, а для защиты от случайного нажатия, вдруг у вас эта кнопка что-то типа "АЗ-5".


Сам по себе тачскрин в связке с чипом XPT2046 является банальным АЦП, и при нажатии выдаёт два 16-ти битных значения (по горизонтали и по вертикали), которые преобразовываются в функции ILI9341_TouchGetCoordinates() в координаты с помощью математических вычислений. В этой функции есть закомментированные строки, которые показывают эти значения. Получая их можно более точно определить края экрана (тачскрины то у всех разные) потыкав и подкорректировав цифры в файле xpt2046_touch.c …


Опытным путём разберётесь какое значение к какому краю относится. У себя я их округлил. Можно было бы сделать калибровку с крестиками по углам, но мне это делать не охота, да и необходимости особой нет.


На этом наверно пока всё, как говорилось выше, в следующей части речь пойдёт о хранении больших картинок на внешнем носителе и выводе их с помощью DMA.



Всем спасибо

Читайте также: