24.10.2019, 01:59
|
|
Частый гость
Регистрация: 24.10.2019
Сообщений: 13
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: ILI9341 + stm32f103c8t6
Использую вот такой дисплей 240x320 2,8" SPI TFT (ILI9341), STM32F103C8. С трудом смог его запустить с использованием HAL. Работает медленно. Пока отлаживал меня это особо не волновало. Но, вот, захотел ускорить работу. Для этого функцию передачи байта
Нажмите, чтобы открыть спойлер
void TFT9341_Write8(uint8_t dt)
{
HAL_SPI_Transmit(&hspi1,&dt,1,1);
}
заменил на такую, более ничего не трогая
Нажмите, чтобы открыть спойлер
void TFT9341_Write8(uint8_t dt)
{
while((SPI1-›SR & SPI_SR_TXE)==RESET){}
SPI1-›DR = dt;
}
Скорость вывода разительно увеличилась. Но при этом начались заморочки. Само изображение выводиться правильно, но его позиционирование не соответствует заданному. Первый вывод выводится с позиционированием в верхнем левом углу с небольшим смещением в право (скажем дельта) вне зависимости от того, какое позиционирование задано. Если попытаться ещё раз вывести, то изображение сместится вниз на величину своей высоты и в право на величину дельта. И так далее при следующих выводах. Функция позиционирования выглядит так
Нажмите, чтобы открыть спойлер
void TFT9341_SetAddrWindow(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
{
//HAL_Delay(10);
unsigned long t;
//CS_ACTIVE;
t = x1;
t‹‹=16;
t |= x2;
TFT9341_WriteRegister32(0x2A,t);//Column Addres Set
t = y1;
t‹‹=16;
t |= y2;
TFT9341_WriteRegister32(0x2B,t);//Page Addres Set
}
Совершенно не могу понять, как процедура вывода байта может повлиять на позиционирование. Может, что то там не успевает и нужно где то поставить задержки. Так же в голову не приходит методика поиска этой заморочки. Что посоветуете?
|
|
|
|
24.10.2019, 10:44
|
|
Почётный гражданин KAZUS.RU
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,504
Сказал спасибо: 401
Сказали Спасибо 2,217 раз(а) в 1,315 сообщении(ях)
|
Re: ILI9341 + stm32f103c8t6
Изучите, что такое DMA, и настройте передачу по SPI через DMA. Даже с HAL это будет гораздо быстрее, чем отдельная передача по одному байту/
Что касается сдвига, то просто передаете неправильно байты. Сверьтесь с мануалом ILI9341. Если сделаете точно по мануалу, все будет работать правильно
Последний раз редактировалось NewWriter; 24.10.2019 в 10:49.
|
|
|
|
24.10.2019, 11:25
|
|
Частый гость
Регистрация: 24.10.2019
Сообщений: 13
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: ILI9341 + stm32f103c8t6
Сообщение от NewWriter
|
Что касается сдвига, то просто передаете неправильно байты. Сверьтесь с мануалом ILI9341. Если сделаете точно по мануалу, все будет работать правильно
|
С этим спорить не приходится. Но не понятно как это, когда в рабочей программе побайтный вывод, сделанный мощью функции HAL, идёт без вопросов, только что медленно. А если эту же функцию побайтного вывода сделать на CMSIS ничего более не трогая, то вывод идёт быстро, но позиционирование не верное.
Что касается
Сообщение от NewWriter
|
Изучите, что такое DMA, и настройте передачу по SPI через DMA. Даже с HAL это будет гораздо быстрее, чем отдельная передача по одному байту/
|
то скорость по второму варианту меня вполне устраивает. И мне видеться, что на допиливание этого варианта время потрачу меньше, чем на проработку использования DMA. Но эта позиция, конечно, спорная.
|
|
|
|
25.10.2019, 01:30
|
|
Прописка
Регистрация: 17.03.2015
Сообщений: 287
Сказал спасибо: 0
Сказали Спасибо 209 раз(а) в 121 сообщении(ях)
|
Re: ILI9341 + stm32f103c8t6
Сообщение от Юрий_48
|
Совершенно не могу понять, как процедура вывода байта может повлиять на позиционирование. Может, что то там не успевает и нужно где то поставить задержки. Так же в голову не приходит методика поиска этой заморочки. Что посоветуете?
|
Скорее всего, Вы забыли про флаг BSY. На картинке - как должно быть.
Т.е., анализируя только TXE, Вы попадаете в ситуацию, когда последний байт команды еще не передался, а Вы уже готовы "дернуть" DC/CS дисплея.
Чтобы проверить это предположение, достаточно поставить задержку в конец Вашей функции TFT9341_Write8, чтобы гарантировать корректную передачу последнего байта команды.
При этом, вывод на дисплей начнет работать медленно, но позиционнирование отображаемых элементов должно соответствовать ожидаемому.
Если так и произошло, то выкидывайте задержку и думайте куда поставить анализ флага BSY.
|
|
|
Сказали "Спасибо" ProtAS-13
|
|
|
26.10.2019, 00:51
|
|
Частый гость
Регистрация: 24.10.2019
Сообщений: 13
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: ILI9341 + stm32f103c8t6
ProtAS-13, огромное спасибо за ответ по существу.
Сообщение от ProtAS-13
|
Если так и произошло, то выкидывайте задержку и думайте куда поставить анализ флага BSY.
|
Именно так и произошло. На сегодня моя думалка ничего лучшего не придумала, как поставить проверку BSY в конец передачи команды
Нажмите, чтобы открыть спойлер
void TFT9341_WriteRegister32(unsigned char r, unsigned long d)
{
CS_ACTIVE;
CD_COMMAND;
TFT9341_Write8(r);
CD_DATA;
TFT9341_Write8(d››24);
//HAL_Delay(10);
TFT9341_Write8(d››16);
TFT9341_Write8(d›› ;
TFT9341_Write8(d);
while((SPI1-›SR & SPI_SR_BSY)!=0) {}
}
Но ничего не изменилось. Сегодня уже нет возможности копать, завтра попробую - всего то у меня на эту работу есть пару часов вечером. Очень радует, что определилась проблема. А от куда у Вас эта временная диаграмма? У меня в официальном описании ILITEK такого нет.
И ещё меня сильно удивило (в хорошем смысле) отношение количества "Спасибо" к количеству сообщений - где то 1. Это высокий класс, такого ещё не видел, снимаю шляпу.
Последний раз редактировалось Юрий_48; 26.10.2019 в 00:59.
|
|
|
|
26.10.2019, 02:10
|
|
Вид на жительство
Регистрация: 27.11.2007
Сообщений: 428
Сказал спасибо: 19
Сказали Спасибо 39 раз(а) в 30 сообщении(ях)
|
Re: ILI9341 + stm32f103c8t6
Сообщение от Юрий_48
|
Совершенно не могу понять, как процедура вывода байта может повлиять на позиционирование. Может, что то там не успевает и нужно где то поставить задержки. Так же в голову не приходит методика поиска этой заморочки. Что посоветуете?
|
Такая реакция очень напоминает ситуацию с неправильным количеством. Проверьте все ли в свое время и в своем месте передается.
|
|
|
|
26.10.2019, 18:11
|
|
Вид на жительство
Регистрация: 10.04.2010
Сообщений: 301
Сказал спасибо: 25
Сказали Спасибо 136 раз(а) в 79 сообщении(ях)
|
Re: ILI9341 + stm32f103c8t6
Сообщение от Юрий_48
|
то скорость по второму варианту меня вполне устраивает. И мне видеться, что на допиливание этого варианта время потрачу меньше, чем на проработку использования DMA. Но эта позиция, конечно, спорная.
|
Вы же HAL используете, Куб за вас все сделает или воспользуйтесь примерами, что там "прорабатывать" ? Можете даже и не вникать в работу DMA, если уж так лень. Подготовили массив и выплюнули. Правда смысл есть, если массив большой, а не по точкам отрисовывать.
|
|
|
|
26.10.2019, 20:48
|
|
Прописка
Регистрация: 17.03.2015
Сообщений: 287
Сказал спасибо: 0
Сказали Спасибо 209 раз(а) в 121 сообщении(ях)
|
Re: ILI9341 + stm32f103c8t6
Сообщение от Юрий_48
|
Но ничего не изменилось.
|
Еще кое чего не хватает
Вы попадаете, как я уже сказал, в ситуацию, когда байт данных еще не передался полностью, а Вы уже "дергаете" DC:
Код:
|
TFT9341_Write8(r);
=====› Вот ЗДЕСЬ ‹======
CD_DATA; |
Поэтому, нужно в этом месте анализировать конец передачи байта.
Делается это просто - анализируете флаг RXNE.
Приведу простой рабочий пример:
Нажмите, чтобы открыть спойлер
Код:
|
/************************************************** *****************************
* brief : Write LCD-Command with Parameters.
* note : This variadic function send LCD-Command to SPI.
* param : size: number of parameters without command code.
* param : codeCMD: command code
* retval: None
************************************************** *****************************/
void LCD_WriteCMD(uint16_t size, uint8_t codeCMD, ...)
{
va_list vl; // Type to hold information about variable arguments
va_start(vl,codeCMD); // Initialize a variable argument list
LCD_CS_YES; // Chip select (CS) -› ENABLE
LCD_DC_COM; // Data/Command (DC) -› COMMAND
while(!LL_SPI_IsActiveFlag_TXE(SPI2)){} // Wait Tx buffer empty
LL_SPI_TransmitData8(SPI2,codeCMD); // Transmit command code
SPI_WaitOneTransmitEnd(SPI2); // Wait transmit command code
LCD_DC_DAT; // Data/Command (DC) -› DATA
// Transmit command parameters
for (int i=0; i‹size; i++)
{
while(!LL_SPI_IsActiveFlag_TXE(SPI2)){}
LL_SPI_TransmitData8(SPI2,(uint8_t)va_arg(vl,int));
}
SPI_WaitAllTransmitEnd(SPI2); // Wait transmit full LCD-Command
LCD_CS_NO; // Chip select (CS) -› DISABLE
}
/************************************************** *****************************
...
/************************************************** *****************************
* brief : Wait transmit one data frame (8- or 16-bit).
* note : After the last sampling clock edge the RXNE bit is set.
* When the SPI_DR register is read, RXNE bit is clearing.
* param : SPIx: SPI Instance
* retval: None
************************************************** *****************************/
__STATIC_INLINE void SPI_WaitOneTransmitEnd(SPI_TypeDef *SPIx)
{
// Wait last sampling clock edge
while(READ_BIT(SPIx-›SR, SPI_SR_RXNE)!=SPI_SR_RXNE){}
READ_REG(SPIx-›DR); // Clearing of the RXNE bit
}
/************************************************** *****************************
* brief : Wait transmit all data frames (n*8- or n*16-bit).
* note : The BSY flag is set when a transfer starts.
* It is cleared when a transfer is finished.
* In master mode, the BSY flag is kept high during all the transfers.
* param : SPIx: SPI Instance
* retval: None
************************************************** *****************************/
__STATIC_INLINE void SPI_WaitAllTransmitEnd(SPI_TypeDef *SPIx)
{
// Wait ending all transfers
while(READ_BIT(SPIx-›SR, SPI_SR_BSY)==SPI_SR_BSY){}
READ_REG(SPIx-›DR); // Clearing of the RXNE bit
} |
|
|
|
|
28.10.2019, 00:25
|
|
Частый гость
Регистрация: 24.10.2019
Сообщений: 13
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: ILI9341 + stm32f103c8t6
Сообщение от ProtAS-13
|
Вы попадаете, как я уже сказал, в ситуацию, когда байт данных еще не передался полностью, а Вы уже "дергаете" DC:
Код:
TFT9341_Write8(r);
=====› Вот ЗДЕСЬ ‹======
CD_DATA;
Поэтому, нужно в этом месте анализировать конец передачи байта.
Делается это просто - анализируете флаг RXNE.
|
ProtAS-13, Здесь что то не понимаю. Каким боком участвует флаг RXNE - он же относится к принимаемым "мной" данным. Ваше замечание о том, что "а Вы уже "дергаете" DC", я прочувствовал, спасибо. Но всё, что туда не подпихивал не давало эффекта. Единственный вариант, который заработал быстро и правильно это такой
Нажмите, чтобы открыть спойлер
void TFT9341_Write8(uint8_t dt)
{
//HAL_SPI_Transmit(&hspi1,&dt,1,1);
while (!(SPI1-›SR & SPI_SR_TXE));
SPI1-›DR = dt;
while (SPI1-›SR & SPI_SR_BSY);
}
Понятно, что это не совсем рационально, поскольку тут посылка нового байта происходит только, когда предыдущий полностью передался, но всё равно быстро.
Что касается Вашего примера, то в общих чертах он понятен, если не считать RXNE. Попробую разобраться более детально. Правда в первой функции что то не хватает. Не знаю сознательно это или случайно.
|
|
|
|
28.10.2019, 04:49
|
|
Прописка
Регистрация: 17.03.2015
Сообщений: 287
Сказал спасибо: 0
Сказали Спасибо 209 раз(а) в 121 сообщении(ях)
|
Re: ILI9341 + stm32f103c8t6
Сообщение от Юрий_48
|
Но всё, что туда не подпихивал не давало эффекта.
|
Добавление анализа флагов в функцию "TFT9341_Write8" - это плохое решение.
Перенесите анализ BSY туда, где я написал "=====› Вот ЗДЕСЬ ‹======".
Т.е. в функции "TFT9341_WriteRegister32" у Вас должно ДВА раза анализироваться BSY.
Можно сделать и по другому - анализировать BSY перед изменение DC/CS.
Что касается RXNE.
Если перевести SPI в "full-duplex mode", то RXNE будет косвенно указывать на конец передачи КАЖДОГО одного байта (см. картинку).
Отличие "Transmit-only mode" от "full-duplex mode" лишь в том, что контакт входного сигнала (MISO) можно использовать как GPIO.
При этом нигде ЯВНО не описано, вырабатывается ли RXNE в "Transmit-only mode".
Если Вы SPI перевели в "Transmit-only mode", то можете попробовать в функции "TFT9341_WriteRegister32" вместо "=› Вот ЗДЕСЬ ‹=" поставить анализ RXNE, оставив в конце анализ BSY.
Если не сработает, то будем ТОЧНО знать, что флаг RXNE в "Transmit-only mode" не формируется.
|
|
|
Сказали "Спасибо" ProtAS-13
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 21:22.
|
|