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



Teraz jest 29 mar 2024, o 08:30


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 18 ] 
Autor Wiadomość
PostNapisane: 30 lis 2015, o 10:58 
Offline
Użytkownik

Dołączył(a): 08 wrz 2012
Posty: 505
Pomógł: 6

Czy może mi ktoś pomóc w wyjaśnieniu dlaczego tak się dzieję, że diody LED które powinny mrugać co 1 sekundę, a tego nie robią?
W poniższym programie (maksymalnie uproszczonym) diody led1,2,3,4 powinny zmieniać swój stan na przeciwny po doliczeniu licznika cnt_1ms do 1000.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Rzecz w tym, że jak mam w pętli głównej te dwie linijki
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Program źle działa. Jak je usunę to jest ok.
Wydawało mi się że nie ważne co jest w głównej pętli programu to, że jak już program wejdzie w przerwanie to póki go nie wykona w całości to w głównym programie nic się nie dzieje. Niestety diody led mrugają nieregularnie lub nawet niektóre wcale co jest dla mnie bardzo dziwne. Zrozumiałby gdyby było ta, że to w pętli głównej są problemy np. przerwanie za często lub za długo, ale dlaczego przerwanie źle działa?
Program jest banalny na razie to tylko początek dla sprawdzenia czy procesor jest dobrze przylutowany i czy ledy działają. W docelowym programie linijkę
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

umieszczę w warunku wykonywanym np co pół sekundy, ale na próbę zrobiłem tak jak wyżej i mocno zastanowiły mnie efekty. Poproszę o wyjaśnienie



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 30 lis 2015, o 21:01 
Offline
Uzytkownik zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 16 lip 2012
Posty: 2088
Lokalizacja: Leżajsk / Kraków
Pomógł: 411

Zmiana stanu na przeciwny z użyciem PORTx ^= (1<<Pxy) zajmuje kilka instrukcji asemblera. Kod asemblera można znaleźć w pliku *.lss w folderze Release. Najpierw wczytywany jest stan portu do rejestru, następnie wartość jest zmieniana i ostatecznie zapisywana z powrotem do portu. Jeśli pomiędzy tymi instrukcjami wystąpi przerwanie w którym zmieniony zostanie stan portu to po powrocie ta zmiana zostanie nadpisana przez instrukcję, która z rejestru wpisuje wartość do portu, a więc zmiana wykonana w funkcji obsługi przerwania zostanie utracona. Ratunkiem jest umieszczenie kodu w bloku gdzie przerwania są wyłączane:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Innym sposobem jest użycie rejestru PINx do funkcji toggle, ale dostępne jest to w nowszych mikokontrolerach np. atmega644PA. Wtedy zmiana stanu to tylko jedna instrukcja asemblera.


Autor postu otrzymał pochwałę

_________________
Dragonus Cracovus: Biomagia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 30 lis 2015, o 21:22 
Offline
Użytkownik

Dołączył(a): 06 maja 2014
Posty: 415
Lokalizacja: Kraków
Pomógł: 26

Czy Atomic Block to jest tylko wyłączenie przerwań, czy spełnia jeszcze jakieś inne funkcje?

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

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

?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 30 lis 2015, o 21:37 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

Prawie, bo zależy od użytego parametru. W tym przykładzie nie będzie sei() tylko odtworzenie zapamiętanego przed cli(); rejestru SREG.
Polecam zaglądać do dokumentacji http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__util__atomic.html lub do atomic.h - w eclipse wchodzi się przez klik z controlem.

--
Pozdrawiam,
Robert



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 30 lis 2015, o 21:38 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

krzysssztof napisał(a):
jest równoznacze z


oczywiście, że nie jest .... bo pomyśl co się stanie gdy któregoś razu wywołasz to wtedy gdy przerwania mają być wyłączone ? Wtedy się na siłę włączą

równoważne jest temu

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

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 30 lis 2015, o 21:57 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

Twój przykład jest zgodny z zapisem jak użyjesz parametr ATOMIC_FORCEON. Bo wtedy nie jest zapamiętywany stan SREG a przerwanie jest włączane automatycznie.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

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

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

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



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 1 gru 2015, o 06:42 
Offline
Użytkownik

Dołączył(a): 08 wrz 2012
Posty: 505
Pomógł: 6

Ale, mnie nie zastanawiają problemy z pętlą główną
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Rzecz w tym, że to w przerwaniu timera dzieją się dziwne rzeczy. Nie wszystkie diody zapalają się, czasem zapala się jedna a za chwilę trzy pozostałe lub odwrotnie. Tego nie mogę zrozumieć. To, że w pętli głównej program się nie wyrabia bo przerwanie może wystąpić w "złym" momencie to jest dla mnie jasne, ale dlaczego program w przerwaniu tak fiksuje?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 1 gru 2015, o 18:24 
Offline
Użytkownik

Dołączył(a): 29 lip 2014
Posty: 195
Pomógł: 44

Witam,

