Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki
Teraz jest 14 lis 2019, o 23:05


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 9 ] 
Autor Wiadomość
PostNapisane: 15 lip 2019, o 14:52 
Offline
Nowy

Dołączył(a): 15 lip 2019
Posty: 5
Pomógł: 0

Witam wszystkich!

Jest to mój pierwszy post na tym forum, gdybym coś nie po kolei zrobił - proszę o zrozumienie i poprawienie ;)


Pracuję nad małym projektem sterowania oświetleniem w zależności od dnia miesiąca, godziny, oszczędnie z energią na ile się da. Sam projekt na razie nie jest tu ważny.

Do tego projektu używam Atmegi32A (wbudowany oscylator RC 1MHz), LCD HD47780 i RTC DS3231 (ostatnie dwa kupione kilka lat temu w chińskim sklepie). To wszystko mam połączone na zestawie uruchomieniowym ZL3AVR, a jak coś trzeba to obok na płytce stykowej.
Biblioteki (lcd, twi) pisałem w oparciu o niebieską książkę Pana Mirka, a początek biblioteki do RTC na podstawie jego filmu, czyli:
- LCD jest sterowane w trybie czterech pinów, bez obsługi pinu RW
- DS3231 jest przez TWI (50kHz).

Do wykrywania impulsu 1Hz używam na razie przerwania INT0 na zbocze rosnące, podciągnięte, z obsługą sprzętową, nie programową w pętli while. Sygnał z DS'a też jest podciągnięty do VCC.
Z rtc będę potrzebować na pewno alarm(y) do wybudzania mikrokontrolera, ale chcę też wykorzystać generowany przez niego 1Hz, gdy będzie potrzeba wyświetlenia czasu na lcd. Napisałem więc funkcję, która włącza/wyłącza ten sygnał. Chcąc ją przetestować, w pętli while ustawiam na przemian włączenie/wyłączenie tego sygnału z przerwami _delay_ms od setek milisekund do paru sekund (przy użyciu for). I tu następuje problem - program się zawiesza.
Co udało mi się ustalić przy "debugowaniu" diodami (używam eclips'a i usbasp), to:
- wyłączenie programowe przerwania eliminuje zawieszenie
- odłączenie pinu przerwania tak samo eliminuje problem
(dwa powyższe sprawdziłem na oscyloskopie, sprawdzając sygnał SQW z DS3231 - pojawia się i znika według ustawień w while)
- zacinanie się jest losowe - w programie dodałem sobie licznik zliczający ilość przerwań od początku programu, czasami jest to pierwsze przerwanie, czasami 20, zależy od "przypadku" i ustawionych przerw w while ("okrągłe" 100, 250ms i "nieokrągłe" 143, 149ms).
- program wiesza się:
1. w pętli while(!(TWCR & (1<<TWINT))) czekającej na zapis/odczyt bajtu
2. i/lub zapisie kilku bajtów funkcją TWI_writeBuf
które pierwsze - 1 czy 2 - to nie wiem, ponieważ oscyloskop mam analogowy, z jedną sondą
- dodanie w obsłudze przerwania pętli oczekującej na zapis jak wyżej nie pomaga, program wiesza się na tym

To na razie tyle, co udało mi się ustalić. Podejrzewam, że podczas zapisu przez TWI wypada przerwanie, które chce odczytać kiedy slave jest w trybie zapisu, lub odwrotnie, lub coś około tego. Szukałem już jakichś podobnych wątków na ten temat, również w języku angielskim, ale nie znalazłem nic pożytecznego.
Gdybym mógł poprosić, pod jakim hasłem szukać rozwiązania, co dodać/usunąć lub jeśli rozwiązanie jest trywialne - to o podanie go.

Za pomoc z góry dziękuję! :)

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


Obsługa DS3231 (w funkcji DS3231_1Hz_SQW ręcznie ustawiłem wartości do wpisania do rejestru, żeby wykluczyć niedziałającą funkcję do ustawiania/zerowania bitu w bajcie; alarmów nie sprawdzałem jeszcze):

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


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


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


Main (zapis daty i czasu działa):
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: 15 lip 2019, o 17:32 
Offline
Użytkownik

