Как преобразовать char[12] в byte[6]

Я пытаюсь преобразовать массив char[12], содержащий Mac-адрес, в byte[6] для использования в методе Ethernet.begin. Я пробовал различные методы из Интернета, но пока безуспешно. Массив символов в настоящее время содержит «A4BDC334688C», и мне нужен массив байтов, содержащий {A4, BD, C3 и т. д.}.

Следующее очень близко к рабочему, с выводом следующего "Файл открыт. А4БДК334688К А4 9Д С3 34 68 6C", где BD неправильно преобразуется в 9D, а 8C становится 68.

#include <SPI.h>
#include <SD.h>
#include <ArduinoJson.h>

byte ByteMacAddress[6]; // ЗАРЕЗЕРВИРОВАННЫЙ MAC-АДРЕС
StaticJsonDocument<200> doc;

int ShotCount = 0;
byte buf[40];

void setup() {
  Serial.begin(9600);

  //Инициализировать SD-карту для конфигурации
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
  }

  // открываем файл для чтения:
  File ConfigFile = SD.open("Config.txt");
  if (ConfigFile) {
    Serial.println("File Opened.");
  } else {
    Serial.println("error opening Config.txt");
  }

  // Десериализовать конфигурацию Json в файле
  delay(5);
  DeserializationError error = deserializeJson(doc, ConfigFile);
  ConfigFile.close();
  // Проверяем, успешен ли синтаксический анализ.
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return;
  }

  char* SDMacAddress = doc["MacAddress"];
  Serial.println(SDMacAddress);



  char arr[12];
  strcpy(arr, SDMacAddress);

  auto getNum = [](char c){ return c > '9' ? c - 'a' + 10 : c - '0'; };
  byte *ptr = ByteMacAddress;

  for(char *idx = arr ; *idx ; ++idx, ++ptr ){
    *ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
  }


  //Проверить преобразованные значения байтов.
  for( byte b : ByteMacAddress )
    Serial.println( b, HEX );  
}


void loop(){
  // Поддерживать аренду DHCP
  //Ethernet.maintain();

  //Получить число выстрелов();
  delay(500);
}

, 👍2

Обсуждение

Вы видели функцию strtol(buf, &targetvariable, BASE), как она используется в ответе на [этот вопрос](https://arduinoprosto.ru/q/36700/convert-serial-value-into- hex-использование-in-genuino-zero)? Вы можете использовать его для преобразования каждого байта (2 символа) по отдельности или даже - с помощью объединения - преобразовать всю строку сразу., @chrisl

В getnum вы не учитываете буквы верхнего регистра. Буквы все строчные или все прописные?, @chrisl

обычно двоичное представление MAC-адреса находится в обратном порядке, чем шестнадцатеричная строка, @Juraj

@chrisl Спасибо также за ваш ответ, я очень ценю всех, кто нашел время, чтобы помочь мне., @BelGaraath


2 ответа


Лучший ответ:

2

Пожалуйста, смотрите комментарии в коде:

// SDMacAdress завершается нулем
// (так и должно быть, потому что вы используете strcp, а не strncp)
// символ обр[12]; вам нужен один дополнительный байт для нуля
char arr[13];
strcpy(arr, SDMacAddress);

auto getNum = [](char c)
{ 
  // вы забыли прописные шестнадцатеричные буквы (AF)
  // не используйте сложный код
  // лучшие программисты пишут понятный код как минимум ИМХО ;-)
  // возможно, вы скопировали его из Интернета
  // возвращаем c > '9'? с - 'а' + 10 : с - '0';

  if ( c >= '0' && c <= '9' ) return c - '0';
  if ( c >= 'a' && c <= 'f' ) return 10 + c - 'a';
  if ( c >= 'A' && c <= 'F' ) return 10 + c - 'A';

  return 0;
};

byte *ptr = ByteMacAddress;

for(char *idx = arr ; *idx ; ++idx, ++ptr )
{
  *ptr = (getNum( *idx++ ) << 4) + getNum( *idx );
}
,

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

Я должен упомянуть, что у @chrisl была эта идея до меня. Я просто привел пример, как это сделать. Пожалуйста, проголосуйте за его/ее (?) комментарий выше. Я сделал это уже. ;-), @Peter Paul Kiefer

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


2

Непонятно, почему вы пытаетесь реализовать это с нуля. Если ваш ввод всегда правильно отформатирован, вы можете выполнить преобразование одним вызовом sscanf

char arr[] = "A4BDC334688C";
byte ByteMacAddress[6];

sscanf(arr, "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", 
  &ByteMacAddress[0],
  &ByteMacAddress[1],      
  &ByteMacAddress[2],
  &ByteMacAddress[3],
  &ByteMacAddress[4],      
  &ByteMacAddress[5]);

Конечно, вы также можете реализовать это [более элегантно] через цикл, т.е. sscanf по одному байту за раз.

,