Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 17:05:51

Всем привет.
Есть дисплей 480х320 на ili9486 с параллельным 16 битным интерфейсом. Дисплей подключен к платке stm32f411.Прога для управления дисплеем написана без использования библиотек,просто на порты стм подключенные к дисплею выводятся нужные данные.Код с настройками портов стм и функцией отправки данных на дисплей приведен ниже.В данный момент использую только первые 8 бит шины из 16,для простоты эксперементов.

Код:
//Настройка портов

#define RCC 0x40023800                       

#define RCC_AHB1ENR ((volatile uint32_t *)(RCC+0x30)) 
#define GPIOA 0x40020000
#define GPIOA_MODER ((volatile uint32_t *)(GPIO+0x00)) 

#define GPIOA_ODR ((volatile uint32_t *)(GPIO+0x14)) 

#define GPIOB 0x40020400
#define GPIOB_MODER ((volatile uint32_t *)(GPIOB+0x00)) 

#define GPIOB_ODR ((volatile uint32_t *)(GPIOB+0x14)) 

  *RCC_AHB1ENR=3;         //Подключаем А ,В
*GPIOA_MODER=349525;  //Пины общего назначения выходы
*GPIOA_MODER=349525;  //Пины общего назначения выходы


*GPIOA_ODR=0;
*GPIOB_ODR=0;
delay(50);
*GPIOB_ODR=1;

//////////




Код:
//Функция отправки посылок

void LCD_Write(char DATA1,char TIP1 ){
*GPIOA_ODR=DATA1;
if(TIP1==1)*GPIOB_ODR=1;else *GPIOB_ODR=9; //Если 1 то команда,если 0 то данные (Устанавливаем лог уровень на пин дисплея данные/команда )

 delayMicroseconds(400);
if(TIP1==1)*GPIOB_ODR=5;else *GPIOB_ODR=13;//Если 1 то команда,если 0 то данные (Устанавливаем лог1 на пин записи с учетом выбора данные/команда)

delayMicroseconds(400);
 *GPIOB_ODR=1; //Устанавливаем лог 0 на пин записи

delayMicroseconds(400); 

  }




На порте А висит шина данных дисплея 8 бит,на порте В управляющие пины rst.cs,wr,rs.
Основной код,это просто многократный вызов функции LCD_Write с необходимыми аргументами.
В общем в данный момент дисплей проходит инициализацию,далее командами Column Address Set и Page Address Set выделяю область куда выводить данные,затем командой Memory Write зажигаю пиксели выделенной области.
В итоге дисплей отрисовывает пиксели. Проблема заключается в том,между командами в функции обязательно должна быть пауза не менее 400микросек,иначе дисплей не реагирует на команды,то есть если в вот в функции LCD_Write паузы установлены на 400 -все нормально работает,рисуються пиксели но медленно,если же просто заменить значение 400 на например 200 ничего не работает вообще.В чем проблемма?
Последний раз редактировалось alkis3 Ср май 18, 2022 17:09:18, всего редактировалось 1 раз.

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 17:09:14

Нострадамлю жуткий говнокод, где адов ногодрыг (функция delayMicroseconds - тому подтверждение) наобум.
Если нет нормального параллельного интерфейса, его можно эмулировать при помощи DMA! По таймеру пинать - чтобы был четкий тайминг. Ну элементарно же это делается!..

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 17:16:51

Можно пример какой нибудь ,ну где почитать про то что вы говорите?Суть в том что я с стм что либо делать начал только 5 дней назад

Добавлено after 1 minute 54 seconds:
И если не трудно,скажите в чем именно причина того ,что в этом коде обязательно нужны такие паузы?Там чтото не поспевает или что?

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 17:28:08

#define GPIOA 0x40020000
*GPIOA_MODER=349525;

:)))
Ну и не надо попиксельно точками рисовать. Поставьте размер окна хотябы 100х100, а лучше 200х200 пикселей и выводите в это окошко картинку из внутреннего буфера в SRAM. Хотя конечно для такого микроконтроллера такого размера дисплей - тут немудренно, что черезопно будет.
Ну и мануал на дисплей прочтите, на стр.298


я с стм что либо делать начал только 5 дней назад

Я 5 дней на СТМке светодиодами мигал и таймеры крутил, а вы сразу прям за дисплей исполинских размеров принялись. Оттого и получается, что управление пинами не освоили и не изучили структуру заголовочника CMSIS, вы пытаетесь передефайнить уже существующие определения и сотворить дикую дичь. Начинать надо с простого, помаленьку. Понимаю, что хочется сразу дисплей, буковки-циферки, большой термометр с интернет-погодой, но.... Но надо начинать с начала, с азов. Все так делали, потому и ошибок в базовых познаниях не допускают.

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 17:44:09

