STM Урок 44. SDIO. FATFS

Урок 44

 

SDIO. FATFS

 

Проект создаём из проекта I2CLCD80. Назовем его SDIO_FATFS. Запустим проект в Cube.

Лапки портов PD4-PD7, PB8, PB9 отключим, это пережиток прошлых занятий

 

image03

 

Включим SDIO

 

image05

 

У нас включатся следующие лапки портов

 

image04

 

На основе данной информации составим таблицу подключения ножек флеш-карты 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 настроим делители (нажмите на картинку для увеличения)

 

image07_0500

 

 

Включим PD12 на выход

 

image06

 

Включим FATFS / SD Card

 

image01

 

В FATFS Configuration включим поддержку больших секторов на всякий случай

 

image00

 

И самое главное те, у кого нет в модуле или на плате, на которой установлен держатель, подтягивающих сопротивлений, включим его на пяти основных лапках SDIO (на всех, кроме CS) (нажмите на картинку для увеличения).

 

image02_0500

 

Сгенерируем и откроем проект, подключим 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 */

Соберем проект, прошьем контроллер, отключим плату, извлечем флеш-карту из картодержателя, воткнем в картовод ПК и убедимся, что новый файл с содержимым у нас на карте появился.

 

 

 

Исходный код

 

 

Отладочную плату можно приобрести здесь STM32F4-DISCOVERY

Модуль Micro SD (SDIO) можно приобрести здесь Micro SD Модуль

 

 

Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)

STM SDIO. FATFS

 

Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)

STM SDIO. FATFS

39 комментариев к “STM Урок 44. SDIO. FATFS

  1. Здравствуйте,

    Не получается запись и чтение файла, при попытке записать файл МК зависает,

    Хотя монтирование диска происходит без ошибки. (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

  2. Не подскажите почему может выдавать ошибку FR_DISK_ERR

    фунуция f_open. Такую же ошибку выдает функция f_mount если поставить последний параметр 1 (монтировать немедленно). Правильность подключения проверил несколько раз все правильлно.

    И ещо вопрос по функции Error_Handler();. Что там должно быть у меня там пустой бесконечний цикл.

    • 1. Видимо не прошла инициализации. Тогда её лучше вызвать отдельно. Либо проект в процессе написания. Бывает такое в этом случае. Надо время от времени снимать питание с носителя. Помогает.

      2. Приблизительно то же самое.

      3. Должен быть бесконечный цикл. Сделано для того, чтобы дальнейший код не пытался выполняться при ошибочных ситуациях.

  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 МГц. Влияет ли длина проводов или что то еще? подтягивающих резисторов нет, только внутренняя подтяжка.

    Спасибо.

  4. Здравствуйте! С удовольствием читаю и смотрю ваши уроки. В данном разделе работы с SDIO все получилось. А вот при попытке превратить связку STM32+SD(SDIO) в картридер (+USB в режиме Mass Stotage Class) получается только запись-чтение на SD карту. Форматирование SD через STM32 средствами Windows никак не проходит и есть вопросы по быстродействию работы с SD через USB. Не могли бы вы посвятить теме «Картридер на STM32» отдельный урок?

    Спасибо!

      • Да, но в нем ничего нет про работу с SD картой через USB Mass Stotage Class (STM32 не хост). Одним словом режим картридера для считывания накопленных ранее данных в ST32+SD через USB.

  5. Googl выдал:
    Внимание! Переход на этот веб-сайт может быть опасен для вашего компьютера.

    при переходе на «Программирование микроконтроллеров STM32. УРОК 37»
    я бы на Вашем месте проверил сайт на вирус и взлом!

  6. У меня STM32F405, плату сам разводил. С помощью вашего урока N44 успешно запустил чтение-запись SD на старом кубе и старой фирмваре для этого чипа. Потом обновился до последней на сегодня версии и того и другого. Работать перестало. Заглянул в fatfs.c — увидел там измение идентификатора SD_Path на SDPath. Поменял соответственно в f_mount. Карта упорно не монтруется.
    Огромная к Вам просьба — сделайте еще один урок по новой версии.

  7. Вышла новая версия STM32CubeMX version 4.24.0
    А так же новая версия STM32Cube FW_F4 V1.19.0
    С ними SD карта снова работает.
    Возможно, придётся пересоздать проект «с нуля».

    • Я приблизительно отвечал где-то то же самое. Для 4 версии контроллера поправили (для 1-й не проверял), а вот для 7-й (библиотека STM32Cube_FW_F7_V1.9.0) — пока нет. Но скоро всё поправят. Я передал в технический отдел.

  8. >Вышла новая версия STM32CubeMX version 4.24.0
    >А так же новая версия STM32Cube FW_F4 V1.19.0

    Да, с ними действительно работает. Чтобы заработало, нужно в FATFS Configuration на вкладке IPs instances выставить Use dma template -> Disabled. По-умолчанию эта штука разрешена и по-умолчанию с ней не работает.

  9. А все же хорошо бы еще один урок, только теперь с использованием SDIO DMA. Самому разобраться не получается, а нормальных примеров я не нашел…

  10. ssp:, Спасибо за ответ! полдня из за этого гребанного DMA Убил. Автору спасибо за сайт, очень много полезной информации!!!

  11. Добрый день очень полезный ресурс.
    Много чему здесь научился.

    Debug зависает именно здесь 4 разных карт перебробовал.
    Форматировал и 16 и 32 бит
    if(f_open(&MyFile,»mywrite.txt»,FA_CREATE_ALWAYS|FA_WRITE)!=FR_OK)
    версия куба 4.25.1

    зарание блогодарен.

  12. Здравствуйте.
    Пытаюсь запустить FATFS на STM32L433, вылетает ошибка на f_open. Версия куба 4.25.1. Не подскажете, где взять более старые версии куба?

  13. Здравствуйте! Хочу записывать логи с разных датчиков, для тестирования сделал вот такую функцию:

    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 только для чтения

  14. Здравствуйте.
    Объясните пожалуйста почему Вы установили MAX_SS =4096?
    В справке по FATfs я нашел «Always set 512 for memory card and hard disk…».
    Может быть имелся ввиду размер кластера а не сектора?
    Вроде бы в спецификации SD размер сектора тоже указан 512.
    Проясните пожалуйста этот момент, а то я запутался.

  15. Здравствуйте.
    Пытаюсь запустить sd карту на stm32f411, сделал все по Вашему уроку, но данные на карту не записываются.
    Команда f_mount проходит, а команда f_open выкидывает в while.
    При проверке Logic-ом, видно что ck тактируется на частоте 400кГц, проходит 3 команды и все.

    • Здравствуйте!
      Посмотрите примеры для своего контроллера в репозитории, так как со времён урока изменилась HAL в отношении работы с SDIO, а также FATFS.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

*