Что неправильно делаю при работе с SD?

staromand
Offline
Зарегистрирован: 17.09.2012

 Сабж, не выводит в терминал массив dirFiles[]

//Включение библиотек карты, дисплея, может быть, и клавиатуры
#include <SD.h>
#include <LiquidCrystalRus.h>

//Инициализация переменных
Sd2Card card;
SdVolume volume;
SdFile root; 
File rootDir;

char* dirFiles[] = {};


void setup()
{
//Инициализация карты, сериалпорта, дисплея, может быть, и клавиатуры
  Serial.begin(9600);
  pinMode(53, OUTPUT);

//Проверка карты
  if (!SD.begin(53)) {
    Serial.println("Initialization SDCard failed!");
    return;
  }
  Serial.println("Initialization SDCard DONE...");

//Первичная загрузка файлов при запуске МК
  rootDir = SD.open("/");
  listDirectory(rootDir);


//Вывод списка файлов в терминал
  //for(int i; i<sizeof(dirFiles); i++)
  //{
  //  Serial.println(dirFiles[i]);
  //}
  Serial.println(dirFiles[0]);
  Serial.println(dirFiles[1]);
  Serial.println(dirFiles[2]);
}

void loop()
{
  
}

//Заводская функция листинга файлов, переделанная мной
void listDirectory(File dir) {
//Очистка массива "dirFiles[]"

//Загрузка списка файлов в массив "dirFiles[]"
while(true) {
  int i = 0;
  File entry = dir.openNextFile();
  if (!entry) break;
    // no more files

  if (entry.isDirectory()) {
    dirFiles[i] = entry.name() + '92';
  } else {
    dirFiles[i] = entry.name();
  }
  
  i++;
}
}
step962
Offline
Зарегистрирован: 23.05.2011

staromand пишет:

void listDirectory(File dir) {
//Загрузка списка файлов в массив "dirFiles[]"
while(true) {
int i = 0;
[...]
i++;
}
}

Не углубляясь в подробное исследование ваших кодов, замечу, что переменная i, значение которой вы усердно пытаетесь увеличивать, никогда не будет больше нуля.

Чтобы убедиться в этом, достаточно откомпилировать вот такой простой скетчик:

void setup() {
  Serial.begin(9600);
  while(true) {
  int i = 0;
  Serial.println(i,DEC);
  i++;
}
}

void loop() {
}

и посмотреть на вывод.

staromand
Offline
Зарегистрирован: 17.09.2012

 точно, спасибо большое. нужно было её объявлять намного выше. всё-таки чужую ошибку легче обнаружить, а свой код примелькался уже

staromand
Offline
Зарегистрирован: 17.09.2012

 Поменял, но теперь пишет три строчки какой-то несусветной хрени из пары символов в каждой строчке.
типа значения в массиве вроде есть, но, может, кодировка или что-то вроде того..

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Попробуйте обявить масив String 

staromand
Offline
Зарегистрирован: 17.09.2012

 Спасибо, помогло, но следующая напасть:

//Заводская функция листинга файлов, переделанная мной
void listDirectory(File dir) {
int i = 0;

//Очистка массива "dirFiles[]"

//Загрузка списка файлов в массив "dirFiles[]"
while(true) {

  File entry = dir.openNextFile();
  if (entry) {
  
    if (entry.isDirectory()) {
      dirFiles[i] = entry.name() + '92';
    } else {
      dirFiles[i] = entry.name();
    }
    
    Serial.print(entry);
    Serial.print("\t");
    Serial.print(i);
    Serial.print("\t");
    Serial.println(dirFiles[i]);
    i++;
  } else {
    break;
   // no more files 
  }
}
}

выводит только первый файл с карты

staromand
Offline
Зарегистрирован: 17.09.2012

 Ребят, выкладывал ранее весь листинг, и чуть выше фрагмент кода, который выводит лишь один файл. Не могу ума дать, ткните, пожалуйста, бестолкового...

staromand
Offline
Зарегистрирован: 17.09.2012

 Ещё боюсь засирать память дуины этими "стрингами", т.к. если файлов будет, например, 100, то это, мне кажется, сильно нагрузит её.
Столько много двумерных массивов. ни к чему

staromand
Offline
Зарегистрирован: 17.09.2012

Прошу внимания к посту - кто знает ответ, помогите, пожалуйста!

staromand
Offline
Зарегистрирован: 17.09.2012

сейчас выдает это:

иногда выплевывает имена фалов, которые действительно находятся на флешке.

код на данный момент выглядит так:

// pin name:        mega(1280 and 2560)
// slave reset:     53 
// MOSI:            51 
// MISO:            50 
// SCK:             52 


//Включение библиотек карты, дисплея, может быть, и клавиатуры
#include <SD.h>
#include <LiquidCrystalRus.h>

//Инициализация переменных
Sd2Card card;
SdVolume volume;
SdFile root; 
File rootDir;

String dirFiles[] = {};


