Top.Mail.Ru
Уведомления
Очистить все

[Решено] TFT дисплей ILI9341. SPI

Страница 5 / 6
(@eduard)
Level 4 Moderator
От: @stm

На ассемблере ещё лучше было бы писать, а в бинарном виде лучше ассемблера

И так и так писал.

От: @stm

Скоро будем голосом или мыслями программировать.

Представляю какой это будет хлам.

ОтветитьЦитата
Размещено : 15.10.2023 16:26
Aveal
(@aveal)
Top level Admin
От: @stm 

Скоро будем голосом или мыслями программировать.

И даже тогда холивар на тему "HAL vs CMSIS" будет продолжаться и продолжаться, снова и снова 😆 

ОтветитьЦитата
Размещено : 16.10.2023 10:26
Aveal
(@aveal)
Top level Admin

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

ОтветитьЦитата
Размещено : 16.10.2023 10:28
 stm
(@stm)
Level 4

Да, раза в 1.5 быстрее стало.

Глазом видно скорость заполнения, но камерой невнятно видно это.
Но с моим дисплеем проблемы при таких скоростях.
Надо обязательно делать небольшую задержку между отсылкой данных.
Например:

SPI1->DR = data;
for(int i=0;i<10;i++){}

Или же просто ставить

SPI1->DR = data;
перед
while((SPI1->SR & SPI_SR_TXE) == RESET)

После SPI1->DR = data; будет постоянно заходить в цикл while и получаться небольшая задержка.

Если память дисплея ещё не закодировала пиксель, а уже приходят данные для следующего пикселя, то дисплей останавливает кодирование пикселей вообще и насовсем.
Думаю поэтому у меня SPI DMA не работает для дисплея.
Массив не передаётся по SPI DMA на дисплей.

ОтветитьЦитата
Создатель темы Размещено : 16.10.2023 22:27
 stm
(@stm)
Level 4

Сейчас такая скорость заполнения дисплея стала.

STM4

Плохо различимо, но чуть чуть видно.

ОтветитьЦитата
Создатель темы Размещено : 16.10.2023 23:05
Aveal
(@aveal)
Top level Admin
От: @stm

Но с моим дисплеем проблемы при таких скоростях.
Надо обязательно делать небольшую задержку между отсылкой данных.

Это не из-за дисплея, SPI не успевает передать данные из регистра DR в сдвиговый регистр, а уже следует новая запись в регистр. Нужно проверять флаги при передаче:

/* ---------------------------------------------------------------------------*/
void ST7735_SendByte(uint8_t data)
{
  while((SPI1->SR & SPI_SR_TXE) == RESET);  
  SPI1->DR = data;
}


/* ---------------------------------------------------------------------------*/

В той же статье, что скидывал, подробнее расписано.

ОтветитьЦитата
Размещено : 17.10.2023 00:06
Aveal
(@aveal)
Top level Admin

@stm Я объяснил, почему дисплей ничего не выводит без проверки флага, и тонко намекнул на то, что вот эту дичь надо выкинуть раз и навсегда:

for(int i=0;i<10;i++){}

Плюс у Вас даже в этих двух строках:

SPI1->DR = data;
перед
while((SPI1->SR & SPI_SR_TXE) == RESET)

неправильная последовательность.

А так да, просто так сижу, ерунду пишу от нечего делать видимо )

ОтветитьЦитата
Размещено : 17.10.2023 00:22
Aveal
(@aveal)
Top level Admin
От: @aveal

@stm Я объяснил, почему дисплей ничего не выводит без проверки флага и тонко намекнул на то, что вот эту дичь надо выкинуть раз и навсегда:

for(int i=0;i<10;i++){}

Плюс у Вас даже в этих двух строках:

SPI1->DR = data;
перед
while((SPI1->SR & SPI_SR_TXE) == RESET)

неправильная последовательность.

А так да, просто так сижу, ерунду пишу от нечего делать видимо )

Для читающих - это мой ответ на удаленное сообщение с претензией, что я будто бы перефразировал то же самое, что ТС написал ранее.

ОтветитьЦитата
Размещено : 17.10.2023 00:25
 stm
(@stm)
Level 4

