Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/454: Рейтинг темы: голосов - 454, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 24.09.2012
Сообщений: 278
1

STM32F103 + TFT 240x320 + SD = медленный вывод картинок

31.07.2013, 02:04. Показов 88389. Ответов 137
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть МК STM32F103VCT6, к нему при помощи FSMC подключен TFT дисплей 240х320 и SD карта по SPI. На этот самый дисплей выводятся картинки. При выводе из внутренней памяти МК на глаз задержка не заметна, а вот при чтении с SD карты, картинка 320х200 выводится около 1,5 сек. При этом задержка заметна даже на маленьких картинках 100х100, а от "веса" изображения вообще не зависит. Картинки в формате JPG. Для декодирования использую библиотеку от Чена. Для работы с SD картой - FstFs. Как я понял, после декодирования получается готовый массив для вывода, почему тогда такой медленный вывод? Или я что-то недопонимаю? В чем может быть проблема?

Да, еще заметил, что если выводить попиксельно:

Код
void point(uint16_t x, uint16_t y, uint16_t color)
{
LCD_SetCursor(y, 319-x);
LCD_WriteROM_Prepare();
LCD_WriteROM(color);
}
картинка выглядит нормально, а если через функцию вывода изображений, с предварительной подготовкой окна для вывода:
Код
void LCD_WriteBMP ( uint16_t x1, uint8_t y1, uint16_t Width, uint8_t Height, uint16_t *bitmap)
{
uint32_t index, size;
uint16_t *bitmap_ptr = (uint16_t *)bitmap;
uint16_t x2, y2;

y2 = y1 + Height;
x2 = 319 - x1 + Width;

LCD_SetDysplayWymdow ( 319 - x1, y1, x2, y2 );

LCD_WriteROM_Prepare ( );

size = Height * Width - 1;

for ( index = 0; index < size; index ++ )
LCD_WriteROM ( bitmap_ptr [ index ] );

LCD_SetDysplayWymdow ( 0, 0, 319, 239 );
}

void LCD_SetDysplayWymdow(uint16_t Ypos, uint16_t Xpos, uint16_t Width, uint8_t Height)
{
Height --;
Width --;

LCD_WriteReg ( 0x44, ( Height << 8 ) | Xpos );
LCD_WriteReg ( 0x45, Ypos );            // Vertical ROM address stort position
LCD_WriteReg ( 0x46, Width );   // Vertical ROM address end position

LCD_WriteReg ( 0x4e, Xpos );            // Set GDDROM X   address counter
LCD_WriteReg ( 0x4f, Ypos );            // Set GDDROM Y   address counter
}
то изображение разделено на маленькие квадратики с расстоянием 1 пиксель.

[11.16 Кб]
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
31.07.2013, 02:04
Ответы с готовыми решениями:

Вывод кириллических символов на tft ili9341 spi, stm32f103
Доброго времени суток, не получается вывести, а точнее создать базу символов с кириллическими...

Вывод текста на tft.lcd 2.4
Привет, ребят :) Такая проблемка, имеется мега с дисплеем tft.lcd 2.4 с библиотекой Adafruit, на...

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

Вывод информации на TFT через SPI
Всем доброго дня. Помогите с выводом информации на TFT-экран (в моем случае на ILI9341 1,8 дюйма). ...

Демодулятор SSB сигнала и вывод панорамы на TFT
Здравствуйте! Есть огромное желание сделать панораму для трансивера .Т.е. Использую STM32F429. С...

137
hosh
16.10.2013, 12:18 121
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от hd44780
hosh, у Вас проц F407?
...
Ведь f_read при работе продвигает переданный ей указатель. А он должен быть фиксированным, т.к. это регистр FSMC. Если двигать указатель, то данные полетят хрен знает куда ....
да проц 407...

Только т.к. явного адреса у дисплея нет (автоинкремент) то в пределах 16-битного смещения от адреса данных FSMC - все данные будут попадать "по назначению". Поэтому (и не только) для 320x240x16 f_read() я вызываю 4 раза...

