Передача данных пакетами

mcmega
Offline
Зарегистрирован: 12.02.2014

Всем привет!

Подсткажите, есть данные (беру из файла), я хочу их передать пакетами размером sizeBlock в UART.

void sendUART (int index, int sizeBlock) {
 if (mcuFlash.available()) {
    while(ждем конец пакета) {
      // Читаем байт
      // Передаем в UART
      // Смещаем index
      // Проверяем чтоб не передали больше чем sizeBlock
    }
  }
}
Я так представляю, что нужно передавать в функцию индекс начала пакета и длинну.
Передавать пакет, сохранять начало для следующего пакета и так до конца.
Как это сделать?
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А чем не устраивает штатная функция write? Зачем огород-то городить?

Serial.write(buf, len)

mcmega
Offline
Зарегистрирован: 12.02.2014

Я не очень понимаю как ей пользоваться, длину я передам (это sizeBlock), а как мне куски этих данных туда вставить? Они ведь сплошняком идут. Мне как то нужно запоминать до куда я передал, выйти из функции и потом снова зайти и передавать уже с конца предыдущего куска.

Я сейчас передаю побайтно, а хочу пакетами

void sendUART (int index, int sizeBlock) {
 if (mcuFlash.available()) {
    Serial.write(mcuFlash.read());
  }
}

 

mcmega
Offline
Зарегистрирован: 12.02.2014

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Первый параметр - адрес начала, второй - сколько байтов передавать - передавайте сколько хотите.

mixail844
Offline
Зарегистрирован: 30.04.2012

mcmega пишет:

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

зависит от того , насколько чуствительна принимающая сторона к размерности блока < sizeBlock

mcmega
Offline
Зарегистрирован: 12.02.2014

Должно быть так?

uint8_t * indexChar = 0;

void sendPack(uint8_t* index, 16) {
  String pack = (String)mcuFlash.read(index, sizePack);  // Очередные 16 Байт
  pack = pack + '\n'; // Закрываем строку (для теста)
  Serial.print(pack); // Передаем 16 Байт
  Serial.flush();     // Ждем, пока передастся пакет
  indexChar += sizePack;  // Меняем индекс для следующего пакета
}

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Кому должно? Откуда нам значть что Вам нужно? Что нужно, то и должно.

mcmega
Offline
Зарегистрирован: 12.02.2014

ЕвгенийП пишет:

Кому должно? Откуда нам значть что Вам нужно? Что нужно, то и должно.

Грубиян ))

Мне нужно файл прошивки передать по 128 Байт в UART.

На той стороне стоит загрузчик, который принимает по 128 Байт, как примет - запишет страницу во флешь и ответит, типа давай следующий пакет 128 Байт.

Не получается у меня пакеты сформировать, не знаю как... Вот и обратился за ПОМОЩЬЮ, а не пустым недовольствием...

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Арифметика же простая: сколько раз пакет размером N вместится в данные размером M, с учётом остатка? можете решить эту задачу?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

mcmega пишет:
обратился за ПОМОЩЬЮ, а не пустым недовольствием...

Я Вам сказал какой функцией нужно пользоваться. Вы это игнорируете и пишете какие-то глупости со строками, что Вам ещё сказать. А если в Вашем пакете 0 попадётся - как Ваша String на него прореагирует?

mcmega
Offline
Зарегистрирован: 12.02.2014

Могу взять размер файла mcuFlash.size() и поделить на размер блока (128), получу число полных блоков... но что это даст?

Я не знаю как указать начало 2, 3... блоков

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

mcmega пишет:

Могу взять размер файла mcuFlash.size() и поделить на размер блока (128), получу число полных блоков... но что это даст?

Я не знаю как указать начало 2, 3... блоков

Это - тоже арифметика: если в массиве данных размером М есть n блоков размером N при условии, что первый блок N располагается по адресу 0, вопрос: по какому адресу будет располагаться второй блок? третий? если блок имеет размерность N?

mcmega
Offline
Зарегистрирован: 12.02.2014

1 - 0+N,
2 - N + N
3 - 2N + N

У меня получилось это

void sendPack(uint8_t* indexChar, size_t sizePack) {
  Serial.write(mcuFlash.read(indexChar, sizePack));
  Serial.flush();
  indexChar += sizePack;
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, не знаю, без цельного  кода ничего не скажешь. Так, на вид, похоже на бред, но тут код целиком смотреть надо.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

mcmega пишет:

1 - 0+N,
2 - N + N
3 - 2N + N

У меня получилось это

void sendPack(uint8_t* indexChar, size_t sizePack) {
  Serial.write(mcuFlash.read(indexChar, sizePack));
  Serial.flush();
  indexChar += sizePack;
}

 

Вопрос на засыпку: что написано в документации к Serial.write? Что возвращает mcuFlash.read ? Вы вызываете Serial.write с одним параметром, следовательно - туда плюнется ОДИН байт.

mcmega
Offline
Зарегистрирован: 12.02.2014

Согласен) не работает!

Приближенно код тако:

uint8_t * posInFile =     0;
size_t sizePack =         128;
bool update = false;    // Меняю, если нужно обновить


loop() {
  if (update) {
    sendPack(posInFile, sizePack);
  }
}

void sendPack(uint8_t* pos, size_t sizePack) {  // Передаю позицию в файле и размер пакета
  Serial.write(mcuFlash.read(pos, sizePack));  // Хочу прочитать sizePack Байт с позиции pos и отправить в UART
  pos += sizePack;  // вычисляю начало следующего блока
  posInFile = pos; // сохраняю позицию следующего блока
}

 

.read(buf, len) - вернет кусок данных от buf длиной len
Serial.write(buf, len) - тоже только не компилиться, если задать длину
DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Опять неправильно. Ещё раз: что возвращает mcuFlash.read? Именно это значение вы пытаетесь вывести в UART.