Код:
  *RCC_AHB1ENR=3;         //Подключаем А ,В
*GPIOA_MODER=349525;  //Пины общего назначения выходы
*GPIOA_MODER=349525;  //Пины общего назначения выходы

В последней строке наверно GPIOB_MODER должно быть?

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 20:05:22

По поводу пинов.Я кодю сейчас в среде ардуино иде,там в общем то есть другой,более простой и наверное грамотный способ выведение инфы на пины.Если допустим выводить значения им,то тогда что то измениться?

Добавлено after 2 hours 4 minutes 2 seconds:
Да в последней написано В в коде

Добавлено after 16 minutes 10 seconds:
Вижу мануал,скорость работы портов очень высокая..Тогда опять таки вопрос почему работает только при наличии этих огромных пауз?
То есть на сколько я понимаю дело не в стм контроллере по сколько во время паузы он тупо ничего не делает, подключение к дисплею верное иначе бы он вообще ничего никогда не выводил ни с паузами ни без,в мануале видно что по скорости дисплей должен справляться..так в чем же может быть причина?

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 20:11:28

Подключите логический анализатор и/или осциллограф, сравните что происходит на шине с тем что нарисовано в даташите.

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 21:10:35

alkis3 писал(а):Есть дисплей 480х320 на ili9486 с параллельным 16 битным интерфейсом.

Посмотри как получилось, и перепиши под свою задачу
Спойлер
Код:
#define GPIO_Pin_0    (uint16_t) 1
#define GPIO_Pin_1    (uint16_t) 1<<1
#define GPIO_Pin_2    (uint16_t) 1<<2
#define GPIO_Pin_3    (uint16_t) 1<<3
#define GPIO_Pin_4    (uint16_t) 1<<4
#define GPIO_Pin_5    (uint16_t) 1<<5
#define GPIO_Pin_6    (uint16_t) 1<<6
#define GPIO_Pin_7    (uint16_t) 1<<7
#define GPIO_Pin_8    (uint16_t) 1<<8
#define GPIO_Pin_9    (uint16_t) 1<<9
#define GPIO_Pin_10   (uint16_t) 1<<10
#define GPIO_Pin_11   (uint16_t) 1<<11
#define GPIO_Pin_12   (uint16_t) 1<<12
#define GPIO_Pin_13   (uint16_t) 1<<13
#define GPIO_Pin_14   (uint16_t) 1<<14
#define GPIO_Pin_15   (uint16_t) 1<<15



///  контакты управления дисплеем ( обязательно на одном порту)
#define SETPIXSEL__CE       GPIO_Pin_2
#define SETPIXSEL__WR       GPIO_Pin_7
#define SETPIXSEL__RS       GPIO_Pin_9
#define SETPIXSEL__RD       GPIO_Pin_6
#define SETPIXSEL__read       GPIOE->CRL=0x44444444;GPIOE->CRH=0x44444444
#define SETPIXSEL__record   GPIOE->CRL=0x33333333;GPIOE->CRH=0x33333333

/// имя порта для жк индикатора
#define GPIO_SETPIXSEL      GPIOE->ODR
#define GPIO_READPIXSEL     GPIOE->IDR
#define GPIO_SETcontrol     GPIOB->BSRR

#define SETPIXSEL_all       (uint32_t)( SETPIXSEL__RD | SETPIXSEL__RS | SETPIXSEL__WR | SETPIXSEL__CE )
#define SETPIXSEL_ce_rs     (uint32_t) (( SETPIXSEL__CE | SETPIXSEL__RS ) << 16) | (SETPIXSEL_all ^ ( SETPIXSEL__CE | SETPIXSEL__RS ))
#define SETPIXSEL_ce_rs_wr  (uint32_t) (( SETPIXSEL__CE | SETPIXSEL__RS | SETPIXSEL__WR ) << 16) | (SETPIXSEL_all ^ ( SETPIXSEL__CE | SETPIXSEL__RS | SETPIXSEL__WR ))
#define SETPIXSEL_ce        (uint32_t) (( SETPIXSEL__CE ) << 16) | (SETPIXSEL_all ^ ( SETPIXSEL__CE ))
#define SETPIXSEL_ce_wr     (uint32_t) (( SETPIXSEL__CE | SETPIXSEL__WR ) << 16) | (SETPIXSEL_all ^ ( SETPIXSEL__CE | SETPIXSEL__WR ))
#define SETPIXSEL_ce_rd     (uint32_t) (( SETPIXSEL__CE | SETPIXSEL__RD ) << 16) | (SETPIXSEL_all ^ ( SETPIXSEL__CE | SETPIXSEL__RD ))

