mopsiok napisał(a):
Dzięki za zainteresowanie, cieszę się że projekt nie został jakoś szczególnie skrytykowany
Projekt działa
... pokazałeś nawet dość fajne efekty. A reszta to tylko uwagi właśnie, które mogą się przyczynić do podniesienia własnego skill'a w dalszym programowaniu.
Dodam więc, tak jak mówił Antystatyczny, że akurat taką obsługę PWMów programowych też bym zrobił w przerwaniu. Flagi owszem są potrzebne no ale nie należy przesadnie do tego podchodzić bo gdyby tak miało być jak u ciebie to można byłoby JESZCZE BARDZIEJ skrócić kod i w ogóle wywalić procedurę obsługi przerwania skoro w nim jest ustawiana tylko flaga. Dlaczego ? już tłumaczę - zresztą nie pierwszy raz na tym forum
.... ano dlatego że masz flagę sprzętową przerwania i z niej można korzystać dokładnie tak samo jak z tej programowej tyle tylko że tracisz O WIELE mniej czasu no i kodu we flashu robi się mniej
... jak ? o tak: (twoja pętla główna)
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
(a oczywiście wywalasz całego ISR'a
no i przy inicjalizacji nie włączasz przerwań w tym timerze0
)
Widzisz jak prosto .... ? ... dlatego twój przykład jest można powiedzieć troszkę nawet (ale nie odbierz tego źle - żartobliwie mówię) wynaturzeniem wręcz korzystania z flag. Ja wprawdzie w niebieskiej książce podaję podobny przykład przy obsłudze RTC i ustawianiu w ten sposób flagi ... ale to TYLKO po to żeby zrozumieć w ogóle o co chodzi w tych mechanizmach flag. Warto ich używać gdy coś jeszcze się dzieje w przerwaniu i niejako przy okazji wtedy można machać flagą
albo flagami do innych celów.
Do tego dodam, że u ciebie to działa bo w pętli głównej nic innego nie robisz poza obsługą tych PWM'ów .... ale gdybyś tam miał jeszcze kawał innego programu to sam byś zobaczył że nastąpiłaby MASAKRAAAA .... wtedy jedynym znowu ratunkiem byłoby przeniesienie tych porównań bezpośrednio do procedury obsługi przerwania ... a program główny robiłby swoje w pętli głównej .... taką drogą warto iść
Kolejna sprawa, to ten dziwoląg mały w kodzie
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
w ogóle niepotrzebny bo domyślnie kompilator sam to robi - to DOKŁADNIE tak samo jak z tą inicjalizacją zerami przez ciebie - niepotrzebną zresztą jak już wiesz.
--------------
unsigned char vs uint8_t
tu nie chodzi o różnicę pomiędzy typami ... bo jest to DOKŁADNIE to samo ale ... ale jest pewne ale ... o którym rzadko kto wspomina a potem początkujący tacy jak ty, którzy mówią z uporem że im się to podoba a programują w AVR GCC później mają rwanie włosów z głowy gdy przyjdzie wchodzić w dalsze bardziej zaawansowane techniki programowania - gdzie szczególnie wtedy początki są trudne ....
Po części wyjaśniam to także w swoim Bluebooku
http://atnel.pl/mikrokontrolery-avr-jezyk-c.htmli także już niejednokrotnie pisałem o tym na forum ale co tam
jeszcze raz
1. char - jest DOMYŚLNIE w opcjach kompilacji w AVR GCC zamieniany i tak na unsigned char - więc już chociażby z tego powodu nie ma w ogóle sensu pisać unsigned char (znowu to coś jak z tymi inicjalizacjami zerem)
... Oczywiście można sobie wyłączyć w opcjach kompilatora tą automatyczną zamianę tylko po co panie? po co ?
A tymczasem taki początkujący jak ty - sporo piszący w AVR GCC dość szybko się przyzwyczaja do kociego unsigned char i jeszcze mówi że mu się to podoba
(matko! TYLE pisaniny
zamiast krótkiego uint8_t)
Ale ok pierwsza zaleta jak widać to mniej pisania, ok ktoś powie czochra mnie to, Druga w takim razie zaleta - jak widać typ uint8_t to dla oka od razu jasne jest że chodzi o unsigned int short (8-bit) ....
No i NAJWAŻNIEJSZE - uważaj teraz dobrze - przede wszystkim twórcy C stworzyli typ char jak myślisz dlaczego ? zadałeś sobie kiedyś to pytanie ? ... ja tak i poszukałem , odpowiedź jest prosta char to skrót od character, czyli znak. I właśnie ten typ zwyczajowo służył do trzymania zmiennych które związane były z trzymaniem w nich np kodów ASCII znaków .... natomiast wszelkiego rodzaju liczby trzyma się w typach wszelkiej maści int, short int, long int itp
Tyle że z kolei stwórcy AVR GCC (mądrzy ludzie zresztą) postanowili znacząco uprościć życie programistom procków i żeby nikt się nie zastanawiał za długo ile bajtów/bitów ma np typ int czy long int czy short int w AVR GCC to stworzono (i słusznie)
uint8_t
int8_t
uint16_t (odpowiednik unsigned int)
int16_t (odpowiednik int)
uint32_t
.... i tak dalej
i teraz UWAGA .... przyjdzie ci w swojej dalszej karierze AVR GCC korzystać z wbudowanych funkcji w AVR GCC szczególnie operujących na wskaźnikach do char , wskaźnikach do uintX_t itp ....
i SZLAG cię będzie trafiał gdy zaczną się pojawiać kocie warningi no bo np do jakiejś tam funkcji przekazać chcesz wskaźnik do tablicy znaków ASCII np twoja zmienna:
unsigned char tab[]="test";
funkcja( tab );
a tu warning i warning - że typy się nie zgadzają
I dobrze ci tak
powiedziałbym - a po co stosujesz KOCI unsigned char zamiast char panie ? Bo z punktu widzenia kompilatora to już jest RÓŻNICA którą trzeba owarningować ....
więc gdybyś szedł za poradami tych ludzi którzy stworzyli kompilator z którego korzystasz - to nie pisałbyś właśnie unsigned char tylko char (bo domyślnie kompilator i tak zamieni to na unsigned) i masz z głowy
ale jak się uprzesz to możesz zostać przy swoim kocim unsigned i funkcję wołać tak
funkcja( (char*) tab );
czyli robiąc jawne rzutowanie na typ char* ... ale skoro lubisz tyle pisania to może przy tym zostaniesz
do czasu aż kiedyś i tak cię to wkurzy - tak samo jak (wciąż wracam - zerowanie zmiennych globalnych)
jak to mówią - wystarczy tylko poczytać instrukcję
------------------------
i ostatni argument dlaczego uint8_t zamiast unsigned char czy też zamiast char.
bo oczywiście taka forma syntaktycznie jest w pełni poprawna, np:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
ale styl dobrego programowania w C a nie jakieś tam wymogi formalne mówi nam że warto to zrobić tak:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
mniej więcej z takiego samego powodu jak ten poniżej, bo np jak widzisz takie zmienne w kodzie gdzie masz akurat tysiąc różnych zmiennych a pomiędzy nimi widać:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
dla mnie - jak widzę taki kod - to widzę od razu niedbalstwo o typy o ich nazewnictwo, bo gdyby to napisać tak:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
to ja od razu na pierwszy rzut oka widzę, że O! gościu używa zmiennej tablicowej buf na jakiś bufor znaków ASCII, tak samo zmiennej zn. A pozostałe zmienne to typowe numeryczne do jakichś tam obliczeń.
Czyli NAWET z tak trywialnego kawałka kodu coś widać dla oka - na pierwszy RZUT ... a wiadomo że im dłuższy kod tym ważniejsza jest jego CZYTELNOŚĆ i PRZEJRZYSTOŚĆ. A to był jeden z NAJWAŻNIEJSZYCH celów jaki przyświecał stwórcom języka C. Tyle że ma on tak dużo możliwości i można go używać na milion sposobów, że bardzo szybko tam gdzie wkrada się niedbałość o styl dobrego programowania to kody są o wiele trudniejsze do analizy nawet dla samego siebie po kilku latach ....
Popytaj ludzi - ci którzy używają char zgodnie z tą zasadą - powiedzą ci , że jak tylko człowiek to zrozumie i się przyzwyczai to później samemu inaczej wręcz czyta się własne nawet kody programów.
O to chodzi
------------------------ [ Dodano po: 1 minucie ]mopsiok napisał(a):
2. Przyzwyczajenia . Staram się nie pakować dłuższego kodu w obsługę przerwania, a stosować raczej flagi.
I sam widzisz - już masz przyzwyczajenia ale wcale nie najlepsze bo nie chodzi o długość
ale o jakość
... to taki żarcik - ale nawiązujący też do tego co napisałem wyżej.