Я пишу код для Arduino. Код становится длинным, поэтому я хочу использовать некоторые отладочные макросы и иметь возможность отображать некоторую отладочную информацию на последовательном порту.
Например, у меня есть несколько макросов, чтобы определить, какие последовательные порты я использую:
#define SERIAL_GPS Serial1
#define SERIAL_IRIDIUM Serial2
#define SERIAL_VN100 Serial3
Как я могу написать макрос, чтобы показать порты, которые я использую для каждого из них? Т.е. какой-то макрос, который будет печатать на последовательном порту отладки:
Port for GPS: Serial1
Port for Iridium: Serial2
Port for VN100: Serial3
Я пытался:
#define SHOW_VAR_NAME(x) #x
вместе с:
SERIAL_DEBUG.println(SHOW_VAR_NAME(SERIAL_GPS));
Но это печатает на серийнике:
SERIAL_GPS
вместо:
Serial1
потому что (я полагаю) препроцессор макроса выполняет только одно сканирование. Какой-нибудь умный способ заставить это работать?
Примечание: здесь я беру простой пример, но есть некоторые переменные отладки (например, некоторые переменные DEBUG_GPS, DEBUG_IRIDIUM и другие), которые я действительно хотел бы распечатать при запуске платы: у меня довольно много таких параметров отладки для отдельных компонентов , а печать их статуса при запуске поможет отслеживать, какие отладки активированы или нет (даже если все они собраны в файле заголовка, не помешает запомнить пользователю обо всех из них).
@UKMonkey: Я все еще довольно близок к новичку, но чем больше я сталкиваюсь с макросами, тем больше я с вами согласен. Если у вас есть предложения по другому способу организации моего кода, мне будет очень интересно. Также обратите внимание, что это для плат Arduino, как написано в вопросе, то есть архитектура с примерно 32 КБ флэш-памяти и 1 КБ ОЗУ (в значительной степени зависит от того, какой конкретный MC). Это немного особые требования;)
Ну, не зная, что такое Serial1; Я собираюсь предположить, что это целое число, чтобы сообщить, какой порт Serial1 включен ... в этом случае создайте функцию с именем getPortUsage(int port), а затем вы можете switch(port) {case SERIAL_GPS: return "GPS";}. Это должно повлиять на использование памяти меньше, чем вы ожидали; особенно если вы встраиваете его или даже constexpr это
Нет, извините за то, что не предоставил больше контекста: это снова код Arduino со всеми вытекающими из него соглашениями;) Итак, если я прав, Serial1 - это полноценный последовательный объект (последовательный порт, управляемый прерываниями).
но я вижу логику в вашем методе;) (даже если это будет связано с некоторыми затратами по сравнению с макросом; переключатель не должен быть слишком плохим, но он быстро складывается на таких маленьких архитектурах, я думаю).
Оберните его в свой собственный объект, затем ... class GPSSerial { public: Serial& getSerial(){} const char* getName(){return "GPS";}
Тактовая частота 4 МГц ... оператор switch, вероятно, составляет 4-5 тактов. Миллион из них займет секунду. Сколько вы планируете сделать?
Не слишком много, вы правы. Если есть простое макро-решение, в качестве принятого ответа, мне оно нравится;)





Оператор препроцессора # предотвращает раскрытие своего операнда. Вам нужно добавить уровень косвенного обращения, чтобы могло произойти расширение:
#define SHOW_VAR_NAME_(x) #x
#define SHOW_VAR_NAME(x) SHOW_VAR_NAME_(x)
Эта функциональность обеспечивается BOOST_PP_STRINGIZE от Boost.Preprocessor, который я рекомендую использовать, если вы начинаете интенсивно использовать препроцессор.
IOW, повторно внедрите BOOST_PP_STRINGIZE.
@Angew Я признаю себя виновным в FGITW. Я на самом деле сейчас беру документацию Boost.PP.
Большое спасибо как за ответ (это отлично работает), так и за указание на повышение. Как вы думаете, подойдет ли использование boost.preprocessor на контроллерах Arduino (обычно 32 КБ флэш-памяти, 1 КБ оперативной памяти), или это будет связано с некоторыми расходами?
@ Zorglub29 это все препроцессор, так что никаких следов :)
ок, спасибо :) Рассмотрим подробнее, когда у меня будет время;)
Строки могут быть сгенерированы препроцессором, но вы собираетесь что-то с ними делать. И как только они компилируются в окончательный исполняемый образ, остается является, занимающий память. При 1кБ ОЗУ даже крошечные струны могут оказаться стопорами для шоу.
Каждый раз, когда кто-то задает здесь макро-вопрос, я бы выделил предложение «посмотрите в зеркало и спросите себя, действительно ли нет лучшего способа».