Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
5 years, 9 months ago.
Can I declare DigitalOut methods as virtual in the header file?
In my project I have a port expander which I use for additional SPI Chip Select (CS) pins. This IC can be configured by using I2C. It would be very comfortable to use all the mbed classes with this new CS pin. Therefore I derive a class DigitalOutVirtual from DigitalOut and overwrite all methods. Hence I can use code like the one blow. The problem is that the methods of DigitalOut are not virtual. What means that I need to change them to virtual in the header file. Now the actuall question. Can you think of problems that might occure by changing the DigitalOut methods to virtual? I know that it is bad practice to modifie the mbed classes but I don't know another way where the effort is manageable. Thank you.
DigitalOut mosi (PIN_1); DigitalIn miso (PIN_2); DigitalOutVirtual cs (PORTEXPANDER, PORT_EXP_PIN_1); cs = 1; SPI mySPI(mosi, miso, cs);
1 Answer
5 years, 9 months ago.
Hello Dominik,
That's a good idea. If you plan to use DigitalOutVirtual
as base class for your new similar classes (and use late binding) then you can do it. But in case you'd just like to have a class that is similar to DigitalOut
then you could try composition with a I2C data member:
- Define a member pointing to I2C class to be shared with all objects (saves resources)
- Design methods similar to
DigitalOut
(do not have to bevirtual
but can be, it's up to you).
Then a draft (not tested)ChipSelect
could look like:
ChipSelect.h
#ifndef CHIPSELECT_H #define CHIPSELECT_H #include "mbed.h" const int ADDR = 0x4E; // default address (A2, A1, A0 not grounded) shifted one bit to the left (to use 8 bit address) for PCF8574 chip controlling the CS pins const int FREQ = 100; // 100kHz class ChipSelect { char m_pin; // pattern to select (pull down) the given pin (P0, P1, ..., P7) I2C* m_i2c; // pointer to a I2C instance shared by all ChipSelect objects int m_addr; // 8 bit address of the I2C chip public: ChipSelect(int pin, I2C* i2c, int addr = ADDR) : m_pin(~(1 << pin)), m_i2c(i2c), m_addr(addr) { const char allPins = 0xFF; // pattern to unselect (pull up) all pins m_i2c->frequency(FREQ); m_i2c->write(m_addr, &allPins, sizeof(allPins)); // unselects (pulls up) all pins } void write(int value) { const char pinPattern = ((value == 0) ? m_pin : 0xFF); // value '0' selects (pulls down) the given pin, '1' unselects (pulls up) all pins m_i2c->write(m_addr, &pinPattern, sizeof(pinPattern)); } ChipSelect &operator=(int value) { write(value); return *this; } // for the convenience }; #endif // CHIPSELECT_H
main.cpp
#include "mbed.h" #include "ChipSelect.h" const int I2C_ADDR = 0x7E; // PCF8574A address (A2, A1, A0 not grounded) shifted one bit to the left (to use 8 bit address) DigitalOut led1(LED1); I2C csI2C(D14, D15); // I2C controlling chip select pins (shared by all ChipSelect objects) - SDA, SCL ChipSelect csDevice0(0, &csI2C, I2C_ADDR); // chip select pin P0 for device #0 ChipSelect csDevice1(1, &csI2C, I2C_ADDR); // chip select pin P1 for device #1 ChipSelect csDevice2(2, &csI2C, I2C_ADDR); // chip select pin P2 for device #2 SPI mySPI(D11, D12, D13); // SPI for communication with devices - MOSI, MISO, SCK int main() { int data = 0; while (true) { data++; // set data csDevice0 = 0; // select device #0 mySPI.write(data); // write data to device #0 csDevice0 = 1; // unselect device #0 // data++; // set data csDevice1 = 0; // select device #1 mySPI.write(data); // write data to device #1 csDevice1 = 1; // unselect device #1 // data++; // set data csDevice2 = 0; // select device #2 mySPI.write(data); // write data to device #2 csDevice2 = 1; // unselect device #2 //... led1 = !led1; wait(0.5); } }