<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=23&amp;t=24058&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2021-12-09T21:30:46+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=23&amp;t=24058&amp;mode</id>
<entry>
<author><name><![CDATA[slawus1998]]></name></author>
<updated>2021-12-09T21:30:46+01:00</updated>
<published>2021-12-09T21:30:46+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234490#p234490</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234490#p234490"/>
<title type="html"><![CDATA[Re: ATMega128 + MODBUS RTU]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234490#p234490"><![CDATA[
<div class="quotetitle">JanuszT napisał(a):</div><div class="quotecontent"><br />Może spróbuj skorzystać z tego, że w MODBUS-ie wiesz jaka długa będzie ramka i że na końcu jest suma kontrolna. Jeżeli twój uC to Master, to na magistrali jest cisza, potem ty &quot;coś&quot; wysyłasz i potem falownik odpowiada. Wiedząc dokładnie co wysłałeś, wiesz dokładnie ile bajtów oczekujesz w odpowiedzi. Po zakończeniu wysłania zapytania odczytujesz w przerwaniu bajty, założoną ich ilość łączysz w całość i sprawdzasz czy mają strukturę ramki (adres:funkcja:ilość:dane:CRC) i czy zgadza się suma kontrolna. Jeżeli jest dobrze to koniec tej transmisji, jeżeli nie, to odczekujesz maksymalny czas trwania transmisji i ponawiasz zapytanie. Nie jest to może optymalne czasowo, ale nie podejrzewam abyś wymieniał dużo/szybko dane z falownikiem, a tak może być prościej.<br /></div><br /><br />Niestety nie mogę sobie na coś takiego pozwolić, bo na magistrali docelowo będą się znajdować trzy falowniki. <br /><br />Tak czy tak, problem udało się rozwiązać. Rozwiązania nie do końca rozumiem, ale działa. Musiałem pozbyć się manewrowania bitem OCIE w rejestrze TIMSK, jako sposobem na włączenie/wyłączenie przerwania. Zastosowałem włączanie i odłączanie preskalera (TCCR0B = 0) w celu uruchamiania i zatrzymywania timera. <br /><br />Otwieram teraz dyskusję, dlaczego to rozwiązanie działa. W tej chwili operuję na całym timerze, wcześniej jedynie na aktywacji/deaktywacji przerwania. Dodatkowo wcześniej przed każdym ustawienie OCIE na 1, ustawiałem TCNT na 0, tak żeby mieć pewność, że timer zawsze zaczyna liczenie od początku, a nie gdzieś w środku. Skąd w takim razie może wynikać różnica w działaniu tych dwóch rozwiązań? <br /><br />JarekK, przede wszystkim Tobie dziękuję za podesłane linki z bibliotekami, których mi się nie udało w sieci znaleźć, a w których podpatrzyłem rozwiązanie finalnie sprawne. Dziękuję jednocześnie za rady i sugestie od wszystkich pozostałych.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1288">slawus1998</a> — 9 gru 2021, o 21:30</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[JanuszT]]></name></author>
<updated>2021-12-09T13:38:23+01:00</updated>
<published>2021-12-09T13:38:23+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234487#p234487</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234487#p234487"/>
<title type="html"><![CDATA[Re: ATMega128 + MODBUS RTU]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234487#p234487"><![CDATA[
Witam<br /><br />Może spróbuj skorzystać z tego, że w MODBUS-ie wiesz jaka długa będzie ramka i że na końcu jest suma kontrolna. Jeżeli twój uC to Master, to na magistrali jest cisza, potem ty &quot;coś&quot; wysyłasz i potem falownik odpowiada. Wiedząc dokładnie co wysłałeś, wiesz dokładnie ile bajtów oczekujesz w odpowiedzi. Po zakończeniu wysłania zapytania odczytujesz w przerwaniu bajty, założoną ich ilość łączysz w całość i sprawdzasz czy mają strukturę ramki (adres:funkcja:ilość:dane:CRC) i czy zgadza się suma kontrolna. Jeżeli jest dobrze to koniec tej transmisji, jeżeli nie, to odczekujesz maksymalny czas trwania transmisji i ponawiasz zapytanie. Nie jest to może optymalne czasowo, ale nie podejrzewam abyś wymieniał dużo/szybko dane z falownikiem, a tak może być prościej. <br /><br />Pozdrawiam<br />Janusz<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=4367">JanuszT</a> — 9 gru 2021, o 13:38</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[fofex]]></name></author>
<updated>2021-12-09T13:21:48+01:00</updated>
<published>2021-12-09T13:21:48+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234486#p234486</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234486#p234486"/>
<title type="html"><![CDATA[Re: ATMega128 + MODBUS RTU]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234486#p234486"><![CDATA[
<div class="quotetitle">slawus1998 napisał(a):</div><div class="quotecontent"><br />resetuje flagę przerwania TOV3<br /></div><br />Przypuszczam, że przypisanie do licznika wartości zero może generować przerwanie więc gaszenie flagi jest jak najbardziej uzasadnione, natomiast manewry z preskalerem wydają mi się &quot;nadmiarowe&quot;. Ale może się mylę. <br />Twoje rozwiązanie może też by zgrało gdybyś gasił flagę przerwania przed wystartowaniem timera (albo po) . Może spróbuj tego na początek?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=21072">fofex</a> — 9 gru 2021, o 13:21</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[slawus1998]]></name></author>
<updated>2021-12-09T12:01:57+01:00</updated>
<published>2021-12-09T12:01:57+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234485#p234485</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234485#p234485"/>
<title type="html"><![CDATA[Re: ATMega128 + MODBUS RTU]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234485#p234485"><![CDATA[
<div class="quotetitle">JarekK napisał(a):</div><div class="quotecontent"><br />a na atmega 128 też takie coś znalazłem w necie:<br /><!-- m --><a class="postlink" href="http://sebastianpawlak.com/pl/Informaty" >http://sebastianpawlak.com/pl/Informaty</a><!-- m --> ... index.html<br /></div><br /><br />Obejrzałem dokładnie to co znajduje się pod tym linkiem. Zastanowiło mnie to, że autor tego kodu chcąc zresetować wartość timera czyli ustawić TCNT = 0, robi coś takiego: <br />[syntax=c]TCCR3B = 0;<br />TCNT3 = 0;<br />ETIFR |= _BV(TOV3);    /* clear interrupt flag */<br />OCR3A = OCRt4_5;<br />TCCR3B = _BV(WGM32) | _BV(CS32) | _BV(CS30);    /* prescaler 1024 */[/syntax]<br /><br />Czyli mniej więcej: ubija timer przez odcięcie go od clocka, resetuje wartość TCNT, resetuje flagę przerwania TOV3, ponownie ustawia OCR i finalnie ponownie ustawia preskaler, tym samym uruchamiając timer. W całym kodzie nie ma praktycznie wykorzystanego bitu OCIE3A, za wyjątkiem jednokrotnego ustawienia go na wartość '1' w celu uruchomienia timera. Muszę sprawdzić takie rozwiązanie, dam znać czy coś to pomogło. <br /><br /><div class="quotetitle">fofex napisał(a):</div><div class="quotecontent"><br />Z tych fragmentów kodu niewiele można wywnioskować.<br />Ja bym szedł w trochę innym kierunku. Zbocze opadające na lini RX startuje timer i się wyłącza (albo i nie, sprawa do przemyślenia). Przerwanie RX resetuje timer tj. ustawia licznik na wartość początkową. Przerwanie OVF albo COMP &quot;zamyka ramkę&quot; i się wyłącza oraz włącza przerwanie INT włączające timer (albo i nie, jw.). &quot;Zamknięcie&quot; ramki zrobił bym przez wstawienie do bufora Rx jakiegoś kodu (zakładając, że są jakieś kody nie pojawiające się w strumieniu Rx). Trzeba przemyśleć czy w warunkach brzegowych to zagra (np. przy jednoczesnym pojawieniu się przerwania INT i OVF). To tak na szybkiego.<br />Albo może na odwrót - przerwanie UART Rx startuje timer a zbocze opadające go resetuje?<br /></div><br /><br />Pomysł ze zboczem opadającym jako trigger resetu timera też jest ciekawy. Teoretycznie wielkiej różnicy to nie zrobi, bo albo zareagujemy na zbocze opadające, albo kilka &quot;bitów dalej&quot; na przerwanie od RXa. Ale racjonalne pomysły przestały już działać, może to coś pomoże. Dam znać jak sprawdzę. <br /><br />Z jedną i drugą odpowiedź już teraz dziękuję.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1288">slawus1998</a> — 9 gru 2021, o 12:01</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[fofex]]></name></author>
<updated>2021-12-09T11:18:22+01:00</updated>
<published>2021-12-09T11:18:22+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234484#p234484</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234484#p234484"/>
<title type="html"><![CDATA[Re: ATMega128 + MODBUS RTU]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234484#p234484"><![CDATA[
Z tych fragmentów kodu niewiele można wywnioskować.<br />Ja bym szedł w trochę innym kierunku. Zbocze opadające na lini RX startuje timer i się wyłącza (albo i nie, sprawa do przemyślenia). Przerwanie RX resetuje timer tj. ustawia licznik na wartość początkową. Przerwanie OVF albo COMP &quot;zamyka ramkę&quot; i się wyłącza oraz włącza przerwanie INT włączające timer (albo i nie, jw.). &quot;Zamknięcie&quot; ramki zrobił bym przez wstawienie do bufora Rx jakiegoś kodu (zakładając, że są jakieś kody nie pojawiające się w strumieniu Rx). Trzeba przemyśleć czy w warunkach brzegowych to zagra (np. przy jednoczesnym pojawieniu się przerwania INT i OVF). To tak na szybkiego.<br />Albo może na odwrót - przerwanie UART Rx startuje timer a zbocze opadające go resetuje?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=21072">fofex</a> — 9 gru 2021, o 11:18</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[JarekK]]></name></author>
<updated>2021-12-09T08:45:04+01:00</updated>
<published>2021-12-09T08:45:04+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234480#p234480</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234480#p234480"/>
<title type="html"><![CDATA[Re: ATMega128 + MODBUS RTU]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234480#p234480"><![CDATA[
Na bazie biblioteki UART Mirka coś tam jeden kolega na forum skomunikował w modbus:<br /><!-- l --><a class="postlink-local" href="https://forum.atnel.pl/post231110.html#p231110" >post231110.html#p231110</a><!-- l --><br />Nie patrzyłem na kod, ale może warto sprawdzić: &quot;Powyższe wszystkie obliczenia dotyczą ramki UART 8-N-1 (tzn. długość 10 bitów)&quot;<br /><br />a na atmega 128 też takie coś znalazłem w necie:<br /><!-- m --><a class="postlink" href="http://sebastianpawlak.com/pl/Informatyka/Atmel/MODBUS/index.html" >http://sebastianpawlak.com/pl/Informaty ... index.html</a><!-- m --><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=224">JarekK</a> — 9 gru 2021, o 08:45</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[slawus1998]]></name></author>
<updated>2021-12-09T00:12:57+01:00</updated>
<published>2021-12-09T00:12:57+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234478#p234478</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234478#p234478"/>
<title type="html"><![CDATA[ATMega128 + MODBUS RTU]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=24058&amp;p=234478#p234478"><![CDATA[
Witam wszystkich forumowiczów,<br /><br />Temat postu mniej więcej sugeruje z czym się zmagam. Otóż implementuję obsługę MODBUSa RTU na mikrokontrolerze ATMega 128 (przy czym testuję program również na ATMega 324P). Niestety mimo wielu godzin, zmagam się z jednym problemem. A mianowicie: mój mikrokontroler połączony jest za pośrednictwem RS485 z falownikiem. Zadanie jest proste - wysłać dane, odebrać odpowiedź od falownika. Bazą do komunikacji jest biblioteka MK_USART, obsługująca pojedynczy port UART (w moim przypadku UART0). O ile nie ma żadnych problemów z nadawaniem danych, problem pojawia się z ich odbiorem. Co do idei, zgodnie ze standardem MODBUS, koniec ramki definiowany jest ciszą na magistrali trwającą około 3.5 znaku, co przy prędkości 9600 wynosi około 4ms. Koncepcja jest zatem prosta - utworzyć timer, który będzie się resetował a następnie uruchamiał wraz z każdym odebranych bajtem z portu szeregowego. Przysłanie danych ciągiem będzie resetowało ten timer. Przysłanie ostatniego bajtu uruchomi go, a z powodu braku resetu - wywoła przerwanie. Tak więc przysłanie danych ciągiem powinno wywołać przerwanie tylko raz, na samym końcu. Przynajmniej tyle teorii...<br /><br />Praktyka niestety daje inne rezultaty. Falownik wysyła do uC ramkę MODBUSa, składającą się z 8 bajtów. Są one wysyłane ciągiem. Niestety mój mikrokontroler, z jakiegoś powodu dwa razy rzuca przerwanie od timera, dzieląc odebrane dane na dwa kawałki 1 i 7 bajtów. Najważniejsze fragmenty kodu wyglądają następująco: <br /><br />Inicjalizacja UARTu i Timera: <br />[syntax=c]// Inicjalizacja modbus_uartu<br />void modbus_usart_init( uint16_t baud ) {<br /><br />// UART init<br />UBRR0H = (uint8_t)(baud&gt;&gt;8);// ustawienie prędkości transmisji<br />UBRR0L = (uint8_t)baud;<br />UCSR0C |= (1&lt;&lt;UPM01) | (3&lt;&lt;UCSZ00);// ustawienie formatu ramki jako 8e1<br />UCSR0B |= (1&lt;&lt;RXEN0)|(1&lt;&lt;TXEN0)|(1&lt;&lt;RXCIE0)|(1&lt;&lt;TXCIE0);// inicjalizacja przerwań<br /><br />// inicjalizujemy linię sterującą nadajnikiem<br />UART_DE_DIR |= UART_DE_BIT;<br />UART_DE_ODBIERANIE;<br />}<br /><br /><br />void modbus_timer_init(void) {<br />// Timer 0 init<br />TCCR0A |= (1 &lt;&lt; WGM01);<br />TCCR0B |= (1 &lt;&lt; CS02) | (1 &lt;&lt; CS00);// preskaler na 1024<br />uint8_t ticks = ((F_CPU / 1024UL / 1000UL) * 4.2);// liczba tyknięc zegara, aby timer odmierzał 3.7 znaku (dla 4 znaków, wpisac * 4.5)<br />OCR0A = ticks;<br />character_counter = 0;// inicjalizacja zmiennej na rozmiar danych modbus<br />frame_size = 0;// inicjalizacja zmiennej na tymczasowy rozmiar ramki danych<br />frame_is_ready_flag = 0;// flaga informująca o poprawnym odebraniu ramki<br />}[/syntax]<br /><br />Przerwanie odbiorcze UARTu:<br />[syntax=c]// przerwanie odbiorcze uartu<br />ISR( USART0_RX_vect ) {<br /><br />    register uint8_t tmp_head;<br />    register char data;<br /><br />    data = UDR0; // pobranie danych z bufora sprzetowego<br /><br />    TIMSK0 &amp;= ~(1 &lt;&lt; OCIE0A);// zablokowanie timera<br />    TCNT0 = 0;// reset timera<br /><br />    character_counter++;//zwiekszenie wartosci licznika modbusowego<br /><br />    // obliczamy nowy indeks „głowy węża”<br />    tmp_head = ( UART_RxHead + 1) &amp; UART_RX_BUF_MASK;<br /><br />    // sprawdzamy, czy wąż nie zacznie zjadać własnego ogona<br />    if ( tmp_head == UART_RxTail ) {<br />    UART_RxHead = UART_RxTail;<br />    }<br />    else {<br />    UART_RxHead = tmp_head;// zapis danych do bufora<br />    UART_RxBuf&#91;tmp_head&#93; = data;<br /><br />    }<br /><br />    TIMSK0 |= ( 1 &lt;&lt; OCIE0A );// ponowne wystartowanie zegara<br />}[/syntax]<br /><br />Przerwanie od timera: <br />[syntax=c]// przerwanie odbiorcze modbusa<br />ISR( TIMER0_COMPA_vect ) {<br /><br />uart_putc(1,'X');                               // diagnostyczne przeslanie danych za pomoca uart 1<br />uart_putc(1,character_counter + 48);<br /><br />character_counter = 0;<br /><br />TIMSK0 &amp;= ~(1 &lt;&lt; OCIE0A);// blokada licznika modbusowego<br /><br />}[/syntax]<br /><br />Próbowałem chyba już wszystkiego - zmian timera, zmian trybu z CTC na tryb licznika, redukcji kodu do absolutnego minimum, pełnej diagnostyki z wysyłaniem dosłownie wszystkiego przez UART1 do komputera. Skutek zawsze zostawał taki sam - zamiast przerwania i 8 bajtów, dwa przerwania i ramka z podziałem 1-7 bajtów. Dla jasności, po &quot;sklejeniu&quot; tych dwóch kawałków ze sobą, odebrane dane z falownika są w pełni poprawne. <br /><br />Pojawia się moje pytanie, czy ktoś ma pomysł co może być nie tak w tym przypadku? Podejrzewam, że to może być jakiś idiotyczny błąd, którego nie zauważam przez ilość godzin spędzonych nad problemem. Będę wdzięczny za jakiekolwiek sugestie. <br /><br />Pozdrawiam!<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1288">slawus1998</a> — 9 gru 2021, o 00:12</p><hr />
]]></content>
</entry>
</feed>