AVR Урок 33. SPI. Карта SD. FAT. Часть 6

 

 

 

 

Урок 33

Часть 6

 

SPI. Карта SD. FAT

 

 

В предыдущей части занятия мы считали данные с флеш-карты и записали на неё также данные, также мы проверили данные результаты.

А в данной части мы устраним мелкие ошибки, а также вместо цифрового отображения результата действий с картой SD мы напишем код для отображения в более удобочитаемом текстовом виде.
Также мы удалим лишние неиспользуемые функции и фрагменты исходного кода.

Сначала удалим вот эти строки из функции main()

 

clearlcd();//очистим дисплей

setpos(0,0);

str_lcd("String 1");

setpos(2,1);

str_lcd("String 2");

setpos(4,2);

str_lcd("String 3");

setpos(6,3);

str_lcd("String 4");

_delay_ms(1000);

 

Также уберём закомментированный буфер в начале главного модуля

 

//char buffer[512] ="Sel…ия";

 

Также в функции disk_initialize в файле mmc.c закомментируем код вывода на дисплей и некоторый другой код. Можно, конечно, и удалить, но мало ли кому пригодится.

Поэтому под спойлером приведу полный код функции со всеми комментариями.

 

disk_initialize

DSTATUS disk_initialize (void)

{

  BYTE n, cmd, ty, ocr[4];

  WORD tmr;

  INIT_SPI();

  // if ((PINB&_BV(SD_INS))!=0x00) return STA_NOINIT;

  #if _WRITE_FUNC

  if (MMC_SEL) disk_writep(0, 0); // Finalize write process if it is in progress

    #endif

    for (n = 100; n; n—) rcv_spi(); // Dummy clocks

    ty = 0;

    if (send_cmd(CMD0, 0) == 1) { // Enter Idle state

    if (send_cmd(CMD8, 0x1AA) == 1) { // SDv2

      // setpos(0,3);

      // str_lcd("SDv2");

      for (n = 0; n < 4; n++) ocr[n] = rcv_spi(); // Get trailing return value of R7 resp

      // setpos(8,0);

      // sprintf(str,"%02X",ocr[3]);

      // str_lcd(str);

      // setpos(11,0);

      // sprintf(str,"%02X",ocr[2]);

      // str_lcd(str);

      // setpos(14,0);

      // sprintf(str,"%02X",ocr[1]);

      // str_lcd(str);

      // setpos(17,0);

      // sprintf(str,"%02X",ocr[0]);

      // str_lcd(str);

      if (ocr[2] == 0x01 && ocr[3] == 0xAA) { // The card can work at vdd range of 2.7-3.6V

        // setpos(5,3);

        // str_lcd("AA01");

        for (tmr = 12000; tmr && send_cmd(ACMD41, 1UL << 30); tmr—) ; // Wait for leaving idle state (ACMD41 with HCS bit)

        if (tmr && send_cmd(CMD58, 0) == 0) { // Check CCS bit in the OCR

          // setpos(10,3);

          // str_lcd("CCS");

          for (n = 0; n < 4; n++) ocr[n] = rcv_spi();

          // setpos(8,1);

          // sprintf(str,"%02X",ocr[3]);

          // str_lcd(str);

          // setpos(11,1);

          // sprintf(str,"%02X",ocr[2]);

          // str_lcd(str);

          // setpos(14,1);

          // sprintf(str,"%02X",ocr[1]);

          // str_lcd(str);

          // setpos(17,1);

          // sprintf(str,"%02X",ocr[0]);

          // str_lcd(str);

          ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; // SDv2 (HC or SC)

        }

      }

    } else { // SDv1 or MMCv3

      if (send_cmd(ACMD41, 0) <= 1) {

        ty = CT_SD1; cmd = ACMD41; // SDv1

      } else {

        ty = CT_MMC; cmd = CMD1; // MMCv3

      }

      for (tmr = 25000; tmr && send_cmd(cmd, 0); tmr—) ; // Wait for leaving idle state

      if (!tmr || send_cmd(CMD16, 512) != 0) // Set R/W block length to 512

      ty = 0;

    }

  }

  CardType = ty;

  // sprintf(str,"%d",CardType);

  // setpos(0,1);

  // str_lcd(str);

  release_spi();

  return ty ? 0 : STA_NOINIT;

}

 

А вообще, весь полный код содержится по ссылке "исходный код" внизу страницы.

Также закомментируем код вывода на дисплей в файле pff.c

 

fmt = check_fs(buf, bsect); /* Check sector 0 as an SFD format */

// sprintf(str,"%d",fmt);

// setpos(4,0);

// str_lcd(str);

 

Теперь внесём некоторые поправки в главной функции main().

Позиционирование дисплея в верхний левый угол перенесём вот в это место, а также напишем туда строку

 

setpos(0,0);

str_lcd("Mount SD… ");

res=pf_mount(&fs);

 

Между вызовом функции монтирования и открытия файла всё удалим, а вместо удалённого вставим вот такой код, в котором мы отчитаемся на дисплее, примонтировался ли у нас раздел, в противном случае собщим об ошибке

 

res=pf_mount(&fs);

