Подписаться на получение новых статей на почту:

Шаг №23. Petit FatFs для ведения базы данных на AVR. Часть 8

Всем привет. Давайте с Вами вспомним, что в прошлый раз мы познакомились с файловой системой Petit FatFs.  А также задались целью решить вопрос, как обойти недостатки системы, для создания, например логгера. Вкратце чего я добился:

  • решил вопрос с запоминанием номера сектора, который мы используем в карте для записи информации;
  • решил вопрос с записью и до записью информации в необходимый сектор без потери предыдущей;
  • решил вопрос с переходом к следующему сектору, если добавляемая информация не вмещается в данный сектор.

Ну и все. Это все что нам необходимо для ведения своеобразной базы данных на микроконтроллере.   Как и в прошлой статье начнем работу в Proteus, а в конце перельем в железо. И подведем итог. Итак вперед. Открываем образ для работы с картой в Proteus.(Рассматривали в предыдущей статье №22). Перетаскиваем текстовый файл, уже предварительно увеличенный, сохраняем. Все у нас на карте лежит текстовый файл(рисунок).Petit FatFs в AVR
1.        Переходим к решению первой задачи. Т.к. система не запоминает места последней записи после демонтажа тома, то с повторным монтированием тома, она просто затирает всю предыдущую информацию. И это важно. Ведь в долгосрочной перспективе  программа не может постоянно «крутится». Чтоб не занимать ресурсы (например периодическая запись данных) а также учитывать аварийные ситуации(сбой программы, пропадание питания и др.), для сохранения «драгоценных» данных мы должны отслеживать самостоятельно последнее место записи. Задача стояла следующим образом: при подготовке записи, нам необходимо знать какой сектор у нас должен быть в работе. Я взял первый сектор как хранилище номера сектора, с которым мы должны работать. Если файл пустой, т.е. первые, например, 7 байт 1-го сектора пустые, это значит что у нас не «паханное поле». Как вы помните сектор состоит из 512 байтов. И обращаться к нему следует также побайтово. Например, если мы используем карту 2 Гб, то это равно 2, 147, 483, 648 байт. Я решил хранить номер сектора. Например, для максимального значения нам надо будет 7 байтов (2147483648/512= 4 194 304 секторов).   Конечно такое количество нам не надо. Т.к. информация будет приходить маленькими порциями. Например показания температуры, в середине, снаружи, показания влажности, дата, время. Пусть порция информации составляет 50 байт, 10 раз в сутки, примерно один сектор в день. 365 секторов в год. И то это по максимуму. Но это для моего случая. А Вы экспериментируйте, как Вам угодно.    На рисунке ниже результат выполнения программы. Как видите в 1-й сектоор произведена запись номера сектора куда мы начинаем “складировать” информацию.             

Ниже кусок кода кAVR и  текстовый файлоторый обеспечивает нашу задачу. Запишем слово “Привет!”
pf_lseek (0); /*ставим указатель на первый сектор*/
pf_read (block1,9,&bw); /*читаем первый сектор, в котором хранится номер сектора*/
/*Т.к. информация у нас хранится в строке, то нам необходимо преобразовать символы в число, для этого мы используем , функцию библиотеки stdlib.h*/
n=strtol (block1,&block1[7],10); /*преобразуем строку в целое long int*/

/*Проверка числа в секторе*/
if (n==0) /*Если сектор пустой, т.е. еще не записывали никакую информацию*/
{
        n=1; /* Записываем 1,т.е. начинаем записывать информацию со второго сектора (1*512)*/
/*Теперь необходимо наоборот преобразовать целое в строку*/
        ltoa (n,block1,10);
        pf_lseek (0);      /*Ставим указатель на первый сектор*/
        pf_write (block1,strlen (block1),&bw);     /*запишем номер сектора*/
        pf_write (0,0,&bw);   /*финализация*/
        /*Сразу добавляем информацию в сектор, без всяких проверок*/
        pf_lseek (512);
        pf_write (block2,strlen (block2),&bw);/*запишем в первый сектор*/
        pf_write (0,0,&bw);
        pf_mount (0×00);
        return 0;
}

Данный кусок кода работает, только тогда когда карту используем в первый раз. 2.       Переходим ко второму пункту: добавление информации уже к существующей записи. В программе я использую буфер, куда считываю информацию с сектора, добавляю информацию в этот буфер и записываю в тот же сектор. Используем функцию компилятора WinAVR strlcat. Добавим слово «Еще привет!».

pf_lseek (n*512); /*ставим указатель на сектор с которого начинаем считівать или записывать*/
pf_read (block,512,&bw);
strlcat (block,block2,512); /*Добавляем новую порцию информации к уже существующей*/
pf_lseek (n*512);
pf_write (block,strlen (block),&bw);
pf_write (0,0,&bw);
pf_mount (0×00);

