Подключение LCD на базе контроллера SSD1289, к STM32F4-Discovery используя FSMC

Давно обещал написать статью по применению LCD дисплея на базе контролера SSD1289 совместно с платой STM32F4-Discovery и используя параллельную шину FSMC. Здесь я просто выложу архив с библиотекой и небольшое описание, извините за неполноценную статью, последнее время было не до неё.

Описание
Для одного из своих проектов я решил использовать GUI от ST, а в качестве индикатора использовать LCD дисплей на контроллере SSD1289. При создании ПО за основу я взять библиотеку LCD для платы STM322xG (её можно найти в утилитах GUI) название файлов оставил оригинальным. На данной плате установлен более «традиционный» дисплей с контролером ILI9320(ILI9325), однако для управления используется та же параллельная шина FSMC. К счастью, по периферии контролеры STM32F2xx и STM32F4xx полностью совместимы. Небольшие изменения в инициализации периферии, в некоторых функциях, а также новая последовательность инициализации контроллера LCD, позволили довольно быстро запустить дисплей. Никаких аппаратных изменений на плате не потребовалось (в частности на двух ножках расположении светодиоды которые в принципе не мешают). Распиновка подключения дисплея к плате указана в файле main.h. Было несколько подводных камней, в частности из-за различий в регистрах LCD-контролеров потребовалось изменения во некоторых функций. Так же есть три функции, которые я не исправлял, кто захочет, сможет потренироваться (это фикции: LCD_PowerOn(); LCD_DisplayOn(); LCD_DisplayOff()). Вывод RESET дисплея можно подключить к выводу PC6, либо к общему сбросу платы NRST.

В архиве находятся следующие файлы:
stm322xg_eval_lcd.c,stm322xg_eval_lcd.h – собственно библиотека;
fonts.c, fonts.h – шрифты;
main.c, main.h – пример использования;
*.jpg – демонстрационные фото;
ILI9320.pdf, SSD1289.pdf – даташиты на исходный(для STM322xG) и используемый контролер LCD.

P.S.
У моего дисплея есть одна особенность. Когда после установки курсора на нужную координату, записывать данные содержащие более 14 логических единиц (например, белый цвет содержит все 16 единиц 0xFF), курсор передвигается, но данные не записывается и на экране отображается информация записанная ранее. Также если перед записью, например белого цвета, записать несколько пикселей с небольшим количеством единиц последующие белые пиксели будут отображаться. Кто-нибудь сталкивался с такой проблемой?

P.P.S.
На возникшие вопросы постараюсь ответить в комментариях.
  • 0
  • 18 марта 2012, 00:16
  • Linx_83

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

RSS свернуть / развернуть
… у меня почему то отображаются (в коллективных) две статьи с таким же названием?
0
Кто-нибудь сталкивался с такой проблемой?
… у меня примерно такая же херня с STM32. Завтра планирую поиграццо с дисплеем и имеются некоторые предположения. Мне кажется там следует использовать строгую очередность инструкций (DSB, ISB, DMB).
0
Непонятно почему не заливают архив сюда на сервер? Я вот уже пол часа немогу его взять с долбаного депозита…
+1
  • avatar
  • wowa
  • 18 марта 2012, 13:17