#define RGB(Pr,Pg,Pb)   ((uint16_t) (((Pr >> 3) << 11) | ((Pg >> 2) << 5) | (Pb >> 3)))


__attribute__( ( always_inline ) ) static inline void delay( uint32_t volatile time_tmp){do {time_tmp--;} while ( time_tmp );};

void setReg (uint16_t re,uint16_t se)
{
    GPIO_SETcontrol = SETPIXSEL_ce_rs_wr;
   GPIO_SETPIXSEL = re ;
   GPIO_SETcontrol = SETPIXSEL_ce_rs;
   GPIO_SETcontrol = SETPIXSEL_ce_wr;
   GPIO_SETPIXSEL = se ;
   GPIO_SETcontrol = SETPIXSEL_ce;
   GPIO_SETcontrol = SETPIXSEL_all;
};




/// рисуем цветную точку
void setPixel (uint16_t x, uint16_t y, uint16_t RGB)
{
   GPIO_SETcontrol = SETPIXSEL_ce_rs_wr;
   GPIO_SETPIXSEL = 0x0200;
   GPIO_SETcontrol = SETPIXSEL_ce_rs;
   GPIO_SETcontrol = SETPIXSEL_ce_wr;
   GPIO_SETPIXSEL = x;
   GPIO_SETcontrol = SETPIXSEL_ce;
   GPIO_SETcontrol = SETPIXSEL_ce_rs_wr;
   GPIO_SETPIXSEL = 0x0201;
    GPIO_SETcontrol = SETPIXSEL_ce_rs;
   GPIO_SETcontrol = SETPIXSEL_ce_wr;
   GPIO_SETPIXSEL = y;
   GPIO_SETcontrol = SETPIXSEL_ce;
    GPIO_SETcontrol = SETPIXSEL_ce_rs_wr;
   GPIO_SETPIXSEL = 0x0202;
   GPIO_SETcontrol = SETPIXSEL_ce_rs;
   GPIO_SETcontrol = SETPIXSEL_ce_wr;
   GPIO_SETPIXSEL = RGB;
   GPIO_SETcontrol = SETPIXSEL_all;
};

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 21:28:46

Это я к тому, что вместо ODR=5; ODR=9, ODR=1 можно же изучить возможности микроконтроллера по раздельному управлению ногами, не затрагивая соседние ноги. Или хотябы на худой конец узнать, что у языка Си есть логические операции AND и OR для влияния только на один бит.
Возможно, что-то накосяпорено с порядком переключений ног. Возможно, косяки в настройке дисплея.

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 22:54:44

Про то как выводить на отдельные пины мне известно,но для простоты кода,чтоб он небыл громозким я сделал вывод сразу на весь порт.
Ну вроде все нормально с переключением ,сейчас переписал функцию чтоб пины дергались строго в той последовательность как на диаграмме в даташите.В итоге у меня получилось 5 пауз не короче чем по 150 микросек.
Есть предположение,что медлительность дисплея вызвана тем,что изображение я в него вывожу попиксельно командами которые сразу эти пиксели выбрасывают на экран.Может быть такая штука ,что контроллер дисплея не готов принимать данные пока он их не проявит на экране или чтото типа того..? То есть допустим еслиб скажем изначально я загнал данные всех пикселей в какойто буфер дисплея,а потом послал ему команду все это вывести на экран, получилось бы гораздо быстрее.Но такой команды я в даташите не нашел что то..И опять же,верно или нет мое опасение не понятно..

Добавлено after 34 minutes 39 seconds:
Хотя нет, инициализация с маленькими паузами тоже не происходит,так что вывод пикселей тут не причем

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 22:57:10

Медлительность связана с тем, что вначале передаются 10 байт координат окна вывода размером в 1 пиксель, затем передается байт команды записи данных и только потом два байта пиксельного цвета. Фактически, в 11 раз медленнее. А если установите окно вывода размерами хотябы в 50х50 пикселей (команда установки начального и конечного столбца и команда установки начальной и конечной строки), затем передатите команду записи пиксельных данных и потом из буфера SRAM последовательно передадите 2500 пикселей, то скорость будет гораздо выше.

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 23:21:28

У меня установлено окно размером 100 на 100,вот код.

Код:


