Функция возвращающая массив
- Войдите на сайт для отправки комментариев
Сб, 27/12/2014 - 21:39
Доброго времени суток!
Некая фукции должна возвращать список файлов на SD карте в виде массива строк. Что то с наскока не удалось решить эту задачу. Это возможно?
Можно поступить проще, передать в функцию указатель на массив строк и в функции его заполнить.
В противном случае Вам придется формировать динамически этот массив, что не всегда хорошо.
Хотя варианты могут быть разными, слишком мало информации.
Если вам не трудно, приведите пожалуйста примеры функций с указателем и без него. У меня что то не получается.
Если покажете кусок кода, где описан массив строк, тогда помогу, иначе гадать на кофейной гуще нет никакого желания. Возможно в Вашем понимании массив строк одно, а в моем - другое. Зачем гадать?
#include <SD.h> void setup() { int i = 0; Serial.begin(9600); if (!SD.begin(4)) { Serial.println("initialization failed!"); return; } String dir[10]; File root = SD.open("/"); while(true) { File entry = root.openNextFile(); if (! entry) break; dir[i] = entry.name(); i ++; entry.close(); } root.close(); for (int i = 0; i < 10; i ++) { Serial.print(i); Serial.println("\t" + dir[i]); } } void loop() { }Строки с 15 по 24 необходимо вынести в функцию. Понятно что массив dir можно было объявить глобально, но меня интересую другие возможные решения, в целях так сказать саморазвития.
Попутно еще 2 вопроса. Возможно ли в данном случае массив сделать динамическим? И как узнать количество элементов в массиве? dir.length не работает
У вас могут довольно быстро и незаметно возникнуть проблемы из за нехватки памяти. Массив строк для 2048 байт памяти звучит весьма угрожающе. Рекомендую вам пересмотреть дизайн программы и делать обработку файлов по одному, считывая их имена с FAT по одному запоминая последний указатель, т.е. Логика "нашли первый", далее за раз берем "один следующий" до тех пор пока "не достигли последний"
Я так пробовал, не получилось. Дело в том, что я пытаюсь реализовать файловый веб сервер. Купил ethernet шилд, воткнул его в uno. Изначальный алгоритм был таков - ждем соединения от клиента, после которого начинаем формировать веб страницу паралельно считывая информацию с SD карты. Сама страница формируется нормально, но как только пытаюсь считывать информацию с карты, начинаются глюки, файлы то видны, то нет или частично.
Погуглив нашел информацию, что ethernet шилд не может одновременно работать и сетью и с картой, т.е. чтобы считать информацию с карты, мне надо разорвать соединение с клиентом, чего делать нельзя. Поэтому пришел к выводу что информацию о файлах надо считать при старте и хранить ее в памяти.
Вот первоначальный кусок кода, возможно я что то упустил или где то ошибся, и не надо городить строковые массивы?
// Web сервер // Символ /n соответствует коду 10, т.е. LF (line feed), подача строки // Символ /r соответствует коду 13, т.е. CR (carriage return), возврат каретки // В Windows для перехода на новую строку используются пара этих символов, т.е. LF + CR // Прослушиваем входящие подключенния на порту 80 EthernetClient client = server.available(); // функция при налиции подключения возвращает объект client, иначе возвращает false if (client) { client.clientIP(clIP); // самописный клас для извлечения адреса клиента Serial.print("Client "); for (int i = 0; i < 4; i ++) { Serial.print(clIP[i], DEC); if (i < 3) Serial.print("."); } Serial.println(" connected"); boolean currentLineIsBlank = true; while (client.connected()) { // цикл пока есть соединение // Данная проверка необходимо для получения клиентского запроса // ответа на него и выхода из цикла if (client.available()) { // если от клиента поступают данные char c = client.read(); // читаем входящие от клиента символы // Serial.write(c); // то что пришло от клиента // Если дошли до конца строки (получили символ новой строки LF) // и строка пустая (т.е. по сути получили два подряд идущих LF LF) // клиентский запрос HTTP закончился и можно отправлять ответ. // Иначе говоря, ждем когда клиент заткнется и даст возможность ответить if (c == '\n' && currentLineIsBlank) { // Отправляем клиенту стандартный HTTP заголовок client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // соединение будет закрыто после завершения ответа client.println("Refresh: 60"); // автоматическое обновление страницы каждые 1 мин. client.println(); client.println("<!DOCTYPE HTML>"); client.println("<html>"); // Тело страницы root = SD.open("/"); while(true) { File entry = root.openNextFile(); if (! entry) break; String en = entry.name(); client.print("<a href=" + en + ">"); client.print(en); client.println("</a>"); entry.close(); } root.close(); client.println("</html>"); break; } if (c == '\n') { currentLineIsBlank = true; // началась новая строка, считаем ее пустой } else if (c != '\r') { currentLineIsBlank = false; // любой входящий символ кроме LF и CR делает текущую строку не пустой } } } client.stop(); // закрывем HTTP сессию Serial.println("Client disonnected\n"); }Оужос, неужели на самом деле так? Нет, я сам-то не пробовал конечно, и мало в этом понимаю, но если это так - в печку нафиг такой шилд.
А чем это поможет? Тогда уж сами файлы надо в памяти хранить, а не информацию о них.
Не, я тоже считаю что тут всю систему надо менять. :)
Оужос, неужели на самом деле так? Нет, я сам-то не пробовал конечно, и мало в этом понимаю, но если это так - в печку нафиг такой шилд.
Если бы Вы потрудились хотя бы почитать описание шилда - у Вас бы не возникало таких вопросов. Да, оно там by design так работает.
Погуглив нашел информацию, что ethernet шилд не может одновременно работать и сетью и с картой, т.е. чтобы считать информацию с карты, мне надо разорвать соединение с клиентом, чего делать нельзя. Поэтому пришел к выводу что информацию о файлах надо считать при старте и хранить ее в памяти.
Мне думается вы ошибаетесь в том, что нельзя одновременно держать активное соединение и работать с SD картой. У ethernet shield бала проблема в работе с SD по той причине, что у чипа wiznet5100 есть баг по работе по SPI интерфейсу из-за которого по сути этот чип не освобождает шину SPI даже когда не выбран кристал (CS). Однако этот баг чипа давно пофикисили установив логическую микросхему на последней версии ethernet shield. Если у вас последняя то все должно работать на ура.
в крайнем случае можно подключить отдельно SD карту и работать с ней по программной шине SPI
Делал такой же серв - возникали проблемы только с получением списка файлов при одновременной записи в этой же директории(производилась запись лога по времени). Сами файлы всегла отдавались как положенно и если открывать другую папку то список также отображался корректно. Работало это дело на стандартном EthernetShield W5100 с SD Card на меге 2560. Я пришол к выводу что проблема в самой библиотеке - где то не обнуляется состояние - ведь работа с поддирикториями шла без проблем. До первой процедуры записи в файл(после перезагрузки) - список показывался так как должен показываться.
Вобщем если решите делать массив то придется ограничить максимальную длинну имени файла и максимальное количество файлов в обрабатываемой папке, потому что С плохо работает с динамическими массивами.
char fs_cache[100][10];//отожрет 1 кб драгоценной памяти.
С другой стороны если файлы нормально читаются в любое время то в каждой папке можно создать ".index" файл CSV формата и туда все запихать при сканировани папок, потом просто читать этот файл.
Си прекрасно работает с динамическими переменными;) это МК плохеет из-за малого размера оперативки
и если у меги ее 8кб то у UNO в 4 раза меньше
и память нужна не только переменным, а еще и на програмный стек. К тому же ардуино использует не Си, а Си++, а это дополнительный расход памяти на скрытые переменные
Поскольку W5100 and SD разделяют одну шину SPI, они не могут быть активны одновременно.
Думаю, имеется в виду именно активность на шине SPI. В это я охотно верю, да.
Но ещё раз говорю - сам ничего не пробовал, поэтому ни на чём не настаиваю.
Если не прав - прошу прощенья. :)
МК всю работу делает последовательно, так что з за того, что на шине SPI одновременно может быть активно только одно устройство проблем вообще никаких нет.
Писали же что W5100 любит быть единственнным у микроконтроллера на шине. Аппаратный баг его.
Писали же что W5100 любит быть единственнным у микроконтроллера на шине. Аппаратный баг его.
на последних шилдах этот баг исправлен так как рекомендовано производителем чипа
Разобрался в чем дело, у меня и без всяких массивов памяти не хватало, потому и не работал скетч. Отключил библиотеку часов реального времени, все забегало как положено, теперь вот думаю, откуда время брать, может по NTP?
Всем спасибо за помощь!