Урок 44
SDIO. FATFS
Проект создаём из проекта I2CLCD80. Назовем его SDIO_FATFS. Запустим проект в Cube.
Лапки портов PD4-PD7, PB8, PB9 отключим, это пережиток прошлых занятий
Включим SDIO
У нас включатся следующие лапки портов
На основе данной информации составим таблицу подключения ножек флеш-карты Micro SD
Порядок подключения Micro SD к микроконтроллеру STM32F407VG
Контакт Micro SD |
Ножка порта МК |
Назначение вывода |
1 |
PC10 |
SDIO_D2 |
2 |
PC11 |
SDIO_D3 |
3 |
PD2 |
SDIO_CMD |
4 |
3V |
+3,3 V (VDD) |
5 |
PC12 |
SDIO_CK |
6 |
GND |
GND (VSS) |
7 |
PC8 |
SDIO_D0 |
8 |
PC9 |
SDIO_D1 |
В Clock Configuration настроим делители (нажмите на картинку для увеличения)
Включим PD12 на выход
Включим FATFS / SD Card
В FATFS Configuration включим поддержку больших секторов на всякий случай
И самое главное те, у кого нет в модуле или на плате, на которой установлен держатель, подтягивающих сопротивлений, включим его на пяти основных лапках SDIO (на всех, кроме CS) (нажмите на картинку для увеличения).
Сгенерируем и откроем проект, подключим lcd.c, настроим программатор на авторезет.
Прошьем контроллер, чтобы проверить, правильно ли мы все подсоединили и работает ли у нас дисплей.
Из функции main() удалим лишнее по дисплею, оставив только инициализацию и очистку
/* USER CODE BEGIN 2 */
LCD_ini();
LCD_Clear();
/* USER CODE END 2 */
Строчную переменную тажке можно удалить
/* USER CODE BEGIN 1 */
char str[100];
/* USER CODE END 1 */
Добавим несколько переменных в main.c
/* USER CODE BEGIN 0 */
FATFS SDFatFs; /* File system object for SD card logical drive */
FIL MyFile; /* File object */
extern char SD_Path[4]; /* SD logical drive path */
/* USER CODE END 0 */
Примонтируем раздел с карты
LCD_Clear();
if(f_mount(&SDFatFs, (TCHAR const*)SD_Path, 0) != FR_OK)
{
Error_Handler();
}
else
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
}
/* USER CODE END 2 */
Соберем проект, прошьем контроллер, проверим, что у нас все примонтировалось.
Откроем файл
else
{
if(f_open(&MyFile, «my001.txt», FA_READ) != FR_OK)
{
Error_Handler();
}
else
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
f_close(&MyFile);
}
}
/* USER CODE END 2 */
Добавим ряд переменных в main()
/* USER CODE BEGIN 1 */
FRESULT res; /* FatFs function common result code */
uint32_t byteswritten, bytesread; /* File write/read counts */
uint8_t wtext[] = «Hello from Stm32!!!»; /* File write buffer */
uint8_t rtext[100]; /* File read buffer */
/* USER CODE END 1 */
Попробуем прочитать текст из файла и отобразить его на нашем дисплее
else
{
res = f_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread);
if((bytesread == 0) || (res != FR_OK))
{
Error_Handler();
}
else
{
LCD_Clear();
LCD_SetPos(0,0);
rtext[bytesread]=0;
LCD_String((char*)rtext);
f_close(&MyFile);
}
}
Соберем проект, прошьем контроллир и посмотрим результат нашей работы на дисплее.
Теперь попробуем что-нибудь записать
Код, который предназанчен для чтения продублируем, один дубль закоментируем и еще вверху подставим комментарий
//Read
// if(f_mount(&SDFatFs, (TCHAR const*)SD_Path, 0) != FR_OK)
// {
// Error_Handler();
// }
// else
// {
// if(f_open(&MyFile, «my001.txt», FA_READ) != FR_OK)
// {
// Error_Handler();
// }
// else
// {
// res = f_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread);
// if((bytesread == 0) || (res != FR_OK))
// {
// Error_Handler();
// }
// else
// {
// LCD_Clear();
// LCD_SetPos(0,0);
// rtext[bytesread]=0;
// LCD_String((char*)rtext);
// f_close(&MyFile);
// }
// }
// }
А другой дубль будем исправлять на запись, кое-что также в нем сначала закоментировав, функцию f_close() перенесем ниже за другую скобку, чтобы файл у нас закрывался строго, также изменим имя файла и флаги открытия файла и зажжем в случае успеха светодиод
//Write
if(f_mount(&SDFatFs, (TCHAR const*)SD_Path, 0) != FR_OK)
{
Error_Handler();
}
else
{
if(f_open(&MyFile, «mywrite.txt«, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
{
Error_Handler();
}
else
{
// res = f_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread);
// if((bytesread == 0) || (res != FR_OK))
// {
// Error_Handler();
// }
// else
// {
// LCD_Clear();
// LCD_SetPos(0,0);
// rtext[bytesread]=0;
// LCD_String((char*)rtext);
// }
f_close(&MyFile);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); }
}
Если светодиод зажегся, то вызовы функций дисплея удалим, а также раскомментируем и исправим следующие строки
else
{
res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten);
if((byteswritten == 0) || (res != FR_OK))
{
Error_Handler();
}
else
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
}
f_close(&MyFile);
Немного исправим текст в переменной wtext, чтобы мы не думали что это текст из другого файла
uint8_t wtext[] = «Hello write from Stm32 to Micro SD!!!«; /* File write buffer */
Соберем проект, прошьем контроллер, отключим плату, извлечем флеш-карту из картодержателя, воткнем в картовод ПК и убедимся, что новый файл с содержимым у нас на карте появился.
Предыдущий урок Программирование МК STM32 Следующий урок
Отладочную плату можно приобрести здесь STM32F4-DISCOVERY
Удобный модуль Micro SD (SPI и SDIO) можно приобрести здесь Micro SD Модуль
Смотреть ВИДЕОУРОК
Здраствуйте!
Как можно скопировать txt. файл с sd большого размера в sdram?
Здравствуйте! Лучше всего организовать цикл и отправить частями.
Здравствуйте,
Не получается запись и чтение файла, при попытке записать файл МК зависает,
Хотя монтирование диска происходит без ошибки. (STM32F103ZET6)
/* USER CODE BEGIN 3 */
if(!HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11)) // ЗАПИСЬ
{
HAL_Delay(200);
if(f_open(&MyFile,"data.txt",FA_CREATE_ALWAYS|FA_WRITE)!= FR_OK)
{
ЗДЕСЬ ОШИБКА
HAL_UART_Transmit_IT(&huart1, err, 5); //
f_close(&MyFile);
Error_Handler();
}
else
{
res=f_write(&MyFile,wtext,sizeof(wtext),(void*)&byteswritten);
if((byteswritten==0)||(res!=FR_OK))
{
HAL_UART_Transmit_IT(&huart1, err2, 5); //отправить байт
Error_Handler();
}
else
{
//HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, GPIO_PIN_SET);
}
f_close(&MyFile);
}
} // end button
Бывает такое, попробуйте другие карты.
Не подскажите почему может выдавать ошибку FR_DISK_ERR
фунуция f_open. Такую же ошибку выдает функция f_mount если поставить последний параметр 1 (монтировать немедленно). Правильность подключения проверил несколько раз все правильлно.
И ещо вопрос по функции Error_Handler();. Что там должно быть у меня там пустой бесконечний цикл.
1. Видимо не прошла инициализации. Тогда её лучше вызвать отдельно. Либо проект в процессе написания. Бывает такое в этом случае. Надо время от времени снимать питание с носителя. Помогает.
2. Приблизительно то же самое.
3. Должен быть бесконечный цикл. Сделано для того, чтобы дальнейший код не пытался выполняться при ошибочных ситуациях.
Здравствуйте! STM32F405 подключена по SDIO карта памяти два вопроса: 1) Куб генерирует код hsd.Init.BusWide = SDIO_BUS_WIDE_1B; хотя мы работаем с 4х битной шиной?? 2) При записи большого файла ( просто пишу 1 млн значений подряд ++) при делителе SDIO 15 и выше работает стабильно, а при меньших делителях вылетает в ошибку FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ Частотата шины 55 МГц. Влияет ли длина проводов или что то еще? подтягивающих резисторов нет, только внутренняя подтяжка.
Спасибо.
Скорее всего длинные провода. Очень влияют. У меня нет подтяжки тоже. С делителем 2 работает стабильно (12 Мгц).
Здравствуйте! С удовольствием читаю и смотрю ваши уроки. В данном разделе работы с SDIO все получилось. А вот при попытке превратить связку STM32+SD(SDIO) в картридер (+USB в режиме Mass Stotage Class) получается только запись-чтение на SD карту. Форматирование SD через STM32 средствами Windows никак не проходит и есть вопросы по быстродействию работы с SD через USB. Не могли бы вы посвятить теме «Картридер на STM32» отдельный урок?
Спасибо!
Да вроде был по SDIO FATFS уже урок. А вообще поаккуратней с FATFS. Версия куба не должна быть новей чем 4.22.1
Да, но в нем ничего нет про работу с SD картой через USB Mass Stotage Class (STM32 не хост). Одним словом режим картридера для считывания накопленных ранее данных в ST32+SD через USB.
Здравствуйте! Все сделал как в описании, только f_open присваивается ошибка и на выходе с ног нету никаких подергиваний( Что может быть не так?
Возможно у Вас Cube версии 4.23. На этой версии работать не будет.
Да, куб действительно версии 4.23 . С большим уважением к Вам, подскажите, какую версию куба лучше использовать и в чем проблема у версии 4.23?
Если Вы регулярно просматриваете все мои страницы, я уже на этот вопрос отвечал много раз.
Изменилась версия FatFS, а в CubeMX это видимо не учли.
Версия 4.22.1
Установил куб 4.11 , подключил SD-reader с 1-канальной шиной данных, с ноги CMD и Dat0 на осциллографе видны сигналы, обмен есть, но файл так и не открывается( может еще что то есть?
Googl выдал:
Внимание! Переход на этот веб-сайт может быть опасен для вашего компьютера.
при переходе на «Программирование микроконтроллеров STM32. УРОК 37»
я бы на Вашем месте проверил сайт на вирус и взлом!
Так что же с новой FatFS? Неужели продолжения не будет? Вот и куб обновился, но этот глюк остался…
Нет, не остался. С 4 серией SDIO FatFS работает. Не работает пока с 7 серией контроллеров, но вскоре поправят.
У меня STM32F405, плату сам разводил. С помощью вашего урока N44 успешно запустил чтение-запись SD на старом кубе и старой фирмваре для этого чипа. Потом обновился до последней на сегодня версии и того и другого. Работать перестало. Заглянул в fatfs.c — увидел там измение идентификатора SD_Path на SDPath. Поменял соответственно в f_mount. Карта упорно не монтруется.
Огромная к Вам просьба — сделайте еще один урок по новой версии.
Вышла новая версия STM32CubeMX version 4.24.0
А так же новая версия STM32Cube FW_F4 V1.19.0
С ними SD карта снова работает.
Возможно, придётся пересоздать проект «с нуля».
Я приблизительно отвечал где-то то же самое. Для 4 версии контроллера поправили (для 1-й не проверял), а вот для 7-й (библиотека STM32Cube_FW_F7_V1.9.0) — пока нет. Но скоро всё поправят. Я передал в технический отдел.
>Вышла новая версия STM32CubeMX version 4.24.0
>А так же новая версия STM32Cube FW_F4 V1.19.0
Да, с ними действительно работает. Чтобы заработало, нужно в FATFS Configuration на вкладке IPs instances выставить Use dma template -> Disabled. По-умолчанию эта штука разрешена и по-умолчанию с ней не работает.
А все же хорошо бы еще один урок, только теперь с использованием SDIO DMA. Самому разобраться не получается, а нормальных примеров я не нашел…
ssp:, Спасибо за ответ! полдня из за этого гребанного DMA Убил. Автору спасибо за сайт, очень много полезной информации!!!
Я рад, что Вам нравится ресурс. Постараюсь и дальше соответствовать.
Добрый день очень полезный ресурс.
Много чему здесь научился.
Debug зависает именно здесь 4 разных карт перебробовал.
Форматировал и 16 и 32 бит
if(f_open(&MyFile,»mywrite.txt»,FA_CREATE_ALWAYS|FA_WRITE)!=FR_OK)
версия куба 4.25.1
зарание блогодарен.
В 4.25 прицепляется совсем другая версия FATFS.
добрый вечер, да вы правы, с 4,21 все работает отлично.
Здравствуйте.
Пытаюсь запустить FATFS на STM32L433, вылетает ошибка на f_open. Версия куба 4.25.1. Не подскажете, где взять более старые версии куба?
Здравствуйте! Хочу записывать логи с разных датчиков, для тестирования сделал вот такую функцию:
void SDwriteLog(uint8_t *wtext, uint8_t sz)
{
f_mount(&SDFatFs, (TCHAR const*)SD_Path, 1);
f_open(&MyFile, «myfile.txt», FA_WRITE);
for (char i=0; i<3; i++)
{
res = f_write(&MyFile, wtext, sz, (void*)&byteswritten);
if((byteswritten != sz) || (res != FR_OK))
{
//Делаем что-то если не записали в файл
}
else
{
//Все хорошо, файл записан
}
}
f_close(&MyFile);
f_mount(&SDFatFs, (TCHAR const*)SD_Path, 0);
}
В цикле удается записать три строки, но если файл каждый раз открывать и закрывать в цикле, то строка получается только одна. Я так понимаю если при записи каждой строки открывать/закрывать файл то дописывать уже не может.
Собственно вопрос — с каким аргументом нужно открыть файл чтобы появилась возможность дописывать строки не удаляя прежнюю информацию
Здравствуйте!
Это от аргументов не зависит. Открываете файл, измеряете его размер и дописывайте куда хотите. Ставите указатель в любое место и пишите сколько угодно. Есть специальная для этого функция f_lseek.
Спасибо!
добавил две строчки:
if(MyFile.fsize)
f_lseek(&MyFile, MyFile.fsize); после открытия файла.
Теперь продолжает писать файл даже после извлечения карты.
А я считал что f_lseek только для чтения
Здравствуйте.
Объясните пожалуйста почему Вы установили MAX_SS =4096?
В справке по FATfs я нашел «Always set 512 for memory card and hard disk…».
Может быть имелся ввиду размер кластера а не сектора?
Вроде бы в спецификации SD размер сектора тоже указан 512.
Проясните пожалуйста этот момент, а то я запутался.
Всегда так делаю, так сказать, навырост. Существует ряд носителей с таким размером блока.
Приведите пожалуйста пример носителя с таким размером блока, сам не смог таких найти.
Здравствуйте.
Подскажите как записать дату создания файла, например 20 мая 2015 14:52?
Здравствуйте.
Пытаюсь запустить sd карту на stm32f411, сделал все по Вашему уроку, но данные на карту не записываются.
Команда f_mount проходит, а команда f_open выкидывает в while.
При проверке Logic-ом, видно что ck тактируется на частоте 400кГц, проходит 3 команды и все.
Здравствуйте!
Посмотрите примеры для своего контроллера в репозитории, так как со времён урока изменилась HAL в отношении работы с SDIO, а также FATFS.