Пришло время обсудить замечательную функцию микроконтроллеров STM32 – а именно модуль FSMC. Это практически незаменимая вещь при работе с внешней памятью, либо, например, с графическим дисплеем. Собственно, с дисплеем то мы и будем экспериментировать...
Но для начала, как обычно, немного теории. Итак, FSMC реализует параллельный интерфейс обмена данными между различными устройствами. Короче говоря — просто параллельная шина. Используя FSMC при работе с внешней памятью, мы получаем возможность включить внешнюю память в адресное пространство микроконтроллера.
Что это дает? А то, что обращение к внешней памяти значительно упрощается — необходимо просто обращаться к ОЗУ микроконтроллера по определенным заданным адресам. То есть все ритуальные танцы с временными диаграммами, таймингами и прочим модуль FSMC берет на себя. Мы просто пишем данные по адресу — а FSMC дергает выводы, полностью осуществляя непосредственную работу с подключаемым устройством.
Схожим образом работает все это дело и при подключении дисплеев. Но все-таки тут все несколько иначе. Пусть у нас есть дисплей, у которого есть следующие выводы:
- DB[17:0] – 18 линий для передачи данных (не забываем, что тут у нас параллельная передача данных, а не последовательная).
- Также есть выводы для разрешения записи/чтения — туда мы должны выдавать строб-импульсы в определенной последовательности.
- Кроме того, у дисплея есть выводы chip select'а, reset и т. д.
И всем этим хозяйством нужно рулить ) Вот тут то нам и поможет FSMC. И не просто поможет, а всю работу возьмет на себя. Итак, пусть мы уже подключили дисплей как надо, как же нам теперь обращаться с дисплеем? А опять все очень просто. Точно также, как с внешней памятью, мы будем всего лишь пихать байты по определенному адресу. А FSMC будет в это время лихорадочно дергать линиями данных, следить за временными интервалами, передавать все остальные нужные дисплею сигналы. А чтобы разделить передачу данных и команд мы должны записывать байты по разным адресам. И тут же встает вопрос - а какие именно адреса, и чем они определяются.
У дисплея есть вывод для выбора — данные/команда. То есть по состоянию этого вывода дисплей решает, что именно сейчас к нему прилетит. А у FSMC есть шина адреса и шина данных. Так вот этот вывод дисплея подключается к какому-нибудь пину шины адреса. И если мы подключили его, например, к 16 выводу шины адреса, то записав какой-нибудь байт по любому(!) адресу с нулевым 16 битом мы подадим дисплею команду. Вот, смотрите, небольшой пример.
Пусть, как уже решили, подключен 16-й бит шины адреса. Берем адрес из доступных FSMC – 0x60000000. Видим, что в этом значении 16 бит равен нулю, а значит, когда мы запишем значение по этому адресу, FSMC подаст дисплею сигнал на запись, также сообщит дисплею, что сейчас будет команда, ну и, конечно же, выдаст на шину сами данные. А если мы запишем значение по адресу 0х60010000 (16-й бит — единица), то FSMC все разрулит и передаст дисплею данные. Вот так все просто )
Кстати, очень важный момент. В 16-битном режиме работы FSMC 16-й бит шины адреса соответствует 17-му биту адреса (то есть 0х60020000). Ну естественно, все остальные адреса также смещены на 1 бит в этом режиме.
По идее работа с дисплеем и с внешней памятью с точки зрения программиста выглядит одинаково, но на деле все не так. При работе с дисплеем никакая память никуда не "проецируется", мы условно пишем данные по адресам, но это всего лишь дает FSMC сигнал о том, что пора начинать действовать. Давайте переходить к делу.
Время традиционной вставки: поскольку компания STMicroelectronics прекратила поддержку библиотеки SPL, которая использовалась в этом курсе, я создал новый, посвященный работе уже с новыми инструментами, так что буду рад видеть вас там - STM32CubeMx. Кроме того, вот глобальная рубрика по STM32, а также небольшая подборка на смежную тему из нового курса:
- Подключение дисплея на базе ST7735 к микроконтроллеру STM32.
- Дисплей на базе ST7735 и STM32. Вывод изображения.
- Дисплей на базе контроллера SSD1306. Библиотека для STM32.
- STM32 и семисегментный индикатор. Динамическая индикация.
Для работы с FSMC будем по традиции использовать Standard Peripheral Library. Там все аналогично любой другой периферии, разве что настроек побольше. Так что об этом не будем особо разговаривать — лучше на практике при написании программы посмотрим как и что конфигурируется.
Итак, что у нас в плане железа... Испытывать FSMC я буду при помощи платы MiniSTM32 (про нее была уже статейка). Там уже установлен дисплей, так что никаких лишних телодвижений не потребуется. Вот как дисплей подключен:
Но вообще есть серьезные опасения, что китайцы нарисовали схему коряво, поскольку тут можно найти явно абсурдные вещи ) Вообще, если посмотреть на распиновку конкретного дисплея и на выводы FSMC микроконтроллера, то там очень хорошо видно, что они довольно точно соответствуют друг другу.
Итак, что же будем делать-то в качестве примера... Давайте разберемся как окрашивать дисплей в определенный цвет. Сначала зальем экран красным, потом зеленым и потом синим. Короче получить мы должны мигающий дисплей, на котором три цвета сменяют друг друга.
Данные будем передавать в 16-битном режиме.
- Красному цвету соответствует - 111111 000000 000000.
- Зеленому - 000000 111111 000000.
- Синему - 000000 000000 111111.
Как мы тут видим на 18 бит цвета приходятся 16 бит данных, в итоге получаем следующее:
- Для красного - 0xF800.
- Для зеленого - 0x07E0.
- Для синего - 0x001F.
Все очень просто, давайте напишем программу. Сразу скажу, шаманская инициализация дисплея взята из кошмарных китайских примеров программ, которые шли вместе с платой...
/***************************************************************************************/ #include "stm32f10x_gpio.h" #include "stm32f10x_fsmc.h" #include "stm32f10x_rcc.h" #include "stm32f10x.h" /***************************************************************************************/ // Определяем адреса, по которым будем записывать данные // Для записи данных #define LCD_DATA ((uint32_t)0x60020000) // Для записи команд #define LCD_REG ((uint32_t)0x60000000) /***************************************************************************************/ // Простенькая функция задержки // Для того, чтобы не нагружать пример здесь задержка сделана просто циклом, // но в "боевых" проектах, конечно же, всегда нужно использовать для этого таймеры void delay(uint32_t delayTime) { uint32_t i; for(i = 0; i < delayTime; i++); } /***************************************************************************************/ // Так мы будем писать команды в регистры LCD void writeLCDCommand(unsigned int reg,unsigned int value) { *(uint16_t *) (LCD_REG) = reg; *(uint16_t *) (LCD_DATA) = value; } /***************************************************************************************/ // А так данные void writeLCDData(unsigned int data) { *(uint16_t *) (LCD_DATA)= data; } /***************************************************************************************/ void initAll() { FSMC_NORSRAMInitTypeDef fsmc; FSMC_NORSRAMTimingInitTypeDef fsmcTiming; GPIO_InitTypeDef gpio; // Включаем тактирование портов RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE , ENABLE); // И тактирование FSMC RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE); // Инициализация пинов, задейстованных в общении по FSMC gpio.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.GPIO_Mode = GPIO_Mode_AF_PP; gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOD, &gpio); gpio.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.GPIO_Mode = GPIO_Mode_AF_PP; gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOE, &gpio); gpio.GPIO_Mode = GPIO_Mode_Out_PP; gpio.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOD, &gpio); // Здесь у нас Reset gpio.GPIO_Pin = GPIO_Pin_1; GPIO_Init(GPIOE, &gpio); // CS gpio.GPIO_Mode = GPIO_Mode_AF_PP; gpio.GPIO_Pin = GPIO_Pin_7; GPIO_Init(GPIOD, &gpio); // RS gpio.GPIO_Pin = GPIO_Pin_11; GPIO_Init(GPIOD, &gpio); // CS -> 1 // Reset -> 0 // RD -> 1 // RW -> 1 GPIO_SetBits(GPIOD, GPIO_Pin_7); GPIO_ResetBits(GPIOE, GPIO_Pin_1); GPIO_SetBits(GPIOD, GPIO_Pin_4); GPIO_SetBits(GPIOD, GPIO_Pin_5); // Настройка FSMC fsmcTiming.FSMC_AddressSetupTime = 0x02; fsmcTiming.FSMC_AddressHoldTime = 0x00; fsmcTiming.FSMC_DataSetupTime = 0x05; fsmcTiming.FSMC_BusTurnAroundDuration = 0x00; fsmcTiming.FSMC_CLKDivision = 0x00; fsmcTiming.FSMC_DataLatency = 0x00; fsmcTiming.FSMC_AccessMode = FSMC_AccessMode_B; fsmc.FSMC_Bank = FSMC_Bank1_NORSRAM1; fsmc.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; fsmc.FSMC_MemoryType = FSMC_MemoryType_NOR; fsmc.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; fsmc.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; fsmc.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; fsmc.FSMC_WrapMode = FSMC_WrapMode_Disable; fsmc.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; fsmc.FSMC_WriteOperation = FSMC_WriteOperation_Enable; fsmc.FSMC_WaitSignal = FSMC_WaitSignal_Disable; fsmc.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; fsmc.FSMC_WriteBurst = FSMC_WriteBurst_Disable; fsmc.FSMC_ReadWriteTimingStruct = &fsmcTiming; fsmc.FSMC_WriteTimingStruct = &fsmcTiming; FSMC_NORSRAMInit(&fsmc); FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); } /***************************************************************************************/ void initLCD() { // Глобальный Reset дисплея GPIO_ResetBits(GPIOE, GPIO_Pin_1); delay(0x0FFFFF); GPIO_SetBits(GPIOE, GPIO_Pin_1); delay(0x0FFFFF); // Пляски с бубном от китайских товарищей writeLCDCommand(0x0000,0x0001); delay(10); writeLCDCommand(0x0015,0x0030); writeLCDCommand(0x0011,0x0040); writeLCDCommand(0x0010,0x1628); writeLCDCommand(0x0012,0x0000); writeLCDCommand(0x0013,0x104d); delay(10); writeLCDCommand(0x0012,0x0010); delay(10); writeLCDCommand(0x0010,0x2620); writeLCDCommand(0x0013,0x344d); delay(10); writeLCDCommand(0x0001,0x0100); writeLCDCommand(0x0002,0x0300); writeLCDCommand(0x0003,0x1030); writeLCDCommand(0x0008,0x0604); writeLCDCommand(0x0009,0x0000); writeLCDCommand(0x000A,0x0008); writeLCDCommand(0x0041,0x0002); writeLCDCommand(0x0060,0x2700); writeLCDCommand(0x0061,0x0001); writeLCDCommand(0x0090,0x0182); writeLCDCommand(0x0093,0x0001); writeLCDCommand(0x00a3,0x0010); delay(10); // Настройки гаммы writeLCDCommand(0x30,0x0000); writeLCDCommand(0x31,0x0502); writeLCDCommand(0x32,0x0307); writeLCDCommand(0x33,0x0305); writeLCDCommand(0x34,0x0004); writeLCDCommand(0x35,0x0402); writeLCDCommand(0x36,0x0707); writeLCDCommand(0x37,0x0503); writeLCDCommand(0x38,0x1505); writeLCDCommand(0x39,0x1505); delay(10); // Включение дисплея writeLCDCommand(0x0007,0x0001); delay(10); writeLCDCommand(0x0007,0x0021); writeLCDCommand(0x0007,0x0023); delay(10); writeLCDCommand(0x0007,0x0033); delay(10); writeLCDCommand(0x0007,0x0133); } /***************************************************************************************/ int main() { initAll(); initLCD(); while(1) { int i; // Начальный и конечный адреса по горизонтали writeLCDCommand(0x0050, 0); writeLCDCommand(0x0051, 239); // Начальный и конечный адреса по вертикали writeLCDCommand(0x0052, 0); writeLCDCommand(0x0053, 319); writeLCDCommand(32, 0); writeLCDCommand(33, 0); *(uint16_t *) (LCD_REG) = 34; // Красный for (i = 0; i < 76800; i++) { writeLCDData(0xF800); } delay(0x0FFFFF); // Зеленый for (i = 0; i < 76800; i++) { writeLCDData(0x07E0); } delay(0x0FFFFF); //Синий for (i = 0; i < 76800; i++) { writeLCDData(0x001F); } delay(0x0FFFFF); } } /***************************************************************************************/
Магическое число 76800 - количество точек дисплея (320 * 240) . Все остальное вроде бы понятно, с настройками FSMC тоже ясно, как всегда в SPL все поля структуры названы логично и адекватно их функции.
После прошивки программы в контроллер дисплей начинает исправно подмигивать. Чего, собственно, и добивались, так что на этом все, скоро попробуем залить в дисплей какое-нибудь изображение.
Имеется похожая плата с таким же процессором. При сборке примера из статьи Keil выдает ошибки:
.\Obj\lcd_01.axf: Error: L6218E: Undefined symbol FSMC_NORSRAMCmd (referred from main.o).
.\Obj\lcd_01.axf: Error: L6218E: Undefined symbol FSMC_NORSRAMInit (referred from main.o).
В чем может быть дело?
Похоже, что файлы из SPL не добавлены в проект
Пример скомпилился, но дисплей к сожалению молчит. Сверю повнимательнее соответствие подключения. Хотя на Вашей схеме странности имеются...
Схема - это да, китайцы знатно поугорали когда ее рисовали ) Там даже сходу на глаз видно несколько абсолютно бредовых моментов.
А дисплей молчит скорее всего по простой причине - дисплей скорее всего другой, а значит все тайминги в настройках FSMC надо менять на соответствующие.
Ну и плюс инициализация естественно тоже у каждого дисплея своя
А какой контроллер у вас стоит на дисплее? у меня вот такая плата http://emproj.com/Alientek
Никак не могу понять какой там контроллер и где мне смотреть настройки для FSMC.
У меня, если не ошибаюсь - lgdp4532 стоит там.
А можно файлы проэкта получить?
Не могу понять, что за ошибки компиляции выдает компилятор
linking...
sdio.axf: Error: L6200E: Symbol __ARM_use_no_argv multiply defined (by sdio.o and main.o).
sdio.axf: Error: L6200E: Symbol __ARM_use_no_argv multiply defined (by sdcard.o and main.o).
sdio.axf: Error: L6200E: Symbol main multiply defined (by sdio.o and main.o).
sdio.axf: Error: L6200E: Symbol main multiply defined (by sdcard.o and main.o).
sdio.axf: Error: L6200E: Symbol writeBuffer multiply defined (by sdcard.o and sdio.o).
sdio.axf: Error: L6200E: Symbol readBuffer multiply defined (by sdcard.o and sdio.o).
sdio.axf: Error: L6200E: Symbol SDCardInfo multiply defined (by sdcard.o and sdio.o).
Target not created
Ну тут проблема явно в файлах для работы с картой, а у меня их в проекте нету совсем
Здравствуйте!
на строку
FSMC_NORSRAMInitTypeDef fsmc;
Ругается...
test.c(24): error: #268: declaration may not appear after executable statement in block
Нельзя в теле функций объявлять переменные после исполняемого кода
Еще ругается...
test.c(32): error: #20: identifier "RCC_AHBPeriph_FSMC" is undefined
Видимо, FSMC на другой шине
Хочу выразить огромную благодарность автору статьи. Для обучения - супер материал! У меня дисплейчик на контроллере ili9325, достаточно было поменять конфиг и таки заморгало разными цветами)
Можете помочь с инициализацией ili9325? Есть рабочий пример?
Спасибо.
Что-то я не понял. Как работает функции writeLCDCommand и writeLCDData ? Как данные из LCD_REG и LCD_DATA уходят в FSMC контроллер? Где связка?
Записываем данные по определенному адресу и модуль FSMC отправляет нужную команду
Попробовал запустить.
Зависает на строчке
*(uint16_t *) (LCD_DATA) = value;
на самой первой строчке инициализации. без нее проходит. При пошаговой отладке проходит по функци инициализации FSMC но регистры остаются пустыми (
А какой контроллер?
stm32f103vet6 на вот такой платке.
http://www.ebay.com/itm/STM32F103VET6-ARM-Cortex-M3-Board-2-4-Touch-TFT-LCD-/200609291886.
Тогда должно работать. Проверь, может что-то не так с тактированием.
Любобытно, но заработало послн того, как добавил строчку
fsmc.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
В инициализацию fsmc
Код работает до отключения питания. Если выключить-включить, то загорается просто белый дисплей, а программатор перестает видеть чип.
Error: Flash driver function execute error
Пока не замкнешь BOOT0 на VCC, программатор не хочет стирать чип. Это проблема именно моего контроллера или она встречается у всех?
Плата такая же точно.
Вполне вероятно, что попалась плата непропаянная. Китай есть китай..
Так это только в случае именно этого кода. Все остальные примеры и коды работают замечательно. Может ли быть битый флэш у микроконтроллера?
Ну тоже вполне возможно, точно помню, что на моей плате работало и после перезагрузки
Хм. Как ни странно, но заработало все после добавления этой строчки
fsmc.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
Волшебная строка какая-то)
Жесть ))))
Интересно, а можно ли заменить этот контроллер на аналогичный только из 4й серии? Перепаять в плате например на stm32f429/439
Ну у них распиновка то разная
А вы не подскажете, как работать со шрифтами с данным дисплеем? Например с hd44780 можно было просто выводить текст командой lcd_out. а тут я не пойму порядок обращения к массиву шрифтов и вывода его на экран. Шрифты взяты от ST
Я не пробовал, честно говоря, со шрифтами играться на этом дисплее..
А можно подключить 2 устройства (скажем, память и дисплей, как с I2C) к одному контроллеру или тут 1 контроллер --- одно устройство?
Скорее всего не прокатит несколько устройств подключать
Работаю в Keil с nor памятью в асинхронном мультиплексном режиме, настройки выставлял по мануалу, чтение проходит, но при записи уходит в прерывание HardFault_Handler, с чем это может быть связано?
Добрый день, что означает данная строчка?
Это указатель типа, а что означает первая звездочка?
*(uint16_t *) (LCD_REG) = reg;
LCD_REG - это адрес. Берем значение по адресу и записываем в него reg.
То что LCD_REG - адрес понятно.
Почему две звездочки - вопрос?
Так было бы понятно
uint16_t * (LCD_REG) = reg;
(uint16_t *) - приведение типа, а первая звездочка - берем значение по адресу )
Разобрался!!!
Добрый день!!! Подскажи пожалуйста что означает строчка
writeLCDCommand(32, 0);
writeLCDCommand(33, 0);
*(uint16_t *) (LCD_REG) = 34;
Интересует магическое число 34. В других местах тоже видел но чуть по другому LCD_REG_34. И еще в функции writeLCDCommand(32, 0); что за числа 32, 33. Как я понял эта первое число в функции должно быть код определенной команды и второе значение (например при инициализации writeLCDCommand(0x0012,0x0010);) а здесь получается другие числа?
Ну да, первое число - адрес регистра контроллера дисплея, второе число - значение.
У меня все сразу скомпилировалось, но отображается некорректно: картинка еле-еле смахивает на оригинальную и все строки разлетелись по сторонам., т.е. показывает, но хрен знает что. Второй день думаю что там может быть не так? У меня контроллер STM32f103ZE, дисплей TFT LCD Ilitec 320х240. Причем я пробовал при разных цветовых палитрах, и поворачивал картинку перед преобразованием в массив - все равно показывает одну и ту же муть.
Видимо при конвертации что-то пошло не так...
У меня на дисплее шрифты работают нормально: и позиционирует, и окрашивает в любой цвет, правда алфавит только английский (с цифрами и знаками препинания), могу скинуть файлы
У меня тоже подозрение что сам массив получается какой-то левый от той программы(Segger Bitmap converter for emWin, качнул с их сайта последнюю версию), причем у меня это мутное изображение еще и повторяется на дисплее, я так понял там 1000 причин может быть
С разными изображениями еще можно попробовать
Попробовал, у меня со всеми изображениями так, но я зашел на сайт Segger-а и там было написано что есть формат DIB (device independed format) и он как раз для того чтобы картинка отображалась корректно на всех дисплеях. Еще может быть (но маловероятно), что дело в компиляторе, например у меня GCC кокосовский. Обычно я делал так: открывал сгенерированный файл, брал из него только сам массив и у себя в коде пробегал в цикле этот массив функцией записи в GRAM (естественно после инициализации lcd) . Отпишу если все таки получится, у меня от этого только интерес вырос)
Aveal, я разобрался с дисплеем, хочу поделиться мыслями: в моем случае изображение было неправильным по 2 причинам:
Во-первых, у меня LCD работает на других настройках RGB палитры нежели в примере, т.е. при прорисовке изображения у меня даже цвета были не те (у меня палитра "565 red and blue swaped").
Во-вторых, я пытался отобразить изображения произвольного размера (как правило меньшего) и из-за этого у меня разъезжались строки в разные стороны и было похоже буд-то у меня изображение плодится по оси Х (по оси Y все рисуется нормально) . Как я понял надо перед отрисовкой задать адресный диапазон для GRAM, в рамках которого я должен пробегать циклом, чего я не делал, а сразу пошел бегать в цикле. И получалось что по оси X (0..240) у меня растягивалось изображение во всю ширь экрана - вот откуда разъехавшиеся полосы. Но как задавать область прорисовки я пока думаю....
Хорошо, что заработало в итоге)
Добрый день почему здесь не указывается режим и частота
// Здесь у нас Reset
gpio.GPIO_Pin = GPIO_Pin_1 ;
GPIO_Init(GPIOE, &gpio);
После настройки предыдущего порта в структуре сохранились нужные значения в полях.
Спасибо!!!
Не за что ))
Здравствуйте, Aveal! Скажите, возможно ли без особых сложностей подключить к STM32 ЖК панель с разрешением 1366x768 с интерфейсом LVDS?
Без особых сложностей точно нет ) Вообще наверно лучше это на ПЛИС реализовывать как мне кажется.
Из кода видно, что для отправки данных в параллельный порт дисплея используются: биты 0, 1, 4, 5, 6, 8, 9, 10, 14, 15 порта D и биты 7, 8, 9, 10, 11, 12, 13, 14, 15 порта E.
Каким волшебным образом эти биты выстраиваются в правильный порядок для отправки в параллельный порт дисплея? Куда, например, мапится на порт дисплея бит 14 порта D, а куда - бит 14 порта E?
Если мне, например, нужно использовать другие биты портов - где это перенастраивается?
Волшебства тут нет )
Это не просто какие-то выводы какого-то порта. Для подключения используется модуль FSMC. Например, PD14 - это сигнал D0 интерфейса FSMC, соответственно, подключаться этот сигнал должен к соответствующему выводу дисплея.
То есть, как я понял, это жёстко задано.
И если у меня плата с STM32 и плата с экраном стыкуются так, что (16 бит интерфейс) D0-D7 дисплея идут на PORTC(0..7), а D8..D15 - на PORTB(0..7) - то мне воспользоваться FSMC не судьба?
http://www.ebay.com/itm/-/400594146303 - вот такое чудо у меня из Китая.
Ну надо проверить на всякий случай по документации на контроллер, где именно у него FSMC, и есть ли возможность ремапинга.
Добрый день!
Как всё это дело заставить работать на 8-битной шине?
Заранее спасибо!
В настройках FSMC надо указать нужную ширину шины, по идее все остальное модуль уже сделает сам.
А как данные слать? Так же по 16бит, а FSMC будет сама их на пачки по 8 бит делить?
Не, по 8 и слать.
кто подскажет как работает выбор чип селекта в FSMC, настраиваю на первый банк в режиме NOR
Добрый день.
Непонятна работа функции, которая отправляет команду..
void writeLCDCommand(unsigned int reg,unsigned int value)
{
*(uint16_t *) (LCD_REG) = reg;
*(uint16_t *) (LCD_DATA) = value;
}
Что пишется в LCD_REG, а что в LCD_DATA?
По адресу LCD_REG пишется адрес регистра дисплея, а в LCD_DATA - значение, которое необходимо в этот регистр записать.
Спасибо.
У меня к STM подключен двухстрочный ЖК МЭЛТ, чтобы его инициализировать, надо отправить несколько команд.
Правильно понимаю, что команды можно отправить так:
*(uint16_t *) (LCD_REG) = 0x30;
LCD_REG определен как ((uint32_t)0x60000000)).
Ну зависит от того, какой интерфейс понимает дисплей.
Программирую на STM32F407
Как правильно подключить pin FSMC и дисплея
pin FSMC есть выводы:
NOE, NE1, NWE и LCD Register Select пусть будет A16 ->PD11
Дисплей имеет:
1 CS1 L Select Segment 1 ~ Segment 64
2 CS2 L Select Segment 65 ~ Segment128
3 Vss 0V Ground
4 VDD 5.0V Supply voltage for logic
5 VO (Variable) Operating voltage for LCD
6 D/I H/L H: Data , L: Instruction
7 R/W H/L H: Read(MPU Module) , L :Write(MPU→ Module)
8 E H Enable signal
9 DB0 H/L Data bus line
10 DB1 H/L Data bus line
11 DB2 H/L Data bus line
12 DB3 H/L Data bus line
13 DB4 H/L Data bus line
14 DB5 H/L Data bus line
15 DB6 H/L Data bus line
16 DB7 H/L Data bus line
17 RST L Reset the LCM
18 VEE Negative Voltage Output
19 A Power supply for B/L(+)
20 K Power supply for B/L(-)
К каким пинам FSMC подключать E, RW, D/I(RS) и RST?
Или E, RW, D/I(RS) и RST дергать в программе, а NOE, NE1, NWE и A16 ->PD11 (LCD Register Select) к дисплею не подключаются?