Преобразование 8-разрядного двоичного файла в шестнадцатеричную пару как unsigned char

У меня есть функция:

void Epd::SendData(unsigned char data) {
  digitalWrite(dc_pin, HIGH);
  SpiTransfer(data);
}

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

SendData(0x03);
SendData(0x1f);

Чтобы получить эти два значения (0x03 и 0x1f) Я преобразую десятичное значение 799 в двоичное: 1100011111, а затем добавляю 0 в начале, чтобы убедиться, что мой двоичный результат имеет длину 16 цифр: 0000 0011 0001 1111. После этого я преобразую каждые 4 бита в шестнадцатеричное значение и отправляю их в виде пар, используя функцию sendData.

Я чувствую, что я почти на месте, но я не знаю, как преобразовать мой результат в правильный тип, чтобы отправить его в функцию sendData:

void Epd::SendDecAsData(int dec) {
  int binary[16];
  for (int i = 0; i < 16; i++) {
    binary[i] = dec % 2;
    dec = dec / 2;
  }

  int dec1 = binary[15] * 8 + binary[14] * 4 + binary[13] * 2 + binary[12];
  int dec2 = binary[11] * 8 + binary[10] * 4 + binary[9] * 2 + binary[8];
  int dec3 = binary[7] * 8 + binary[6] * 4 + binary[5] * 2 + binary[4];
  int dec4 = binary[3] * 8 + binary[2] * 4 + binary[1] * 2 + binary[0];

  String val1 = "0x" + String(dec1, HEX) + String(dec2, HEX);
  String val2 = "0x" + String(dec3, HEX) + String(dec4, HEX);

  SendData(val1); // ошибка, потому что я отправляю `String` вместо `unsigned char`
  SendData(val2);
}

Мне нужна помощь в преобразовании этих строк (val1, val2) в правильный тип данных или, что еще лучше, в оптимизации этого процесса, чтобы получить конечный результат в нужном типе с меньшим количеством кода / вычислений (вероятно, избегая преобразования в строку).

, 👍0

Обсуждение

Если я вас правильно понял, вы хотите разделить 16-битный int на два неподписанных символа и отправить их. Зачем такое запутанное преобразование в шестнадцатеричное? Почему бы не использовать что-то вроде sendData (dec >> 8); sendData (dec & 0xff);. Это просто двоичные данные, их не нужно преобразовывать., @StarCat

@StarCat Я только что получил существующий код (e-ink board), и я вижу, что они отправляют шестнадцатеричное значение, поэтому я предположил, что должен сделать то же самое. Существует тонна жестко закодированных "sendData", которые вручную преобразуются из dec в hex (по какой-то причине в виде двух вызовов "sendData" из 2-значного шестнадцатеричного числа). Таким образом, даже когда мне просто нужно отправить 0 dec, он отправляется как sendData (0x00), вызываемый дважды. Я надеюсь, что это объяснение поможет, @pingDino

То, что вы отправляете с помощью sendData(0x00), * не является шестнадцатеричным значением *. Он просто представлен в тексте вашего кода шестнадцатеричным значением, но во время компиляции преобразуется в двоичное значение (unsigned char). Вы можете заменить все вхождения 0xNN их десятичным значением (если они не являются частью строки), и ваша программа будет работать точно так же. Просто попробуй., @StarCat

799, 0x031f и B0000001100010111 хранятся как одно и то же 16-битное двоичное число... различия заключаются только в исходном коде для чтения человеком .... скомпилированный код всегда имеет дело с 0000001100010111... вся ваша программа конверсии - пустая трата ресурсов ... сделайте то, что предложил @StarCat в первом комментарии, @jsotola

Спасибо вам, ребята. Я попробую завтра, как только доберусь до офиса, @pingDino

`Я жестко кодирую данные , отправляемые в него , путем вычислений на бумаге , а затем записываю результат в виде кода" ... что именно ты здесь делаешь? ... пожалуйста, приведите пример данных, задействованных в расчете, @jsotola

@jsotola например, 031f - это 799, который представляет ширину изображения, которое я добавляю на плату e-ink. Код, который я использую, говорит, что его нужно разбить на два отдельных вызова sendData, но я попробую воспользоваться приведенными выше предложениями. Если это сработает, я могу удалить оооочень много кода: D, @pingDino

хорошо, ширина изображения жестко запрограммирована... если одно и то же значение используется часто, то определите что-то вроде width_h и width_l ... в противном случае используйте код, предложенный @StarCat ... причина, по которой вам приходится разбивать 16-битные значения, заключается в том, что данные передаются в байтах .... проверьте библиотеку, может быть 16-битная функция передачи, которая делает это за вас, @jsotola

@jsotola есть много изображений, и каждое из них имеет значения (x, y, width, height), и их нелегко понять, потому что они разделены как эти две команды sendData, поэтому я хотел упростить добавление новых изображений и упростить чтение существующих + удалить много кода, @pingDino

Я действительно могу отправлять десятичные значения вместо шестнадцатеричных (умопомрачительных). Плата, с которой я работаю, может принимать только 8 бит данных одновременно, поэтому для отправки десятичной дроби "799" я сначала отправляю "3", а затем 31 (3*256 + 31). Зная это, я сумею радикально очистить код. Я просто напишу новый метод, который разбивает десятичное значение, которое я отправляю, на пару меньших десятичных значений. Спасибо StarCat и jsotola, @pingDino


1 ответ


1

Как предложилStarCat, я могу просто отправлять десятичные значения, используя ту же функцию sendData, которая мне была предоставлена. Поскольку плата e-ink может обмениваться данными только с помощью 8-битных команд, мне все равно пришлось разделить десятичное значение перед его отправкой.

Это функция, которую я использовал для отправки десятичных данных в 8-битных парах:

void Epd::SendDecAsData(int dec) {
  if (dec == 0) {
    SendData(0);
    SendData(0);
  } else {
    SendData((dec-1) / 256);
    SendData((dec-1) % 256);
  }
}
,