Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 28 lis 2024, o 21:15


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 17 ] 
Autor Wiadomość
PostNapisane: 5 lis 2013, o 21:08 
Offline
Użytkownik

Dołączył(a): 28 paź 2013
Posty: 28
Pomógł: 1

Witam wszystkich ponownie.

Mam drobny problem. Mianowicie, czy istnieje możliwość (jeśli tak, to jak) przeciążania funkcji w C dla AVR. Nie ma z tym problemu w C++, ale ten niestety generuje większy kod, a uC to jednak uC a nie PC :)

Już tłumaczę o co chodzi:

Mam takie oto deklaracje w swoim pliku Serial.h:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Oczywiście próba rozwinięcia tych funkcji w deklaracje w stosownym pliczku Serial.c

I tutaj kompilator drze się na mnie w następujący sposób:

../Serial/Serial.h:38:6: error: conflicting types for 'RS_begin'
../Serial/Serial.h:37:6: note: previous declaration of 'RS_begin' was here In file included from ../Serial/Serial.c:9:0:

Czy jest jakiś sposób na to, czy muszę się obejść smakiem?

PS. Potrafię sobie z tym poradzić (choćby poprzez przekazywanie w parametrze odpowiedniej struktury i tam wartość NULL determinowałaby sposób funkcjonowania jednej funkcji), jednak moje pytanie dotyczy konkretnie przeciążania. Czy istnieje w AVR C?

Jeśli nie ma przeciążania, to czy istnieje mechanizm wartości domyślnych?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 lis 2013, o 21:43 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 gru 2012
Posty: 729
Lokalizacja: Białystok
Pomógł: 12

Cytuj:
../Serial/Serial.h:38:6: error: conflicting types for 'RS_begin'

A nie chodzi o to że masz dwie funkcje które nazywają się tak samo?

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 lis 2013, o 21:50 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 lut 2013
Posty: 600
Pomógł: 47

Przy przeciążeniach jest to dopuszczalne, wręcz nieodzowne.
Ale czy da się to na uC?

_________________
https://www.instagram.com/myfirstquadcopter/



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 lis 2013, o 22:01 
Offline
Użytkownik

Dołączył(a): 28 paź 2013
Posty: 28
Pomógł: 1

LogTeam

To jest właśnie przeciążanie :)

Kod na podstawie typu argumentu, decyduje, którą wersję funkcji wywołać :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 lis 2013, o 22:11 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 17 gru 2012
Posty: 729
Lokalizacja: Białystok
Pomógł: 12

To przepraszam za moją niewiedzę ;)

EDIT:
Dobra, już mnie google oświecił :)

_________________
sig off ;(



Ostatnio edytowano 5 lis 2013, o 22:19 przez LogTeam, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 lis 2013, o 22:14 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 lut 2013
Posty: 600
Pomógł: 47

Jaką tam niewiedzę, człowiek uczy się całe życie.
Moje motto to czym więcej wiem to widzę ile jeszcze nie wiem.

_________________
https://www.instagram.com/myfirstquadcopter/



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 lis 2013, o 23:06 
Offline
Użytkownik

Dołączył(a): 28 paź 2013
Posty: 28
Pomógł: 1

Wiem o tym :) Ale czy obiektowość nie jest niestrawna dla takiego małego AVRka. Chodzi mi o to, że o ile oczywiście dużo wygodniejsze jest C++, to jednak jest to dla uP dodatkowy narzut. (Konstruktory, destruktory, pola). Chodzi mi o to, że sama obiektowość powiększa kod, powoduje to, że samego kodu "organizacyjnego" układ musi przetrawić więcej...

...Czy się mylę i demonizuję?

Niech mnie ktoś oświeci, proszę...
Szczerze mówiąc, w C++ pod tym względem czuję się o wiele lepiej :) Choćby klasa String :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 5 lis 2013, o 23:41 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 05 sty 2013
Posty: 272
Pomógł: 3

Nie musisz tworzyć konstruktorów, destruktorów :)

Moim zdaniem dobrze rozplanowany projekt w OOP, nawet gdyby zajął więcej miejsca... co za problem? Coś kosztem czegoś. Chcesz szybki samochód? Będzie więcej palił. Chcesz pisać wygodniej kod? Szybciej? Bezpieczniej? (hermetyzacja) Możliwe (aczkolwiek niekonieczne), że będzie zajmował więcej.

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 lis 2013, o 01:25 
Offline
Użytkownik

Dołączył(a): 28 paź 2013
Posty: 28
Pomógł: 1

artuf209

