Правильный ли выбор - открывать / закрывать текстовый файл для записи каждые 0,01 сек? - PullRequest
1 голос
/ 21 мая 2019

Я должен собрать данные через акселерометр, выполнить некоторые вычисления и добавить результат в текстовый файл (на карту MicroSD, подключенную через SPI). Код работает, но я должен увеличивать скорость до лога каждые 0,01 секунды. Здорово ли открывать / закрывать MicroSD на этой скорости?

#include "mbed.h"
#include "SDFileSystem.h"

SDFileSystem sd (SPI_MOSI_SD, SPI_MISO_SD, SPI_SCK_SD, SPI_SS_SD, "sd");

int main (void)
{
  mkdir("/sd/data", 0777);
  while (1)
  {
    // record from accelerometer and perform calculations
    FILE *fp = fopen("/sd/data/parameters.txt", "a");
    if(fp == NULL)
    {
      error("Could not open file for write.\n");
    }
    fprintf(fp, "%.4f\n", parameter);
    fclose(fp);
    wait_ms(100);
  }
}

Моя проблема в том, что цикл while никогда не заканчивается: мне приходится непрерывно записывать данные и принимать решение об прерывании только путем выключения устройства. Таким образом, fclose (fp) никогда не происходит.

Ответы [ 4 ]

3 голосов
/ 21 мая 2019

В мои дни SD-карты обычно записывали свои данные в виде полных секторов, даже если вы записывали один байт.Я предполагаю, что это все еще так, поэтому, делая это по-своему, вы будете носить сектор много раз без необходимости делать это.Вот почему буферизация важна.Данные должны быть в буфере размером около 512 байт (типичный размер сектора). Создайте буфер, пока он не достигнет 512 байт, затем очистите, записав на SD-карту.

char sd_buffer[512];
unsigned short buffer_idx = 0;
:
void append_buffer ( char *str )
{
   while ( *str )
   {
       sd_buffer[buffer_idx++] = *str++;

       if ( buffer_idx >= 512 )
       {
            FILE *fp = fopen("/sd/data/parameters.txt", "a");
            if ( fp == NULL )
                  return; // error
            // flush buffer
            fwrite(sd_buffer,1,512,fp);
            fclose(fp);
            buffer_idx = 0;
       }
   }
}
:
while (1) 
{
    char buf[32];
    sprintf(buf,"%.4f\n", parameter);
    append_buffer(sd_buffer,buf);
    wait_ms(100);
}

Это просто означает, что запись будет меньше вSD-карта (с интервалом 512 байт)

Отказ от ответственности: не проверено

Ps.Открыть / закрыть файл теперь в append_buffer, поэтому все буферы файловой системы также очищаются.

Если у вас есть проблемы с циклами.Используйте конечный автомат

3 голосов
/ 21 мая 2019

Здорово ли открывать / закрывать MicroSD на этой скорости?

Пишет, что носит его.Я не понимаю, почему открытие и закрытие должно иметь значение.Но совершенно не нужно делать, как ты.Сделайте так вместо этого:

FILE *fp = fopen("/sd/data/parameters.txt", "a");

if(fp == NULL) {
    error("Could not open file for write.\n");
}

while (1) {
    fprintf(fp, "%.4f\n", parameter);
    // If your worry is that the file buffer won't be written to disk
    // in case of a power off, just flush the stream.
    fflush(fp);
    wait_ms(100);
}

fclose(fp);

Но, конечно, хорошей практикой является проверка возвращаемого значения для fprintf и fflush для обнаружения ошибок.

Моя проблемав том, что цикл while никогда не заканчивается: мне приходится непрерывно записывать данные и принимать решение об прерывании только путем выключения устройства.Таким образом, fclose (fp) никогда не происходит.

Похоже, вам нужна Журналируемая файловая система

2 голосов
/ 21 мая 2019

Вы можете буферизовать данные, если считаете, что открытие / закрытие недостаточно быстро.Просто соберите 100 или более точек данных из вашего аккаунта и напишите их, например, раз в секунду, например.

1 голос
/ 21 мая 2019

Моя проблема в том, что цикл while никогда не заканчивается: мне приходится непрерывно записывать данные и принимать решение об прерывании только путем выключения устройства. Таким образом, fclose (fp) никогда не происходит.

В случае, описанном выше, добавление fclose каждые 100 мс все равно не поможет. Вы можете потерять последние записанные данные, если отключение произойдет во время записи.

  1. Если вы в порядке, возможно, потеря последней записи, то

    • Буферизованная запись в любом случае произойдет в конце символа строки \n
    • Таким образом, вы можете закрыть файл в конце основного (или вовсе не)
  2. Если вы хотите, чтобы запись на SD-карту всегда выполнялась даже при выключении, дизайн будет более сложным. Вам понадобится -

    • для обнаружения выключения. Вы можете использовать канал АЦП.
    • Конденсатор в блоке питания, который будет некоторое время поддерживать питание контроллера (возможно, 50 мс)
    • Процедура завершения работы, которая будет выполняться при отключении питания, которая обеспечит завершение буферизованной записи и закроет файл.
...