BUSY flag – The BSY flag is useful to detect the end of a transfer if the software wants to disable the SPI and enter Halt mode (or disable the peripheral clock). This avoids corrupting the last transfer. For this, the procedure described below must be strictly respected. The BSY flag is also useful to avoid write collisions in a multi-master system.
---------------------------------------------
Ок, может дело в SPI.
Как написано в описании флага BUSY : предыдущая передача может повреждаться.
This avoids corrupting the last transfer.

>Плюс у Вас даже в этих двух строках неправильная последовательность.
У вас для передачи данных служат эти функции:

ST7735_SendByte(data);
ST7735_WaitLastData();

Если их раскрыть, то получится:

while((SPI1->SR & SPI_SR_TXE) == RESET);
SPI1->DR = data;
while((SPI1->SR & SPI_SR_TXE) == RESET);
while((SPI1->SR & SPI_SR_BSY) != RESET);

Для чего у вас два раза? while((SPI1->SR & SPI_SR_TXE) == RESET);
-------------------------------------
Попробуйте заменить все эти 3 while просто HAL_Delay()
Ок, это понятно, что флаги лишь ускоряют передачу и по готовности флагов начинается передача.
Дело немного в другом.
Если не ждать нужное время после передачи, то предыдущая передача повреждается и пиксели у меня перестают кодироваться.

Достаточная пауза HAL_Delay() между передачами и while((SPI1->SR & SPI_SR_TXE) == RESET); по сути одно и то же, но вы сказали, что у меня неправильная последовательность

SPI1->DR = data;
while((SPI1->SR & SPI_SR_TXE) == RESET);

Этот цикл как раз и обеспечивает нужную задержку, чтоб предыдущая передача не повреждалась

while((SPI1->SR & SPI_SR_TXE) == RESET);

У вас этот код работает точно по такому же принципу:

while((SPI1->SR & SPI_SR_TXE) == RESET);
SPI1->DR = data;
while((SPI1->SR & SPI_SR_TXE) == RESET);
while((SPI1->SR & SPI_SR_BSY) != RESET);
ОтветитьЦитата
Создатель темы Размещено : 17.10.2023 01:11
Aveal
(@aveal)
Top level Admin

@stm 

изображение
ОтветитьЦитата
Размещено : 17.10.2023 01:17
Aveal
(@aveal)
Top level Admin

По поводу последовательности, Ваш вариант:

SPI1->DR = data;
while((SPI1->SR & SPI_SR_TXE) == RESET);

Это плюс-минус то же самое, что сесть на стул, а только после этого проверить, не занят ли он.

ОтветитьЦитата
Размещено : 17.10.2023 01:22
 stm
(@stm)
Level 4

>Это плюс-минус то же самое, что сесть на стул, а только после этого проверить, не занят ли он.
Ок, это да)
Но работает как пауза между передачами только нижний цикл, который под SPI1->DR = 0;

while((SPI1->SR & SPI_SR_TXE) == RESET);

Ок, верхний цикл while((SPI1->SR & SPI_SR_TXE) == RESET);  для безопасности)

ОтветитьЦитата
Создатель темы Размещено : 17.10.2023 01:32
 stm
(@stm)
Level 4

Для кодирования пикселей достаточно только нижнего цикла while((SPI1->SR & SPI_SR_TXE) == RESET);, верхний для безопасности, это хорошо, но неправильной последовательностью думаю это нельзя назвать. Ок, пусть будет.

Я просто хотел описать мысль, а не доказать как будет правильнее)

ОтветитьЦитата
Создатель темы Размещено : 17.10.2023 01:38
 stm
(@stm)
Level 4

У меня после каждой отсылки данных была деактивация Чип Селекта TFT_CS_SET();
Поэтому играло роль где написан цикл, снизу или сверху передачи данных.

Я посмотрел, вы не деактивируете Чип Селект после передачи данных.
Я в драйверах видел деактивацию Чип Селекта после передачи данных, поэтому её всегда вставлял в код.

ОтветитьЦитата
Создатель темы Размещено : 17.10.2023 02:38
 stm
(@stm)
Level 4

HAL овским функциям может было необходимо деактивировать Чип Селект после каждой передачи данных.
Передаче данных через регистры это не нужно.
Ещё быстрее стали пиксели кодироваться и дисплей заполняться без деактивации Чип Селект после передачи данных.

ОтветитьЦитата
Создатель темы Размещено : 17.10.2023 02:44
Страница 5 / 6
Поделиться: