На ассемблере ещё лучше было бы писать, а в бинарном виде лучше ассемблера
И так и так писал.
Скоро будем голосом или мыслями программировать.
Представляю какой это будет хлам.
Скоро будем голосом или мыслями программировать.
И даже тогда холивар на тему "HAL vs CMSIS" будет продолжаться и продолжаться, снова и снова 😆
Да, раза в 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 на дисплей.
Сейчас такая скорость заполнения дисплея стала.
Плохо различимо, но чуть чуть видно.
Но с моим дисплеем проблемы при таких скоростях.
Надо обязательно делать небольшую задержку между отсылкой данных.
Это не из-за дисплея, SPI не успевает передать данные из регистра DR в сдвиговый регистр, а уже следует новая запись в регистр. Нужно проверять флаги при передаче:
/* ---------------------------------------------------------------------------*/ void ST7735_SendByte(uint8_t data) { while((SPI1->SR & SPI_SR_TXE) == RESET); SPI1->DR = data; } /* ---------------------------------------------------------------------------*/
В той же статье, что скидывал, подробнее расписано.
@stm Я объяснил, почему дисплей ничего не выводит без проверки флага, и тонко намекнул на то, что вот эту дичь надо выкинуть раз и навсегда:
for(int i=0;i<10;i++){}
Плюс у Вас даже в этих двух строках:
SPI1->DR = data; перед while((SPI1->SR & SPI_SR_TXE) == RESET)
неправильная последовательность.
А так да, просто так сижу, ерунду пишу от нечего делать видимо )
@stm Я объяснил, почему дисплей ничего не выводит без проверки флага и тонко намекнул на то, что вот эту дичь надо выкинуть раз и навсегда:
for(int i=0;i<10;i++){}Плюс у Вас даже в этих двух строках:
SPI1->DR = data; перед while((SPI1->SR & SPI_SR_TXE) == RESET)неправильная последовательность.
А так да, просто так сижу, ерунду пишу от нечего делать видимо )
Для читающих - это мой ответ на удаленное сообщение с претензией, что я будто бы перефразировал то же самое, что ТС написал ранее.
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);
По поводу последовательности, Ваш вариант:
SPI1->DR = data; while((SPI1->SR & SPI_SR_TXE) == RESET);
Это плюс-минус то же самое, что сесть на стул, а только после этого проверить, не занят ли он.
>Это плюс-минус то же самое, что сесть на стул, а только после этого проверить, не занят ли он.
Ок, это да)
Но работает как пауза между передачами только нижний цикл, который под SPI1->DR = 0;
while((SPI1->SR & SPI_SR_TXE) == RESET);
Ок, верхний цикл while((SPI1->SR & SPI_SR_TXE) == RESET); для безопасности)
Для кодирования пикселей достаточно только нижнего цикла while((SPI1->SR & SPI_SR_TXE) == RESET);, верхний для безопасности, это хорошо, но неправильной последовательностью думаю это нельзя назвать. Ок, пусть будет.
Я просто хотел описать мысль, а не доказать как будет правильнее)
У меня после каждой отсылки данных была деактивация Чип Селекта TFT_CS_SET();
Поэтому играло роль где написан цикл, снизу или сверху передачи данных.
Я посмотрел, вы не деактивируете Чип Селект после передачи данных.
Я в драйверах видел деактивацию Чип Селекта после передачи данных, поэтому её всегда вставлял в код.
HAL овским функциям может было необходимо деактивировать Чип Селект после каждой передачи данных.
Передаче данных через регистры это не нужно.
Ещё быстрее стали пиксели кодироваться и дисплей заполняться без деактивации Чип Селект после передачи данных.