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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-12-26T12:47:35+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=9861&amp;mode</id>
<entry>
<author><name><![CDATA[holo]]></name></author>
<updated>2014-12-26T12:47:35+01:00</updated>
<published>2014-12-26T12:47:35+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=9861&amp;p=110530#p110530</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=9861&amp;p=110530#p110530"/>
<title type="html"><![CDATA[[C] [PRZERWANIE] [SOLVED - EDIT4] - problem z menu na LCD]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=9861&amp;p=110530#p110530"><![CDATA[
Witam<br /><br />Nie wiedzieć czemu program mimo poprawnej kompilacji nie działa jak powinien.  W przerwaniu chciałem obsługiwać klawisze, które by zmieniały zmienną do obsługi menu. Niestety wyświetlanie menu &quot;show_menu()&quot; wygląda jakby tylko raz się wykonywało. Testowałem (do testów użyłem lcd_puts(buf) w przerwaniu) i przerwanie zmienia wartość menu_pos ale funkcja, która by miała wyświetlać menu nie reaguje na te zmiany. Poniżej kod:<br /><br />keyboard.c<br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;stdio.h&gt;<br /><br />#include &quot;keyboard.h&quot;<br />#include &quot;menu.h&quot;<br />#include &quot;hd44780.h&quot;<br /><br />enum t_key {left, enter, right};<br />enum t_key sw_check(void);<br />void set_var(void);<br /><br /><br />void keyboard_init(void)<br />{<br />    KEYS_DDR &amp;= ~KEY_LEFT | ~KEY_ENTER | ~KEY_RIGHT;<br />    KEYS_PORT |= KEY_LEFT | KEY_ENTER | KEY_RIGHT;<br /><br /><br />    TCCR0 |= (1&lt;&lt;WGM01);<br />    TCCR0 |= (1&lt;&lt;CS02) | (1&lt;&lt;CS00);<br />    //OCR0 |= 38;<br />    TIMSK |= (1&lt;&lt;OCIE0);<br /><br />}<br /><br />ISR(TIMER0_COMP_vect)<br />{<br />    set_var();<br />}<br /><br /><br />enum t_key sw_check(void)<br />    {<br />        _delay_ms(10);<br />        if( ! (KEYS_PIN &amp; KEY_LEFT) ) return left;<br />        if( ! (KEYS_PIN &amp; KEY_ENTER) ) return enter;<br />        if( ! (KEYS_PIN &amp; KEY_RIGHT) ) return right;<br />        else return -1;                                     //musi byc jakis return inaczej jesli nie nacisniemy zadnego klawisza funkcja domyslnie zwroci 0 co odpowiada za przycisk lewo<br />    }<br /><br />void set_var(void)<br />{<br /><br /><br /><br /><br /><br /><br />    switch( sw_check() )<br />    {<br />        case left:<br />            if (menu_pos &lt;= 0)<br />            {<br />                menu_pos = 0;<br />                break;<br />            }<br />            else menu_pos--;<br />            break;<br />        case enter:<br />            lcd_clrscr();<br />            lcd_puts(&quot;enter&quot;);<br />            break;<br />        case right:<br />            if(menu_pos &gt;= MENU_OPTIONS_NUMBER - 1)<br />            {<br />                menu_pos = MENU_OPTIONS_NUMBER;<br />                break;<br />            }<br />            else menu_pos++;<br />            break;<br /><br />      }<br /><br /><br />}[/syntax]<br /><br />menu.c<br /><br />[syntax=c]#include &lt;avr/io.h&gt;<br />#include &quot;hd44780.h&quot;<br />#include &lt;stdio.h&gt;<br />#include &quot;menu.h&quot;<br /><br />#include &lt;util/delay.h&gt;<br /><br />/**********************************************************************<br />Cursor positioning<br />Input: Row,Position<br />Returns: None<br />**********************************************************************/<br /><br />void lcd_gotoRP(uint8_t row,uint8_t pos)<br />  {<br />    switch(row)<br />    {<br />        case 1: lcd_goto(pos); break;<br />        case 2: lcd_goto(0x40+pos); break;<br />    }<br /><br />  }<br /><br /><br />extern volatile int menu_pos;<br /><br />void show_menu(t_menu_item *ptr_menu_tab)<br />{<br />    char buf&#91;50&#93;;<br />    sprintf(buf,&quot;%d&quot;,menu_pos);<br /><br />        if(menu_pos == 0)<br />        {<br />            /*lcd_clrscr();<br />            lcd_gotoRP(1,6);<br />            lcd_puts(ptr_menu_tab&#91;menu_pos&#93;.m_name);<br />            lcd_gotoRP(1,12);<br />            lcd_puts(ptr_menu_tab&#91;menu_pos + 1&#93;.m_name);<br />            _delay_ms(10);*/<br />            lcd_clrscr();<br />            lcd_puts(buf);<br /><br />        }<br />        if(menu_pos == MENU_OPTIONS_NUMBER -1)<br />        {<br />            /*lcd_clrscr();<br />            lcd_puts(ptr_menu_tab&#91;menu_pos - 1&#93;.m_name);<br />            lcd_gotoRP(1,6);<br />            lcd_puts(ptr_menu_tab&#91;menu_pos&#93;.m_name);<br />            _delay_ms(10);*/<br />            lcd_clrscr();<br />            lcd_puts(buf);<br /><br />        }<br />        else<br />        {<br />            /*lcd_clrscr();<br />            lcd_puts(ptr_menu_tab&#91;menu_pos - 1&#93;.m_name);<br />            lcd_gotoRP(1,6);<br />            lcd_puts(ptr_menu_tab&#91;menu_pos&#93;.m_name);<br />            lcd_gotoRP(1,12);<br />            lcd_puts(ptr_menu_tab&#91;menu_pos + 1&#93;.m_name);<br />            _delay_ms(10);*/<br />            lcd_clrscr();<br />            lcd_puts(buf);<br /><br />        }<br /><br /><br /><br /><br />}[/syntax]<br /><br />main.c<br />[syntax=c]/*<br /> */<br /><br />#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;avr/interrupt.h&gt;<br /><br />#include &quot;hd44780.h&quot;<br />#include &quot;hd44780_settings.h&quot;<br />#include &quot;menu.h&quot;<br />#include &quot;keyboard.h&quot;<br /><br /><br /><br /><br />t_menu_item main_menu&#91;MENU_OPTIONS_NUMBER&#93; =<br />                        {<br />                            {&quot;tes1&quot;, 1},<br />                            {&quot;tes2&quot;, 2},<br />                            {&quot;tes3&quot;, 3},<br />                            {&quot;tes4&quot;, 4},<br />                            {&quot;tes5&quot;, 5},<br />                        };<br /><br />volatile int menu_pos = 0;<br /><br /><br /><br />int main(void)<br />{<br /><br />    lcd_init();<br />    sei();<br />    keyboard_init();<br /><br /><br />    while(1)<br />    {<br />     show_menu(main_menu);<br />    }<br /><br />    return 0;<br />}[/syntax]<br /><br />Jeśli ręcznie zmienię menu_pos na inną wartość to show_menu wyświetli zgodnie z &quot;if'ami&quot; jak należy jeśli jednak manipuluję tą zmienną z przerwania niestety nic się nie dzieje. Co ciekawe gdy wcisnę klawisze &quot;enter&quot; wyświetla sie napis &quot;enter&quot; (tak jak jest ustawione w przerwaniu i już tak zostaje nie znika.. jakby funkcja wyswietlająca menu wykonywała się tylko raz na samym początku. Czy ktoś może widzi jakiś błąd? Może to jakaś oczywista oczywistość a ja nie potrafię tego zauważyć.<br /><br />Co ciekawe funkcje &quot;debugujące&quot; lcd_puts(buf) w funkcji &quot;show_menu&quot; na ekranie nie zwracają nic - pusty ekran aż do naciśnięcia &quot;enter&quot;. W przypadku obecnie wykomentowanego kodu, pokazują menu dla pozycji zależnej od menu_pos ustawionego w main.c.. niestety nie reaguje jak wspomniałem na zmianę.<br /><br />EDIT:<br /><br />Spróbowałem jeszcze taki test w main.c:<br /><br />[syntax=c]...<br /><br />    while(1)<br />    {<br />        sprintf(buf,&quot;%d&quot;,menu_pos);<br />        lcd_clrscr();<br />        lcd_puts(buf);<br />        _delay_ms(100);<br />     //show_menu(main_menu);<br /><br /><br />    }<br />...[/syntax]<br /><br /><br /><br />Dzieje się to samo. Jakby pętla while wykonywała się tylko raz.. przy naciśnięciu lewo/prawo nic się nie dzieje cały czas jest na wyświetlaczu &quot;0&quot; gdy nacisnę &quot;enter&quot; pojawia się napis &quot;enter&quot; i już nie znika.<br /><br />EDIT2:<br /><br />Próbowałem również zablokować przerwania na czas wykonywania &quot;set_var&quot;:<br /><br />[syntax=c]...<br />ISR(TIMER0_COMP_vect)<br />{<br />    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)<br />    {<br />       set_var();<br />    }<br />}<br />...[/syntax]<br /><br />Nie pomoglo :/<br /><br />EDIT 3 - PROBLEM ROZWIAZANY<br /><br />Problemem okazała się funkcja delay w przerwaniu. Przerwanie wykonywało się tak długo, że nie było czasu na główną funkcję.. wystarczyło odpalić  przewodnik z przerwaniam Mirka <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" />. Jednak teraz mam nowy problem gdyż sprawdzanie wciśniętego klawisza odbywa się tak szybko, że przeskakuje od 0 - 5 przy jednym naciśnięciu. Jak to teraz rozwiązać?<br /><br />EDIT 4 - PROBLEM CALKOWICIE ROZWIAZANY<br /><br />Udało mi się rozwiązać drgania styków bez użycia &quot;delay&quot; za pomocą następującego przerwania (co przerwanie sprawdzam czy dany klawisz jest wciśnięty i zwiększam zmienną kontrolną o jeden). W ten sposób idzie idealnie wysterować switch bez przerywania głównej funkcji programu:<br /><br />[syntax=c]...<br />ISR(TIMER0_COMP_vect)<br />{<br />    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)<br />    {<br />       static uint8_t left_ck = 0;<br />       static uint8_t enter_ck = 0;<br />       static uint8_t right_ck = 0;<br /><br />       if( ! (KEYS_PIN &amp; KEY_LEFT) ) left_ck++;<br />       if( ! (KEYS_PIN &amp; KEY_ENTER) ) enter_ck++;<br />       if( ! (KEYS_PIN &amp; KEY_RIGHT) ) right_ck++;<br /><br />       if(left_ck &gt;= 50){<br />        if(menu_pos == 0) left_ck = 0;<br />        else{<br />            menu_pos--;<br />            left_ck=0;<br />        }<br />       }<br /><br />       if(enter_ck &gt;= 50) enter_ck = 0;<br /><br />       if(right_ck &gt;= 50){<br />        if(menu_pos &gt;= MENU_OPTIONS_NUMBER -1){<br />            menu_pos = MENU_OPTIONS_NUMBER -1;<br />            right_ck = 0;<br />        }<br />        else{<br />            menu_pos++;<br />            right_ck = 0;<br />        }<br />       }<br /><br />    }<br />}<br />..[/syntax]<br /><br /><br />Pozdrawiam<br />//holo<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=6068">holo</a> — 26 gru 2014, o 12:47</p><hr />
]]></content>
</entry>
</feed>