Наконец то! Спасибо! Правда уже почти сам разобрался. Но все равно есть еще кое-какие пробелы. Буду изучать.
0
Второй экземпляр загружен по ошибке в связи с перебоями в работе сети. Так как Коментарии можно оставлять только здесь это и будет основная статья.
0
Залейте пожалуйста архив сюда.
0
Непонятка с дисплеем — отображает информацию в вертикальной ориентации, а мне нужно в горизонтальной.
Крутил-вертел параметры (ID[1:0] и AM) регистра Entry Mode (R11h), вообще не влияет на отображение. Что инициализация write_com( 0x0011,0x60F8 ), что write_com( 0x0011,0x6000 ) не дают никакой разницы.
Нужно чтото включить чтобы управлять порядком инкремента строк/столбцов? Не пойму почему параметры не влияю на отображение?
0
Разобрался — я координаты принудительно из программы задавал… Параметр работает нормально
0
большой минус — нет кириллицы
0
А что… должна быть??? ))))))))
0
Я правильно понял — я должен в кейле добавить в проект три файла, main.c, fonts.c, и stm322xg_eval_lcd.c?
я так сделал, у меня куча ошибок выводится(
main.c(45): warning: #223-D: function «LCD_Init» declared implicitly
вот это я не очень понял… в инете пишут что функция не объявлена явно(
stm322xg_eval_lcd.c(102): error: #20: identifier «GPIO_InitTypeDef» is undefined
это наверное для какого-то другого компилятора писалось, да?
там еще много ошибок, но мне кажется что все из-за второй.
как можно исправить?
заранее спасибо)
0
Очевидно, что у тебя не подключен заголовочный файл #include «stm32f4xx_gpio.h»
0
просто, на всякий случай — я правильно делаю?
в папку с проектом кидаю файлы stm32f4xx_gpio и stm32f4xx_rcc с расширениями .h и .c и файлы которые .c добавляю в проект.
но ошибка все равно выходит(
что я неправильно делаю?
0
Кроме Вами перечисленных необходимо добавить файлы stm32f4xx.h и stm32f4xx_conf а в настройках проекта закладка С/С++ в строке Define указать определение USE_STDPERIPH_DRIVER.
0
добавил, спасибо. кстати, не посоветуете, где можно почитать, как все подключать, настраивать, и т.п.?
Выдает:
main.c(45): warning:  #223-D: function "LCD_Init" declared implicitly
LCD_1289.axf: Error: L6218E: Undefined symbol FSMC_NORSRAMCmd (referred from stm322xg_eval_lcd.o).
...еще несколько ошибок, связанных с FSMC...
LCD_1289.axf: Error: L6218E: Undefined symbol LCD_Init (referred from main.o).
0
Лучше всего в общении с другими программистами, коллегами, ну а если самостоятельно, при наличии небольшого опыта, очень помогают готовые проекты, например стандартные проекты-примеры от ST и того-же keil и IAR
0
Не могли бы вы мне подсказать, как подключить эту библиотеку в Keil?
Или подкинуть ссылки, где написано как правильно подключать библиотеки…
Заранее спасибо)
0
выдает ошибки:
stm322xg_eval_lcd.h(60): error: #256: invalid redeclaration of type name «Point» (declared at line 60)
stm322xg_eval_lcd.h(60): error: #256: invalid redeclaration of type name «pPoint» (declared at line 60)
я не могу найти, где эти типы переопределяются. не подскажете?
0
Всем привет! Как раз сейчас пытаюсь завести LCD на stm32f103vet. Столкнулся с проблемой: FSMC совсем не хочет работать. То есть при настройке этой периферии его регистры не изменяются, и даже не равны своим reset value. Известная тема: нужно подать тактирование, но оно подается — перед настройкой выполняю RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);, в соответствующем регистре RCC появляется нужный бит. Проблема в том, что попытка считать что-то из области памяти, за которую отвечает fsmc, приводит к хард-фолту. Может, я еще что-то упустил перед настройкой fsmc? Использую CoIDE, регистры смотрю через jtag отладчик olimex.
0
  • avatar
  • j3v
  • 29 июля 2012, 23:38
код в студию, ептыть. Вариантов собственно немного — проинитил не тот банк, забыл включить, накосячил с ножками.
0
С железом косяк исключен — использую готовую плату stm32-mini, у нее демо-прошивка вполне с экраном дружила.
void LCD_CtrlLinesConfig(void)
		{
			GPIO_InitTypeDef GPIO_InitStructure;

			/* Enable GPIOD, GPIOE, GPIOF, GPIOG and AFIO clocks */

			RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
					RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
					RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
					RCC_APB2Periph_AFIO, ENABLE);

			/* Set PD.00(D2), PD.01(D3), PD.04(NOE), PD.05(NWE), PD.08(D13), PD.09(D14),
     	 	 PD.10(D15), PD.14(D0), PD.15(D1) as alternate
     	 	 function push pull */
			GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
					GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 |
					GPIO_Pin_15;
			GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
			GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
			GPIO_Init(GPIOD, &GPIO_InitStructure);

			/* Set PE.07(D4), PE.08(D5), PE.09(D6), PE.10(D7), PE.11(D8), PE.12(D9), PE.13(D10),
     	 	 PE.14(D11), PE.15(D12) as alternate function push pull */
			GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
					GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
					GPIO_Pin_15;
			GPIO_Init(GPIOE, &GPIO_InitStructure);

			/* Set PD.11(A16 (RS)) as alternate function push pull */
			GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
			GPIO_Init(GPIOD, &GPIO_InitStructure);

			/* Set PD.07(NE1 (LCD/CS)) as alternate function push pull - CE3(LCD /CS) */
			GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
			GPIO_Init(GPIOD, &GPIO_InitStructure);

			GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
			GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
			GPIO_Init(GPIOD, &GPIO_InitStructure);

			GPIO_WriteBit(GPIOD, GPIO_Pin_13, Bit_SET);

			GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
			GPIO_Init(GPIOE, &GPIO_InitStructure);

			GPIO_SetBits(GPIOD, GPIO_Pin_7);			//CS=1
			GPIO_SetBits(GPIOD, GPIO_Pin_14| GPIO_Pin_15 |GPIO_Pin_0 | GPIO_Pin_1);
			GPIO_SetBits(GPIOE, GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10);
			GPIO_ResetBits(GPIOE, GPIO_Pin_0);
			GPIO_ResetBits(GPIOE, GPIO_Pin_1);			//RESET=0
			GPIO_SetBits(GPIOD, GPIO_Pin_4);		    //RD=1
			GPIO_SetBits(GPIOD, GPIO_Pin_5);			//WR=1

		}

		/**
		 * @brief  Configures the Parallel interface (FSMC) for LCD(Parallel mode)
		 * @param  None
		 * @retval : None
		 */
		void LCD_FSMCConfig(void)
		{
			RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

			FSMC_NORSRAMDeInit(FSMC_Bank1_NORSRAM1);

			FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
			FSMC_NORSRAMTimingInitTypeDef  p;

			/*-- FSMC Configuration ------------------------------------------------------*/
			/* FSMC_Bank1_NORSRAM4 timing configuration */
			p.FSMC_AddressSetupTime = 2;
			p.FSMC_AddressHoldTime = 0;
			p.FSMC_DataSetupTime = 5;
			p.FSMC_BusTurnAroundDuration = 0;
			p.FSMC_CLKDivision = 0;
			p.FSMC_DataLatency = 0;
			p.FSMC_AccessMode = FSMC_AccessMode_B;

			/* FSMC_Bank1_NORSRAM4 configured as follows:
        - Data/Address MUX = Disable
        - Memory Type = SRAM
        - Data Width = 16bit
        - Write Operation = Enable
        - Extended Mode = Disable
        - Asynchronous Wait = Disable */
			FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
			FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
			FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;
			FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
			FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
			FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
			FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
			FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
			FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
			FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
			FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
			FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
			FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
			FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;

			FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

			/* Enable FSMC_Bank1_NORSRAM4 */
			FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
		}