a jaki to konkretnie procek? I co masz podłączone do tych wyjść LED_TES_TOG i WDI_TOG ? Najlepiej pokaż schemat, jak masz to wszystko podłączone.

Pozdrawiam, QuadMan.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 1 gru 2015, o 19:30 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 29 sty 2012
Posty: 777
Lokalizacja: Karpicko k. Wolsztyna
Pomógł: 197

A próbowałeś zrobić tak jak radzą koledzy? Sprawdziłem to i faktycznie umieszczenie kodu z pętli głównej w ATOMIC_BLOCK sprawia, że diody w przerwaniu zaczynają działać poprawnie.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 1 gru 2015, o 20:53 
Offline
Uzytkownik zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 16 lip 2012
Posty: 2088
Lokalizacja: Leżajsk / Kraków
Pomógł: 411

Tom277 napisał(a):
Tego nie mogę zrozumieć.

Prostsze wytłumaczenie:
1. Procesor wykonuje instrukcje w pętli głównej. Zmiana stanu pinu LED_TEST wygląda tak:
a) odczyt zawartości portu B do rejestru Rx
b) wykonanie operacji Rx ^ 0b00000100
c) zapis liczby z rejestru Rx do portu B

2. W przerwaniu inne operacje na porcie B zmieniają jego wartość.

3. Jeśli przerwanie wystąpi we wskazanych miejscach i zmieni wartość portu B to jaka będzie wartość na końcu?
a) odczyt zawartości portu B do rejestru Rx
======= przerwanie i zmiana wartości portu B
b) wykonanie operacji Rx = Rx ^ 0b00000100
======= przerwanie i zmiana wartości portu B
c) zapis liczby z rejestru Rx do portu B

Odpowiedź:
Wynikająca z odczytanej i zmienionej przez Rx = Rx ^ 0b00000100. Zmiany wykonane w funkcji obsługi przerwania zostaną nadpisane w ostatnim kroku c

_________________
Dragonus Cracovus: Biomagia



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 1 gru 2015, o 21:23 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

Weź pod uwagę, że to co napisał Krauser, musi nastąpić z bardzo dużym prawdopodobieństwem, bo tylko to robisz w swojej pętli głównej. Więc te operacje operowania na porcie muszą być przerwane przez wygenerowane przerwanie.
Jak dałbyś jakiś delay-a w pętli głównej, to zmniejszyłbyś prawdopodobieństwo wystąpienia takiego efektu proporcjonalnie do proporcji czasu zajętego na delaya i potrzebnego na toggle.

Oczywiście dodanie delay-a nie spowoduje zniknięcia problemu a raczej stworzenia kodu w stylu Windows - działa dobrze ale co jakiś czas coś się wyłoży :)

--
Pozdrawiam,
Robert



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 gru 2015, o 00:05 
Offline
Użytkownik

Dołączył(a): 29 lip 2014
Posty: 195
Pomógł: 44

Panowie,

Tom277 napisał(a):
...Rzecz w tym, że to w przerwaniu timera dzieją się dziwne rzeczy. Nie wszystkie diody zapalają się, czasem zapala się jedna a za chwilę trzy pozostałe lub odwrotnie. Tego nie mogę zrozumieć. To, że w pętli głównej program się nie wyrabia bo przerwanie może wystąpić w "złym" momencie to jest dla mnie jasne, ale dlaczego program w przerwaniu tak fiksuje?

Kolega Tom277 napisał o czymś zupełnie odwrotnym, niż Wy usiłujecie Mu wytłumaczyć. Nie wyobrażam sobie, aby opisane przez Niego zjawisko w normalnych warunkach było w ogóle możliwe, dlatego dopytywałem się, jaki to procek, jak ma to wszystko podłączone, itd.

Pozdrawiam, QuadMan.

P.S. Podejrzewam jakiś problem sprzętowy - "to coś" dopięte do portu D powoduje resetowanie się procka, albo np. krótkotrwały spadek napięcia zasilania, itp... Nie wiem, nie znam się, nie pytać... ;-).



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 gru 2015, o 00:22 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 29 sty 2012
Posty: 777
Lokalizacja: Karpicko k. Wolsztyna
Pomógł: 197

QuadMan napisał(a):
Kolega Tom277 napisał o czymś zupełnie odwrotnym, niż Wy usiłujecie Mu wytłumaczyć. Nie wyobrażam sobie, aby opisane przez Niego zjawisko w normalnych warunkach było w ogóle możliwe, dlatego dopytywałem się, jaki to procek, jak ma to wszystko podłączone, itd.

Pozdrawiam, QuadMan.

P.S. Podejrzewam jakiś problem sprzętowy - "to coś" dopięte do portu D powoduje resetowanie się procka, albo np. krótkotrwały spadek napięcia zasilania, itp... Nie wiem, nie znam się, nie pytać...

Jest dokładnie tak jak piszą koledzy. Nie wierzysz? Weź procka i sprawdź.
Najpierw bez wyłączania przerwań w pętli while a potem z wyłączeniem.

