<?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=4&amp;t=7965&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-08-01T14:04:01+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=7965&amp;mode</id>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2014-08-01T14:04:01+01:00</updated>
<published>2014-08-01T14:04:01+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89733#p89733</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89733#p89733"/>
<title type="html"><![CDATA[Re: Wysyłanie i odbieranie danych poprzez serwer UDP_etherne]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89733#p89733"><![CDATA[
<div class="quotetitle">mirek1968 napisał(a):</div><div class="quotecontent"><br />Mam jeszcze pytanko dotyczące własnego programu podobnego do Twojego &quot;Klient/serwer/UDP&quot; czy stworzenie podobnego programu dostosowanego do własnych potrzeb jest skomplikowane?,a może jest coś podobnego dostępne w sieci?<br /></div><br /><br />Nawet na naszym forum nie sprawdziłeś panie kochany <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> ... a nasi koledzy już podawali różne przykłady i kursy w C#, w tym także z tego co pamiętam było o komunikacji UDP<br /><br />ja ten mój program pisałem w Delphi więc jego źródła i tak mało dadzą komukolwiek i będą poza zasięgiem ... chociaż na życzenie, wysyłam źródła tego programu ...<br /><br />ale uważam, że na dzisiaj zdecydowanie lepiej robić to sobie i uczyć się programować w C# bo i środowisko od MS masz za darmo<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 1 sie 2014, o 14:04</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirek1968]]></name></author>
<updated>2014-08-01T13:48:23+01:00</updated>
<published>2014-08-01T13:48:23+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89728#p89728</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89728#p89728"/>
<title type="html"><![CDATA[Re: Wysyłanie i odbieranie danych poprzez serwer UDP_etherne]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89728#p89728"><![CDATA[
Osobiście uważam że temat komunikacji serwera i klienta po UDP jest dosyć trudny jak dla mnie do zrozumienia tym bardziej cieszę się że to działa:-).<br />Dzięki Twojej książce BB  ,dołączonemu programowi na cd i pomocy ruszyło:-)<br />Przyznam się szczerze że żałuję troszkę że nie kupiłem całego kompletu sprzedawanego w Twoim sklepie (tzn. książki +PCB).<br />Kupując książkę BB posiadałem już inną płytkę testową ,ale nie wszystko na niej jest przemyślane do końca o czym się co jakiś czas przekonuję (np w tym teraz przypadku są współdzielone porty PORTB dla SPI oraz LCD).<br />Ale ma to malutki plusik take bardziej zmuszony jestem do myślenia bo przeważnie nic mi nie działa na samym starcie (to żart:-)).<br />zrobiłem sobie taki moduł zasilająco-konwertujący na układzie konwertera sygnałów 74LVC125 oraz  stabilizatorach MC7805 oraz LM1117-3,3V i całość zasilam zasilaczem 12V DC skutkiem tego jest niezły grzejnik na stabilizatorze 7805 pomimo radiatora:-)<br />Pewnie muszę sobie kupić jakiś zasilacz np.7,5V zamiast 12V żeby nie było takiej wielkiej temperatury.<br />Mam jeszcze pytanko dotyczące własnego programu podobnego do Twojego &quot;Klient/serwer/UDP&quot; czy stworzenie podobnego programu dostosowanego do własnych potrzeb jest skomplikowane?,a może jest coś podobnego dostępne w sieci?<br />Przyznam się że nie szukałem jeszcze dokładnie,ale fajnie by było mieć taki program który by mógł sterować czymś w domu:-),super sprawa naprawdę:-)<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=922">mirek1968</a> — 1 sie 2014, o 13:48</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2014-08-01T13:11:48+01:00</updated>
<published>2014-08-01T13:11:48+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89719#p89719</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89719#p89719"/>
<title type="html"><![CDATA[Re: Wysyłanie i odbieranie danych poprzez serwer UDP_etherne]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89719#p89719"><![CDATA[
Bo przy starcie nie jest sprawdzany ich stan po prostu .... to tylko program demonstracyjny - a nie jakiś sterownik, który jest gotowy na tzw KAŻDĄ sytuację <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br />cieszę się że ruszyło<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 1 sie 2014, o 13:11</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirek1968]]></name></author>
<updated>2014-08-01T13:01:35+01:00</updated>
<published>2014-08-01T13:01:35+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89716#p89716</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89716#p89716"/>
<title type="html"><![CDATA[Re: Wysyłanie i odbieranie danych poprzez serwer UDP_etherne]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89716#p89716"><![CDATA[
Wina leżała po mojej stronie a konkretnie problem był w tym że porty PB4-7 na mojej płytce mam na stałe przypiete także do LCD HD44780 a przecież są to porty używane do komunikacji.Zablokowałem na razie LCD z zakomentowałem go w programie.<br />Teraz diody LED mogę załączać i wyłanczać  z programu Klient/serwer /UDP i działa mi to dobrze,działa mi także komunikacja zwrotna od płytki testowej do laptopa tzn przyciski dają mi tekst amka &lt;-- [ SuperDebounce klawsz nr: 128 ]<br />ramka &lt;-- [ SuperDebounce klawsz nr: 64 ] w zależności który wcisna. <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":-)" title="Szczęśliwy" />  <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":-)" title="Szczęśliwy" /><br />Czyli wszystko było by OK,mam tylko pytanie dlaczego po odpaleniu programu Klient/serwer /UDP mam już na starcie aktywne okienka zapalenia LED-ów? (w tym momencie diody na płytce nie świeca jeszcze)<br />tak jak poniżej na fotce.Co prawda jak je odznaczę i ponownie zaznaczę to zaświecaja się i gasną wtedy ledy prawidłowo ,czy tak ma ten program czy też jest to związane z czymś innym?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=922">mirek1968</a> — 1 sie 2014, o 13:01</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2014-08-01T12:26:21+01:00</updated>
<published>2014-08-01T12:26:21+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89709#p89709</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89709#p89709"/>
<title type="html"><![CDATA[Re: Wysyłanie i odbieranie danych poprzez serwer UDP_etherne]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89709#p89709"><![CDATA[
No ATmega16 ma o połowę mniej pamięci RAM .... więc sprawdź ile zostaje ci wolnego po kompilacji ... jeśli zajętość RAM wynosi max ok 90% to może zostać taki bufor jak jest<br /><br />zmieniłeś też jak widzę MAC address - naprawdę nie wiem po co ? ... widzisz tak to jest .... gdy ktoś ma kłopoty z pierwszym odpaleniem kodu to zawsze mówię - sprawdź na oryginale ... zmień tylko swoje adresy IP .... i często każdy tak jak ty odpowiada - że &quot;NO sprawdzam na oryginale&quot; a później się okazuje że .... a zmieniłem tylko to i siamto ale wg mnie to nie powinno mieć znaczenia. To wiesz - tak to można to uruchamiać miesiącami .... i w końcu powiedzieć że kod z książki nie działa <img src="https://forum.atnel.pl/images/smilies/icon_e_sad.gif" alt=":(" title="Smutny" /><br /><br />weź więc nie kombinuj - odpal kod z książki , ustaw tylko swoje adresy IP i wtedy jestem w stanie coś pomóc ... <br /><br />Na kombinacje przyjdzie czas później i zobaczysz że wszystkie ci wyjdą ok ?<br /><br />ty na razie masz jakiś mega poważny problem bo np te adres w tablicy kilku adresów jak się źle wpisze to co najwyżej nie ma komunikacji zwrotnej po UDP z procka do programu na PC ... a poza tym WSZYSTKO MUSI DZIAŁAĆ<br /><br />powiedz mi czy jak odpalasz program na PC to zapala ci się takie jasno niebieskie światełko w lewym rogu górnym i masz napisane w statusie, że serwer UDP jest aktywny ?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 1 sie 2014, o 12:26</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirek1968]]></name></author>
<updated>2014-08-01T12:11:21+01:00</updated>
<published>2014-08-01T12:11:21+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89705#p89705</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89705#p89705"/>
<title type="html"><![CDATA[Re: Wysyłanie i odbieranie danych poprzez serwer UDP_etherne]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89705#p89705"><![CDATA[
Sprawdzałem firewall dodał ten program do wyjątku i nie blokuje go.<br />Zastanawiam się nad jedną sprawą jeśli Twój program serwera działał u mnie bardzo dobrze to czym to może być spowodowane że teraz mam problem.co prawda program serwera  testowałem na procku Atmega328P a teraz klienta UDP testuję na Atmedze 16 taktowanym 16Mhz.<br />Zastanawiam się także nad wielkością bufora ramki <br />[syntax=c]// ustalamy wielkość bufora dla ramek TCP/UDP<br />#define BUFFER_SIZE 650[/syntax]<br /><br />Czy u mnie nie powinno być mniej?,a jeśli tak to ile być zaproponował?<br /><br />No i jeszcze jedna spawa ze względu na to że mój procesor jest tatowany zewnętrznym kwarcem 16MHz to musiałem zmienić OCR<br />[syntax=c]OCR2 = 156; //bo 16000000/1024/100[/syntax]<br /><br />Poniżej podaje ustawienia fusebitów do sprawdzenia czy na pewno się nie pomyliłem  gdzieś.<br /><br /><a href="http://forum.atnel.pl/_obrazki/o/922/17056dca9b81fa9f09d4ae106b36ce3c.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/922/17056dca9b81fa9f09d4ae106b36ce3c.jpg" alt="Obrazek" /></a><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=922">mirek1968</a> — 1 sie 2014, o 12:11</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2014-08-01T11:32:26+01:00</updated>
<published>2014-08-01T11:32:26+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89699#p89699</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89699#p89699"/>
<title type="html"><![CDATA[Re: Wysyłanie i odbieranie danych poprzez serwer UDP_etherne]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89699#p89699"><![CDATA[
Być może Firewall windowsa zablokował program na PC ?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 1 sie 2014, o 11:32</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirek1968]]></name></author>
<updated>2014-08-01T10:09:49+01:00</updated>
<published>2014-08-01T10:09:49+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89690#p89690</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89690#p89690"/>
<title type="html"><![CDATA[Re: Wysyłanie i odbieranie danych poprzez serwer UDP_etherne]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89690#p89690"><![CDATA[
Poprawiłem te numery IP zgodnie z uwagami jakie napisałeś ale nadal jak próbuję np. wysłać tekst ,czy zapalić LED to nie działa mi nic.<br />Diody led oraz przyciski  mam podłączone jak na rysunku poniżej<br /><br /><a href="http://forum.atnel.pl/_obrazki/o/922/3bcfe319bfba62bc89e6157b749c3d05.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/922/3bcfe319bfba62bc89e6157b749c3d05.jpg" alt="Obrazek" /></a><a href="http://forum.atnel.pl/_obrazki/o/922/805cc1173a366375f1f37c312af6387e.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/922/805cc1173a366375f1f37c312af6387e.jpg" alt="Obrazek" /></a><br /><br />Na każde kliknięcie w danym oknie w programie Klient/server UDP reaguje mi dioda na karcie sieciowej ENC ale brak reakcji na płytce testowej Atmega16.<br />Cały kod main.c dokładnie taki sam jak w BB z moimi modyfikacjami dotyczącymi wejść przycisków oraz wyjść na LED-y<br />oraz mac adresu i IP poniżej.<br /><br />[syntax=c]/*********************************************<br /> * vim:sw=8:ts=8:si:et<br /> * To use the above modeline in vim you must have &quot;set modeline&quot; in your .vimrc<br /> * Author: Guido Socher<br /> * Copyright: GPL V2<br /> *<br /> * Tuxgraphics AVR webserver/ethernet board<br /> *<br /> * http://tuxgraphics.org/electronics/<br /> * Chip type           : Atmega88/168/328 with ENC28J60<br /> *<br /> *<br /> * ---&gt; OBSŁUGA KLIENT/SERWER komunikacji UDP &lt;-----<br /> * MODYFIKACJE: Mirosław Kardaś --- ATmega32<br /> *<br /> *********************************************/<br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;string.h&gt;<br />#include &quot;ip_arp_udp_tcp.h&quot;<br />#include &quot;enc28j60.h&quot;<br />#include &quot;util/delay.h&quot;<br />#include &quot;net.h&quot;<br /><br />#include &quot;LCD/lcd44780.h&quot;<br /><br />//-------------------------- definicje preprocesora ---------------------------------<br />#define LED1_DDRDDRD<br />#define LED1_PORTPORTD<br />#define LED1(1&lt;&lt;PD4) //dioda na CEPARK PWM2<br />#define LED1_ONLED1_PORT |= LED1<br />#define LED1_OFFLED1_PORT &amp;= ~LED1<br />#define LED1_TOGLED1_PORT ^= LED1<br /><br />#define LED2_DDRDDRD<br />#define LED2_PORTPORTD<br />#define LED2(1&lt;&lt;PD5) //dioda na CEPARK PWM1<br />#define LED2_ONLED2_PORT |= LED2<br />#define LED2_OFFLED2_PORT &amp;= ~LED2<br />#define LED2_TOGLED2_PORT ^= LED2<br /><br />#define KL_PORTPORTD<br />#define KL1(1&lt;&lt;PD6) //przycisk na CEPARK K19<br />#define KL2(1&lt;&lt;PD7) //przycisk na CEPARK K20<br />//-------------------------- definicje preprocesora ---------------------------------<br /><br /><br />//---------------------------------------------------------------------------------------------------------------<br />// ustalamy adres MAC<br />static uint8_t mymac&#91;6&#93; = {0x00,'K','U','B','U','S'};<br />// ustalamy adres IP urządzenia<br />static uint8_t myip&#91;4&#93; = {192,168,0,10};<br /><br />// ustalamy porty UDP z jakich będziemy korzystać<br />// może ich być dowolna ilość<br />static uint16_t myport&#91;&#93; = {1200,22700};<br />// ustalamy adres IP bramy domyślnej w sieci LAN<br />static uint8_t gwip&#91;4&#93; = {192,168,0,1};<br /><br />// ustalamy wielkość bufora dla ramek TCP/UDP<br />#define BUFFER_SIZE 650<br />static uint8_t buf&#91;BUFFER_SIZE+1&#93;;<br /><br />// wskaźnik do funkcji zwrotnej własnego zdarzenia UDP_EVENT()<br />static void (*mk_udp_event_callback)(uint8_t *peer_ip, uint16_t port,<br />uint16_t datapos, uint16_t len);<br /><br />// funkcja do rejestracji funkcji zwrotnej w zdarzeniu UDP_EVENT()<br />void register_udp_event_callback(void (*callback)(uint8_t *peer_ip,<br />uint16_t port, uint16_t datapos, uint16_t len))<br />{<br />mk_udp_event_callback = callback;<br />}<br />//---------------------------------------------------------------------------------------------------------------<br /><br /><br />//---------------------------------- deklaracje funkcji -------------------------------<br />void ping_callback(uint8_t *ip);<br /><br />void SuperDebounce( volatile uint8_t *KPIN,<br />uint8_t key_mask, uint16_t rep_time, uint16_t rep_wait,<br />void (*push_proc)(uint8_t), void (*rep_proc)(uint8_t) );<br /><br />void mk_send_udp(uint8_t nr_klawisza);<br /><br />void udp_event_callback(uint8_t *peer_ip, uint16_t port,<br />uint16_t datapos, uint16_t len);<br /><br />void UDP_EVENT(uint16_t *port);<br /><br />void parse_set_led(char * buf);<br />void parse_get_led(char * s);<br />void parse_set_lcd(char * buf);<br />//---------------------------------- deklaracje funkcji -------------------------------<br /><br /><br />//---------------------------------- deklaracje zmiennych globalnych -------------------------------<br />// indeksy adresów IP w postaci przyjaznych nazw<br />enum ip_names {ip_pc, ip_sterownik1};<br />// adresy IP sterowników z którymi będziemy się komunikować<br />// za pomocą protokołu UDP<br />static uint8_t farip&#91;2&#93;&#91;4&#93; = { {192,168,0,11}, {192,168,0,180} };<br /><br />// timer programowy na usługi funkcji SuperDebounce()<br />volatile uint8_t Timer1;/* timer programowy 100Hz */<br /><br /><br />// separator tokenów we własnych ramkach przesyłanych przez UDP<br />char sep&#91;&#93; = &quot;^&quot;;<br /><br />// przydzielenie kodów we własnych ramkach przesyłanych przez UDP<br />#define ILOSC_KOMEND 3<br />enum commands {set_led, get_led, set_lcd};<br /><br />// tablica wskaźników do funkcji parsujących w pamięci FLASH<br />void (*parse_fun&#91;ILOSC_KOMEND&#93;)(char *buf) PROGMEM = {<br />parse_set_led,<br />parse_get_led,<br />parse_set_lcd<br />};<br /><br />//---------------------------------- deklaracje zmiennych globalnych -------------------------------<br /><br /><br /><br /><br /><br /><br /><br /><br /><br />//======================= main() ================================================<br />int main(void){<br /><br /><br /><br />/********** inicjalizacja pinów/portów *********************/<br />// podświetlenie wyświetlacza LCD<br />DDRA |= (1&lt;&lt;PA7);<br />PORTA |= (1&lt;&lt;PA7);<br /><br />// po resecie piny klawiszy są wejściami<br />// podciągnięcie wejść klawiszy do VCC<br />KL_PORT |= KL1|KL2;<br /><br />// kierunki pinów diod LED jako wyjścia<br />LED1_DDR |= LED1;<br />LED2_DDR |= LED2;<br />// wyłączenie diod LED<br />LED1_OFF;<br />LED2_OFF;<br /><br />/********** inicjalizacja modułów sprzętowych procesora *********************/<br />/* Timer2 – inicjalizacja przerwania co 10ms */<br />TCCR2 |= (1&lt;&lt;WGM21);// tryb pracy CTC<br />TCCR2 |= (1&lt;&lt;CS22)|(1&lt;&lt;CS21)|(1&lt;&lt;CS20);// preskaler = 1024<br />OCR2 = 156;// przerwanie porównania co 10ms (100Hz) było 108 bo 11059200/1024/100<br />TIMSK = (1&lt;&lt;OCIE2);// Odblokowanie przerwania CompareMatch<br /><br />/********** inicjalizacja funkcji bibliotecznych *********************/<br />    lcd_init();<br />    lcd_str(&quot;Start..&quot;);<br /><br /><br />/********** inicjalizacja funkcji obsługi stosu TCP *********************/<br />    /*inicjalizacja układu enc28j60*/<br />    enc28j60Init(mymac);<br /><br />    // konfiguracja diod LED w gnieździe RJ45<br />    // zielona (LEDA) - link<br />    // żółta (LEDB) - rx/tx<br />    // enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10);<br />    enc28j60PhyWrite(PHLCON,0x476);<br /><br />    // inicjalizacja stosu TCP<br />    init_ip_arp_udp_tcp(mymac,myip,80);<br /><br />    // inicjalizacja bramy domyślnej<br />    // konieczne dla funkcji klienckich<br />    client_set_gwip(gwip);<br />/********** inicjalizacja funkcji obsługi stosu TCP *********************/<br /><br />    // zarejestrowanie własnej procedury obsługi/reakcji na ping<br />    register_ping_rec_callback(&amp;ping_callback);<br /><br />    // zarejestrowanie własnej procedury obsługi/reakcji na<br />    // przychodzące pakiety UDP<br />    register_udp_event_callback(udp_event_callback);<br /><br />/********** włączenie przerwań globalnych *********************/<br />    sei();<br /><br /><br />/******************************************************/<br />/************                    **********************/<br />/********** główna pętla programu *********************/<br />/***********                     **********************/<br />/******************************************************/<br />    while(1){<br /><br />    // zdarzenie sprawdzające czy są jakieś dane<br />    // z sieci/układu ENC28j60<br />    UDP_EVENT(myport);<br /><br />    // przykładowa obsługa klawiszy i wysyłanie<br />    // własnych klienckich ramek UDP do wybranych urządzeń w sieci<br />    SuperDebounce(&amp;PIND, (1&lt;&lt;PD6), 100, 200, mk_send_udp, mk_send_udp);<br />    SuperDebounce(&amp;PIND, (1&lt;&lt;PD7), 20, 200, mk_send_udp, 0);<br /><br />    }<br />}<br />//======================= main() koniec =========================================<br /><br /><br /><br /><br /><br /><br />/******* funkcja obsługująca komendę set_led  ******/<br />void parse_set_led(char * buf) {<br />char *wsk;<br />uint8_t nr_led, led_on;<br /><br />wsk = strtok_r(NULL, sep, &amp;buf);<br />if( wsk ) {<br />nr_led = atoi(wsk);<br />wsk = strtok_r(NULL, sep, &amp;buf);<br />if( wsk ) {<br />led_on = atoi(wsk);<br />switch( nr_led ) {<br />case 1: if(led_on) LED1_ON; else LED1_OFF; break;<br />case 2: if(led_on) LED2_ON; else LED2_OFF; break;<br />case 3: if(led_on) PORTA |= (1&lt;&lt;PA7); else PORTA &amp;= ~(1&lt;&lt;PA7);<br />}<br />}<br />}<br />}<br /><br />/******* funkcja obsługująca komendę get_led  ******/<br />void parse_get_led(char * s) {<br />char str&#91;20&#93;;<br />sprintf(str,&quot;%i^%i^%i^%i&quot;, get_led, (PIND &amp; (1&lt;&lt;PD4))&gt;&gt;4, (PIND &amp; (1&lt;&lt;PD5))&gt;&gt;5, (PINA &amp; (1&lt;&lt;PA7))&gt;&gt;7 );<br />make_udp_reply_from_request(buf,str,strlen(str), myport&#91;0&#93;);<br />}<br /><br />/******* funkcja obsługująca komendę set_lcd  ******/<br />void parse_set_lcd(char * buf) {<br />char *wsk, *wsk1;<br /><br />wsk = strtok_r(NULL, sep, &amp;buf);<br />wsk1 = strtok_r(NULL, sep, &amp;buf);<br />if( wsk  ) {<br />lcd_cls();<br />lcd_str( wsk );<br />lcd_locate(1,0);<br />lcd_str( wsk1 );<br />}<br />}<br /><br />/****/<br />/******* własna funkcja użytkownika w której możemy reagować na ramkę UDP ***********/<br />/****/<br />void udp_event_callback(uint8_t *peer_ip, uint16_t port, uint16_t datapos, uint16_t len) {<br />uint8_t i=0;<br />    char str&#91;40&#93;;<br /><br />    // wskaźnik na potrzeby funkcji strtok_r<br />    char *wsk, *reszta;<br /><br />    // wyświetlamy na LCD z jakiego IP nadeszła ramka<br />    // wyświetlamy na jaki port nadeszła ramka<br />lcd_cls();<br />lcd_str(&quot;UDP from: &quot;);<br />lcd_int(port);<br />lcd_locate(1,0);<br />    while(i&lt;4){<br />        lcd_int(peer_ip&#91;i&#93;);<br />        if(3==i) break;<br />        lcd_str(&quot;.&quot;);<br />        i++;<br />    }<br /><br />    // jeśli ramka przyszła na drugi numer portu z listy myport&#91;&#93;<br />    if(port == myport&#91;1&#93;) {<br />    // odpowiadamy na zapytanie UDP po ten sam port<br />    strcpy(str,&quot;Ramka odpowiedzi UDP&quot;);<br />    make_udp_reply_from_request(buf,str,strlen(str), port);<br /><br />        // wysyłamy nową ramkę na dowolny inny port<br />    strcpy((char*)&amp;buf&#91;datapos&#93;,&quot;Nowa ramka UDP!&quot;);<br />        send_udp_prepare(buf, 1200, farip&#91;ip_pc&#93;, 43500);<br />        send_udp_transmit(buf,strlen(str));<br />    }<br /><br />    // jeśli ramka przyszła na pierwszy numer portu z listy myport&#91;&#93;<br />    if(port == myport&#91;0&#93;) {<br />    // sprawdzamy czy zawiera dane<br />    wsk = strtok_r((char*)&amp;buf&#91;datapos&#93;, sep, &amp;reszta);<br />    if( wsk ) {<br />    // jeśli zawiera dane to sprawdzamy jaka komenda<br />    switch( atoi(wsk) ) {<br />    // i w zależności od komendy wywołujemy odpowienią<br />    // funkcję parsującą z tabeli wskaźników do funkcji parsujących<br />    // przekazujemy jednocześnie wskaźnik do pozostałej części<br />    // łańcucha z danymi, który funkcje będą parsować we własnym zakresie<br />    case set_led: parse_fun&#91;set_led&#93;(reszta); break;<br />    case get_led: parse_fun&#91;get_led&#93;(reszta); break;<br />    case set_lcd: parse_fun&#91;set_lcd&#93;(reszta);<br />    }<br />    }<br />    }<br />}<br /><br /><br />/********** zdarzenie UDP EVENT ***********************/<br />void UDP_EVENT(uint16_t *port) {<br />// zmienne tymczasowe (automatyczne)<br />    uint16_t plen, dat_p;<br />    uint16_t dport;<br />    uint8_t is_my_port=0;<br />    uint8_t i=0;<br /><br /><br />    uint8_t udp_data_len=0;<br /><br /><br />    // sprawdzamy czy istnieje nowy odebrany pakiet<br />    plen = enc28j60PacketReceive(BUFFER_SIZE, buf);<br />    // obsługa niższych warstw stosu TCP jak ICMP, ARP itp<br />    // m.inn tą drogą obsługiwane są zewnętrzne PING'i<br />    // w tym miejscu sprawdzane jest od razu czy odczytana ramka<br />    // jest posiada typ jaki obsługiwany jest przez ten stos TCP<br />    // oraz czy jest ona zaadresowana do nas (w numeru IP)<br />    dat_p=packetloop_icmp_tcp(buf,plen);<br /><br />    // jeśli długość odebranej ramki jest większa niż 0<br />    // to oznacza, że mamy do czynienia z prawidłowo odebraną<br />    // ramką wraz z prawidłową sumą kontrolną<br />    // sprawdzamy także, czy na pewno mamy do czynienia z ramką UDP a nie np TCP<br />    if( plen &amp;&amp; buf&#91;IP_PROTO_P&#93;==IP_PROTO_UDP_V ) {<br /><br />    // sprawdzamy do jakiego nr portu kierowana jest ta ramka UDP<br />    dport = (buf&#91;UDP_DST_PORT_H_P&#93;&lt;&lt;8) | buf&#91;UDP_DST_PORT_L_P&#93;;<br /><br />    // sprawdzamy w pętli czy jest to ramka przeznaczona do<br />    // portu nasłuchowego, które obsługuje nasze urządzenie<br />    // listę dowolnej ilości portów definiujemy w tablicy myport&#91;&#93;<br />    // która przekazywana jest jako parametr do zdarzenia/funkcji UDP_EVENT()<br />    do {<br />    if( (is_my_port = (port&#91;i++&#93; == dport)) ) break;<br />    } while (i&lt;sizeof(port));<br /><br />    // sprawdzamy czy informacja przyszła na obsługiwany przez nas port UDP<br />    if ( is_my_port ){<br />udp_data_len=buf&#91;UDP_LEN_L_P&#93;-UDP_HEADER_LEN;<br /><br />// jeśli wszystko się zgadza to sprawdzamy, czy zarejestrowana jest<br />// funkcja zwrotna przez użytkownika. Jeśli nie jest zarejestrowana<br />// to nie wykonana się żadna akcja poza powyżej obsługą<br />// niższych warstw stosu TCP (np PING czy ARP)<br />// Jeśli jest zarejestrowana to zostanie wywołana z odpowiednimi parametrami<br />// 1. podany będzie adres IP skąd nadeszła ramka<br />// 2. podany będzie port na jaki została do nas skierowana ramka<br />// 3. indeks do bufora całej ramki TCP, wskazujący na początek danych w ramce UDP<br />// 4. ilość danych w bajtach przesłanych w ramce UDP<br />if(mk_udp_event_callback) (*mk_udp_event_callback)(&amp;(buf&#91;IP_SRC_P&#93;), dport, UDP_DATA_P, udp_data_len);<br />        }<br />    }<br />}<br /><br /><br />/******* funkcja wysyłająca własne dane przez UDP w zależności od klawisza  ******/<br />void mk_send_udp(uint8_t nr_klawisza) {<br />char str&#91;30&#93;;<br />// przygotowanie własnej ramki (tekest) oraz np numer wciśniętego klawisza<br />sprintf(str,&quot;SuperDebounce klawsz nr: %i&quot;, nr_klawisza);<br />// przesłanie ramki do wybranego adresu IP pod wskazany (dowolny) port<br />// w tym przypadku wysyłamy dane do komputera PC<br />    send_udp(buf, str, strlen(str), 1100, farip&#91;ip_pc&#93;, 21000);<br />}<br /><br /><br />/******* funkcja callback ping *********/<br />// dzięki tej funkcji zwrotnej możemy dowiedzieć się<br />// jaki adres IP PING'uje nasz układ i reagować na<br />// to w specyficzny sposób<br />void ping_callback(uint8_t *ip) {<br />// za każdym razem gdy przychodzi PING do naszego urządzenia<br />// zmieniamy stan diody LED na przeciwny<br />LED1_TOG;<br />}<br /><br /><br /><br /><br />/************** funkcja SuperDebounce do obsługi pojedynczych klawiszy ***************<br /> * AUTOR: Mirosław Kardaś<br /> * ZALETY:<br /> * - nie wprowadza najmniejszego spowalnienia<br /> * - posiada funkcję REPEAT (powtarzanie akcji dla dłużej wciśniętego przycisku)<br /> * - można przydzielić różne akcje dla trybu REPEAT i pojedynczego kliknięcia<br /> * - można przydzielić tylko jedną akcję wtedy w miejsce drugiej przekazujemy 0 (NULL)<br /> * - zabezpieczenie przed naciśnięciem dwóch klawiszy jednocześnie<br /> *<br /> * Wymagania:<br /> * Timer programowy utworzony w oparciu o Timer sprzętowy (przerwanie 100Hz)<br /> *<br /> * Parametry wejściowe - 6 :<br /> *  *KPIN - nazwa PINx portu na którym umieszczony jest klawisz, np: PINB<br /> *  key_mask - maska klawisza np: (1&lt;&lt;PB3)<br /> *  rep_time - czas powtarzania funkcji rep_proc w trybie REPEAT<br /> *  rep_wait - czas oczekiwania do przejścia do trybu REPEAT<br /> *  push_proc - wskaźnik do własnej funkcji wywoływanej raz po zwolenieniu przycisku<br /> *  rep_proc - wskaźnik do własnej funkcji wykonywanej w trybie REPEAT<br /> **************************************************************************************/<br />void SuperDebounce(volatile uint8_t *KPIN,<br />uint8_t key_mask, uint16_t rep_time, uint16_t rep_wait,<br />void (*push_proc)(uint8_t), void (*rep_proc)(uint8_t) ) {<br /><br />enum KS {idle, debounce, go_rep, wait_rep, rep};<br /><br />static enum KS key_state;<br />static uint8_t last_key;<br />uint8_t key_press;<br /><br />// zabezpieczenie przed wykonywaniem tej samej funkcji dla<br />// dwóch klawiszy wciskanych jednocześnie (zawsze będzie<br />// wykonywana odpowiednia akcja dla tego, który został<br />// wciśnięty jako pierwszy<br />if( last_key &amp;&amp; last_key != key_mask ) return;<br /><br />key_press = !(*KPIN &amp; key_mask);<br /><br />if( key_press &amp;&amp; !key_state ) {<br />key_state = debounce;<br />Timer1 = 5;<br />} else<br />if( key_state  ) {<br />if( key_press &amp;&amp; debounce==key_state &amp;&amp; !Timer1 ) {<br />key_state = go_rep;<br />Timer1=3;<br />last_key = key_mask;<br />} else<br />if( !key_press &amp;&amp; key_state&gt;debounce &amp;&amp; key_state&lt;rep ) {<br />if(push_proc) push_proc(key_mask);/* KEY_UP */<br />key_state=idle;<br />last_key = 0;<br />} else<br />if( key_press &amp;&amp; go_rep==key_state &amp;&amp; !Timer1 ) {<br />if(!rep_time) rep_time=20;<br />if(!rep_wait) rep_wait=150;<br />key_state = wait_rep;<br />Timer1=rep_wait;<br />} else<br />if( key_press &amp;&amp; wait_rep==key_state &amp;&amp; !Timer1 ) {<br />key_state = rep;<br />} else<br />if( key_press &amp;&amp; rep==key_state &amp;&amp; !Timer1 ) {<br />Timer1 = rep_time;<br />if(rep_proc) rep_proc(key_mask);/* KEY_REP */<br />}<br />}<br /><br />if( key_state&gt;=wait_rep &amp;&amp; !key_press ) {<br />key_state = idle;<br />last_key = 0;<br />}<br />}<br /><br /><br /><br />/**** obsługa przerwania Timer2 CompareMatch *****/<br />// potrzebnego do realizacji timera programowego dla SuperDebounce()<br />// można je wykorzystać na utworzenie dodatkowych własnych timerów programowych<br />ISR(TIMER2_COMP_vect)<br />{<br />uint8_t n;<br /><br />n = Timer1;/* 100Hz Timer1 */<br />if (n) Timer1 = --n;<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=922">mirek1968</a> — 1 sie 2014, o 10:09</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2014-08-01T03:50:19+01:00</updated>
<published>2014-08-01T03:50:19+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89672#p89672</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89672#p89672"/>
<title type="html"><![CDATA[Re: Wysyłanie i odbieranie danych poprzez serwer UDP_etherne]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89672#p89672"><![CDATA[
<div class="quotetitle">mirek1968 napisał(a):</div><div class="quotecontent"><br />W programie Klient/serwer UDP jest tam takie okno adres IP urzadzenia czy tam mam wpisać adres IP z mojej atmegi?<br /></div><br /><br />No pewnie że adres procka.<br /><br /><div class="quotetitle">mirek1968 napisał(a):</div><div class="quotecontent"><br />Następna sprawa nie rozumiem tych numerów portów UDP<br /></div><br /><br />Gdy działasz w sieci lokalnej (mam nadzieję) ... to po co konfigurować porty na routerze? nie trzeba ... Ja nie za bardzo rozumiem czego nie rozumiesz w tych portach jak mówisz? ot są to przykładowe porty strzelone z głowy. Jak chcesz możesz je zamienić na dowolne inne ale musisz pamiętać aby wtedy je wszędzie w programie też podmienić. Nie mniej jednak po co mieszać na początek ? Lepiej odpalić to tak jak jest bo na 100000% to działa - a jeśli nie to pewnie robisz jakiegoś babola ... ale może zaraz się coś wyjaśni.<br /><br /><div class="quotetitle">mirek1968 napisał(a):</div><div class="quotecontent"><br />Następne pytanie jakie adresy powinienem wpisać poniżej??<br /></div><br /><br />I tu pewnie leży pies pogrzebany - bo przecież w Bluebooku opisuję ten kod dokładnie i do czego są jakie adresy .. ale już przypominam:<br /><br />linia kodu:<br /><br />[syntax=c]// indeksy adresów IP w postaci przyjaznych nazw<br />enum ip_names {ip_pc, ip_sterownik1};[/syntax]<br />mówi o tym, który adres w tej tablicy za co odpowiada, więc widać że pierwszy, te o indexie = 0 {ip_pc}, to adres naszego komputera gdzie masz odpalony program do testowania UDP, a drugi adres {ip_sterownik1} to jakiś np inny procek gdybyś testował ... ale jest on chyba nawet w programie nie używany ... pokazałem tylko że można w ten sposób dodać adresy kolejnych urządzeń bądź komputerów z którymi chcemy się kontaktować. Więc pierwszym adresem w tej tabeli:<br /><br />[syntax=c]static uint8_t farip&#91;2&#93;&#91;4&#93; = { {192,168,0,10}, {192,168,0,11} };[/syntax]<br /><br />powinien być koniecznie adres twojego komputera, a drugi ? nie ważne na razie jaki będzie<br /><br /><div class="quotetitle">mirek1968 napisał(a):</div><div class="quotecontent"><br />Wpisałem tu adres Atmegi oraz swojego laptopa jako druga pozycja ale nie jestem pewien czy dobrze zrobiłem??<br /></div><br /><br />No to teraz już chyba widzisz, że niedobrze zrobiłeś (bo adres twojego kompa - lapka) powinien być jako pierwszy a drugi jest nieistotny w tym przykładzie programu<br /><br /><div class="quotetitle">mirek1968 napisał(a):</div><div class="quotecontent"><br />Następne pytanie dotyczące programu Klient/serwer UDP czy zapalanie i gaszenie diód led 1 i 2 jest skonfigurowane w tym programie i przydzielone do konkretnych wyjść czy też niema to znaczenia na jakich wyjściach mam diody LED w swoim projekcie?<br /></div><br /><br />Programu na PC nie interesuje na jakich pinach masz diody panie kochany - to sobie ustalasz w programie w procku<br /><br /><div class="quotetitle">mirek1968 napisał(a):</div><div class="quotecontent"><br />Poniżej znajduje się mój plik main i proszę o korektę i pomoc bo poza serwerem nic mi nie działa na UDP<br /></div><br /><br />Programu na razie nie mam czasu analizować - proponuję NAJPIERW zawsze odpal to tak jak z książki - żeby zobaczyć że rusza i działa - a później dopiero modyfikuj kod ... bo tak, to sam sobie dodatkowe problemy robisz gdy namodyfikujesz kod i nic ci nie działa. Mówię tu o modyfikacjach poza tymi konfiguracyjnymi odnośnie adresów IP<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 1 sie 2014, o 03:50</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirek1968]]></name></author>
<updated>2014-07-31T23:43:37+01:00</updated>
<published>2014-07-31T23:43:37+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89668#p89668</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89668#p89668"/>
<title type="html"><![CDATA[Wysyłanie i odbieranie danych poprzez serwer UDP_ethernet]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=7965&amp;p=89668#p89668"><![CDATA[
Mam problem z wysyłaniem i odbieraniem danych poprzez moduł karty ethernetowej ENC28J60 na Atmegę 16 taktowaną kwarcem 16MHz.<br />pierwsza częśc opisana w BB dotycząca serwera działa mi dobrze ,natomiast z nadawaniem i odbieraniem ramek mam problem.Korzystam z programu Klient/serwer UDP zamieszczonego na płycie cd z BB i nie potrafię nic wysterować na mojej płytce testowej.Mam kilka pytań co do tego programu oraz do poprawności mojego kodu w c.<br />W programie Klient/serwer UDP jest tam takie okno adres IP urzadzenia czy tam mam wpisać adres IP z mojej atmegi? czyli 192,168,0,10 czy też może adres IP mojego laptopa??  192,168,0,11 ?<br />Następna sprawa nie rozumiem tych numerów portów UDP <br />[syntax=c]// ustalamy porty UDP z jakich będziemy korzystać<br />// może ich być dowolna ilość<br />static uint16_t myport&#91;&#93; = {1200,22700};[/syntax]<br /><br />Dlaczego 1200 i 22700 osobiście nie mam dostępu do parametrów mojego routera i niewiem czy tam mam to wpisać jak w przykładzie.<br /><br />Następne pytanie jakie adresy powinienem wpisać poniżej??<br /><br />[syntax=c]// indeksy adresów IP w postaci przyjaznych nazw<br />enum ip_names {ip_pc, ip_sterownik1};<br />// adresy IP sterowników z którymi będziemy się komunikować<br />// za pomocą protokołu UDP<br />static uint8_t farip&#91;2&#93;&#91;4&#93; = { {192,168,0,10}, {192,168,0,11} };[/syntax]<br /><br />Wpisałem tu adres Atmegi oraz swojego laptopa jako druga pozycja ale nie jestem pewien czy dobrze zrobiłem??<br />Następne pytanie dotyczące programu Klient/serwer UDP czy zapalanie i gaszenie diód led 1 i 2 jest skonfigurowane w tym programie i przydzielone do konkretnych wyjść czy też niema to znaczenia na jakich wyjściach mam diody LED w swoim projekcie?<br /><br />Poniżej znajduje się mój plik main i proszę o korektę i pomoc bo poza serwerem nic mi nie działa na UDP<br /><br />[syntax=c]/*********************************************<br /> * vim:sw=8:ts=8:si:et<br /> * To use the above modeline in vim you must have &quot;set modeline&quot; in your .vimrc<br /> * Author: Guido Socher<br /> * Copyright: GPL V2<br /> *<br /> * Tuxgraphics AVR webserver/ethernet board<br /> *<br /> * http://tuxgraphics.org/electronics/<br /> * Chip type           : Atmega88/168/328 with ENC28J60<br /> *<br /> *<br /> * ---&gt; OBSŁUGA KLIENT/SERWER komunikacji UDP &lt;-----<br /> * MODYFIKACJE: Mirosław Kardaś --- ATmega32<br /> *<br /> *********************************************/<br />#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;avr/pgmspace.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;stdio.h&gt;<br />#include &lt;string.h&gt;<br />#include &quot;ip_arp_udp_tcp.h&quot;<br />#include &quot;enc28j60.h&quot;<br />#include &quot;util/delay.h&quot;<br />#include &quot;net.h&quot;<br /><br />#include &quot;LCD/lcd44780.h&quot;<br /><br />//-------------------------- definicje preprocesora ---------------------------------<br />#define LED1_DDRDDRD<br />#define LED1_PORTPORTD<br />#define LED1(1&lt;&lt;PD4) //dioda na CEPARK PWM2<br />#define LED1_ONLED1_PORT |= LED1<br />#define LED1_OFFLED1_PORT &amp;= ~LED1<br />#define LED1_TOGLED1_PORT ^= LED1<br /><br />#define LED2_DDRDDRD<br />#define LED2_PORTPORTD<br />#define LED2(1&lt;&lt;PD5) //dioda na CEPARK PWM1<br />#define LED2_ONLED2_PORT |= LED2<br />#define LED2_OFFLED2_PORT &amp;= ~LED2<br />#define LED2_TOGLED2_PORT ^= LED2<br /><br />#define KL_PORTPORTD<br />#define KL1(1&lt;&lt;PD6) //przycisk na CEPARK K19<br />#define KL2(1&lt;&lt;PD7) //przycisk na CEPARK K20<br />//-------------------------- definicje preprocesora ---------------------------------<br /><br /><br />//---------------------------------------------------------------------------------------------------------------<br />// ustalamy adres MAC<br />static uint8_t mymac&#91;6&#93; = {0x00,'K','U','B','U','S'};<br />// ustalamy adres IP urządzenia<br />static uint8_t myip&#91;4&#93; = {192,168,0,10};<br /><br />// ustalamy porty UDP z jakich będziemy korzystać<br />// może ich być dowolna ilość<br />static uint16_t myport&#91;&#93; = {1200,22700};<br />// ustalamy adres IP bramy domyślnej w sieci LAN<br />static uint8_t gwip&#91;4&#93; = {192,168,0,1};<br /><br />// ustalamy wielkość bufora dla ramek TCP/UDP<br />#define BUFFER_SIZE 650<br />static uint8_t buf&#91;BUFFER_SIZE+1&#93;;<br /><br />// wskaźnik do funkcji zwrotnej własnego zdarzenia UDP_EVENT()<br />static void (*mk_udp_event_callback)(uint8_t *peer_ip, uint16_t port,<br />uint16_t datapos, uint16_t len);<br /><br />// funkcja do rejestracji funkcji zwrotnej w zdarzeniu UDP_EVENT()<br />void register_udp_event_callback(void (*callback)(uint8_t *peer_ip,<br />uint16_t port, uint16_t datapos, uint16_t len))<br />{<br />mk_udp_event_callback = callback;<br />}<br />//---------------------------------------------------------------------------------------------------------------<br /><br /><br />//---------------------------------- deklaracje funkcji -------------------------------<br />void ping_callback(uint8_t *ip);<br /><br />void SuperDebounce( volatile uint8_t *KPIN,<br />uint8_t key_mask, uint16_t rep_time, uint16_t rep_wait,<br />void (*push_proc)(uint8_t), void (*rep_proc)(uint8_t) );<br /><br />void mk_send_udp(uint8_t nr_klawisza);<br /><br />void udp_event_callback(uint8_t *peer_ip, uint16_t port,<br />uint16_t datapos, uint16_t len);<br /><br />void UDP_EVENT(uint16_t *port);<br /><br />void parse_set_led(char * buf);<br />void parse_get_led(char * s);<br />void parse_set_lcd(char * buf);<br />//---------------------------------- deklaracje funkcji -------------------------------<br /><br /><br />//---------------------------------- deklaracje zmiennych globalnych -------------------------------<br />// indeksy adresów IP w postaci przyjaznych nazw<br />enum ip_names {ip_pc, ip_sterownik1};<br />// adresy IP sterowników z którymi będziemy się komunikować<br />// za pomocą protokołu UDP<br />static uint8_t farip&#91;2&#93;&#91;4&#93; = { {192,168,0,10}, {192,168,0,11} };<br /><br />// timer programowy na usługi funkcji SuperDebounce()<br />volatile uint8_t Timer1;/* timer programowy 100Hz */<br /><br /><br />// separator tokenów we własnych ramkach przesyłanych przez UDP<br />char sep&#91;&#93; = &quot;^&quot;;<br /><br />// przydzielenie kodów we własnych ramkach przesyłanych przez UDP<br />#define ILOSC_KOMEND 3<br />enum commands {set_led, get_led, set_lcd};<br /><br />// tablica wskaźników do funkcji parsujących w pamięci FLASH<br />void (*parse_fun&#91;ILOSC_KOMEND&#93;)(char *buf) PROGMEM = {<br />parse_set_led,<br />parse_get_led,<br />parse_set_lcd<br />};<br /><br />//---------------------------------- deklaracje zmiennych globalnych -------------------------------<br /><br /><br /><br /><br /><br /><br /><br /><br /><br />//======================= main() ================================================<br />int main(void){<br /><br /><br /><br />/********** inicjalizacja pinów/portów *********************/<br />// podświetlenie wyświetlacza LCD<br />DDRA |= (1&lt;&lt;PA7);<br />PORTA |= (1&lt;&lt;PA7);<br /><br />// po resecie piny klawiszy są wejściami<br />// podciągnięcie wejść klawiszy do VCC<br />KL_PORT |= KL1|KL2;<br /><br />// kierunki pinów diod LED jako wyjścia<br />LED1_DDR |= LED1;<br />LED2_DDR |= LED2;<br />// wyłączenie diod LED<br />LED1_OFF;<br />LED2_OFF;<br /><br />/********** inicjalizacja modułów sprzętowych procesora *********************/<br />/* Timer2 – inicjalizacja przerwania co 10ms */<br />TCCR2 |= (1&lt;&lt;WGM21);// tryb pracy CTC<br />TCCR2 |= (1&lt;&lt;CS22)|(1&lt;&lt;CS21)|(1&lt;&lt;CS20);// preskaler = 1024<br />OCR2 = 156;// przerwanie porównania co 10ms (100Hz) było 108 bo 11059200/1024/100<br />TIMSK = (1&lt;&lt;OCIE2);// Odblokowanie przerwania CompareMatch<br /><br />/********** inicjalizacja funkcji bibliotecznych *********************/<br />    lcd_init();<br />    lcd_str(&quot;Start..&quot;);<br /><br /><br />/********** inicjalizacja funkcji obsługi stosu TCP *********************/<br />    /*inicjalizacja układu enc28j60*/<br />    enc28j60Init(mymac);<br /><br />    // konfiguracja diod LED w gnieździe RJ45<br />    // zielona (LEDA) - link<br />    // żółta (LEDB) - rx/tx<br />    // enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10);<br />    enc28j60PhyWrite(PHLCON,0x476);<br /><br />    // inicjalizacja stosu TCP<br />    init_ip_arp_udp_tcp(mymac,myip,80);<br /><br />    // inicjalizacja bramy domyślnej<br />    // konieczne dla funkcji klienckich<br />    client_set_gwip(gwip);<br />/********** inicjalizacja funkcji obsługi stosu TCP *********************/<br /><br />    // zarejestrowanie własnej procedury obsługi/reakcji na ping<br />    register_ping_rec_callback(&amp;ping_callback);<br /><br />    // zarejestrowanie własnej procedury obsługi/reakcji na<br />    // przychodzące pakiety UDP<br />    register_udp_event_callback(udp_event_callback);<br /><br />/********** włączenie przerwań globalnych *********************/<br />    sei();<br /><br /><br />/******************************************************/<br />/************                    **********************/<br />/********** główna pętla programu *********************/<br />/***********                     **********************/<br />/******************************************************/<br />    while(1){<br /><br />    // zdarzenie sprawdzające czy są jakieś dane<br />    // z sieci/układu ENC28j60<br />    UDP_EVENT(myport);<br /><br />    // przykładowa obsługa klawiszy i wysyłanie<br />    // własnych klienckich ramek UDP do wybranych urządzeń w sieci<br />    SuperDebounce(&amp;PIND, (1&lt;&lt;PD6), 100, 200, mk_send_udp, mk_send_udp);<br />    SuperDebounce(&amp;PIND, (1&lt;&lt;PD7), 20, 200, mk_send_udp, 0);<br /><br />    }<br />}<br />//======================= main() koniec =========================================<br /><br /><br /><br /><br /><br /><br />/******* funkcja obsługująca komendę set_led  ******/<br />void parse_set_led(char * buf) {<br />char *wsk;<br />uint8_t nr_led, led_on;<br /><br />wsk = strtok_r(NULL, sep, &amp;buf);<br />if( wsk ) {<br />nr_led = atoi(wsk);<br />wsk = strtok_r(NULL, sep, &amp;buf);<br />if( wsk ) {<br />led_on = atoi(wsk);<br />switch( nr_led ) {<br />case 1: if(led_on) LED1_ON; else LED1_OFF; break;<br />case 2: if(led_on) LED2_ON; else LED2_OFF; break;<br />case 3: if(led_on) PORTA |= (1&lt;&lt;PA7); else PORTA &amp;= ~(1&lt;&lt;PA7);<br />}<br />}<br />}<br />}<br /><br />/******* funkcja obsługująca komendę get_led  ******/<br />void parse_get_led(char * s) {<br />char str&#91;20&#93;;<br />sprintf(str,&quot;%i^%i^%i^%i&quot;, get_led, (PIND &amp; (1&lt;&lt;PD4))&gt;&gt;4, (PIND &amp; (1&lt;&lt;PD5))&gt;&gt;5, (PINA &amp; (1&lt;&lt;PA7))&gt;&gt;7 );<br />make_udp_reply_from_request(buf,str,strlen(str), myport&#91;0&#93;);<br />}<br /><br />/******* funkcja obsługująca komendę set_lcd  ******/<br />void parse_set_lcd(char * buf) {<br />char *wsk, *wsk1;<br /><br />wsk = strtok_r(NULL, sep, &amp;buf);<br />wsk1 = strtok_r(NULL, sep, &amp;buf);<br />if( wsk  ) {<br />lcd_cls();<br />lcd_str( wsk );<br />lcd_locate(1,0);<br />lcd_str( wsk1 );<br />}<br />}<br /><br />/****/<br />/******* własna funkcja użytkownika w której możemy reagować na ramkę UDP ***********/<br />/****/<br />void udp_event_callback(uint8_t *peer_ip, uint16_t port, uint16_t datapos, uint16_t len) {<br />uint8_t i=0;<br />    char str&#91;40&#93;;<br /><br />    // wskaźnik na potrzeby funkcji strtok_r<br />    char *wsk, *reszta;<br /><br />    // wyświetlamy na LCD z jakiego IP nadeszła ramka<br />    // wyświetlamy na jaki port nadeszła ramka<br />lcd_cls();<br />lcd_str(&quot;UDP from: &quot;);<br />lcd_int(port);<br />lcd_locate(1,0);<br />    while(i&lt;4){<br />        lcd_int(peer_ip&#91;i&#93;);<br />        if(3==i) break;<br />        lcd_str(&quot;.&quot;);<br />        i++;<br />    }<br /><br />    // jeśli ramka przyszła na drugi numer portu z listy myport&#91;&#93;<br />    if(port == myport&#91;1&#93;) {<br />    // odpowiadamy na zapytanie UDP po ten sam port<br />    strcpy(str,&quot;Ramka odpowiedzi UDP&quot;);<br />    make_udp_reply_from_request(buf,str,strlen(str), port);<br /><br />        // wysyłamy nową ramkę na dowolny inny port<br />    strcpy((char*)&amp;buf&#91;datapos&#93;,&quot;Nowa ramka UDP!&quot;);<br />        send_udp_prepare(buf, 1200, farip&#91;ip_pc&#93;, 43500);<br />        send_udp_transmit(buf,strlen(str));<br />    }<br /><br />    // jeśli ramka przyszła na pierwszy numer portu z listy myport&#91;&#93;<br />    if(port == myport&#91;0&#93;) {<br />    // sprawdzamy czy zawiera dane<br />    wsk = strtok_r((char*)&amp;buf&#91;datapos&#93;, sep, &amp;reszta);<br />    if( wsk ) {<br />    // jeśli zawiera dane to sprawdzamy jaka komenda<br />    switch( atoi(wsk) ) {<br />    // i w zależności od komendy wywołujemy odpowienią<br />    // funkcję parsującą z tabeli wskaźników do funkcji parsujących<br />    // przekazujemy jednocześnie wskaźnik do pozostałej części<br />    // łańcucha z danymi, który funkcje będą parsować we własnym zakresie<br />    case set_led: parse_fun&#91;set_led&#93;(reszta); break;<br />    case get_led: parse_fun&#91;get_led&#93;(reszta); break;<br />    case set_lcd: parse_fun&#91;set_lcd&#93;(reszta);<br />    }<br />    }<br />    }<br />}<br /><br /><br />/********** zdarzenie UDP EVENT ***********************/<br />void UDP_EVENT(uint16_t *port) {<br />// zmienne tymczasowe (automatyczne)<br />    uint16_t plen, dat_p;<br />    uint16_t dport;<br />    uint8_t is_my_port=0;<br />    uint8_t i=0;<br /><br /><br />    uint8_t udp_data_len=0;<br /><br /><br />    // sprawdzamy czy istnieje nowy odebrany pakiet<br />    plen = enc28j60PacketReceive(BUFFER_SIZE, buf);<br />    // obsługa niższych warstw stosu TCP jak ICMP, ARP itp<br />    // m.inn tą drogą obsługiwane są zewnętrzne PING'i<br />    // w tym miejscu sprawdzane jest od razu czy odczytana ramka<br />    // jest posiada typ jaki obsługiwany jest przez ten stos TCP<br />    // oraz czy jest ona zaadresowana do nas (w numeru IP)<br />    dat_p=packetloop_icmp_tcp(buf,plen);<br /><br />    // jeśli długość odebranej ramki jest większa niż 0<br />    // to oznacza, że mamy do czynienia z prawidłowo odebraną<br />    // ramką wraz z prawidłową sumą kontrolną<br />    // sprawdzamy także, czy na pewno mamy do czynienia z ramką UDP a nie np TCP<br />    if( plen &amp;&amp; buf&#91;IP_PROTO_P&#93;==IP_PROTO_UDP_V ) {<br /><br />    // sprawdzamy do jakiego nr portu kierowana jest ta ramka UDP<br />    dport = (buf&#91;UDP_DST_PORT_H_P&#93;&lt;&lt;8) | buf&#91;UDP_DST_PORT_L_P&#93;;<br /><br />    // sprawdzamy w pętli czy jest to ramka przeznaczona do<br />    // portu nasłuchowego, które obsługuje nasze urządzenie<br />    // listę dowolnej ilości portów definiujemy w tablicy myport&#91;&#93;<br />    // która przekazywana jest jako parametr do zdarzenia/funkcji UDP_EVENT()<br />    do {<br />    if( (is_my_port = (port&#91;i++&#93; == dport)) ) break;<br />    } while (i&lt;sizeof(port));<br /><br />    // sprawdzamy czy informacja przyszła na obsługiwany przez nas port UDP<br />    if ( is_my_port ){<br />udp_data_len=buf&#91;UDP_LEN_L_P&#93;-UDP_HEADER_LEN;<br /><br />// jeśli wszystko się zgadza to sprawdzamy, czy zarejestrowana jest<br />// funkcja zwrotna przez użytkownika. Jeśli nie jest zarejestrowana<br />// to nie wykonana się żadna akcja poza powyżej obsługą<br />// niższych warstw stosu TCP (np PING czy ARP)<br />// Jeśli jest zarejestrowana to zostanie wywołana z odpowiednimi parametrami<br />// 1. podany będzie adres IP skąd nadeszła ramka<br />// 2. podany będzie port na jaki została do nas skierowana ramka<br />// 3. indeks do bufora całej ramki TCP, wskazujący na początek danych w ramce UDP<br />// 4. ilość danych w bajtach przesłanych w ramce UDP<br />if(mk_udp_event_callback) (*mk_udp_event_callback)(&amp;(buf&#91;IP_SRC_P&#93;), dport, UDP_DATA_P, udp_data_len);<br />        }<br />    }<br />}<br /><br /><br />/******* funkcja wysyłająca własne dane przez UDP w zależności od klawisza  ******/<br />void mk_send_udp(uint8_t nr_klawisza) {<br />char str&#91;30&#93;;<br />// przygotowanie własnej ramki (tekest) oraz np numer wciśniętego klawisza<br />sprintf(str,&quot;SuperDebounce klawsz nr: %i&quot;, nr_klawisza);<br />// przesłanie ramki do wybranego adresu IP pod wskazany (dowolny) port<br />// w tym przypadku wysyłamy dane do komputera PC<br />    send_udp(buf, str, strlen(str), 1100, farip&#91;ip_pc&#93;, 21000);<br />}<br /><br /><br />/******* funkcja callback ping *********/<br />// dzięki tej funkcji zwrotnej możemy dowiedzieć się<br />// jaki adres IP PING'uje nasz układ i reagować na<br />// to w specyficzny sposób<br />void ping_callback(uint8_t *ip) {<br />// za każdym razem gdy przychodzi PING do naszego urządzenia<br />// zmieniamy stan diody LED na przeciwny<br />LED1_TOG;<br />}<br /><br /><br /><br /><br />/************** funkcja SuperDebounce do obsługi pojedynczych klawiszy ***************<br /> * AUTOR: Mirosław Kardaś<br /> * ZALETY:<br /> * - nie wprowadza najmniejszego spowalnienia<br /> * - posiada funkcję REPEAT (powtarzanie akcji dla dłużej wciśniętego przycisku)<br /> * - można przydzielić różne akcje dla trybu REPEAT i pojedynczego kliknięcia<br /> * - można przydzielić tylko jedną akcję wtedy w miejsce drugiej przekazujemy 0 (NULL)<br /> * - zabezpieczenie przed naciśnięciem dwóch klawiszy jednocześnie<br /> *<br /> * Wymagania:<br /> * Timer programowy utworzony w oparciu o Timer sprzętowy (przerwanie 100Hz)<br /> *<br /> * Parametry wejściowe - 6 :<br /> *  *KPIN - nazwa PINx portu na którym umieszczony jest klawisz, np: PINB<br /> *  key_mask - maska klawisza np: (1&lt;&lt;PB3)<br /> *  rep_time - czas powtarzania funkcji rep_proc w trybie REPEAT<br /> *  rep_wait - czas oczekiwania do przejścia do trybu REPEAT<br /> *  push_proc - wskaźnik do własnej funkcji wywoływanej raz po zwolenieniu przycisku<br /> *  rep_proc - wskaźnik do własnej funkcji wykonywanej w trybie REPEAT<br /> **************************************************************************************/<br />void SuperDebounce(volatile uint8_t *KPIN,<br />uint8_t key_mask, uint16_t rep_time, uint16_t rep_wait,<br />void (*push_proc)(uint8_t), void (*rep_proc)(uint8_t) ) {<br /><br />enum KS {idle, debounce, go_rep, wait_rep, rep};<br /><br />static enum KS key_state;<br />static uint8_t last_key;<br />uint8_t key_press;<br /><br />// zabezpieczenie przed wykonywaniem tej samej funkcji dla<br />// dwóch klawiszy wciskanych jednocześnie (zawsze będzie<br />// wykonywana odpowiednia akcja dla tego, który został<br />// wciśnięty jako pierwszy<br />if( last_key &amp;&amp; last_key != key_mask ) return;<br /><br />key_press = !(*KPIN &amp; key_mask);<br /><br />if( key_press &amp;&amp; !key_state ) {<br />key_state = debounce;<br />Timer1 = 5;<br />} else<br />if( key_state  ) {<br />if( key_press &amp;&amp; debounce==key_state &amp;&amp; !Timer1 ) {<br />key_state = go_rep;<br />Timer1=3;<br />last_key = key_mask;<br />} else<br />if( !key_press &amp;&amp; key_state&gt;debounce &amp;&amp; key_state&lt;rep ) {<br />if(push_proc) push_proc(key_mask);/* KEY_UP */<br />key_state=idle;<br />last_key = 0;<br />} else<br />if( key_press &amp;&amp; go_rep==key_state &amp;&amp; !Timer1 ) {<br />if(!rep_time) rep_time=20;<br />if(!rep_wait) rep_wait=150;<br />key_state = wait_rep;<br />Timer1=rep_wait;<br />} else<br />if( key_press &amp;&amp; wait_rep==key_state &amp;&amp; !Timer1 ) {<br />key_state = rep;<br />} else<br />if( key_press &amp;&amp; rep==key_state &amp;&amp; !Timer1 ) {<br />Timer1 = rep_time;<br />if(rep_proc) rep_proc(key_mask);/* KEY_REP */<br />}<br />}<br /><br />if( key_state&gt;=wait_rep &amp;&amp; !key_press ) {<br />key_state = idle;<br />last_key = 0;<br />}<br />}<br /><br /><br /><br />/**** obsługa przerwania Timer2 CompareMatch *****/<br />// potrzebnego do realizacji timera programowego dla SuperDebounce()<br />// można je wykorzystać na utworzenie dodatkowych własnych timerów programowych<br />ISR(TIMER2_COMP_vect)<br />{<br />uint8_t n;<br /><br />n = Timer1;/* 100Hz Timer1 */<br />if (n) Timer1 = --n;<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=922">mirek1968</a> — 31 lip 2014, o 23:43</p><hr />
]]></content>
</entry>
</feed>