Урок 37
Часть 8
Дисплей TFT 240×320 8bit
В прошлой части данного урока мы написали ряд функций по работе со шрифтами. Также мы не дописали функцию вывода строк на экран в видеоверсии, в текстовой она выложена полностью.
Поэтому проверим мы данную функцию уже в этой части.
Соберём код, прошьём контроллер и посмотрим результат
Теперь давайте займемся приятным делом – красивыми изображениями на дисплее из файлов картинок.
Для этого на флешку скопируем несколько рисунков, один мой авторский, остальные – файлы из папок примеров, переименованные в удобные имена, чтобы не запутаться.
В файл ili9341.h добавим макрос для конвертирования пикселей в 16-битный формат.
#define WHITE 0xFFFF
#define convert24to16(x) (((x & 0x00f80000) >> 8 ) | ((x & 0x0000fc00) >> 5) |((x & 0x000000f8) >> 3))
Напишем функцию для вывода изображения
void TFT9341_DrawBitmap(uint16_t x, uint16_t y, char *s)
{
uint16_t i,h;
uint32_t index = 0, width = 0, height = 0, bitpixel = 0;
FRESULT res; /* FatFs function common result code */
uint32_t bytesread;
uint32_t tmpcolor;
uint8_t *bufbmp = NULL;
f_close(&MyFile);
if(f_open(&MyFile, s, FA_READ) != FR_OK)
{
Error_Handler();
}
else
{
bufbmp = (uint8_t*) malloc(100);
res = f_read(&MyFile, bufbmp, 90, (void *)&bytesread);
if((bytesread == 0) || (res != FR_OK))
{
Error_Handler();
}
else
{
index = bufbmp[10];//адрес начала данных в файле
index |= bufbmp[11] << 8;
index |= bufbmp[12] << 16;
index |= bufbmp[13] << 24;
width = bufbmp[18];//ширина растра
width |= bufbmp[19] << 8;
width |= bufbmp[20] << 16;
width |= bufbmp[21] << 24;
height = bufbmp[22];//высота растра
height |= bufbmp[23] << 8;
height |= bufbmp[24] << 16;
height |= bufbmp[25] << 24;
bitpixel = bufbmp[28];//формат пикселя (бит/пиксель)
bitpixel |= bufbmp[29] << 8;
for(h=0;h<height;h++)
{
for(i=0;i<width;i++)
{
switch(bitpixel)
{
case 24:
f_lseek(&MyFile,index+((height-h-1)*width*3)+(i*3));
res = f_read(&MyFile, bufbmp, 3, (void *)&bytesread);
if((bytesread == 0) || (res != FR_OK))
{
Error_Handler();
}
tmpcolor = bufbmp[0];
tmpcolor |= bufbmp[1]<<8;
tmpcolor |= bufbmp[2]<<16;
break;
}
if(((i+x)<width)|((h+y)<height))
TFT9341_DrawPixel(i+x,h+y,(uint16_t)convert24to16(tmpcolor));
}
}
f_close(&MyFile);
}
free(bufbmp);
}
}
//—————————————————————
Дальнейшую работу с данной функцией мы продолжим в следующей части занятия.
Предыдущая часть Программирование МК STM32 Следующая часть
Техническая документация на контроллер дисплея
Отладочную плату можно приобрести здесь STM32F4-DISCOVERY
Переходник I2C to LCD можно приобрести здесьI2C to LCD1602 2004
Где приобрести именно такой дисплей TFT 240×320, написать затрудняюсь, так как может прийти не всегда именно такой дисплей, какой заявлен в продаже. Либо придет подключаемый по SPI, либо с другим контроллером. Поэтому все тонкости уточняйте у продавца.
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)
Статьи конечно у вас интересные. Сам я часто посещаю ваш сайт и с удовольствием читаю опубликованные статьи.) Но вот код… И откуда вы его берете?(( Глазам больно от такого кода…
При открытии файла достаточно выполнить позиционирование функцией f_lseek один раз.
В цикл его помещать не надо.
Далее в цикле файл будет читаться с помощью функции f_read.
Также из цикла надо исключить функцию проверки формата пикселя. Зачем каждый раз проверять одно и то же значение?
А эти функции конвертирования цветов… Сначала из трех байтов «стряпается» 32-х разрядное значение, а потом оно конвертируется уже в 16-ти разрядное. Делаются совершенно лишние сдвиги которые отнимают процессорное время. Можно сразу же сделать 16-ти разрядное значение…
вот привожу свой код подпрограммы чтения bmp-файлов
Status_LCD ShowBMPfile (uint16_t x0, uint16_t y0, char *image)
{
FIL bmp;
UINT bytesRead;
uint16_t width_img, height_img; // ширина и высота картинки
if (f_open(&bmp, image, FA_READ )==FR_OK)
{
f_read(&bmp, img_buf, 48, &bytesRead);
if ((img_buf[0] != 0x42) || (img_buf[1] != 0x4D))
{
ILI_9341_Out_String(5, 290, RED, WHITE, «Этот файл не bmp- файл» );
f_close(&bmp);
return IMG_ERR;
}
width_img = img_buf[0x12] | img_buf[0x13] << 8 | img_buf[0x14] << 16 | img_buf[0x15] << 24; // ширина картинки
height_img = img_buf[0x16] | img_buf[0x17] << 8 | img_buf[0x18] << 16 | img_buf[0x19] << 24; // высота картинки
if ((width_img!=240) || (height_img != 320))
{
ILI_9341_Out_String(5, 290, RED, WHITE, "Неправильный формат файла!" );
f_close(&bmp);
return IMG_ERR;
}
uint32_t index = img_buf[0x0A] | (img_buf[0x0B] << 8) | (img_buf[0x0C] << 16) | (img_buf[0x0D] << 24); // начало данных
f_lseek(&bmp, index ); // позиционирование
uint16_t i;
uint16_t B, G, R;
for(int16_t y = 0; y < height_img; y++)
{
i=0;
f_read(&bmp, img_buf, width_img*3, &bytesRead);
for(int16_t x = 0; x >3;
G = (*(img_buf+i++) & 0xFC) <<3;
R = (*(img_buf+i++) & 0xF8) <<8;
Lcd_Write_Data ( R | G | B);
}
}
f_close(&bmp);
}
return IMG_OK;
}
что-то при вставке кода выпала строчка((
B = (*(img_buf+i++) & 0xF8) >>3;