Sam się zdziwiłem bo myślałem, że nie będzie miało to wpływu.

rskup napisał(a):
Jak dałbyś jakiś delay-a w pętli głównej, to zmniejszyłbyś prawdopodobieństwo wystąpienia takiego efektu proporcjonalnie do proporcji czasu zajętego na delaya i potrzebnego na toggle.

Dokładnie. Wystarczy w pętli dać opóźnienie o wartości kilkadziesiąt us i już program zaczyna działać poprawnie.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 gru 2015, o 01:15 
Offline
Użytkownik

Dołączył(a): 29 lip 2014
Posty: 195
Pomógł: 44

Ok, panowie.

Oczywiście macie racje. Nie dawało mi to spokoju, odkurzyłem zestaw ATB, sprawdziłem i przemyślałem jeszcze raz. Tłumaczenie Kolegi Krauser jest jak najbardziej ok i zjawisko to będzie występowało zawsze, jeśli w programie głównym i w przerwaniu będziemy się odwoływać do tych samych zasobów ( w tym konkretnym przypadku chodzi o PORTB ). Swoją drogą, to całe "C" jest zdradliwe ;-), w .asm nawet mi by do głowy nie przyszło by popełnić tak kardynalny błąd.

Pozdrawiam serdecznie, QuadMan.



Ostatnio edytowano 2 gru 2015, o 01:46 przez QuadMan, łącznie edytowano 1 raz

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 gru 2015, o 01:19 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

Kod o którym mówimy w C wygląda następująco
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

co daje nam taki wynik po skompilowaniu:
Składnia: [ Pobierz ] [ Ukryj ]
język asm
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

w linii 70 pobieramy aktualną wartość portu do rejestru r24, wykonujemy operacje na rejestrze i dopiero w 74 zapisujemy wynik z rejestru do portu. Robimy ponownie to samo w 76 ..7a a następnie skaczemy (wracamy) do 70. I tak w kółko.
Gdy przerwanie wyzwoli się nam po pobraniu wartości z portu w 70 ale przed 74 oraz po 76 ale przed 7a, to wpiszemy do portu wartość już nie aktualną, bo przerwanie nam przecież ją zmieniło i powinna być inna.
Przerwanie przed 72, 74, 78, 7a powoduje problem a przerwanie przez 70, 76, 7c nie powoduje. Ale jak widać szansa na problem to 4/7, czyi ponad 57% :(

Jak damy delay, który ma do wykonania np. 993 instrukcji w swoim przebiegu, to szansa wystąpienia problemu to 4/1000, czyli 0,4% :) I już tego nie zauważamy. Choć problem jest nadal. Dlatego ten delay to maskowanie problemu i sposób na prezentację przyczyny problemu a nie jego rozwiązanie.
Oczywiście dla rozwiązania należy użyć operacji w ATOMIC_BLOCK.

--
Pozdrawiam,
Robert

------------------------ [ Dodano po: 5 minutach ]

Cytuj:
Oczywiście macie racje.
Ja się tu męczę a to już nie trzeba udowadniać :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 gru 2015, o 11:38 
Offline
Użytkownik

Dołączył(a): 08 wrz 2012
Posty: 505
Pomógł: 6

Dziękuję Krauser!
Sprawdziłem i faktycznie z ATOMIC_BLOCK(ATOMIC_RESTORESTATE) działa, bez nie działa. Trochę mnie Krauser przeraziłeś, ja tu zadaję wydawało by się banalne pytanie a Ty mi wyskakujesz z jakimiś ATOMIC-ikami. W pierwszej chwili blady strach na mnie padł, ale chwila skupienia i wszystko nagle okazało się nie tylko zrozumiałe a wręcz logiczne. Kto by pomyślał, że to takie zdradliwe, na prawdę trzeba mieć oczy z każdej strony.
Dziękuję serdecznie.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 gru 2015, o 12:48 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 11 mar 2014
Posty: 1475
Pomógł: 167

Rozwiązanie bez korzystania z ATOMIC_BLOCk jest też bardzo proste (choć nie zawsze się da tak zrobić :( ). Nie modyfikuj portu w przerwaniu, tylko ustawiaj w nim zmienną mówiącą, że masz to zrobić oraz ewentualnie z informacją jak. A całą operację zmiany dokonuj w pętli głównej.

--
Pozdrawiam,
Robert



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 2 gru 2015, o 13:31 
Offline
Użytkownik

Dołączył(a): 27 lis 2015
Posty: 36
Zbananowany użytkownik

Pomógł: 5

Cześć...

To jest zastosowanie czegoś co się nazywa RAII (ang. Resource Acquisition Is Initialization). W C to będzie zasada nie odwoływania się do zasobu z którego (ktoś/gdzieś) korzysta lub odwoływania się w sposób atomowy bez naruszania elementów które zajmuje ktoś inny. Stąd stosowanie ATOMIC_BLOCK bo zasobem jest cały port a nie pojedynczy bit :-)



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: 18 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

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


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