Nie musisz mnie przekonywać do OOPu :) Znam doskonale jego zalety, jak choćby polimorfizm. Ale nie w tym rzecz. Pytam o C++ (skoro w C na AVR nie ma przeciążania) w kontekście mikrokontrolerów. Takie 328P które jest sercem mojego urządzenia ma tylko 2KB RAMu, czyli pamięci w której siedzą zmienne (obiekty). Trzeba zostawić jakieś miejsce na STOS. Zdaję sobie sprawę z tego, że w RAM obiekty mają podobną reprezentację do struktur. Metody zaś siedzą we FLASHU. Niemniej jednak nawet jak ja nie będę robił obiektów z konstruktorami i destruktorami, to już obiekty występujące w C++ (np. String) owszem korzystają. Jeśli do tego pisać zgodnie ze sztuką obiekty potomne, to tworzy się łańcuszek kontruktorów klas bazowych... I właśnie ze względu na to czy C++ to dobry pomysł w kontekście mikrokontrolerów. Albo inaczej, czy korzystać z dobrodziejstw OOPu, czy jednak wykombinować alternatywne rozwiązanie w C? Ideą mojego zamysłu było przeciążanie. Jeśli się nie da, to trudno, przykład z pierwszego postu można rozwiązać jedną dwuargumentową funkcją RS_begin. Najwyżej drugi parametr o wartości NULL może być dla mnie tożsamy z wywołaniem jednoargumentowej funkcji :) Tak też się da.

Zatem ponownie zapytam.... Tych co mają doświadczenie. Rozwiązywać problemy choćby (w C) tak jak to opisałem teraz, czy śmiało sięgać po C++ ?? W kontekście właśnie ograniczonych zasoobów mikrokontrolerów?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 lis 2013, o 09:40 
Offline
Użytkownik

Dołączył(a): 28 paź 2013
Posty: 28
Pomógł: 1

Tu się zgodzę, kiedyś próbowałem stringować i mi to nie wyszło :) Z drugiej strony rzecz ujmując, takie arduino oparte jest o C++ i żyje :) A w UNO sercem jest 328P :) Także może nie jest z tym tak źle :) Chyba wszystkie "firmowe" biblioteki są obiektowe. To znaczy np. LiquidCrystal Czy Serial są obiektami. Gdzie jest wiele przeciążonych konstruktorów i ładnie tworząc obiekt podaje się w parametrach piny do których podłączyliśmy np. LCD :) Jest to napewno milion razy wygodniejsze, niż zmiany w dyrektywach prekompilatora w milionie "zewnętrznych" plików. Ale czuję poprostu przez skórę, że taki "wygodny" mechanizm niesie za sobą dużo kodu, który wygodę programisty musi przenieść na barki uC. W C i programowaniu strukturalnym czy liniowym nadmierny kod jest głównie naszą produkcją. Piszemy inicjalizację LCD "na miarę" i już. Oczywiście, w takim Arduino działają mechanizmy optymalizacyjne, które np. nieskompilują nieużytych konstruktrów...

Czuję się po prostu jakbym miał w ręku wagę szalkową i na jednej szalce kładł zalety i minusy programowania w C++, na drugiej w C A wszystko w aspekcie mikrokontrolerów :)

Wiem, mam genialny pomysł, zacznę się uczyć BASCOMa i nie będę miał takiego dylematu (żarcik taki :) )



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 lis 2013, o 19:47 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 05 sty 2013
Posty: 272
Pomógł: 3

Ale mi chodziło o to, że możesz pisać jak chcesz. Nie lepiej napisać sobie jakiś kod w dwóch wersjach i sprawdzić? Pokazać na forum i ew. dopytać o jakieś uwagi?
Choćby to miałaby być biblioteka (C), klasa(C++) do np obsługi UART, nie musi być zaawansowana, chodzi o koncepcję i zobaczenie na własne oczy co i jak.

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 6 lis 2013, o 22:34 
Offline
Użytkownik

Dołączył(a): 28 paź 2013
Posty: 28
Pomógł: 1

W sumie masz rację. W takim razie skrobnę sobie klasę do obsługi UARTA, zaprezentuję na forum a sam sprawdzę zajętość w podsumowaniu kompilacji :)

Jak tylko skończę, to przekażę klaso - bibliotekę ku potomności, może komuś się zda gotowa klasa :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 7 lis 2013, o 00:55 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 05 sty 2013
Posty: 272
Pomógł: 3

A ja z miłą chęcią zobaczę :) więc czekam niecierpliwie :>

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 lis 2013, o 02:44 
Offline
Użytkownik