void setup()
{
//Инициализация карты, сериалпорта, дисплея, может быть, и клавиатуры
  Serial.begin(9600);
  pinMode(53, OUTPUT);
  delay(1500);
//Проверка карты
  if (!SD.begin(53)) {
    Serial.println("Initialization SDCard failed!");
    return;
  }
  Serial.println("Initialization SDCard DONE...");

//Первичная загрузка файлов при запуске МК
  rootDir = SD.open("/");
  listDirectory(rootDir);
  

  Serial.println(dirFiles[0]);
  //Serial.println(dirFiles[1]);
//Вывод списка файлов в терминал
  //for(int i; i<sizeof(dirFiles); i++)
  //{
  //  Serial.println(dirFiles[i]);
  //}
}

void loop()
{
  
}

//Заводская функция листинга файлов, переделанная мной
int listDirectory(File dir) {
int i = 0;

//Очистка массива "dirFiles[]"

//Загрузка списка файлов в массив "dirFiles[]"
while(true) {

  File entry = dir.openNextFile();
  if (entry) {
  
    if (entry.isDirectory()) {
      dirFiles[i] = entry.name() + '92';
    } else {
      dirFiles[i] = entry.name();
    }
    
    //Serial.print(i);
    //Serial.print("\t");
    //Serial.println(dirFiles[i]);
    i++;
  } else {
    return i+1;
    break;
  }
   // no more files
}
}

 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Не пробовали скорость SPI подбирать, может SD не успевает? (это так, мысль пришла...)

staromand
Offline
Зарегистрирован: 17.09.2012

AlexFisher, все стандартные примеры работают на ура - выборка всей флешки в список из примера listfiles  работает. Скорости должно хватать.

А вообще скорость SPI какой функцией меняется?

staromand
Offline
Зарегистрирован: 17.09.2012

нашел класс смены скорости

.setClockDivider()

Допустимые параметры:

 

0x04 - Константа: SPI_CLOCK_DIV2
0x00 - Константа: SPI_CLOCK_DIV4
0x05 - Константа: SPI_CLOCK_DIV8
0x01 - Константа: SPI_CLOCK_DIV16
0x06 - Константа: SPI_CLOCK_DIV32
0x02 - Константа: SPI_CLOCK_DIV64
0x03 - Константа: SPI_CLOCK_DIV128
 
Снижал до 2 - нет разницы. Тот же мусор валит...
staromand
Offline
Зарегистрирован: 17.09.2012

Может кто-нибудь кинуть напутствие какое? На этом форуме всегда откликались и помогали, что сейчас случилось?

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Эххх... Жаль, leshak куда-то пропал, он бы помог.

staromand
Offline
Зарегистрирован: 17.09.2012

Короче, вот это:

Serial.println(dirFiles[0]);
Serial.println(dirFiles[1]);

в терминале возвращает какой-то буферный хлам.

И выяснил, что функция

int listDirectory1(File dir) {

  File entry = dir.openNextFile();
  delay(10);
  dirFiles[0] = entry.name();
  // no more files
}

отрабатывает правильно, а функция

int listDirectory(File dir) {
int i = 0;

//Очистка массива "dirFiles[]"

//Загрузка списка файлов в массив "dirFiles[]"
while(true) {

  File entry = dir.openNextFile();
  delay(10);
  if (entry) {
  
    if (entry.isDirectory()) {
      dirFiles[i] = entry.name() + '92';
    } else {
      dirFiles[i] = entry.name();
    }
    
    //Serial.print(i);
    //Serial.print("\t");
    //Serial.println(dirFiles[i]);
    i++;
  } else {
    return i+1;
    break;
  }
   // no more files
}
}

шлет в терминал ХЛАМ.

staromand
Offline
Зарегистрирован: 17.09.2012

И ещё: если ли какой-нибудь класс в работе с SD картами, показывающий, что выполнение прекращено? Типа

.available

 

staromand
Offline
Зарегистрирован: 17.09.2012

Или в цикле while как условие всё же  использовать "true" ?

while(true)
{
...
}

 

staromand
Offline
Зарегистрирован: 17.09.2012

Прошу свежим взглядом посмотреть на проблему.

Спасибо.

maksim
Offline
Зарегистрирован: 12.02.2012

А у вас какая дуина? Мега? Вывод ридера SS точно к 53 выводу подключен?

leshak
Offline
Зарегистрирован: 29.09.2011

 

AlexFisher пишет:

Эххх... Жаль, leshak куда-то пропал, он бы помог.

Ну, оно по всякому бывает. Кушать (а значит работать) - тоже хочется ;) Рекламная, хе-хе, пауза: оплачивая работу leshak, по высоким расценкам, - ты помогаешь обществу :)  Больше времени на форум можно уделить :)

Не вникая долго, не уверен, но смущает бросается в глаза строчка вида:

String (или char*) dirFiles[] = {};   

 

