Я ищу абстракции C ++ для аппаратных точек ввода / вывода или выводов. Такие вещи, как in_pin, out_pin, inout_pin, может быть open_collector_pin и т. Д.
Я, конечно, могу сам придумать такой набор абстракций, поэтому я не ищу ответы типа «эй, ты мог бы сделать это таким образом», а скорее «посмотри на эту библиотеку, которая использовалась в этом, этом и этот проект'.
Google не обнаружил ничего, возможно, потому что я не знаю, как другие назвали бы это.
Моя цель состоит в том, чтобы создать библиотеки ввода-вывода, которые основаны на таких точках, но также обеспечивают такие точки, поэтому было бы легко, например, подключить HD44780 LCd либо к выводам ввода-вывода микросхемы, либо к I2C (или SPI) Расширитель ввода / вывода или любая другая точка, которой можно каким-либо образом управлять, без каких-либо изменений в классе LCD.
Я знаю, что это на грани электроники / программного обеспечения, извините, если это не принадлежит здесь.
@leon: проводка Это большой пакет программного обеспечения, мне нужно будет присмотреться. Но, похоже, они не используют абстракцию булавки, как я хочу. Например, в реализации клавиатуры я вижу
digitalWrite(columnPins[c], LOW); // Activate the current column.
Это подразумевает, что есть одна функция (digitalWrite), которая знает, как записать на вывод ввода / вывода. Это делает невозможным добавление нового типа вывода ввода / вывода (например, на MCP23017, поэтому его необходимо записать через I2C) без перезаписи функции digitalWrite.
@Oli: Я погуглил пример Arduino IO, но похоже, что он использует тот же подход, что и библиотека Wiring:
int ledPin = 13; // LED connected to digital pin 13
void setup(){
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
источник
Ответы:
Краткий ответ: к сожалению, нет библиотеки, чтобы делать то, что вы хотите. Я делал это сам много раз, но всегда в проектах без открытого исходного кода. Я подумываю над тем, чтобы положить что-то на github, но я не уверен, когда смогу.
Почему С ++?
источник
Позвольте мне бесстыдно подключить мой проект с открытым исходным кодом https://Kvasir.io . Часть Kvasir :: Io предоставляет функции управления выводами. Сначала вы должны определить свой пин с помощью Kvasir :: Io :: PinLocation следующим образом:
Обратите внимание, что на самом деле это не использует RAM, потому что это переменные constexpr.
Во всем коде вы можете использовать эти положения выводов в функциях «фабрики действий», таких как makeOpenDrain, set, clear, makeOutput и так далее. «Фабрика действий» фактически не выполняет действие, а возвращает Kvasir :: Register :: Action, который можно выполнить с помощью Kvasir :: Register :: apply (). Причина этого заключается в том, что apply () объединяет переданные ему действия, когда они воздействуют на один и тот же регистр, что дает выигрыш в эффективности.
Поскольку создание и объединение действий выполняется во время компиляции, это должно привести к тому же коду ассемблера, что и к типичному эквиваленту, закодированному вручную:
источник
Проект Wiring использует такую абстракцию:
http://wiring.org.co/
и компилятор написан на C ++. Вы должны найти множество примеров в исходном коде. Программное обеспечение Arduino основано на проводке.
источник
В C ++ можно написать класс, чтобы вы могли использовать порты ввода-вывода, как если бы они были переменными, например
без учета базовой реализации. Например, если используется аппаратная платформа, которая не поддерживает операции на битовом уровне, но поддерживает операции регистра на уровне байтов, можно (возможно, с помощью некоторых макросов) определить статический класс IO_PORTS со встроенным чтением-записью свойства, называемые bbRB3 и bbLATB4, так что последнее приведенное выше утверждение превратится в
который в свою очередь будет преобразован во что-то вроде:
Компилятор должен иметь возможность замечать константное выражение в операторе?: И просто включать «истинную» часть. Можно было бы уменьшить количество свойств, создаваемых макрокомандой, до чего-то вроде:
или
но я не уверен, что компилятор сможет встроить код так хорошо.
Я ни в коем случае не хочу подразумевать, что использование портов ввода-вывода, как если бы они были переменными, - это всегда хорошая идея, но, поскольку вы упоминаете C ++, это полезная уловка. Моим собственным предпочтением в C или C ++, если совместимость с кодом, использующим вышеупомянутый стиль, не требуется, вероятно, будет определять некоторый тип макроса для каждого бита ввода-вывода, а затем определять макросы для «readBit», «writeBit», «setBit» и «clearBit» при условии, что аргумент идентификации битов, передаваемый этим макросам, должен быть именем порта ввода / вывода, предназначенного для использования с такими макросами. Например, приведенный выше пример будет записан как
и переводится как
Это будет немного больше работы для препроцессора, чем стиль C ++, но это будет меньше работы для компилятора. Это также позволило бы обеспечить оптимальную генерацию кода для многих реализаций ввода-вывода и достойную реализацию кода практически для всех.
источник
Если вы ищете что-то действительно классное для абстрагирования аппаратного обеспечения и уверены в своих навыках C ++, попробуйте этот шаблон:
https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
Я использовал его в одной попытке абстрагировать аппаратное обеспечение для чипа Cortex-M0. Я еще ничего не писал об этом опыте (я сделаю это когда-нибудь), но поверьте мне, он был очень полезен из-за его статической полиморфной природы: один и тот же метод для разных чипов, без затрат (по сравнению с динамическим полиморфизмом).
источник