Ошибка Cast from 'char*' to 'uint8_t {aka unsigned char}' loses precision [-fpermissive]

Я пытаюсь преобразовать строку, полученную из Websocket, в uint8_t, которую я могу скопировать в байты данных кадра протокола CAN. Я использую чип ESP32 и программирую его в Arduino IDE. Строка, которую он получает из веб-сокета, имеет вид "0322F12155555555".

#include <WiFi.h>
#include <SPIFFS.h>
#include <ESPAsyncWebServer.h>
#include <WebSocketsServer.h>
#include <esp32_can.h>
#include <SPI.h>
#include <string.h>

uint8_t payload1;
char payload2[100];
...
AsyncWebServer server(80);
WebSocketsServer webSocket = WebSocketsServer(1337);
...
// Обратный вызов: получение любого сообщения WebSocket
void onWebSocketEvent(uint8_t client_num,
                      WStype_t type,
                      uint8_t * payload,
                      size_t length) {
...
      Serial.printf("[%u] Received text: %s\n", client_num, payload);
      strcpy(payload2, (const char*)payload);
      payload1 = (uint8_t)(payload2);
...

Ошибка:

error: cast from 'char*' to 'uint8_t {aka unsigned char}' loses precision [-fpermissive]
       payload1 = (uint8_t)(payload2);
                                    ^

Позже я сегментирую данные в массив, но не уверен, что приведение правильное. Может ли кто-нибудь помочь с этим? Спасибо

-- Кит

, 👍2

Обсуждение

Это должно быть uint8_t *, а не uint8_t., @Majenko

@Majenko, мне нужно, наконец, сегментировать данные и скопировать их в массив, который принимает `uint8_t`. Как я могу это сделать?, @ObviousActivity936

Я думаю, это звучит так, как будто вам нужно делать гораздо больше, чем просто кастинг. Вам нужно интерпретировать содержимое строки., @Majenko


1 ответ


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

2

Вы не можете просто привести строку к числовому типу — C так не работает. На самом деле вы передаете адрес в памяти, по которому находится строка.

Вместо этого вам нужно взять содержимое строки и интерпретировать его.

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

Например:

char temp[3]; // Временное место для строки преобразования
// Копируем два символа во временную строку
temp[0] = payload[0];
temp[1] = payload[1];
// и закончим строку правильно
temp[2] = 0;
// Преобразование строки с использованием базы 16
uint8_t val = strtol(temp, NULL, 16);

В строке примера у вас есть 16 символов, что соответствует 8 байтам данных. Таким образом, вы можете поместить его в цикл:

char temp[3]; // Временное место для строки преобразования
uint8_t vals[8]; // Массив для хранения ваших значений

// Перебираем значения
for (int i = 0; i < 8; i++) {
    // Копируем два символа во временную строку
    temp[0] = payload[i * 2];
    temp[1] = payload[i * 2 + 1];
    // и закончим строку правильно
    temp[2] = 0;
    // Преобразование строки с использованием базы 16
    vals[i] = strtol(temp, NULL, 16);
}

Конечно, есть "более легкие" способы сделать это, которые не включают промежуточную строку или функцию strtol(). Например, я часто использую эту маленькую функцию:

uint8_t h2d(char hex) {
    if(hex > 0x39) hex -= 7; // настроить шестнадцатеричные буквы в верхнем или нижнем регистре
    return(hex & 0xf);
}

Это берет один символ и преобразует его из шестнадцатеричного в десятичный. Таким образом, вы можете комбинировать это со сдвигом битов и ИЛИ, чтобы создать байт из двух символов:

val = h2d(payload[0]) << 4 | h2d(payload[1]);

В вашем цикле это будет выглядеть так:

for (int i = 0; i < 8; i++) {
    // Преобразование строки с использованием базы 16
    vals[i] = h2d(payload[i * 2]) << 4 | h2d(payload[i * 2 + 1]);
}
,