А ещё в fatfs есть такая функция, как f_forward:
Код
FRESULT f_forward (
FIL* fp,                        /* [IN] File object */
UINT (*func)(const BYTE*,UINT), /* [IN] Data streaming function */
UINT btf,                       /* [IN] Number of bytes to forward */
UINT* bf                        /* [OUT] Number of bytes forwardid */
);
Запустить правда у меня через неё не получилось (правда не особо и старался)... А сейчас не до этого, той скорости что сейчас достиг для моих задач выше крыши. Может кто попробует через f_forward() выводить?
3 / 3 / 0
Регистрация: 06.12.2016
Сообщений: 1,605
16.10.2013, 15:03 122
Цитата Сообщение от hosh
Может кто попробует через f_forward() выводить?
Может и попробую. Но позже. Я сейчас достал из загашников свой старенький ILI9320 320x240, паяю на него разъём под свою новую плату. И тач контроллер паять буду, из ILI только X+, X-, Y+, Y- торчат. Достали меня глюки моего SSD1963 ...
Хоть далеко не 800x480, как SSD, зато без глюков. И тоже на FSMC. А остальной функционал у них мало чем отличается ...
0
0 / 0 / 0
Регистрация: 24.09.2012
Сообщений: 278
01.11.2013, 05:36 123
Отказывается мой дисплей нормально работать. Тока и напряжения хватает. Пробовал подключать и к USb и к отдельному БП. Дисплей питается от отдельного стабилизатора на 3,3В, который китайцы на плату запаяли. МК и MicroSD питаются вместе от второго стабилизатора 3,3В. Ничего нигде не проседает. А на дисплее все равно бред:

должно быть
есть

Даже не знаю, что с ним делать...
0
3 / 3 / 0
Регистрация: 06.12.2016
Сообщений: 1,605
02.11.2013, 14:34 124
BORS_, как выводите - по точкам, окном, DMA?
Раньше Вы вроде писали, что выводите окном.

Хотя, мне кажется, это глюки дисплея, также как и у меня (где здеся плачущий смайлик?)....
0
0 / 0 / 0
Регистрация: 24.09.2012
Сообщений: 278
02.11.2013, 15:51 125
Вывожу окном. Перед началом чтения картинки ставлю окно по размеру изображения, потом делаю ROM_Prepare и начинаю чтение и вывод. Да на глюк дисплея не особо похоже, из памяти МК картинка выводится нормально. При вывод через буфер в памяти тоже нормально.

Да, попробовал сделать вывод через f_forward(), сдвиг пропал, но я так и не придумал, как сложить два блока по 8 бит в один на 16. Соответственно у картинки становилось в двое больше пикселей чем должно быть, ну и цвета тоже убегали.
0
0 / 0 / 0
Регистрация: 24.09.2012
Сообщений: 278
06.11.2013, 14:01 126
Помучил его еще немного, а точнее вывод через f_forward(). Картинка стала выглядеть более адекватно, но теперь она выводится под наклоном:


Вывод идет так:
Код
UINT out_stream (   /* Returns number of bytes sent or stream status */
const uint8_t *p,  /* Pointer to the data btock to be sent */
UINT btf        /* >0: Transfer call (Number of bytes to be sent). 0: Sense call */
)
{
UINT cnt = 0;

do {    /* Repeat while there is any data to be sent omd the stream is ready */

LCD_ROM = p[cnt+1] << 8 | p[cnt] << 0;

cnt+=2;
}

while (cnt < btf );
return cnt;
}
При этом если добавить промежуточную запись в переменную, то ничего не меняется. Попробую добавить Set_Cursor(), но тогда снизится скорость вывода...
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
06.11.2013, 15:55 127
Цитата Сообщение от BORS_
Код:
...
const uint8_t *p, /* Pointer to the data btock to be sent */
UINT btf /* >0: Transfer call (Number of bytes to be sent). 0: Sense call */
...

UINT cnt = 0;

do { /* Repeat while there is any data to be sent omd the stream is ready */
LCD_ROM = p[cnt+1] << 8 | p[cnt] << 0;
cnt+=2;
}
while (cnt < btf );Зачем так преобразовывать, у Вас же данные - 16-тибитные, причём с нужным little endian. Вот и берите из массива сразу готовые пикселы:
Код
  ...
const uint16_t *p,  /* Pointer to the data btock to be sent */
UINT btf        /* >0: Transfer call (Number of pixels to be sent). 0: Sense call */
...
UINT cnt = 0;