mcmega
Offline
Зарегистрирован: 12.02.2014

mcuFlash.read(pos, sizePack) должен вернуть кусок данных от pos длиной sizePack

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Кому должен? Никому он не должен возвращать никакого куска данных. Откройте, наконец, библиотеку и посмотрите,что он возвращает.

mcmega
Offline
Зарегистрирован: 12.02.2014

Я не понимаю, смотрел это https://www.arduino.cc/en/Reference/FileRead

что не так?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

mcmega пишет:

Я не понимаю, смотрел это https://www.arduino.cc/en/Reference/FileRead

что не так?

Returns

The next byte (or character), or -1 if none is available.

Вопросы?

mcmega
Offline
Зарегистрирован: 12.02.2014

Значит, она возвращает 1 очередной Байт из файла. Значит мне нужно вызвать ее 128 раз и сделать счетчик позиции?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

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

mcmega
Offline
Зарегистрирован: 12.02.2014

Вроде это заработало.

void sendPack(int sizePack) {
  for (int i = 0; i < sizePack; i++) {
    Serial.write(mcuFlash.read());
  }
  posInFile += sizePack;
  uartFlowCtrl = false;
}

А куда дальше смотреть?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Дальше - по потребностям. Отправлять по блокам в Serial - уже вышло. Правда, без контроля ошибок ;) Внимательно читали документацию? Что возвратит read, если уже нет в файле данных, т.е. - достигнут конец файла при чтении? В этом случае вы всё равно 128 раз отправите не существующие в файле данные.

mcmega
Offline
Зарегистрирован: 12.02.2014

Да, отправляет 128 Байт и сбрасывается флаг контроля потока (uartFlowCtrl), потом я с терминала шлю xOn и продолжается передача еще 128 Байт

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

mcmega пишет:

Да, отправляет 128 Байт и сбрасывается флаг контроля потока (uartFlowCtrl), потом я с терминала шлю xOn и продолжается передача еще 128 Байт

Я не про это. Допустим, в файле 150 байт. Поскольку вы нигде не анализируете значение, возвращаемое read - сколько байт вы отправите вашим кодом, если надо отправить весь файл, двумя пакетами, максимальный размер пакета - 128 байт?

mcmega
Offline
Зарегистрирован: 12.02.2014

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

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Нет. ещё раз: ваш код НЕ анализирует тот факт, что из файла уже всё прочитано.

mcmega
Offline
Зарегистрирован: 12.02.2014

Сделал контроль наличия данных файла, работает

void sendPack(int sizePack) {
  for (int i = 0; i < sizePack; i++) {
    if (mcuFlash.available())
      Serial.write(mcuFlash.read());
    else {
      posInFile = 0;
      uartFlowCtrl = false;
      Serial.println("End FW"); // Здесь передам служебный символ конца передачи
      return;
    }
  }
  posInFile += sizePack;
  uartFlowCtrl = false;
}

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

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

mcmega
Offline
Зарегистрирован: 12.02.2014

Сделал, спасибо Огромное!

А как читать сейчас блоками или не стоит этого делать?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Если устраивает, как сделано - пока забейте. Потом - потихонку осилите. Читать блоками - в read передавать указатель на буфер и размер буфера, вызов read вернёт, сколько вычитано в буфер. Далее этот буфер скармливаем Serial.write, с указанием, сколько в буфере данных (что вернул вызов блочного варианта read).

mcmega
Offline
Зарегистрирован: 12.02.2014

Что то очень сложно это... я планирую BIN передавать, он максимум 20к, думаю оставлю пока как есть
Спасибо за помощь!!!

Возьму на заметку описание выше, буду экспериментировать, если скорость не устроит.

hardrive
Offline
Зарегистрирован: 06.10.2022

Добрый день уважаемые знатоки!

Помогите пожалуйста нубу разобраться. Есть измерительное устройство, которое при измерении посылает пакет данных с результатами измерения в COM порт компьютера.

Пакеты эти, вот такого формата, если смотреть в терминале:

55 83 0C 13 51 5F 43 03 00 00 2D AA

В этом пакете содержаться три числа -    21.39 , 4945 и 0

Разработчик прибора оставил информацию о том, как можно выполнить преобразование и вытащить эти цифры из пакета, но к сожалению, спустя 3 дня после всяческих шаманств так ничего путнего у меня и не вышло.

Вот что оставил разработчик:

// ИНФОРМАЦИЯ ДЛЯ ПРОГРАММИСТОВ, РАЗРАБОТЧИКОВ ПО ВЫВОДА ДАННЫХ
 
/*
формат пакета
0 - признак начала пакета
1 - тип пакета
2 - длина пакета ( n=k+5)
(3 - k) - тело пакета
k+1 - контрольная сумма
k+2 - признак конца пакета
*/

Преобразование лучше делать так:

union
{
float a;
char  b[4];
}b2f;


const unsigned char
PACK_BEGIN =   0x55,
PACK_END =     0xAA,
PACK_PING =    0x05,

PACK_GETCHAR = 0x80,   // запрос характеристик
PACK_SETCHAR = 0x81,   // запись характеристик
PACK_NUMVAL =  0x82,   // запрос/количество измерений
PACK_VAL =          0x83,   // запрос/измерение

PACK_OK =           0x06,
PACK_REPEAT =  0x07,
PACK_NULL =       0x08,
PACK_NO =           0x09,	// конец связи
PACK_ERROR =   0xff;

/*
Чтение значений:
на каждое значение дает пакет PACK_VAL(2)
вначале старший потом младший
*/

Помогите пожалуйста, буду очень признателен.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

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