Re: Ukazka C++ pro děti
Pavel Brychta
pavel.brychta na duhasys.eu
Čtvrtek Duben 1 10:15:16 CEST 2021
Jistě, alespoň jeden za všechny:
Mějme dva vývody mikrokontroléru, nazvané obecně GPIO1 a GPIO2, na které
se připojují různé RFID čtečky rozhraní Wiegand, MG, nebo sériový port.
Původní řešení bylo v C++, kde pro obsluhu každé čtečky byl vytvořený
objekt, jehož konstruktor vypadal řekněme takto:
WIEGAND::WIEGAND(int pinD0, int pinD1) {
...
}
MGTrack::MGTrack(int pinDta, int pinClk) {
...
}
V aplikaci pak bylo použité:
WIEGAND rdrWie(GPIO1, GPIO2);
MGTrack rdrMg(GPIO1, GPO2);
Tady bych jen chtěl zvýraznit to, co jsem psal o konstruktorech - v obou
objektech jsou použité stejné GPIO, takže konstruktory nesmí ty GPIO
žádným způsobem nastavovat co se týče hardware. To se děje až v begin()...
Inicializace čteček pak probíhala ve stylu:
if (RT_WIEGAND == rdrType) {
rdrWie.begin();
} else if (RT_MAGSTRIPE == rdrType) {
rdrMg.begin();
}.....
A vlastní obsluha vlastního čtení pak probíhala ve stylu:
bool haveCard;
if (RT_WIEGAND == rdrType) {
haveCard = rdrWie.haveCard();
} else if (RT_MAGSTRIPE == rdrType) {
haveCard = rdrMg.haveCard();
} ...
Nevýhoda je jasná - objekty jsou statické, takže sežerou RAM i v
případě, že nejsou používané a přidání dalšího typu čtečky je opruz.
Přepsal jsem to tedy na polymorfní tím, že jsem vytvpřil třídu RdrBase,
kterou jsem použil jako předka pro všechny čtečky. Současná varianta pak
vypadá takto:
class rdrBase
{
public:
virtual void begin(void);
virtual bool haveCard(void);
...
};
...
rdrBase *reader = nullptr;
Inicializace pak vypadá takto:
if (RT_WIEGAND == rdrType) {
reader = new WIEGAND(GPIO1, GPIO2);
} else if (RT_MAGSTRIPE == rdrType) {
reader = new MGTrack(GPIO1, GPIO2);
}.....
if (reader) {
reader->begin();
}
A obsluha pak vypadá takto:
bool haveCard = false;
if (reader) {
haveCard = reader->haveCard();
}
Už v tomto jednoduchém příkladu obsazení paměti RAM výrazně kleslo a
výhoda tohoto řešení se ukázala ještě více v okamžiku, kdy bylo třeba
obsluhovat více čteček na jednom zařízení. Cena za to je dynamická
alokace new, ale - protože si toho jsem vědom, tak vím, kdy ji můžu
udělat, aby nezpůsobila fragmentaci heapu. Stejným způsobem mám řešené
například pravidla pro dekódování karet, respektive jejich převod do
interního formátu systému, stejným způsobem mám řešené různé formáty
exportů/komunikace, nebo například typy výkonových prvků (relé na zámek,
flip/flop relé, impulz pro turniket, relé přes UDP, ...).
Tohle řešení používám v různých obměnách na platformě AVR(atmega328,
32U8), ESP8266, ESP32 a SAMD21.
Pavel Brychta
Dne 01. 04. 21 v 9:35 Jan Waclawek napsal(a):
>
>> právě polymorfní objekty v praxi
>>
>> pomohly pár věcí vyřešit hodně elegantní cestou
> Mozete prosim uviest priklady?
>
> Dakujem
>
> wek
>
>
>
> On 1 April 2021 06:38:54 CEST, Pavel Brychta <pavel.brychta na duhasys.eu> wrote:
>> Když už jsme se dostali k přetěžování operátorů, tak by bylo dobré
>> zmínit i šablony (templates), které s přetížením můžou souviset a
>> umožní
>> vytvořit konverze mezi jednotlivými datovými typy. No a odtud je pak už
>>
>> jen krůček k polymorfním objektům, které, jak jsem se zde dozvěděl, by
>> měly na 8-bitech "vadit", což považuji za blábol, protože je běžně
>> používám a paradoxně paměť RAM jejich použitím spíš šetřím (asi to
>> používám "v míře menší, než zanedbatelné", nebo to prostě to AVRko
>> neví,
>> tak mu to nevadí). V každém případě mi právě polymorfní objekty v praxi
>>
>> pomohly pár věcí vyřešit hodně elegantní cestou, takže bych je
>> neopomenul zmínit...
>>
> _______________________________________________
> HW-list mailing list - sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
Další informace o konferenci Hw-list