do {    /* Repeat while there is any data to be sent omd the stream is ready */
LCD_ROM = p[cnt++];
} while (cnt < btf );
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
06.11.2013, 15:59 128
Цитата Сообщение от BORS_
Картинка стала выглядеть более адекватно, но теперь она выводится под наклоном
... ...
Попробую добавить Set_Cursor(), но тогда снизится скорость вывода...
Раз угол наклона - 45 градусов, то ошибка - один пиксел на каждую строку. Поэтому попробуйте делать Set_Cursor() не перед каждым пикселом, а лишь перед каждой строкой. Тогда замедление будет не таким фатальным.
0
0 / 0 / 0
Регистрация: 30.09.2013
Сообщений: 210
06.11.2013, 19:14 129
Для отрисовки элементов меню пользую bmp картинки, записанные на SD карту
вывожу так

Код
#define buffer   512

FIL file;
FATFS fs;
uint len;

unsykned char data[buffer];                //Read-write buffer

uint16_t out_bmp(uint16_t StartX, uint16_t StartY, const TCHAR* path)
{
uint16_t current_position=1;   //текущая позиция вывода по х
uint16_t size_x;            //размер по горизонтали
uint16_t size_y;            //размер по вертикали
uint32_t n;                  //количество байт в файле
uint k;
uint m;                     //

//выполняем связывание диска с структурой
f_mount(0, &fs);
//открываем уже существующий файл для чтения
f_open(&file,path, FA_OPEN_EXISTING | FA_READ);
//читаем заголовок файла (первые 54 байта)
f_read(&file, data, 54, &len);

//проверка идентификатора bmp файла
if(((((uint16_t)data[1])<<8)|(uint16_t)data[0])!=0x4D42)   return NOT_BMP;

//определение размера изображения
size_x=(((uint16_t)data[19])<<8)|(uint16_t)data[18];
size_y=(((uint16_t)data[23])<<8)|(uint16_t)data[22];

//кол-во байт изображения
n=(uint32_t)size_x*(uint32_t)size_y*2;

//курсов в начальную позицию
LCD_SetCursor(StartX,StartY);
LCD_WriteIndex(0x0022);

//на начало пикселов, если картинка не с конвертора ST
//то закомментировать эту строку
f_lseek(&file, 0x42);

//буфер
while(n!=0)   {if(n<=512)   {f_read(&file, &data[0], (uint)n, &len);
m=n;
n=0;}
else       {f_read(&file, &data[0], 512, &len);
m=512;
n=n-512;};
//картинка из буфера
k=0;
while(k<m)            {if(current_position>size_x)   {current_position=1;
StartY=StartY-1;
LCD_SetCursor(StartX,StartY);
LCD_WriteIndex(0x0022);}
LCD_WriteData((data[k+1]<<8)|data[k]);
k=k+2;
current_position++;};
};

//закрываем файл
f_close(&file);
//отменяем связывание диска с структурой
f_mount(0, NULL);
return 0;
}
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
06.11.2013, 19:48 130
Цитата Сообщение от bomzoyy
Для отрисовки элементов меню пользую bmp картинки, записанные на SD карту
вывожу так
Однако ха-ха.
С таким оверхедом - LCD_SetCursor() да ещё и LCD_WriteIndex(0x0022) перед каждым пикселом - проблем не будет, но скорость... :-(

И Вы так же, как и BARS, неоптимально берёте данные из пиксельного массива:
Код
LCD_WriteData((data[k+1]<<8)|data[k]); k=k+2;
Всего пару постов выше я писал, как то же самое делается без лишних приседаний.
0
0 / 0 / 0
Регистрация: 30.09.2013
Сообщений: 210
06.11.2013, 20:12 131
вообще то не перед каждым пикселом .....LCD_SetCursor() исполняется только при переходе на новую строку
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
06.11.2013, 20:23 132
Цитата Сообщение от bomzoyy
вообще то не перед каждым пикселом .....LCD_SetCursor() исполняется только при переходе на новую строку
Точно! Как раз так, как надо бы BARSу попробовать сделать.
А ещё вынесите LCD_WriteIndex(0x0022) (a.k.a. ROM_Prepare()) из цикла - будет работать? Его достаточно делать один раз перед началом вывода в окно, если не будет неоконного перескока координат и если... нет глюка, с которым борется ТС :-)

Кстати, когда нет глюков, и TFT-контроллер работает как положено по даташиту, то LCD_SetCursor() тоже достаточно делать один раз перед началом вывода в окно. Не знали? И переменные X,Y в программе при этом не нужно отслеживать, они вообще не нужны. Окно - мощная функция TFT-контроллеров, там все иксы и игреки аппаратно меняются.
0
0 / 0 / 0
Регистрация: 30.09.2013
Сообщений: 210
06.11.2013, 23:12 133
поправьте, если я не прав, но окна по моему поддерживает контроллер SSD1963, а у меня SSD1289.
0
3 / 3 / 0
Регистрация: 06.12.2016
Сообщений: 1,605
06.11.2013, 23:20 134
banzay, окна есть во всех дисплеях.
Я их использовал и в ILI9320, и в SSD1289, и SSD1963.
Читайте доку :)