int x1=1,x2=100,y2=1,y3=100;
 //////////////////////////

 LCD_Write(0x2a,0);
 LCD_Write(x1>>8,1);
  LCD_Write(x1,1);
  LCD_Write(x2>>8,1);
  LCD_Write(x2,1;
  LCD_Write(0x2b,0);
  LCD_Write(y2>>8,1);
  LCD_Write(y2,1);
  LCD_Write(y3>>8,1);
  LCD_Write(y3.1);
 
  LCD_Write(0x2c,0); 
//////////////////////


Речь об этом?

Из буфера стм32 вы имеете в виду?Если да,то я практически так и делаю,не совсем так,а вот так

Код:
for(v=0;v<10000;v++)LCD_Write(170,1);


Добавлено after 10 minutes 5 seconds:
Все,вопрос разрешился!
Странно конечно,но в итоге заработало так,что я для вывода команд оставил туже самую длину пауз,а для данных более короткую ,и оно заработало...Не понятно почему так конечно..но вот при паузе на данные в 5 микросек изображение выводит почти мгновенно..может и меньше можно поставить паузу..

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 23:23:59

LCD_Write(0x2a,0);
LCD_Write(x1>>8,1);
LCD_Write(x1,1);
LCD_Write(x2>>8,1);
LCD_Write(x2,1;
LCD_Write(0x2b,0);
LCD_Write(y2>>8,1);
LCD_Write(y2,1);
LCD_Write(y3>>8,1);
LCD_Write(y3.1);

Японский городовой! Ну если нет сил на DMA по таймеру, уж неужели нет сил использовать цикл?
Кстати, советую обратить внимание на последнюю строчку. Там точка вместо запятой. Не может оно скомпиляться!

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 23:28:33

Ну у меня другой код просто в среде написан,там у меня 2 функции есть ,1 команды,другая данные,этот тут для форума скомпоновал в одну..
Да ладно уже,сейчас очень быстро отрисовываеться и так сойдет.Я паузы на данные вообще убрал,изображение выводит почти мгновенно

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Ср май 18, 2022 23:52:46

alkis3 писал(а):выводит почти мгновенно..может и меньше можно поставить паузу..

И всё-же посмотри как у меня сделано. Под новый экран и мк требуется переписать несколько строк. Буквально указать порт данных, порт управления, и пины управления. А дальше оно само.
При записи в BSRR - сброс имеет более высокий приоритет чем установка единицы. Это позволяет использовать макрос на автомате. В программном коде будет прямая запись в регистр готовой константы. F103 успевает рисовать 30 кадров в таком режиме.
Следующий уровень - это использование дма и таймера. Там намного веселей рисуется. Но привязка к мк очень жёсткая, на новом проекте нужно переписывать слишком много. Зато стабильные 60 кадров анимации на дохлом F030.

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Чт май 19, 2022 00:08:07

И всё-же посмотри как у меня сделано.


Спасибо, хорошо, я поподробнее посмотрю ваш вариант.

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Чт май 19, 2022 00:51:08

... и так сойдет
;) напомнило советский мультик

возможно Вы в ините дисплея не отрабатываете необходимые паузы, и он просто не инитится
если дело в этом - подкорректируйте по паузам инит (пара мест где нужно подождать там бывает), и в LCD_Write задержек не потребуется.

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Чт май 19, 2022 03:18:47

Я инит взял из библиотеки UTFT ,там прям в столбик написаны данные для инициализации вместе с задержками

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Чт май 19, 2022 04:48:46

При записи в BSRR - сброс имеет более высокий приоритет чем установка единицы. Это позволяет использовать макрос на автомате.
Ну вы хоть читайте что ТС пишет. У него 8 бит данных на GPIOA подключены и самым быстрым вариантом будет *(volatile uint8_t*)&GPIOA->ODR = data; Через BSRR ему надо только сигналы CS, WR и RS. А так как, судя по всему, и они у ТС монопольно на GPIOB висят, то уж извините, но код ТС таки быстрее вашего макроса будет. Единственное, надо позаботиться, чтобы LCD_Write заинлайнилась.

СпойлерВообще, запись в порт выглядит как-то так. У ТС реализован первый вариант. Я предлагаю второй - он такой же по скорости и высвободит 8 старших бит порта. Вы же предлагаете 4-й - самый медленный.
Код:
template<uint16_t PM=PinsMask>
  static inline void write(uint16_t data)
  {
    if constexpr (PM==0) return;
    if constexpr (PM == 0xFFFF)
      base()->ODR = data; // 1
    else if constexpr (PM == 0x00FF)
      *pVU8(&base()->ODR) = data; //2
    else if constexpr (PM == 0xFF00)
      *(pVU8(&base()->ODR) + 1) = data >> 8; //3
    else
    {
      base()->BSRR = (PM << 16) | (data & PM); //4
    }
  } 

Re: Дисплей на ili9486 + stm32f411 медленная скорость обмена

Чт май 19, 2022 08:03:13

Это хорошо если используются PA0-PA7. А вдруг PA5-PA12? Для BSRR разницы нет. Хотя для DMA придется хранить не 8 бит на байт, а 32.
Я паузы на данные вообще убрал,изображение выводит почти мгновенно
У вашего дисплея случайно нет ножки, отвечающей за готовность?
Ответить