Сохраняем данные на SD-картеСлева на рисунке результат добавления информации. Например, добавим «Еще привет!»         3.         И последний пункт. Переход на следующий сектор, если добавляемая информация не влезает. На данном этапе, после соединения строк, я ставлю условие проверки длины буфера. На рисунке ниже слева выведено число байтов при последней записи слова «Привет» в сектор. Обратите внимание на условие в программе (ниже). При превышение указанного предела, программа входит в данный блок, увеличивает номер сектора, ставит указатель и уже записывает в следующий сектор не поместившуюся информацию. Результат, еще одной записи слова на рисунке справа. Как видите в первом секторе стоит уже цифра 2. Соответственно новая порция информации записалась в следующий сектор. Добавляем данные в SD-карту на AVR

if (strlen (block)>510)    /*проверка сектора на количества заполняемых битов*/
{
     n++;    /*увеличиваем номер сектора*/
     ltoa (n,block1,10);   /*Переводим в строку*/
     pf_lseek (0);       /*запишем номер сектора*/
     pf_write (block1,strlen (block1),&bw);
     pf_write (0,0,&bw);
     pf_lseek (n*512);
     pf_write (block2,strlen (block2),&bw);      /*запишем информацию указанный сектор*/
    pf_write (0,0,&bw);
    pf_mount (0×00);
}

Итак мы рассмотрели варианты обхода недостатков данной системы. Ниже я привожу полный текст программы.

#include <stdint.h>
#include<string.h>
#include <stdio.h>
#include <stdlib.h>
#include «pff.h»
#include «diskio.h»
#include «integer.h»
int main (void)
{
      long int n; /*Переменная для хранения номера сектора*/
      char block[512];//={"Привет"}; /*буфер записи/чтения данных на карту*/
      char block1[9];  /*буфер для записи номера сектора*/
      char block2[]={"Еще привет!"};   /*буфер для передачи информации*/
      FATFS fs;
      FRESULT res;
      WORD bw;
      res=pf_mount (&fs);
      if ((res=pf_open («data.txt»)) != FR_OK)
      {
           return 0;
       }
     /************Операция проверки числа в секторе**************/
      pf_lseek (0);
      pf_read (block1,9,&bw);
      n=strtol (block1,&block1[7],10); // преобразуем строку в целое
      //Проверка числа в секторе
      if (n==0)
      {
            n=1;
            ltoa (n,block1,10);
            pf_lseek (0);
            pf_write (block1,strlen (block1),&bw);
            pf_write (0,0,&bw);
            pf_lseek (512);
            pf_write (block2,strlen (block2),&bw);
            pf_write (0,0,&bw);
            pf_mount (0×00);
            return 0;
        }
             /*******************Операция дозаписи числа*************/
       pf_lseek (n*512); /*ставим указатель на необходимый сектор*/
       pf_read (block,512,&bw);
       strlcat (block,block2,512);
       if (strlen (block)>510) /*проверка сектора на количества заполняемых байтов*/
      {
          n++;
          ltoa (n,block1,10);
          pf_lseek (0);
          pf_write (block1,strlen (block1),&bw);
          pf_write (0,0,&bw);
          pf_lseek (n*512);
          pf_write (block2,strlen (block2),&bw);
          pf_write (0,0,&bw);
          pf_mount (0×00);
          return 0;
       }
      pf_lseek (n*512);
      pf_write (block,strlen (block),&bw);
      pf_write (0,0,&bw);
      pf_mount (0×00);
      return 0;
}

Ниже на рисунке результат работы программы в “железе”Запись строки на SD-карту на AVR. Производилась запись блока данных, размером 80 байт:{"ПриветllllПриветllllПриветllllПриветllllПриветllllПриветllllПриветllllПриветllll"}.  При работе в “железе” было замечено, что при повторной записи, например в блоке проверки числа сектора, последующая запись проходила без ошибок. При открытии файла, запись не обнаруживалась. Поэтому я, в данном случае перед каждой записью проводил повторную инициализацию, монтирование и открытие файла. Пробуйте ,экспериментируйте, буду рад увидеть другие результаты. Ну а так код от работы Proteus, более не чем не отличается. Что ж на этом этапе, дорогие читатели мы пока закончим. Данная файловая система готова к применению в логгере. Перед этим Контроллер сбора данных и Petit FatFsмы доработаем плату. До разведём оставшееся место под еще один контроллер AVR, рассмотрим способ изготовления печатной платы с помощью пленочного фоторезиста, изучим параллельную работу микроконтроллеров, часы реального времени.Вследующей статье я выложу осциллограммы инициализации карт и расскажу о возможных проблемах. До следующих постов. Всем пока.

Просмотрено 4288 раз.

Я на Google+

Шаг №23. Petit FatFs для ведения базы данных на AVR. Часть 8: 2 комментария

  1. Уважаемый автор скажите пожалуйста все таки удалось нет решить недостаток ф.с. из за которого нельзя создавать фаил на SD карте?

    • Здравствуйте. Как видите описанным способом, в этой статье, я программно решил этот недостаток. У меня информация до записывалась. А т.к. Вы используете систему FatFs, то там с до записью все нормально. Это я просто из спортивного интереса впихивал систему Petit FatFs в мк 8, то пришлось как то выкручиваться.

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

Ваш e-mail не будет опубликован.

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Subscribe without commenting