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



Teraz jest 28 mar 2024, o 10:08


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 11 ] 
Autor Wiadomość
PostNapisane: 14 sie 2017, o 16:54 
Offline
Nowy

Dołączył(a): 18 lis 2015
Posty: 6
Pomógł: 0

Witam. Piszę sobie program do komunikacji z modułem sim800L. Chcę wysyłać do niego, a także odbierać z niego dane.
Napisałem sobie już całą obsługę tego modułu, ale mam jeden problem. Komunikacja z modułem zwykle działa dobrze, ale od czasu do czasu podczas przesyłania danych ATMega resetuje się :o.

Używam dosyć popularnej biblioteki uart dostępnej na tej stronie:
http://homepage.hispeed.ch/peterfleury/avr-software.html

Bibliotekę tą zmodyfikowałem dla własnych potrzeb tak, abym mógł odbierać całe stringi ;)

W pliku uart.c dopisałem sobie taką funkcję wzorując się na poradniku YT pana Mirka:

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


Zmienna ascii_line inkrementowana jest w przerwaniu od odbioru danych uarta, gdy odebrany znak = 13 (ENTER). W ten sposób funkcja uart_get_str jest informowana, że dostępna jest linijka do odebrania. Wydaje mi się, że funkja uart_get_str jest tutaj problemem, ponieważ gdy ją usunę i ręcznie wysyłam z komputera dane do mikrokontrolera, resetów nie ma. Gdy funkcja jest włączona, podczas wysłania większej ilości danych następuje reset.



Ostatnio edytowano 17 sie 2017, o 21:53 przez kamilo0, łącznie edytowano 3 razy

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 14 sie 2017, o 17:53 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Spróbowałbym przed instrukcją ascii_line--; wyłączyć przerwania instrukcją cli();, a po instrukcji ascii_line--; włączyć przerwania instrukcją sei();



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 14 sie 2017, o 21:14 
Offline
Użytkownik

Dołączył(a): 02 cze 2014
Posty: 123
Pomógł: 0

Moja rada jest taka zrób sobie podsłuch taki to odbiera atmega poprzez terminal w kompie tzn. podlacz sie pod pin RX atmegi jakims konwerterem rs na usb i wyswietlaj co otrzymuje atmega.
Moim zdaniem masz zle zbudowany program odbierajacy ale nie w tej czesci co przedstawiles tylko juz w tym gdzie rozpatrujesz odebrane linie. mam tu na mysli nadchodzacy ciag danych o zbyt wielkim rozmiarze w porownaniu do zadeklarownaj zmiennej. Powodje to nadpisywanie innych zmiennych z ramu i w konsekwencji reset przypadkowy.

_________________
http://mojekonstrukcje.pl/



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 sie 2017, o 08:54 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

TomekTomek55 napisał(a):
Moim zdaniem masz zle zbudowany program odbierajacy ale nie w tej czesci co przedstawiles
W tej części, którą autor przedstawił, też jest błąd mogący powodować nieporządane efekty. Polega on na braku atomowości dostępu do zmiennej globalnej ascii_line i pokazałem sposób, jak ten błąd naprawić. Nie wykluczam oczywiście błędów w innych miejscach programu i nie neguję całkowicie tego co napisałeś, jednak niezależnie od wszystkiego akurat w tym miejscu zmiana jest niezbędna, jeśli program ma pracować stabilnie.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 sie 2017, o 10:52 
Offline
Nowy

Dołączył(a): 18 lis 2015
Posty: 6
Pomógł: 0

@andrews
A możesz powiedzieć, dlaczego przerwania z ascii_line mogą powodować problemy?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 sie 2017, o 14:45 
Offline
Nowy

Dołączył(a): 18 lis 2015
Posty: 6
Pomógł: 0

Zmodyfikowałem sobie funkcję uart_get_str, tak aby niemożliwe było zapisanie do bufora wiecej bajtów niż posiada bufor UART (oraz mój bufor z odebraną linijką w programie).

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


Teraz wygląda, że jest ok. Narazie nie zauważyłem resetów. Wie ktoś, dlaczego tak się działo? Przecież jeśli przerwanie inkrementowało zmienną ascii_line, to znaczy, że w buforze był znak Enter (13), a widocznie pętla while nie "zauważała" tego znaku i zapisywała więcej danych niż rozmiar mojego bufora.



Ostatnio edytowano 17 sie 2017, o 21:52 przez kamilo0, łącznie edytowano 2 razy

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 sie 2017, o 14:58 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

Szczerze mówiąc chciałem tego uniknąć, bo to trochę pisania jest... Liczyłem, że po prostu spróbujesz czy to pomoże, nie wnikając w szczegóły.

No ale spróbuję w miarę możliwości krótko. Zmienna globalna ascii_line jest modyfikowana zarówno w programie głównym, jak i w procedurze obsługi przerwania. Operacja ascii_line--; nie odbywa się w jednym takcie zegara, ponieważ jest zapisana w pamięci RAM, a nie mikrokontroler nie może wykonywać operacji bezpośrednio na komórkach pamięci. Wymagane więc jest:
  • wczytanie zmiennej z pamięci RAM do rejestru,
  • wykonanie operacji pomniejszenia wartości rejestru,
  • zapisanie wartości rejestr z powrotem do RAM.