0
И к какому адресу в итоге обращаешься?
0
Обращаюсь за данными к адресу 0x6002 0000: для RS использую линию A16 — смещение 0х20000; банк 1-й (так как NE1) — базовый адрес 0х6000 0000. Адрес видеопамяти, соответственно, передаю по базовому адресу без смещения. При передаче адреса все ок, а вот при попытке что-то считать с 0х6002 0000 микруха зависает.
Кстати, по адресу регистров настройки fsmc — это начиная с 0xA000 0000, все совершенно пусто: как после подачи тактирования, так и после «деинита» и инициализации. Все-таки, грешу на не запустившийся почему-то fsmc (потому что при этом другие регистры в окне просмотра памяти видно, как настроены). Попробую сегодня на работе платку в IARе поковырять.
0
Итак, вести с полей! Попробовал скомпилировать и запустить этот код с другим тулчейном — вместо CoIDE с GNU-ARM компилятором и OLIMEX ARM-TINY-USB-H в качестве отладчика дома, использовал IAR EWARM 6.3 на работе и MT-Link. Проблема исчезла. Странно и интересно, в чем же дело и что не так может быть с кокосом? Есть у народа идеи?
0
Йеее, я наконец то запустил!) все работает отлично, кроме одного момента: если поставить цвет текста черный, а фона — белый, то на экран выводится мусор( почему так?
0
  • avatar
  • Ledzz
  • 03 августа 2012, 11:35
я буду внимательно читать пост. я буду внимательно читать пост. я буду внимательно читать пост.
а как картинку вывести на дисплей? и как ее в мк запихать?
0
картинку преобразовать в массив данных (16-битный режим используете? Два байта = 1 пиксель), массив забить лучше всего, конечно, во внешнюю флэш — ибо много места занимает. Выводить последовательно в нужный момент. Все несложно. =)
0
Вам удалось решить проблему с 14-ю логическими единицами?
0
  • avatar
  • rius
  • 20 сентября 2012, 14:11
Нет, но в своем проекте я переделал механизм записи данных с посылки одного слова (режим 16бит) в посылку по два слова (режим 18бит), в принципе проблема решилась, в данном режиме эффект отсутствует!
0
Понятно, тоже выход)
Я вместо белого могу почти белый передавать, но причина такого поведения контроллера больше интересует.
Такое впечатление, что иногда данные воспринимаются как команда. Но при цвете 0xffff вероятность этого события значительно увеличивается.
0
Обнаружил, что эффект (в режиме 16 бит) также устраняется добавлением команды Write Data to GRAM (R22h) перед записью каждой точки.
0
Можно подробнее про режим 18 бит, у дисплея ведь 16 линий данных?
0
Обнаружил, что эффект (в режиме 16 бит) также устраняется добавлением команды Write Data to GRAM (R22h) перед записью каждой точки

