AVR115: сбор данных с использованием Atmel File System |
![]() |
Добавил(а) microsin |
Прим. переводчика: в библиотеке LUFA есть аналогичный проект, записывающий данные температуры (см. архив LUFA, папка Projects\TempDataLogger). Сохранение данных можно организовать также на основе любой макетной платы, например [6], если в качестве носителя данных использовать к примеру стандартную карту SD/MMC, подключенную к микроконтроллеру через интерфейс SPI. [2 Требования к аппаратуре] Пример приложения для сбора данных (Data Logging) требует для себя следующее железо (hardware): • Отладочную плату ATEVK527 для микроконтроллеров серий AVR, которая включает в себя: [3 Чем программировать (прошивать) ATmega32U4] Для того, чтобы прошить память микроконтроллера, Вы можете использовать следующие методы: • Интерфейс JTAG, для этого нужен аппаратный отладчик JTAGICE mkII [4](2). Примечания: Пожалуйста обратитесь к содержимому справки FLIP для того, чтобы узнать, как установить драйвер USB и как запрограммировать микроконтроллер ATmega32U4 через интерфейс USB. Прим. переводчика: простые указания на русском языке по установке драйвера USB и перепрошивке микроконтроллера через FLIP можно получить из статьи "Макетная плата AVR-USB32U4" [6]. [4 Быстрый старт] Как только прошили Ваш микроконтроллер ATmega32U4 HEX-файлом проекта EVK527-series4-datalogging [3], Вы можете запустить демонстрацию сбора данных (data logging): 1. Отключите кабель USB и подключите кабель питания (9V). Рис. 4-1. Отладочная плата EVK527 Rev1. Примечание: это заводская конфигурация платы EVK527 по умолчанию, за исключением того, что нужно запаять перемычки SP2 и SP4 (чтобы разрешить работу светодиодов LED0 и LED2). По умолчанию записываемые данные содержат только 16-битное число, инкрементируемое каждые 120 мкс. Это можно изменить, и задать источник данных через опции времени компиляции в файле datalogging.c: #define LOG_ADCMIC_EXAMPLE // От ADC микрофона в файл WAV #define LOG_ADCEXT_EXAMPLE // От другого входа ADC в файл BIN #define LOG_PIN_EXAMPLE // Записать состояние ножек в файл BIN #define LOG_ENUM_EXAMPLE // Записывать значение счетчика в файл BIN (по умолчанию) [5 Описание работы приложения EVK527-series4-datalogging] 5.1 Как это работает Пример приложения firmware предоставляет 2 рабочих режима: Download mode (режим загрузки): пользователь подключает EVK527 к компьютеру PC через USB (получая при этом извлекаемый виртуальный диск "U-Disk", USB Mass Storage Device), чтобы получить доступ к лог-файлу, записанному в имеющиеся носители данных (это может быть запаянная на плате память DataFlash, или стандартная карта SD/MMC, установленная в слот). В этом режиме встроенная в firmware Atmel File System не имеет доступа к носителям данных, и файл лога не может быть создан записан микроконтроллером. Примечание: это сделано специально, чтобы предотвратить повреждение данных - в любой момент времени только одна файловая система (или только MassStorage Device, поддерживаемая операционной системой Windows, или только Atmel File System, работающая в firmware микроконтроллера ATmega32U4) может получить доступ к носителю данных. Рис. 5-1. Режим загрузки, Download mode (U-Disk). Data logging mode (режим сбора данных): когда активен этот режим, то в файл могут быть записаны какие-либо данные. Кит EVK527 отключен от хоста USB (компьютера), и может начать/остановить запись, если нажать соответствующие кнопки EVK527 (см. рис 4-1). Когда запись началась, то файл создается на носителе данных. Таймер создает прерывания с частотой 8 кГц, и обработчик прерывания таймера делает выборки сигнала со входа канала ADC (ЦАП), или другого источника данных, и записывает их в буфер SRAM. Заполненные буферы переносятся в файл лога, эту работу выполняет задача логгинга (data logging task). Рис 5-2. Режим сбора данных, Data Logging mode. 5.2 Firmware Эта секция разъясняет только работу файловой системы Atmel, и не касается модуля USB. Приведенные примеры кода взяты из файла data_logging.c проекта EVK527-series4-datalogging [3]. 5.2.1 Разрешение/запрет работы встроенной файловой системы Инициализация модуля File System и выход из него управляется задачей datalogging_task(). Когда чип выходит из режима USB Device (в котором оно работало как USB MassStorage Device), один вызов nav_reset() приводит к инициализации встроенной Atmel File System. Когда нужно остановить встроенную Atmel File System, или когда запускается режим устройства USB, нужно вызвать nav_exit(), чтобы сбросить (flush) содержимое кэша на диск. Ниже показан пример подпрограммы datalogging_task(), исходный код можно скачать по ссылке [3]. void datalogging_task(void) { // Изменение состояния сбора данных if( Is_joy_down() // Если сбор данных запускается пользователем && (!Is_device_enumerated())) // и если неактивен режим устройства USB { if( !g_b_datalogging_running ) { // Запуск сбора данных nav_reset(); //** Инициализация File System g_b_datalogging_running = datalogging_start(); } } if( Is_hwb() // если сбор данных остановлен пользователем || Is_device_enumerated() ) // или если запустился режим USB Device { if( g_b_datalogging_running ) { // Остановка сбора данных g_b_datalogging_running = FALSE; datalogging_stop(); nav_exit(); //** Выход из модуля File System } } // Выполнение фоновой задачи сбора данных if( g_b_datalogging_running ) { g_b_datalogging_running = datalogging_file_write_sector(); if( !g_b_datalogging_running ) { datalogging_stop(); nav_exit(); //** Выход из модуля File System } } } 5.2.2 Открытие диска (Open disk) В этом примере нужен только один навигатор handle1, потому что в приложении есть только один просмотр диска, и в любой момент времени открыт только один файл. В этом случае мы выбрали навигатор по умолчанию, default navigator handle 0 (nav_select(0)). Примечание: См. апноут AVR114 [2] для получения дополнительной информации по навигаторам (navigator handle). Алгоритм для открытия диска зависит от количества подключенных дисков (см. конфигурацию в файле conf_access.h). По умолчанию пример кода использует DataFlash и драйвер MMC/SD. При этом используется следующий алгоритм: Попытка смонтировать диск MMC/SD, и отформатировать его, если это необходимо Если ошибка (диск отсутствует, неработоспособный, и т. п.) Попытка смонтировать диск на носителе DataFlash, и отформатировать его, если это необходимо Если ошибка (диск отсутствует, неработоспособный, и т. п.) Прервать процесс сбора данных Ниже приведен код подпрограммы datalogging_open_disk(), которая пытается открыть диск. Bool datalogging_open_disk(void) { U8 u8_i; nav_select(FS_NAV_ID_DEFAULT); #if( (LUN_2 == ENABLE) && (LUN_3 == ENABLE)) // конфиг установлен в conf_access.h // Выбрать и попытаться смонтировать диск MMC/SD (lun 1) или DataFlash (lun 0) // Сначала надо попробовать MMC/SD for( u8_i=1; u8_i!=0xFF; u8_i-- ) #else // В этом месте только один вариант памяти, MMC/SD или DataFlash (lun 0) for( u8_i=0; u8_i!=0xFF; u8_i-- ) #endif { if( nav_drive_set(u8_i) ) // Выбор драйвера (не диска) { // Драйвер доступен, смонтировать его if( !nav_partition_mount() ) { // Ошибка при монтировании, проверить статус ошибки if( FS_ERR_NO_FORMAT != fs_g_status ) continue; // Ошибка диска (отсутствует, аппаратная ошибка, // системная ошибка, и т. п.) // Диск не отформатирован, отформатируем его if( !nav_drive_format(FS_FORMAT_DEFAULT) ) continue; // Формат завершился неудачно } return TRUE; // В этом месте диск смонтирован } } return FALSE; // Не найден работоспособный диск } 5.2.3 Создание пути до файла (path) Эта часть кода создает путь до файла наподобие Disk:\logxxx\logxxx.bin. Подпрограмма datalogging_create_path_file() создает каталог \logxxx\. Подпрограмма nav_setcwd() ищет и в конечном счете создает путь (третий аргумент должен быть TRUE). Ниже показан код подпрограммы datalogging_create_path_file(), которая создает путь. Bool datalogging_create_path_file(void) { char ascii_name[15]; U16 u16_dir_num = 0; if( !nav_dir_root() ) return FALSE; // Ошибка файловой системы while( u16_dir_num < 30 ) // Это ограничение на количество директорий // сделано здесь только для примера. { sprintf( ascii_name, "./log%03d/", u16_dir_num); // Вход в подкаталог, и в конечном счете создание его, если // такой подкаталог не существует if( !nav_setcwd(ascii_name, FALSE, TRUE) ) return FALSE; // Ошибка файловой системы // Создание файла if( datalogging_create_file() ) return TRUE; // Файл создан // В этом месте каталог заполнен, тогда делается переход // в родительский каталог для создания там другого каталога. if( !nav_dir_gotoparent() ) return FALSE; // Ошибка файловой системы u16_dir_num++; } return FALSE; // Слишком много каталогов и файлов } Подпрограмма datalogging_create_file() создает файл \logxxx.bin. Здесь имеется ограничение на количество файлов лога в каталоге логов (до 10), потому что просмотр каталога с большим количеством файлов может работать довольно медленно. Bool datalogging_create_file(void) { char ascii_name[15]; U16 u16_file_num = 0; while( u16_file_num < 10 ) { // Создание файла sprintf(ascii_name, "log%03d.bin", u16_file_num); if( nav_file_create(ascii_name) ) return TRUE; // Здесь файл создан, закрыт, и он пустой // Ошибка при создании файла, нужно проверить код ошибки if( fs_g_status != FS_ERR_FILE_EXIST ) return FALSE; // Ошибка файловой системы (диск переполнен, // каталог переполнен, ...) // Такой файл существует, увеличение числа в имени u16_file_num++; } return FALSE; // Слишком много файлов в текущей директории } 5.2.4 Выделение места под файл Эта секция не обязательна для рассмотрения и использования, однако позволяет повысить быстродействие сбора данных (что полезно, когда нужно сохранять данные с высокой скоростью). Для получения подробностей, как это работает, см. раздел 6.5 апноута AVR114 [2]. Примечание: по окончании сбора данных остаток от выделенной памяти на носителе (размер выделенной памяти минус конечный размер файла) будет освобожден, когда файл закрывается. Ниже показан код подпрограммы datalogging_alloc_file_space(), которая выделяет место под файл на носителе данных. Bool datalogging_alloc_file_space(void) { Fs_file_segment g_recorder_seg; // Открыть файл, созданный в режиме записи if( !file_open(FOPEN_MODE_W)) return FALSE; // Задать размер сегмента для выделения (в единицах 512 байт) // Примечание: Вы можете выделить место побольше в том случае, // если не знаете общий размер файла. g_recorder_seg.u16_size = FILE_ALLOC_SIZE; // Выделение в FAT списка кластеров равного или меньшего // в размере сегмента if( !file_write(&g_recorder_seg) ) { file_close(); return FALSE; } // Если хотите, то можете проверить минимальный выделенный размер. if( g_recorder_seg.u16_size < FILE_ALLOC_SIZE_MIN ) { file_close(); nav_file_del(FALSE); return FALSE; } // Закрыть/открыть файл, чтобы обнулить его размер // Примечание: это действие не удаляет предварительно созданное // выделение в таблице FAT file_close(); // закрытие файла if( !file_open(FOPEN_MODE_W) ) // открытие файла в режиме записи, при // этом принудительно обнуляется его размер return FALSE; return TRUE; //** Файл открыт и место в FAT выделено } 5.2.5 Заполнение файла данными Подпрограмма file_write_buf() является самой лучшей для заполнения файла. Использование размера буфера и текущей позиции записи, кратных 512 байтам, повысит скорость работы и даст оптимальное быстродействие, потому интерфейс с памятью использует блоки по 512 байт. Буферы (2 * 512 байт) заполняются обработчиком прерывания timer0. Максимальная полоса пропускания для сохранения данных ATmega32U4 на частоте 8 МГц составляет 18 килобайт/сек. Это значение было измерено в следующем примере (подпрограмма datalogging_file_write_sector()). Bool datalogging_file_write_sector(void) { // !!!! Внимание: // Если размер записываемого буфера кратен 512 байтам, // и если текущая позиция записи в файл тоже кратна 512 // байтам, то подпрограмма file_write_buf() будет работать // очень эффективно. if( g_b_buf_full[g_u8_cur_buf] ) { if( !file_write_buf(&g_data_buf[g_u8_cur_buf*FS_SIZE_OF_SECTOR], FS_SIZE_OF_SECTOR) ) return FALSE; // Ошибка записи g_b_buf_full[g_u8_cur_buf] = FALSE; // Теперь ждем нового буфера g_u8_cur_buf++; if( NB_DATA_BUF == g_u8_cur_buf ) g_u8_cur_buf = 0; } return TRUE; } [Ссылки] 1. AVR115: Data Logging with Atmel File System on ATmega32U4 site:atmel.com. |