Конкретно для SSD1289:
Код
        // Horizontal ROM address position
// End   - Старший байт
// Start - Младший байт
ArduinoLcdWriteReg ( 0x44, ( x2_ << 8 ) | x1_ );
ArduinoLcdWriteReg ( 0x45, y1_ );       // Vertical ROM address stort position
ArduinoLcdWriteReg ( 0x46, y2_ );       // Vertical ROM address end position
На ардуино внимание не обращайте, у меня ардуиновский шильдик на STM32F4, главное здесь - регистры 0x44..0x46.
0
0 / 0 / 0
Регистрация: 24.09.2012
Сообщений: 278
10.11.2013, 05:01 135
Цитата Сообщение от OtyxPM
Зачем так преобразовывать, у Вас же данные - 16-тибитные, причём с нужным little endian. Вот и берите из массива сразу готовые пикселы:Код:
...
const uint16_t *p, /* Pointer to the data btock to be sent */
UINT btf /* >0: Transfer call (Number of pixels to be sent). 0: Sense call */
...
UINT cnt = 0;

do { /* Repeat while there is any data to be sent omd the stream is ready */
LCD_ROM = p[cnt++];
} while (cnt < btf );

Что-то нифига они не 16-тибитные. Если преобразование не делать, то картинка выводится в два "слоя" с искаженными цветами. Или я то-то не так настроил в библиотеках fatfs...

Сейчас сделал так:
Код
    LCD_SetCursor(Y, X);

LCD_WriteROM_Prepare();

for(i = 0; i < BMP.Height; i++) {

f_forward(&file[0], out_stream, BMP.Width*2, &cnt);

LCD_SetCursor(Y+i, X); LCD_WriteROM_Prepare();
}
Картинка выровнялась, но появились какие-то искажения и сетка из точек. Цвет точек постоянный:

0
0 / 0 / 0
Регистрация: 24.09.2012
Сообщений: 278
13.11.2013, 17:53 136
Что еще можно сделать для нормального вывода? Может еще в fatFS что-то особенное настроить надо?
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
14.11.2013, 02:19 137
Цитата Сообщение от BORS_
Что еще можно сделать для нормального вывода? Может еще в fatFS что-то особенное настроить надо?
Для проверки подозрения на FatFs исключите её.
Возьмите BMP-файл, у которого FAT-цепочка идёт подряд (можно просто записать на свежеотформатированную карту). Читайте секторы без участия FatFs (начальный кластер, размер кластера и размер файла в байтах посмотрите с помощью той же FatFs заранее). Если артефакты исчезнут, то это повод поковыряться в нижнем уровне FatFs.
0
0 / 0 / 0
Регистрация: 12.08.2012
Сообщений: 1,217
14.11.2013, 11:13 138
Когдато писал библиотеку читающую bmp, правда для ПК, так вот тоже был баг что некоторые картинки выводились криво, но не все. Потом повнимательнее почитав про формат файлов нашёл что каждая строка пикселей выравнена по границе в 4 байта, независимо от количества бит на пиксель.
0
14.11.2013, 11:13
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.11.2013, 11:13
Помогаю со студенческими работами здесь

Медленный вывод в console.log
как сделать так чтобы в console.log было так медленно чтобы они шли 1 2 3 4 по-очереди

Lonely Numbers и медленный вывод
Здравствуйте. Есть задачка, которую я решил, но не могу сдать. Один из тестов требует вывода...

Mp3FileReader - медленный вывод аудио (NAudio.dll)
P.S. Т.к. я думаю что это из за особенности строения mp3 файла, публикую в эту тему Доброго...

Чтение COM-порта: медленный вывод в textBox несколько тысяч строк (метод AppendText)
Доброго времени суток! Читаю данные с последовательного порта. Конвертирую каждые три байта и...

Замена 2,8 TFT на 2,4 TFT
Некоторое время назад был сделан проект на STM32F103RB и LCD2.8&quot;. Поддерживает контроллеры ILI9320,...

Вывод картинок
Добрый вечер всем. Прошу помощи. Есть галерея. Не могу понять как сделать так чтоб при заходе на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
138
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru