Попытка разрешить недопустимое преобразование из «байта» {он же «беззнаковый символ»} в

Я пытаюсь использовать существующую библиотеку Arduino на Raspberry Pi Pico. Библиотека находится здесь:

https://github.com/j-bellavance/EdgeDebounce/tree/master

Это основано на интересной идее из блога Джека Ганселя: http://www.ganssle.com/debouncing.htm

Библиотека отлично работает на ATMega 328, но при переходе на Raspberry Pi Pico возникли две ошибки.

Первая проблема была решена путем редактирования последней строки EdgeDebounce.h следующим образом:

//#endif; // Версия Arduino ATMega
#endif   // Версия Pico, также работает на ATMega

Второй вариант немного сложнее. Вот соответствующий раздел кода, это строки 78–102 в EdgeDebounce.cpp:

  byte EdgeDebounce::debounce(byte pin) {
  unsigned long pinStatus;
  do {
    pinStatus = 0xffffffff;
    for (byte i = 1; i <= MYsensitivity; i++) pinStatus = (pinStatus << 1) | digitalRead(pin);
  } while ((pinStatus != debounceDontCare) && (pinStatus != 0xffffffff));
  return byte(pinStatus & 0x00000001);  
}//debounce----------------------------------------------- --------------------------------------------------

//updateStatus============================================= ====================
//После выпуска EdgeDebounceLite я понял, что EdgeDebounce может больше
//С помощью этого небольшого фрагмента кода EdgeDebounce может вернуться, если переключатель
// .закрыто(); //Проведение тока
// .открыт(); //Не проводит ток
// .Роза(); //Просто перешел из открытого состояния в закрытое
// .упал(); //только что перешёл из закрытого состояния в открытое
//------------------------------------------------ -------------------------------
void EdgeDebounce::update() {
  byte newStatus = debounce();
  if (MYmode == PULLUP) newStatus = !newStatus;
  if (MYstatus == OPEN && newStatus == CLOSED) MYrose = true;
  else                                         MYrose = false; 
  if (MYstatus == CLOSED && newStatus == OPEN) MYfell = true;
  else                                         MYfell = false;
  MYstatus = newStatus;
}//обновлять---------------------------------------------- ---------------------------

Когда я пытаюсь скомпилировать, я получаю следующую ошибку:

c:\Users\thisuser\Documents\Arduino\libraries\EdgeDebounce\EdgeDebounce.cpp: In member function 'void EdgeDebounce::update()':
c:\Users\thisuser\Documents\Arduino\libraries\EdgeDebounce\EdgeDebounce.cpp:102:14: error: invalid conversion from 'byte' {aka 'unsigned char'} to 'pinStatus' [-fpermissive]
  102 |   MYstatus = newStatus;
      |              ^~~~~~~~~
      |              |
      |              byte {aka unsigned char}

exit status 1

Compilation error: exit status 1

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

, 👍4

Обсуждение

Где объявлен «pinStatus»? Не внутри EdgeDebounce::debounce — это локальное объявление., @Nick Gammon


2 ответа


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

4

В C и во многих достандартных C++ ничто не мешает вам просто присвоить целочисленное значение переменной перечислимого типа. В стандарте C++ (начиная с 1998 года) это требует явного преобразования типов («приведение»).

Ядро AVR Arduino расходные материалы опция -fpermissive для компилятора, которая, среди прочего, позволяет неявно преобразование, которое они выполняют, несмотря на то, что они не соответствуют стандартам C++. Что бы вы ни использовали (вероятность: это или это) для RPI Pico Ядро Arduino не предоставляет опцию -fpermissive. Многие ядра Arduino этого не делают и, вероятно, не должны этого делать.

Вы можете изменить файл Platform.txt ядра RPI Pico, чтобы предоставить параметр -fpermissive для g++, но, вероятно, лучше сделать код совместимым.

>

Минимальные изменения

Вероятно, существуют десятки способов сделать это, но комбинация минимального и приятного для любителей C++, вероятно, выглядит так:

MYstatus = static_cast<pinStatus>(newStatus);

Альтернативные варианты

MYstatus = static_cast<decltype(MYstatus)>(newStatus); // любитель
MYstatus = (pinStatus)newStatus;  // традиционный состав
MYstatus = pinStatus(newStatus);  // приведение в стиле функции
MYstatus = (decltype(MYstatus))newStatus;  // уххх
MYstatus = (decltype(MYstatus))(newStatus);  // конечно... почему бы и нет?

static_cast объявляет намерение так, как этого не делают другие типы приведения. decltype позволит этой строке лучше пережить изменения типа MYstatus, но decltype не так широко известен.

Альтернативно без преобразования типов

Вы также можете заметить, что возвращаемый байт(pinStatus & 0x00000001); — это единственный пункт возврата из byte EdgeDebounce::debounce(byte pin). Итак, вы знаете, что эта функция возвращает либо 0 (ложь), либо 1 (правда). Именно это и произойдет при применении & 1.

Они определили тип перечисления:

enum pinStatus {OPEN, CLOSED};

Правила C и C++ (даже предстандартных C++) присваивают эти константы числовые значения 0 и 1, где им не были явно заданы значения и они были перечислены в указанном порядке.

Итак, вы можете заменить MYstatus = newStatus; на:

{
  if (newStatus) {
      MYstatus = CLOSED;
  } else {
      MYstatus = OPEN;
  }
}

Или используйте тернарный оператор, если хотите не возражать против того, чтобы люди пытались с вами спорить:

MYstatus = newStatus ? CLOSED : OPEN;
,

Очевидно, также возможно использовать фигурные скобки для приведения в стиле функции без диагностики сужающего преобразования, чего я не ожидал в этом случае. Но я не буду редактировать это снова, просто чтобы упомянуть об этом., @timemage

Спасибо, что нашли время написать такой подробный ответ! - Я использую ядро Earle Philhower RP2040. - Я читал (и перечитываю) ваши комментарии, пока не понял их все. - Я протестировал все предложенные вами выше исправления, и все они работают. Я не возражаю против тернарного оператора, но я приму первое предложенное вами изменение. Еще раз спасибо., @Jeff Haas


0

pinStatus — это перечисление:

enum pinStatus {OPEN, CLOSED};

Опубликованный вами pinStatus — это локальная переменная, не имеющая ничего общего с pinStatus в файле EdgeDebounce.h.

Ошибка указывает на то, что вы не можете назначить беззнаковый символ перечислению, которое может содержать только OPEN и CLOSED. Беззнаковый символ может содержать и другие значения.

Тот, кто это написал, создал какой-то запутанный код.

,