Урок 58
Часть 2
System Workbench. System Workbench. LCD. SDIO
В предыдущей части урока мы познакомились с организацией памяти SDRAM на плате Discovery и подключили библиотеки, включая SDIO, FATFS, также подготовили проект и примонтировали файловую систему FAT.
Теперь собственно начнем писать функцию, которая будет переписывать содержимое файла в нужное место памяти SDRAM
/* USER CODE BEGIN 0 */
uint32_t OpenBMP(uint8_t *ptr, const char* fname)
{
uint32_t ind = 0, sz = 0, i1 = 0, ind1 = 0;
static uint32_t bmp_addr;
if(f_open(&MyFile, fname, FA_READ) != FR_OK)
{
BSP_LCD_Clear(LCD_COLOR_RED);
}
else
{
}
return 0;
}
/* USER CODE END 0 */
Здесь, я думаю всё понятно, так как с SD мы уже работали в стандартном проекте, тут ничего не изменилось.
Вызовем функцию в бесконечном цикле задачи по умолчанию
/* Infinite loop */
for(;;)
{
OpenBMP((uint8_t *)bmp1,«image01.bmp«);
osDelay(100);
}
/* USER CODE END 5 */
Можно собрать проект и убедиться, что дисплей у нас не покраснеет.
Добавим библиотеку в файл main.c
/* USER CODE BEGIN Includes */
#include <stdlib.h>
#include <string.h>
Теперь пишем код данной функции дальше. Определим размер нашего файла, а также размер заголовка, чтобы перейти непосредственно к данным изображения
BSP_LCD_Clear(LCD_COLOR_RED);
}
else
{
if (f_read (&MyFile, sect, 30, (UINT *)bytesread) != FR_OK)
{
Error_Handler();
}
else
{
bmp_addr = (uint32_t)sect;
sz = *(uint16_t *) (bmp_addr + 2);
sz |= (*(uint16_t *) (bmp_addr + 4)) << 16;
/* Get bitmap data address offset */
ind = *(uint16_t *) (bmp_addr + 10);
ind |= (*(uint16_t *) (bmp_addr + 12)) << 16;
f_close (&MyFile);
}
Продолжаем писать дальше.
Файл нужно будет открыть заново (хотя это и необязательно), а потом не забыть закрыть.
Пока напишем счётчик размера, чтобы не уйти за его пределы
f_close (&MyFile);
f_open (&MyFile, fname, FA_READ);
ind=0;
do
{
if (sz < 512)
{
i1 = sz;
}
else
{
i1 = 512;
}
sz -= i1;
}
while (sz > 0);
f_close (&MyFile);
Теперь будем читать постепенно секторы с SD-карты (не обязательно по 512, я пробовал по 8192 — работает ещё быстрее)
sz -= i1;
f_lseek(&MyFile,ind1);
f_read (&MyFile, sect, i1, (UINT *)&bytesread);
memcpy((void*)(bmp1+ind1), (void*)sect, i1);
ind1+=i1;
}
Также не забываем обнулить счётчик
f_close (&MyFile);
}
ind1=0;
}
Теперь в задаче по умолчанию вызовем функцию библиотеки BSP для отрисовки изображения из памяти SDRAM на экран дисплея
OpenBMP((uint8_t *)bmp1,«image01.bmp«);
BSP_LCD_DrawBitmap(0,0,(uint8_t *)bmp1);
osDelay(100);
Но прежде чем собирать проект, запускать его и любоваться картинкой, необходимо отключить оптимизацию, иначе никаких картинок мы не увидим. В свойствах проекта в C/C++ Build -> Settings -> Tool Settings -> MCU GCC Compiler -> Optimization установим следующий параметр Optimization level
Теперь можно собрать проект и запустить его на выполнение. Картинка должна появиться на экране
Можно подключить остальные картинки, пусть появляются по очереди
osDelay(100);
OpenBMP((uint8_t *)bmp1,«image02.bmp«);
BSP_LCD_Clear(LCD_COLOR_BLACK);
BSP_LCD_DrawBitmap(0,0,(uint8_t *)bmp1);
osDelay(100);
OpenBMP((uint8_t *)bmp1,«image03.bmp«);
BSP_LCD_DrawBitmap(0,0,(uint8_t *)bmp1);
osDelay(100);
OpenBMP((uint8_t *)bmp1,«image04.bmp«);
BSP_LCD_DrawBitmap(0,0,(uint8_t *)bmp1);
osDelay(100);
}
/* USER CODE END 5 */
Соберем проект и посмотрим ещё раз на все 4 картинки
На этом можно было бы закончить урок, но надо же нам как-то увидеть нотку многозадачности.
Давайте время от времени будем рисовать в углу прямоугольник неопределённого цвета. Для этого во вторую задачу добавим следующий код
void StartTask02(void const * argument)
{
/* USER CODE BEGIN StartTask02 */
/* Infinite loop */
for(;;)
{
BSP_LCD_SetTextColor((uint32_t)(LCD_COLOR_TRANSPARENT|((rand()%256)<<16)|((rand()%256)<<8)|(rand()%256)));
BSP_LCD_FillRect(384,136,96,136);
osDelay(10000);
}
/* USER CODE END StartTask02 */
}
Соберем проект и прошьём контроллер. Прямоугольник иногда появляется
Также теперь можно поиграть с размером сектора.
Сначала заменим в трех местах значение 512 на 4096
extern char SD_Path[4]; /* SD logical drive path */
uint8_t sect[4096];
…
do
{
if (sz < 4096)
{
i1 = sz;
}
else
{
i1 = 4096;
}
После этого мы с вами увидим значительное увеличение скорости перебороски изображения с карты в память SDRAM. Прежде чем вернуть всё на место, попробуем увеличить до 8192 и тогда мы заметим ещё прирост производительности считывания файла.
Ну теперь можно вернуть всё на место, а можно и так оставить.
Считаю, что цель нашего занятия сегодня достигнута. Мы подключили шину SDIO, причём автономно, без применения библиотеки BSP. Сейчас данная библиотека у нас используется только для работы с дисплеем.
Также советую посмотреть видеоурок особенно тем у кого нет такой платы, чтобы увидеть всё воочию.
Предыдущая часть Программирование МК STM32 Следующий урок
Отладочную плату можно приобрести здесь 32F746G-DISCOVERY
Смотреть ВИДЕОУРОК
Добрый день!
Интересует такой вопрос. А как посчитать: сколько памяти отвести под задачу для записи на карту памяти по SDIO? У Вас отведено 1280. Однако это достаточно много, так как FreeRTOS requires to allocate in the heap for that user task:
number of bytes = TCB size + (4 * task stack size), то есть аж 5240.
Использую плату STM32F4Discovery. По умолчанию в CubeMX стоит TOTAL_HEAP_SIZE=15360. Таким образом, памяти остается маловато на другие задачи (всего 9488 Bytes). И сколько можно отвести вообще? Всю RAM?
Спасибо!
Здравствуйте!
Я не считал, сколько именно нужно. Последовал совету коллеги и увеличил в 10 раз, приписав 0. Поэтому подсказать не могу, так как нужно от и до знать алгоритм работы ОС.
Привет и приятный день, в первую очередь большой комплимент для этой домашней страницы с большим количеством интересных уроков о STM32. Я пришел на урок 58, и все предыдущие уроки были понятны и работали. У меня есть вопрос о уроке 58, с которым у меня возникают проблемы. Я могу понять, какая программа создана, но она не работает над обнаружением STM32F746. По-видимому, новые версии драйверов CubeMX версии 4.27 и F7V1.12 создают другой код. Вы также столкнулись с этими проблемами? По-видимому, программа зависает в f_open до таймаута.
У вас есть подсказка для меня, как получить пример с более новыми версиями или подходом, который был изменен? (SD-карта работает без FREERTOS)
Заранее спасибо!
С наилучшими пожеланиями
Карстен Шульц