Dołączył(a): 09 lut 2017
Posty: 45
Lokalizacja: 51°03′22″N 15°45′48″E
Pomógł: 10

Czy ja dobrze widzę, że w obsłudze przerwania masz całe wyświetlanie na LCD?? To są bardzo długotrwałe operacje. Przede wszystkim wywal to z przerwania. W przerwaniu najlepiej ustawiaj tylko jakąś flagę, a odczyt daty, czasu i wyświetlanie na LCD załatwiaj w głównej pętli.


Autor postu otrzymał pochwałę


Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 lip 2019, o 18:30 
Online
Moderator
Avatar użytkownika

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

Adam12 napisał(a):
Przede wszystkim wywal to z przerwania.

Ło Matko, kolega ma sokole oko !.... bardzo słuszna uwaga

_________________
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: 15 lip 2019, o 19:23 
Offline
Nowy

Dołączył(a): 15 lip 2019
Posty: 5
Pomógł: 0

Adam12 napisał(a):
Czy ja dobrze widzę, że w obsłudze przerwania masz całe wyświetlanie na LCD?? To są bardzo długotrwałe operacje. Przede wszystkim wywal to z przerwania. W przerwaniu najlepiej ustawiaj tylko jakąś flagę, a odczyt daty, czasu i wyświetlanie na LCD załatwiaj w głównej pętli.


O kurcze, rzeczywiście... Nie wpadłem na to :P Dzięki :)
Źródła problemu szukałem w funkcjach do komunikacji TWI albo w tych do DS3231. Na szybko zrobiłem, zostawiając tylko odczyt (potem go wrzucę do głównej pętli) i przełączanie diody - działa.

Ale jak już poruszyłem temat, to gdybym teoretycznie miał dużą ilość danych do wysłania po TWI, a ponadto miał jakieś przerwanie, którego obsługa byłaby absolutnie priorytetowa, zajmowała chwilę (nie tak długą jak ten LCD, ale jednak znaczną) i nie mogła być wykonana przez flagę - w jakim kierunku powinna iść implementacja tego?

Edit:
Poza tym, czy jeżeli przerwanie INT0 jest na zbocze narastające, to poprawnym jest podciągnięcie tego pinu? Teraz działa, ale nie jestem pewny poprawności i bezawaryjności tego

Edit 2:
Nawet funkcja odczytania czasu w przerwaniu zawiesza program (implementacja flagi w drodze)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 16 lip 2019, o 15:34 
Offline
Nowy

Dołączył(a): 15 lip 2019
Posty: 5
Pomógł: 0

Mam problem z tą flagą.

Wszystkie funkcje, jakie sobie tworzę, przerzuciłem do zewnętrznego pliku źródłowego funkcje_do_programu.c. (dalej będę to nazywał funkcje.c)
Spodziewam się, że będę potrzebował dużo flag, więc w pliku nagłówkowym funkcje_do_programu.h zdefiniowałem typ TFLAGS z 8 jednobitowymi flagami (jak będzie rzeczywiście dużo, to zmienię sobie tylko rozmiar "typu"). Jako że flag zamierzam używać w funkcje.c i main.c, w nagłówku zdeklarowałem od razu zmienną flagi1 typu TFLAGS.

W funkcje.c mam obsługę przerwania do obsługi SQW, o którym pisałem w pierwszym poście - oznacz flagę, a dla debugowania przełącz diodę (dioda się przełącza).
W pętli głównej w main.c mam prostego if'a, który przy oznaczeniu flagi ma (narazie) wyzerować ją i przełączyć inną diodę - i tutaj już dioda się nie przełącza. Kombinowałem różnymi sposobami, fladze przypisywałem (i sprawdzałem) wartości dziesiętne i szesnastkowe. Utworzyłem tymczasową zmienną uint8_t która miała być tymczasową flagą, kombinowałem z deklaracją jej jako extern - nic nie pomogło.

Wrzucam fragmenty kodów, jak na obecną chwilę wygląda program, flaga tymczasowa jest zakomentowana.

Tak jak wcześniej, byłbym wdzięczny za wskazanie, pod jakim hasłem szukać jakiś materiałów na ten temat, albo jeśli rozwiązanie jest trywialne - to o podanie go (obstawiam pomieszanie widoczności zmiennych albo inną bździnę). Poza tym, pytania o ten konflikt zapis-odczyt i o podciągnięcie z poprzedniego wpisu nadal aktualne ;)

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


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