Тут мы объявляем массив указателей. А какой размера массив? НУЛЕВОГО! То есть памяти под хранение хоть чего-нибудь мы не выделили. Любая попытка записи в этот массив - должна приводить к порче данных/кода в памяти. Любое чтение - мусор из случаных обсластей памяти.

Вообщем читать про массивы (и то как важно следить за тем, что-бы не выходить за границы массива).

Вот это

 dirFiles[i] = entry.name() + '92';

Тоже не очень понял "что это" (не хочется хмурить мозг, но есть "настороженность"). Возможно стоит почитать про указатели и строки в C Не объект String, а именно char* .  Кстати, imho char* diFiles[] - было лучше (если забыть про размер массива). Все-таки enity.name() возвращает char*   .

Я вообще дико не люблю String.   Он, вроде, как и "проще в использвании". Но блин, он же не совместим с обычным C/C++ кодом. Куда не кинься везде char* ожидается/возвращается. И как оно будет конвертироватся/приводится к String - еще попробуй разберись.

Вообщем я бы, отложил пока SD и взял какой-нибудь учебничек по C и почитал "массивы, строки (сишные), указатели".

staromand
Offline
Зарегистрирован: 17.09.2012

Спасибо за ответ.

По порядку:

        >>  А у вас какая дуина? Мега? Вывод ридера SS точно к 53 выводу подключен?

У меня подключено всё правильно. Говорю с уверенностью, т.к. стандартные примеры SD отрабатывают, а это для меня - показатель.

        >>  String (или char*) dirFiles[] = {};

Это у меня (были и чэр* и стринг) считывание списка файлов в массив. Массив, естесственно, неопределенный, т.к. мы не знаем кол-во файлов.

        >>  dirFiles[i] = entry.name() + '92';

Добавляю символ "\".

        >>  Вообщем я бы, отложил пока SD и взял какой-нибудь учебничек по C и почитал "массивы, строки (сишные), указатели".

Теперь я понимаю, что именно так и нужно сделать.

 

Спасибо за ответы.

maksim
Offline
Зарегистрирован: 12.02.2012

staromand пишет:
У меня подключено всё правильно. Говорю с уверенностью, т.к. стандартные примеры SD отрабатывают, а это для меня - показатель.
Вот это меня и настораживает, ведь в стандартном примере SS это 10 вывод, а у вас в коде 53, вот поэтому и спрашиваю дуина то у вас Мега? SS подключен к 53 выводу?

staromand
Offline
Зарегистрирован: 17.09.2012

Конечно

leshak
Offline
Зарегистрирован: 29.09.2011

staromand пишет:

        >>  String (или char*) dirFiles[] = {};

Это у меня (были и чэр* и стринг) считывание списка файлов в массив. Массив, естесственно, неопределенный, т.к. мы не знаем кол-во файлов.

Причины вашего {} - понятны

Он не "не определен". Он имеет ноль элементов. У нас нет тут динамических массивов. Фишлка dirFileas.add() - не прокатит. Мы не просто объявляем массив, а еще и резервируем память под элементы.

Так что тут либо нужно выделять память сишными средствами (не знаю, будут ли они работать в дуине), либо смотреть в сторону не массивов, а связных списков (и опять-таки выделять память, вообщем "гимор еще тот").

Обычно поступают просто - резервируют какой-то количество (например 50) и надеются что "у нас не будет больше файлов. А если больше - то выкручиватся как-то по частям их загружать в тот размер массива который есть.

Вообщем, пока, сделайте ему какой-нибудь размер заведомо больший чем у вас файлов на карте. И какоую-топ еременную, сколько вы уже положили в него элементов. dirFiles[filesCount]=.... ;filesCount++;   if(fielsCount>MAX_FILES)КАРАУЛ

maksim
Offline
Зарегистрирован: 12.02.2012

Так что обьявите просто 

char dirFiles[32][16];

32 строки по 16 символов. Полкило памяти будет занято, но для Меги это не критично.

staromand
Offline
Зарегистрирован: 17.09.2012

В общем, придется, наверное, поступить, как поступал с "Pagination" на PHP+SQL, т.е. "под размер экрана" кэшировать

Спасибо ещё раз

leshak
Offline
Зарегистрирован: 29.09.2011

Да.. аналогия с web-овоским pager тут вполне уместна.

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Обязательно нужно читать учебник по с++ ! Тут я бы объявил массив указателей, при добавлении элементов (строк) - выделял память под каждую (обращу внимание, что в С и в С++ это делается по-разному) с присваиванием указателю адреса начала соответствующей строки...

Мудрено, наверно... но в качестве самообразовательного процесса разобраться с указателями - крайне полезно.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Я себе написал шаблон, типа Vector<_type>, храню в нем разные структуры, но он еще сырой и недопиленный. Впрочем, если кто то хочет допилить - могу выложить. Тогда делаете Vector<String> и юзаете его.

ПС Конечно это не стантартный Vector, а своя реализация, достаточно тупая, хранит массив указателей на объекты и если массива не хватает расширяет его через realloc. Сколько жрет памяти - не смотрел, допилю, тогда увижу.