if (res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

res=pf_open("/123.txt"); //Попытка открыть файл 123.txt

 

Теперь соберём код, прошьём контроллер и посмотрим, как у нас всё отображается

 

Image51

 

Всё у нас получилось, только конечно информация затем затирается, но это мы всё постепенно поправим.

После задержки вставим следующий подобный код только для открытия файла

 

_delay_ms(1000);

setpos(0,3);

str_lcd("Open file… ");

res=pf_open("/123.txt"); //Попытка открыть файл 123.txt

 

 

Затем между функцией открытия файла и позиционирования указателя в файле удалим весь код и вставим вот такой код, который отчитается об успешном или неуспешном открытии файла и также подготовит следующую строку о попытке установки указателя в определённую позицию в файле

 

res=pf_open("/123.txt"); //Попытка открыть файл 123.txt

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

setpos(0,2);

str_lcd("Move pointer… ");

res=pf_lseek(0); //Установим курсор чтения на 0 в 123.txt

 

Подобные действия проделаем и между вызовом функции установки уазателя и функции чтения байтов из файла

 

res=pf_lseek(0); //Установим курсор чтения на 0 в 123.txt

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

setpos(0,3);

str_lcd("Read file… ");

res=pf_read(buffer2,128,&s1);

 

Теперь мы дошли до такого момента, когда у нас закончились строки на дисплее, а также до того состояния, когда нам нужно будет вывести строку. Отлично, что всё совпало. Поэтому между функцией чтения байтов в буфер и размонтирования раздела мы сначала отчитаемся о результате считывания, подождём побольше, очистим дисплей выведем строку и на следующей строке заготовим информацию о размонтированиии раздела

 

res=pf_read(buffer2,128,&s1);

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(2000);

clearlcd();//очистим дисплей

setpos(0,0);

str_lcd(buffer2);

_delay_ms(1000);

setpos(0,1);

str_lcd("Unmout SD… ");

res=pf_mount(0x00);//Демонтируем файловую систему карты

 

Соберём код, пршьём контроллер и посмотрим результат, а то если не проверять, исправлять будет потом трудно

 

Image52 Image53

 

Отлично всё сработало.

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

 

продолжаем писать main()

res=pf_mount(0x00);//Демонтируем файловую систему карты

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

setpos(0,2);

str_lcd("Mount SD… ");

res=pf_mount(&fs);

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

setpos(0,3);

str_lcd("Open file… ");

res=pf_open("/123.txt"); //Попытка открыть файл 123.txt, чтобы в него записать данные

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(2000);

sprintf(buffer2,"World Hello!");

clearlcd();//очистим дисплей

setpos(0,0);

str_lcd("Write data… ");

res=pf_write(buffer2,strlen(buffer2),&s1);//Запишем текст из buffer2 в файл 123.txt

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

setpos(0,1);

str_lcd("Finalise… ");

res=pf_write(0,0,&s1);//Финализируем файл 123.txt

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

setpos(0,2);

str_lcd("Unmout SD… ");

res=pf_mount(0x00);//Демонтируем файловую систему карты

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

setpos(0,3);

str_lcd("Mount SD… ");

res=pf_mount(&fs);

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(2000);

clearlcd();//очистим дисплей

setpos(0,0);

str_lcd("Open file… ");

res=pf_open("/123.txt"); //Попытка открыть файл 123.txt

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

setpos(0,1);

str_lcd("Move pointer… ");

res=pf_lseek(0); //Установим курсор чтения на 0 в 123.txt

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

setpos(0,2);

str_lcd("Read file… ");

res=pf_read(buffer2,128,&s1);

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

_delay_ms(1000);

setpos(0,3);

str_lcd(buffer2);

_delay_ms(3000);

clearlcd();//очистим дисплей

setpos(0,0);

str_lcd("Unmout SD… ");

res=pf_mount(0x00);//Демонтируем файловую систему карты

if(res==FR_OK) str_lcd("Done");

else str_lcd("Error");

while(1)

 

Проверим код на практике, собрав его сначала и затем прошив контроллер

 

Image52 Image53 Image54 Image55 Image56 Image57

 

Теперь давайте удалим лишние функции, оставим только port_ini() и main().

Также удалим локальную переменную

 

int main(void)

{

  char str[10];

 

Соберём код и прошьём контроллер.

 

Предыдущая часть Программирование МК AVR Следующий урок

 

Исходный код

 

 

Техническая документация на Secure Digital

 

Программатор, модуль SD и дисплей можно приобрести здесь:

Программатор (продавец надёжный) USBASP USBISP 2.0

Модуль карты SD SPI

Дисплей LCD 20×4

 

 

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

 

AVR SPI. Карта SD. FAT

10 комментариев на “AVR Урок 33. SPI. Карта SD. FAT. Часть 6
  1. Андрей:

    А где у Вас mmc.c  подключается?

  2. Андрей:

    Вопрос снят. В 7-й студии загрузился нормально.

  3. Андрей:

    Не планируете рассказать, как с SD-карты картинки (RAW-файл, например) выводить на экран?

  4. Андрей:

    Пытался переделать функцию TFT9341_DrawBitmap из проекта STM, заменив обращения к USB на SD. Почему-то закрашивает весь экран черным. ):

  5. meren:

    Привет, я не говорю по-русски, и это перевод Google.
    Извиняюсь заранее.
    Я запускаю эту программу, но текстовый файл не создается.
    Если я создам текстовый файл с компьютером и пишу текст в нем, содержимое внутри него читается и даже может быть записано.
    Но если карта памяти пуста, этот файл не будет создан.
    Я использую микроконтроллер at90can128. И я также использую другое аппаратное соединение spi.
    Как вы думаете, в чем проблема?
    Благодарю вас!

  6. Алексей:

    Здравствуйте, а как можно воспроизвести музыку с SD?

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

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

*