Dołączył(a): 28 paź 2013
Posty: 28
Pomógł: 1

Witam ponownie...

Przy pracach nad klasą do UARTA okazało się, że będę potrzebował pewną klasę pomocniczą. Prezentuję wszystkim chętnym klasę CSoftTimer służącą do stworzenia sobie (mam nadzieję) wygodnego obiektu organizującego ośmio-kanałowy TIMER programowy. Klasa "podpina" się pod sprzętowy TIMER0.

W załączniku umieszczam przykładowy programik oraz folder z klasą timera.

Programik miga sobie diodami podpiętymi do pinów B0 i B1. Oczywiście częstotliwości migania są całkowicie różne i niezależne.

A tutaj krótki opis metod tej klasy:

CSoftTimer (uint16_t Prescaller, uint8_t Tick)
Konstruktor, który inicjuje tabelę timerków oraz TIMER0 w ATMEGA 328P, pierwszy parametr to preskaler, drugi to wartość rejestru porównawczego. Czyli co ile tyknięć zegara systemowego (podzielonego przez preskaler) ma następować tyknięcie timera programowego.
Preskaler może przyjmować wartości: 1, 8, 64, 256 i 1024.

Assign (uint8_t HandlerNumber, uint64_t Interval, void(*Funkcja)())
Metoda ustawia jeden z ośmiu kanałów timera programowego, do wywoływania funkcji użytkownika co pewien czas. Jako parametry podajemy:
* HandlerNumber - Numer kanału timera programowego w zakresie od 0 do 7
* Interval - Częstotliwość wywoływania funkcji użytkownika wyrażoną w ilości tyknięć timerka ustawioną przy konstruowaniu obiektu.
* Funkcja - Wskaźnik do funkcji użytkownika, która ma być wywoływana

UnAssign (uint8_t HandlerNumber)
Zwolnienie kanału w timerku. Jako parametr podajemy numer kanału (od 0 do 7)

Enable (uint8_t HandlerNumber)
Pozwolenie na odmierzanie wskazanego kanału. Jako parametr podajemy numer kanału.

Disable (uint8_t HandlerNumber)
Zablokowanie odmierzania czasu przez kanał, którego numer podajemy jako parametr.
Po ponownym odblokowaniu, kanał zadziała po upływie całego interwału ustawionego w funkcji Assign.

Hold (uint8_t HandlerNumber)
Wstrzymanie odmierzania czasu przez kanał.

UnHold (uint8_t HandlerNumber)
Wznowienie odmierzania czasu przez kanał.

Enabled (uint8_t HandlerNumber)
Funkcja zwraca TRUE, gdy dany kanał jest aktywny. Oczywiście numerek kanału podajemy jako parametr.

:) Mam nadzieję, że komuś się przyda. W razie pytań wątpliwości czy uwag, postaram się odpowiedzieć...


Załączniki:

Aby zobaczyć załączniki musisz się zalogować. Tylko zalogowani użytkownicy mogą oglądać i pobierać załączniki.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 lis 2013, o 22:36 
Offline
Użytkownik

Dołączył(a): 28 paź 2013
Posty: 28
Pomógł: 1

Witam Ponownie.

GwynBleidD - Bardzo słuszna uwaga :) W związku z powyzszym prezentuję wersję drugą klasy - biblioteczki.

Doszedłem do wniosku, ze być może będę szeroko używał tej klasy. Np w klasie do obsługi UART, LCD, SERWO. Ponieważ w takim przypadku dla każdego projektu musiałbym edytować każdy taki moduł, by zmienić numerek kanału dla metody Assign. Tak, by każdy moduł obsługiwany był przez inny kanał. Może to być trochę uciążliwe, dlatego doszła nowa wersja metody Assign, która wykorzystuje pierwszy "wolny" kanał i zwraca jego numerek, bądź wartość -1 gdy nie ma już wolnych kanałów. Dodałem jeszcze cztery inne metody oraz za radą GwynBleidD'a zamieniłem uint16_t na typ wyliczeniowy z możliwymi wartościami preskalera sprzętowego. Poniżej usystematyzowana lista zmian:

Parametr określający preskaler został zamieniony typem wyliczeniowym i może teraz przyjąć jedną z następujących wartości:

PS_0, PS_1, PS_8, PS_64, PS_256, PS_1024

Dotyczy to metod: Konstruktora, SetPrescaller

Doszły następujące metody:

Assign (uint64_t Interval, void(*Funkcja)())
Metoda próbuje ustawić pierwszy wolny kanał timera programowego, do wywoływania funkcji użytkownika co pewien czas. Jeśli się to uda, to funkcja zwraca numer kanału, który został wykorzystany. Jeśli niestety nie mamy już żadnego wolnego kanału, funkcja zwróci wartość -1 i niestety nasza funkcja nie będzie wywoływana. Zwracana wartość jest typu int8_t.

Jako parametry podajemy:
* Interval - Częstotliwość wywoływania funkcji użytkownika wyrażoną w ilości tyknięć timerka ustawioną przy konstruowaniu obiektu.
* Funkcja - Wskaźnik do funkcji użytkownika, która ma być wywoływana

SetInterval (uint8_t HandlerNumber, uint64_t Interval) - Zmienia częstotliwość kanału.

GetInterval (uint8_t HandlerNumber) - Pobiera wartość częstotliwości z jaką pracuje kanał.

SetPrescaller (STPrescallers Prescaller) - Zmienia sprzętowy preskaler.

SetPeriod (uint8_t Tick) - Ustawia wartość rejestru porównania sprzętowego timer0

To tyle w wersji 2 :)


Załączniki:

Aby zobaczyć załączniki musisz się zalogować. Tylko zalogowani użytkownicy mogą oglądać i pobierać załączniki.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 lis 2013, o 18:33 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 05 sty 2013
Posty: 272
Pomógł: 3

Działa? Jesteś zadowolony? Jeżeli odpowiedziałeś 2x tak - przechodzisz dalej. :D

Ja osobiście bym zrobił dwie klasy, jedna do obsługi samego timera i zdarzeń (procesów) a druga to same procesy. Czyli tworzysz obiekt proces, ustawiasz mu w polach czy jest active, interval, fn i następnie do klasy obsługi timer (np timermanager) dodajesz proces (wskaźnik na tamten obiekt) i on sobie już tam lata.
Co zyskasz? Nie musisz pamiętać o tych numerkach :> rozpoznajesz za pomocą obiektów co jest wygodniejsze.

Mogę się oczywiście mylić, Ty pokazałeś jeden punkt widzenia a ja pokazuję jak można w inny sposób, według mnie wygodniejszy.

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 lis 2013, o 22:28 
Offline
Użytkownik

Dołączył(a): 28 paź 2013
Posty: 28
Pomógł: 1

Wszystko się zgadza :) I zrobiłbym to troszkę inaczej, gdyby tylko było możliwe dynamiczne tworzenie obiektów w GCC C++ :)

Chodzi mi o to, że niestety AVR GCC nie obsługuje operatorów new [] oraz delete [] Stąd na sztywno tabelka 8 elementów ("kanałów"). Poza tym, by zrobić sobie takie niezależne np. miganie diodkami, musiałbym robić własną klasę do migania diodą, dziedziczącą po klasie PROCES (przecież trzeba byłoby mieć pola organizacyjne typu ACTIVE i INTERVAL).

Tak sobie Twój sposób wyobrażam, bo przecież klasa PROCESS nie wie do czego będzie wykorzystywana a klasa właściwego procesu (ta, która umie migać diodą) nie wie przecież nic o mechanizmach naszego timerka. Chodziło o stworzenie uniwersalnej klasy narzędziowej, którą każdy może sobie załączyć do projektu i podać własną funkcję. Całkowicie pomijając sprawy implementacyjne obsługi timerka programowego.

Dokładnie tak, jak to pokazałem w funkcji main.cpp przykładowej aplikacji :) Czyli enkapsulacja. Chodzi o to, że "Kowalski" musi "jedynie" dołączyć do swojego kodu #include i reszta ma się dziać sama :) Kowalski ma przecież ważniejsze funkcje do napisania i nie chce sobie głowy zawracać jakimś tam timerkiem, on chce go tylko wykorzystać. Taka idea mi tutaj przyświecała i będzie przyświecać przy projektowaniu pozostałych klas :)

Twój sposób jak najbardziej mi się podoba, ale chyba jest bardzo ciężki do zastosowania w uniwersalnym, "cywilnym" narzędziu.

W planach mam cały framework do obsługi wszystkich komponentów uC a później peryferiów zewnętrznych. Mam nadzieję, ze uda mi się to zgrabnie skomponować, tak, by wyprodukować poszczególne klocki, które będą potrafiły ze sobą współpracować. W ten sposób powinno udać się stworzyć bazę do tego, by nie przejmować się przy każdym projekcie jak obsłużyć LCD, klawiaturkę, odbiornik IR itd, a skupić się na głównych funkcjach projektowanego urządzenia.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 17 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO