Передавать данные структуры во внешнюю структуру через serial?

Используя две платы аналогичной архитектуры, я хотел бы отправить содержимое структуры с отправляющей платы на принимающую плату. Я использую UART для передачи данных.

Мой план состоял в том, чтобы заполнить массив начальными данными structs. Перенесите это, а затем распакуйте массив в структуру принимающих плат.

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

Вот как выглядит мой скетч отправки.

Отправить:

typedef struct NWK_DataReq_t
{
 uint8_t      state;
 uint8_t      options;
} NWK_DataReq_t;

//Структура экземпляра
NWK_DataReq_t dataRequest;

void setup() 
{
  // Дайте ему некоторые значения
  dataRequest.state = 2;
  dataRequest.options = 4;

  Serial.begin(9600);
}

void loop() 
{  
  //установить переменный массив в длину структуры
  uint8_t payload[sizeof(dataRequest)];

  //скопировать структуру в переменный массив
  memcpy(payload,&dataRequest,sizeof(dataRequest));

  //отправить каждый элемент структуры, который теперь содержится в массиве полезной
  for(int i=0;i < sizeof(payload);i++)
  {
    //Serial.print(i);
    //Serial.print(":");
    Serial.println(payload[i]);
  }

  Serial.println("");
  delay(1000);
}

Получите:

typedef struct NWK_DataReq_t
{
 uint8_t      state;
 uint8_t      options;
} NWK_DataReq_t;

//Структура экземпляра
NWK_DataReq_t dataRequest;
uint8_t incomingPayload[sizeof(dataRequest)];

void setup() 
{
  Serial.begin(9600);
  Serial.print("Recieve started");
}

void loop() 
{

  if (Serial.available())
  {
    //добавление входящих данных в массив
    for(int i=0;i<sizeof(dataRequest);i++)
    {
      uint8_t incomingByte = Serial.read();
      incomingPayload[i] = incomingByte;
    }
  }

  //установите значения массива в structs
  for (int i= 0;i < sizeof(dataRequest);i++)
  {
    structIndexPosition = incomingPayload[i];
  }
}

structIndexPosition не прикреплен, так как я не был уверен, как я мог бы проиндексировать структуру, или если это правильный подход.

, 👍1

Обсуждение

Возможно, вы захотите взглянуть на мою библиотеку КМГС. Он обрабатывает этот вид передачи очень чисто и надежно. Не стесняйтесь использовать его, злоупотреблять им, рвать его на куски, красть у него кусочки, учиться на нем, черпать из него идеи, что угодно: https://github.com/MajenkoLibraries/ICSC, @Majenko


4 ответа


0

Зачем идти за водой по мосту?

Доступ к данным в структуре можно получить в виде символьного указателя. Нет необходимости переносить в буфер и т.д.

void loop() 
{ 
  ...
  ...
  const char* dp = (const char*) &dataRequest;
  for (int i = 0; i < sizeof(dataRequest); i++) Serial.print(*dp++);
  Serial.println();
  delay(1000);
  ...
  ...
 }

Может быть, трудно экстраполировать, как это получить?

void loop() 
{ 
  if (Serial.available() > sizeof(dataRequest)) {
     char* dp = (char*) &dataRequest;
     for (int i = 0; i < sizeof(dataRequest); i++) *dp++ = Serial.read(); 
     Serial.read();
     ...
     ...
  }
}

Serial.println() и дополнительный Serial.read() могут быть заменены "маркером кадра" и / или контрольной суммой.

Ваше здоровье!

,

Хорошо, но как мне заполнить новую структуру с помощью dp?, @Womble

Похоже, какое-то время это работает. У меня есть строка Serial.print(DataRequest.options) для подтверждения. Иногда он достигает 4, но также достигает пары других чисел в циклическом порядке., @Womble


1

Я думаю, что вы слишком усложняете его, чтобы отправить два байта. Просто отправьте их в виде прямого ASCII с новой строкой после и расшифруйте его на принимающей стороне.

например.

42,87

Однако, если вопрос был просто примером чего-то гораздо более сложного, то вам, возможно, потребуется проделать больше работы. Вам нужно, чтобы принимающая сторона знала, когда начинается и заканчивается пакет данных, и желательно иметь некоторую проверку того, что он не был поврежден. Если вы хотите продолжить эту идею, посмотрите мою тему об отправке данных через RS485, в которой есть библиотека, которая делает подобные вещи.

,

Спасибо за ссылку, Ник. Это будет сложнее, чем это. Я скоро займусь валидацией, просто хотел разобраться с некоторыми основами., @Womble


1

Самый простой из возможных способов отправки данных структуры - это:

Serial.write((const uint8_t *)&myData, sizeof(myData));

Получите адрес myData, преобразуйте его в указатель int без знака и, начиная с этого адреса, запишите количество байтов, указанное в sizeof(myData). Это позволит передавать необработанные данные структуры через serial, не связываясь с копированием данных в другие массивы, назначением указателей и т.д.

Однако: это не сработает.

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

Итак, вам нужно написать протокол. Метод, при котором один конец сообщает другому концу: "Это начало данных. Это и есть данные. На этом данные заканчиваются ". Но также вы должны быть в состоянии сказать: "Этот бит, который выглядит так же, как сообщение "начало данных", на самом деле является битом данных, а не началом данных". Видите ли, на самом деле это довольно сложная задача.

,

1

Если вы не смогли запустить этот код, как я, то все, что вам нужно сделать, это вырезать: " структурный пакет { }; typedef структура пакета Package; Данные о пакете; " И вставьте его в "пустой цикл", и он должен работать нормально. P / s: Большое вам спасибо за это полезное видео, но надеюсь, что вы обновите это в будущем (я предполагаю, что обновление что-то изменило в кодах Arduino)

,

Как бы то ни было, я смотрю на вопрос и смотрю на ваш ответ, и это выглядит почти так, как будто вы отвечаете на совершенно другой вопрос, чем тот, который был задан. Но я не могу сказать наверняка., @timemage