Write Data to GRAM (R22h) это как выполнить, пишу через SMFC?
0
Возникла проблема с дисплеем, никак не получается избавится, возможно ктото сталкивался.
Не работает маска в дисплее.
Командой «write_com(0x0023,0xFСFС);» задается маскировка зеленого и красного канала на запись. Проблема в том что младший байт никак не влияет на отображение на дисплее (т.е. при записи маски от FF00 до FFFF зеленый и красный каналаы полностью замаскированы, хотя 0xFF00 должен размаскировать зеленый канал полностью.)
Старший байт работает, но маскирует одновременно красный и зеленый каналы одинаково Вообще непонятно ничего.
Командой «write_com(0x0024,0x00FF);» маскируется синий канал и тут все работает нормально. В остальном дисплей полностью функционирует (отображает графику, текст, задает область рабочего окна)
0
А как организовать режим 8 ьбит? У меня есть пара таких только www.ebay.com/itm/251253811021?ssPageName=STRK:MEWAX:IT&_trksid=p3984.m1423.l2649
Но у них нет адресных выводов 8 и 9
0
Ребят, я вот не пойму, а где можно скачать оригинал библиотеки на данный дисплей (или не оригинал на STM32)? У меня сзади написано TFT_320QVT, контроллер ssd1289. Наверное я после работы сильно устал и не могу найти, только кидает по ссылкам по кругу… уже кумарит…
0
Я брал оригинальную библиотеку здесь, она вполне рабочая.
0
Огромное спасибо!!! ;)
0
Вы указали «ILI9320(ILI9325)». Эти контроллеры (ILI9320 и ILI9325) идентичны?
0
P.S. У моего дисплея есть одна особенность. Когда после установки курсора на нужную координату, записывать данные содержащие более 14 логических единиц (например, белый цвет содержит все 16 единиц 0xFF), курсор передвигается, но данные не записывается и на экране отображается информация записанная ранее. Также если перед записью, например белого цвета, записать несколько пикселей с небольшим количеством единиц последующие белые пиксели будут отображаться. Кто-нибудь сталкивался с такой проблемой?

Есть у меня смутные сомнения, пока не подтвержденные, что дело в STM32F4Discovery — так как я подключал два разных дисплея и у обоих были проблемы, у одного точно такая же, у другого не совсем такая. Пока проблему не решил, ковыряюсь.
Костыль для описанного в статье случая сделал пока очень просто — маскировал все определения цветов так, чтобы самые младшие разряды всех трех цветов были нулевыми, тем самым уменьшив количество выводимых цветов до 2^(4х4х4) = 4096, что в общем-то для графического интерфейса вполне хватает. Вот например определение какого-то произвольного цвета BURDA:
#define BURDA (0xFFFF & 0xF79E)

При этом не нужно уходить на восьмибитную шину или дописывать какие-то команды.
А проблему все еще исследую, получится — поделюсь.
0
Поясню, 0xFFFF — цвет (в данном случае белый), 0xF79E — маска, годится для любого цвета.
0
Опечаточка вышла, конечно же 2^(4+4+4).
Проблему со вторым дисплейчиком решил, виноват был я сам с неправильными настройками SSD1963. Так что может быть Discovery и не при чем.
Тогда вопрос к автору темы, какой дисплейчик используете? У меня это вот такая красная платочка:

Симптомы точно такие же, нормально выводятся цвета с максимумом 14 единиц в слове.
0
Что-то я конкретно запутался. Почему-то ни слова не могу найти про FSMC в документации на stm32f401. Искал в даташите и референс мануале. Они название как-то поменяли? Или я не там ищу?
0
А может FSMC просто нет в младших моделях STM32F4xx? Насколько мне помнится, нет… проверьте на сайте ST
0
Да вот на плате дискавери, для которой сделана эта библиотека, стоит тот же stm32f401. При чём стоит как раз таки один из младших. Странно всё это, т.к. на сайте st в разделе этого контроллера даже в аппноутах есть упоминание о FSMC. Правда описывается там f103, но всё равно не зря ж они это туда пихнули.
0
Еще корпус посмотри. В корпусах меньше 100 выводов FSMC, вроде, нет. По крайней мере в 103/105/107 именно так.
0
Опа, это я тупанул. На дискавери оказывается STM32F407 стоит. Вот там уже всё есть. Спасибо за ответы!
0
Привет всем! Если ещё актуальна проблема с 14-ю логическими единицами, то вот
возможное решение. При инициализации FSMC я изменил время установки адреса
FSMC_AddressSetupTime с 6 на 0, а время установки данных FSMC_DataSetupTime
— уменьшил с 6 до 3-х.
Теперь отображается нормально.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.