Я работаю над проектом с ESP32 и MCP23017.
В основной программе я создаю объект для MCP и инициализирую адрес.
Adafruit_MCP23X17 pin_Expander;
const int expander_addr = 0x20; // Adress 0x20
void setup()
{
Serial.begin(9600);
pin_Expander.begin_I2C(expander_addr);
expander_Init(pin_Expander);
}
Поскольку я использую в проекте много операций ввода-вывода, я хотел передать их инициализацию на аутсорсинг и написал функцию. Я создал отдельный заголовочный файл для функции.
void expander_Init(Adafruit_MCP23X17 pin_Expander)
{
// Load the GPIOs
pin_Expander.pinMode(pin1_Motor1, OUTPUT); // I have removed the other pins
// Set all GPIOs to LOW
pin_Expander.digitalWrite(pin1_Motor1, LOW); // I have removed the other pins
}
Интересно, это законный способ передать объект в другую функцию?
Вам нужно expander_Init
принять по ссылке (Adafruit_MCP23X17 & pin_Expander
), если вы хотите, чтобы он влиял на экземпляр, переданный ему из main
.
Правильно это или нет, зависит от объекта Adafruit. Передача по значению означает копирование объекта! Это может быть просто прекрасно (небольшой объект не должен быть изменен в любом случае или если изменение внутри функции нормально, в то время как исходный объект должен оставаться неизмененным), это может быть дорогостоящей операцией, но в остальном хорошо (если объект большой или требует динамического выделения памяти , иначе как раньше), и это может пойти совершенно неправильно (если исходному объекту нужно каким-либо образом изменить свое состояние) - к сожалению, последнее является наиболее распространенным случаем...
Adafruit_MCP23X17 — это класс C++ , а не какое-то определение типа, которое имитирует семантику ссылок в C, поэтому, когда вы объявляете свою функцию:
void expander_Init(Adafruit_MCP23X17 pin_Expander)
вы принимаете объект по значению, а не по ссылке, что означает expander_Init(pin_Expander);
копирование pin_Expander
и передачу копии. Любые изменения в копии обычно не влияют на исходную версию (если только класс плохо спроектирован†).
Если вы хотите изменить исходную версию, измените прототип на:
void expander_Init(Adafruit_MCP23X17& pin_Expander)
// ^ added & to make it accept by reference
это означает, что вы примете ссылку на то, что передал вызывающий объект, без каких-либо копий, и все, что вы делаете с этой ссылкой, эквивалентно выполнению этого с исходным переданным вызывающим объектом.
† Отмечу: я не удивлюсь, если класс будет плохо спроектирован, а все методы экземпляра эффективно модифицируют глобальное, а не отдельное состояние экземпляра (низкоуровневые аппаратные манипуляции часто могут делать подобные предположения), так что ваш первоначальный код может работать просто отлично, но это не гарантируется без проверки исходного кода, и это может привести к некоторой неэффективности дополнительной работы по копированию и уничтожению, которой избегает передача по ссылке.
Спасибо. Сегодня я смог протестировать ваше решение. Теперь все работает нормально.
Вы передаете по значению, так что это, вероятно, неверно.