0 / 0 / 0
Регистрация: 06.11.2013
Сообщений: 26
1

[Решилось]Странная проблема с FatFs

24.02.2014, 07:30. Показов 4640. Ответов 5
Метки нет (Все метки)

Наткнулся на очень странную проблему с FatFs Chanа и есть подозрения что что-то делаю не так, но непонятно что.

Ситуация такая: я делаю MP3-плеер который читает файлы с карты. У меня есть рабочий файловый менеджер и плеер, который проигрывает файл без проблем. Я хочу сделать ему кнопку, которая позволяет пропускать песню и играть следующую. Следующую в смысле ту, которая после текущей песни в данной папке.

Алгоритм такой - по нажатию на кнопку:

1. Открываем текущую папку (текущая папка корректная, потому что мы зашли в нее с помощью файлового менеджера, который работает хорошо).
2. Пропускаем первые два объекта ("." и "..").
3. Ищем ту песню, которая только что проигрывалась.
4. Когда мы ее находим, то остается только отправить на проигрывание следующую песню (объект с расширением ".mp3", ".wav" и так далее).

Код вот такой:

Код
int VSTestHomdleFile(const char *fileName, int record) {
poymt_areaLCD(0, 0, 479, 271, 0xFFFF);
uint8_t next_action = 1;
if (!record) {
DIR directory;
FIL audyo_file;
while (next_action) {
FRESULT result = f_open(&audyo_file, fileName, FA_READ|FA_OPEN_EXISTING); //открыть текущую песню
if (result == FR_OK) {
uint32_t size = f_size(&audyo_file);
char size_to_dysplay[11];
itoo32bits(size, size_to_dysplay);
uint16_t length = write_phraseLCD((char *)fileName, 13, 29, 0, 0x0000, 0xFFFF);
poymt_areaLCD(length + 1, 0, 199, 31, 0xFFFF);
length = write_numberLCD(size_to_dysplay, 11, 240, 0, 0x0000, 0xFFFF);
write_phraseLCD(" bytes", 6, length + 1, 0, 0x0000, 0xFFFF);
next_action = VS1053PlayFile(&audyo_file/*fp*/); //воспроизвести ее
f_close(&audyo_file); //закрыть файл на всякий случай
if (next_action == 2) { //если пользователь нажал на кнопку, VS1053PlayFile() вернет 2
result = f_opendir(&directory, current_directory_path); //current_directory_path[0] = ., current_directory_path[1] = 0
FILINFO next_file;
if (depth != 0) { //читаем первые два объекта - "." и ".."
result = f_readdir(&directory, &next_file);
result = f_readdir(&directory, &next_file);
}
if (result == FR_OK) {
uint8_t found_next = 0;
uint8_t found_current = 0;
while(!found_next) {
result = f_readdir(&directory, &next_file);
if (next_file.fname[0] == 0 || result != FR_OK) { //если мы дошли до конца папки
if (next_file.fname[0] == 0) { //постоянно заходит сюда
[...];
}
found_next = 1;
}
else { //еще не дошли до конца
if (!mem_cmp((void*)fileName, (void*)next_file.fname, 12)) found_current = 1; //нашли текущий файл
else if (found_current && (check_extension((char*)fileName, ".WAV", 4) || //если нашли текущий, то проверяем каждый следующий, песня ли это
check_extension((char*)fileName, ".MP3", 4) ||
check_extension((char*)fileName, ".FLA", 4) ||
check_extension((char*)fileName, ".WMA", 4) ||
check_extension((char*)fileName, ".M4A", 4))) {
mem_cpy((void*)fileName, (char*)next_file.fname, 13);
found_next = 1;
}
}
}
f_closedir(&directory);
}
}
}
else {
[...]
}
Этот код не работает. По непонятным причинам он постоянно заходит в то ответвление, которое для случая, когда мы дошли до конца папки (а текущая песня последняя).

Странность заключается в том, что я использую идентичный алгоритм для файлового менеджера и он работает без проблем в тех же самых папках. Он читает все файлы в одной папке пропустив первые два объекта. Читает их до тех пор, пока не дойдем для условия, что мы в конце папки. Здесь же, независимо от того, какой файл был открыт, он всегда как будто в самом конце папки.

Причем в одной из папок этот код все-таки работает и крайне странно. Если я открываю первый файл в папке (с именем dod.mp3), то его нельзя пропустить. Зато если открою следующий файл (NUMBER_9.WAV), то этот файл можно будет пропустить и так дойти до конца папки. Если после этого снова открыть dod.mp3, то его теперь вдруг тоже можно пропустить, правда не с первого раза. Если нажать на кнопку один раз, то он выдаст, что мы в конце папки. Если нажать второй, то он пропустит файл и начнет играть NUMBER_9.WAV.

В других папках, где я тестирую эту функцию такого не происходит, но там везде однородные файлы (либо .mp3, либо .wav) и у них имена типа 01.mp3, 02.mp3 и так далее.

Честно говоря, это один из самых странных багов, какие я видел. Пытаюсь понять в чем дело, но думаю что хуже не будет если я напишу здесь и спрошу вашего мнения.

Пробовал делать rewind после каждого открытия папки - без толку. Параметр _FS_RPATH == 1. Имена имеют ограничение 8 символов + 3 символа расширения.
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.02.2014, 07:30
Ответы с готовыми решениями:

FatFs STM32F407 проблема с записью на SDHC
Здравствуйте, дело в том, что пытаюсь записать файл на SD карту. Пробывал через SPI и через SDIO....

STM32F4 + fatfs проблема (ошибка FR_NO_FILESYSTEM)
Здравствуйте. Столкнулся с такой проблемой. Использую контроллер STM32F407. Пытаюсь поднять...

Странная проблема с обращением к переменной
Предельно простой код: volatile uint32_t counter_of_free_time, full_time, schet_pressotir; void...

FATFS и HardFault
Доброго времени суток! Играюсь с LPC1769 (ARM M3). точнее прикручиваю Fat_FS. В процессе...

5
0 / 0 / 0
Регистрация: 06.11.2013
Сообщений: 26
24.02.2014, 07:48 2
Сделал DIR directory глобальной переменной, открывает ее только файловый менеджер. Вместо открытия в коде вверху делаю rewind: result = f_readdir(&directory, (FILINFO*)0);

Разницы вообще никакой, работает так же, как с локальным DIR.
0
0 / 0 / 0
Регистрация: 06.11.2013
Сообщений: 26
25.02.2014, 08:32 3
Проблема решилась. В общем, я просто неправильно использовал функцию mem_cmp(). Я считал, что имена файлов в памяти выглядят так: song.mp300000. На самом деле имя файла всегда заканчивается на /0, но нет никакой гарантии что дальше там тоже именно нули. Поэтому, так как mem_cmp() проверяла все 13 символов, она выдавала разными одинаковые имена с определенной вероятностью, которая я не знаю от чего именно зависела, но, в общем, проблема была именно в этом.

Сейчас я использую функцию, которая сравнивает имя файла до того момента, как она найдет ноль.

Еще в коде вверху ошибка: вместо check_extension((char*)fileName, ".WAV", 4) и других должно быть check_extension((char*)next_file.fname, ".WAV", 4).
0
0 / 0 / 0
Регистрация: 11.09.2016
Сообщений: 78
22.09.2016, 18:15 4
У меня есть рабочий файловый менеджер и плеер
оЧЕНЬ интересно.. у меня есть плата с дисплеем и micro-SD библиотеки STemWin и FatFs подключены.. все работает, а вот файлового менеджера нету. Не могли бы Вы им поделиться?
0
0 / 0 / 0
Регистрация: 23.10.2014
Сообщений: 243
22.09.2016, 18:26 5
функция, которая сравнивает имя файла до того момента, как она найдет ноль - это функция сравнения строк str_cmp. Очевидно имя файла это строка
0
0 / 0 / 0
Регистрация: 15.02.2015
Сообщений: 444
27.09.2016, 10:51 6
А у вас какая версия FatFS? Совсем недавно автор переработал библиотеку и улучшил поддержку длинных имен файлов (раньше тоже можно было, но с костылями). В общем, имеет смысл обновиться, если еще нет.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.09.2016, 10:51

STM32F103 + FatFS
Доброго времени суток! Макет диктофона, SD-Card. Дискретизация 6.250кГц. Буфер 512, через DMA. В...

STM32 Fatfs+MS
Всем доброго дня! Возникла следующая проблема - есть плата steval-ccm008v1, с контроллером...

fatfs и 4ГБ SDHC
Всем доброго времени суток. Столкнулся с такой проблемой, что подключил к МК TFT_320QVT, но...

STM32L053 Nucleo+ fatfs
Товарищи, я уже отчаялся. В cube выставил spi, прикрутил галочкой fatfs и как дальше то быть? Где...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.