..i plik źródłowy:
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: 16 lip 2019, o 17:30 
Offline
Użytkownik

Dołączył(a): 09 lut 2017
Posty: 45
Lokalizacja: 51°03′22″N 15°45′48″E
Pomógł: 10

Może tak:
volatile uint8_t flaga_tmp;

Masz talent do komplikowania sobie życia w momencie kiedy trzeba wszystko uprościć żeby znaleźć źródło problemu. Jeśli dalej program będzie się zawieszał, nie twórz nowych plików tylko przeciwnie to z czym jest problem wrzuć do main.c czyli główną pętlę, obsługę przerwania, podstawowe inicjalizacje i funkcję odczytu daty_czasu. Potem jeśli dalej nie działa wywal np. wszystko związane z LCD itd. Taki okrojony kod łatwiej będzie też komuś analizować na forum.

Poza tym polecam zakup analizatora stanów logicznych. Sam szybko znalazłbyś odpowiedź na pytanie o konflikt zapis-odczyt generując jakieś zakłócające przerwanie i podglądając co się dzieje na liniach TWI.

Co do podciągnięcia INT0 - zajrzałem do noty i na pierwszej stronie jest jak byk schemat z rezystorem podciągającym więc podciągnięcie programowe jest ok.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 16 lip 2019, o 18:10 
Offline
Nowy

Dołączył(a): 15 lip 2019
Posty: 5
Pomógł: 0

Czyli tak jak myślałem - bździna. Już nadrobiłem rozdział o volatile w niebieskiej książce.

Działa z volatile uint8_t flaga_tmp, jak i dla volatile TFLAGS flagi1. Odświeża też czas.

Z tym komplikowaniem to zgodzę się i nie. Funkcje, definicje, deklaracje itp. stopniowo przerzucałem z main.c do innych plików, za każdym razem sprawdzając, czy program się skompiluje i czy wciąż działa tak jak wcześniej. Jak już wszystko przeniosłem, to chciałem dodać obsługę flagi. No i tu był chyba błąd, bo zamiast w main.c to od razu tworzyłem w funkcje.h i funkcje.c. Później jak obsługa flagi w głównej pętli nie działała, to pierwsze co wywaliłem to właśnie obsługa rtc i lcd, później zamiast struktury flag utworzyłem jedną zmienną tymczasową, a na końcu dodałem diodę.
Pozostałe rady co do kodu - dzięki za rady, przydadzą się na pewno.

Może wyposażę się w ten analizator - na moje potrzeby lepszy od oscyloskopu cyfrowego - tańszy a bardziej przydatny.

Chyba się nie zrozumieliśmy z podciągnięciem przerwania. Wnioskuję, że Ty piszesz o DS3231, bo tam jest na pierwszej stronie ten schemat.
Przerwanie INT/SQW z DS3231 mam podciągnięte przez rezystor do 5V. Moje pytanie dotyczy podciągania programowego wejścia PD2/INT0 Atmegi32A (przerwanie na zbocze narastające). Teraz przyszło mi na myśl jeszcze jedno pytanie - czy gdybym podciągnął tylko wejście uC, to wyjścia RTC nie muszę w sumie już podciągać, prawda?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 16 lip 2019, o 19:05 
Offline
Użytkownik

Dołączył(a): 09 lut 2017
Posty: 45
Lokalizacja: 51°03′22″N 15°45′48″E
Pomógł: 10

Właśnie to chciałem napisać, że podciągnięcie tylko wejścia uC jest poprawne i jest wystarczające.

To, że działa z flagą to znaczy, że już się nie wiesza?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 lip 2019, o 16:59 
Offline
Nowy

Dołączył(a): 15 lip 2019
Posty: 5
Pomógł: 0

Ok, dzięki.

Tak, nie wiesza się. Specjalnie nawet zapchałem główna pętlę delayami, zapisami do RTC, całość około 2 sekundy - i co tyle się odświeża, więc flaga działa.



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

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Google [Bot], MSN [Bot] i 4 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