Jeśli w trakcie tej operacji (po wczytaniu zmiennej do rejestru) wystąpi przerwanie i zmodyfikuje wartość zmiennej, to program główny o tym nie wie, i nie wczyta ponownie zmiennej do rejestru, tylko wykona operację na rejestrze i zapisze wynik operacji z rejestru do zmiennej w RAM, czyli przykładowo:
  • program główny wczytuje do rejestru wartość zmiennej ascii_line równą 3,
  • występuje przerwanie i procedura jego obsługi zmienia wartość zmiennej ascii_line na 4,
  • po zakończeniu procedury obsługi program główny wraca do miejsca, w którym skończył, i wykonuje następną instrukcję, czyli zmniejsza wartość rejestru z 3 na 2,
  • po wykonaniu operacji zapisuje wartość z rejestru (czyli 2, a powinno być 3) do zmiennej ascii_line w pamięci RAM.
W efekcie wartość zmiennej po tej operacji jest nieprawidłowa, bo nie uwzględnia tego, co doliczyła w międzyczasie procedura obsługi przerwania. W ten sposób w buforze zawsze zostaną dane nie uwzględnione przez zmienną ascii_line, przez co prędzej czy później bufor się przepełni. Jaki będzie tego efekt to jest uzależnione od tego, jak masz zorganizowaną resztę programu (szczególnie chodzi o obsługę bufora, czyli zadbanie o to, by nie szło go przepełnić).

Prawdopodobieństwo "trafienia" nie jest wprawdzie duże, ale jakieś jest, dlatego program może przez jakiś czas pozornie pracować prawidłowo, a czas ten będzie losowy, choć w pewnej mierze zależny np. od częstotliwości i długości przesyłanych pakietów danych (u Ciebie ciągów znaków oddzielonych znakiem '\r', jeśli dobrze rozumiem). Im więcej krótkich pakietów w jednostce czasu, tym ryzyko problemów będzie większe.

EDIT:
kamilo0 napisał(a):
Bibliotekę tą zmodyfikowałem dla własnych potrzeb tak, abym mógł odbierać całe stringi
...
Zmodyfikowałem sobie funkcję uart_get_str, tak aby niemożliwe było zapisanie do bufora wiecej bajtów niż posiada bufor UART.
...
Teraz wygląda, że jest ok. Narazie nie zauważyłem resetów. Wie ktoś, dlaczego tak się działo?

By można było odpowiedzieć na to pytanie musiałbyś pokazać więcej kodu, szczególnie tego dotyczącego obsługi buforów. Bardzo istotne jest np. to, co tak na prawdę zwraca funkcja uart_getc(), bo nie jestem pewien, czy Twoja pętla odczytu bufora działa prawidłowo.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 15 sie 2017, o 18:34 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

roske napisał(a):
Dlatego, że w tej bibliotece uart_getc, przy braku znaków do pobrania zwraca całkiem coś innego niż Ci się wydaje.

Przepraszam, a skąd kolega wie, co zwraca funkcja uart_getc(), skoro "biblioteka" była modyfikowana.

Poza tym, nawet jeśli autor wątku nie jest jakiś biegły w programowaniu i popełnia błędy, to komentarze czy sformułowania w stylu "recepta na uzyskanie pierwszorzędnej popeliny" nie są raczej na tym forum mile widziane. Wydaje mi się oczywiste, że na forum pytania zadają Ci, którzy wiedzą mniej. Ci, którzy wiedzą więcej, pomagają z zachowaniem kultury osobistej lub wcale. Błąd można równie dobrze wskazać, nie używając tego typu zwrotów.

roske napisał(a):
A nawet jak się ma o niej pojęcie to nadal jest to bzdura (nie będę tłumaczył dlaczego).

A dlaczego nie będzie kolega tłumaczył? Ja na przykład chciałbym wiedzieć, bo w swojej nieświadomości kilka razy już popełniłem ten błąd (i jakoś nie przestały działać, a nawet działały lepiej czy też były bardziej zgodne z moimi oczekiwaniami). Aż tu nagle okazuje się, że to "bzdura"...



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 sie 2017, o 16:49 
Offline
Nowy

Dołączył(a): 18 lis 2015
Posty: 6
Pomógł: 0

Nie denerwujcie się tak Panowie. Nie każdy ma za sobą kilkanaście lat doświadczenia w programowaniu uC. Ja nie mam, więc zdarzają się czasem takie błędy. Ważne, że w jakiś sposób udało mi się osiągnąć to, na czym mi zależało, a że w nie do końca dobry sposób, dlatego zapytałem na forum ;)

Biblioteka nie jest modyfikowana, dołożyłem do niej tylko tą jedną flagę (ascii_line) w obsłudze przerwania, i dopisałem sobie tą funkcję do odbierania stringu.

Dzięki za porady, w wolnym czasie je przetestuję i mam nadzieję, że problem już nie będzie występował.

@andrews
Dziękuję za dokładne wyjaśnienie problemu przerwań ;)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 sie 2017, o 17:08 
Offline
Użytkownik

Dołączył(a): 07 cze 2016
Posty: 563
Pomógł: 143

kamilo0 napisał(a):
Nie denerwujcie się tak Panowie.

Tak to wyglądało?
Zapewniam, że ja akurat jestem zupełnie spokojny. Chciałem tylko delikatnie zwrócić na coś uwagę. Nie miałem zamiaru być agresywny czy nieuprzejmy, ale wygląda na to, że chyba zostało to odebrane inaczej ;)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 17 sie 2017, o 19:15 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 04 paź 2011
Posty: 8583
Pomógł: 337

<proszę autora o umieszczenie kodów w znacznikach syntax>

_________________
[b]San Escobar! Patria mia! Tu eres como la salud.[/b]



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

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 6 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