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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2013-07-27T15:46:07+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=3685&amp;mode</id>
<entry>
<author><name><![CDATA[oseri]]></name></author>
<updated>2013-07-27T15:46:07+01:00</updated>
<published>2013-07-27T15:46:07+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=3685&amp;p=43585#p43585</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=3685&amp;p=43585#p43585"/>
<title type="html"><![CDATA[Timer CTC, przejście z flagi na przerwanie]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=3685&amp;p=43585#p43585"><![CDATA[
Otóż sprawa jest taka, że napisałem programik do odczytywania przycisków z klawiatury i wyświetlania ich wartości na 7 segmentowym.<br /><br />Samo odczytywanie i wyświetlanie działa bez problemu, jedynie problem jest z użyciem timera.<br /><br />Poniższy kod działa prawidłowo (proszę nie starać się dogłębnie analizować, chodzi tylko o część z timerem co wyjaśnie nieco niżej):<br />[syntax=c]#define F_CPU 1000000L<br />#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br /><br />void wysw(unsigned char cyfra&#91;&#93;) //funkcja obslugujaca wyswietlacz 7 seg<br />{<br />// pierwsza cyfra/segment<br />PORTC = (1&lt;&lt;1);<br />PORTD = (cyfra&#91;0&#93;&lt;&lt;4);<br />_delay_ms(5);<br />// droga cyfra/segment<br />PORTC = (1&lt;&lt;0);<br />PORTD = (cyfra&#91;1&#93;&lt;&lt;4); //wyswietlanie wcisnietej cyfry<br />_delay_ms(5);<br />}<br /><br /><br />void wciskaj(unsigned char cyfra&#91;&#93;) //wywolywana po wcisnieciu jakiegos klawisza<br />{<br />unsigned char n,j,k;<br /><br />PORTC = 0x00; //wylaczenie wyswietlacza<br />PORTA |=0x07; //ustawienie jedynki na pierwszych 3 bitach<br />j=0;<br /><br />while(j&lt;2)<br />{<br />for (k=0 ; k&lt;=2; k++) // zmienic do 3 gdy ostatni rzadek zacznie dzialac<br />{<br />PORTA ^= (1&lt;&lt;k); //ustawienie zera na linii<br />_delay_ms(5);<br /><br />for(n=1;n&lt;=3;n++) //sprawdzenie kolumn (wejsc)<br />{<br />if(bit_is_clear(PINA,n+4)) <br />{<br />cyfra&#91;j&#93;=n+(k*3); <br />j++; <br /><br />if (j==1) //po wcisnieciu pierwszej cyfry pojawi sie ona na wyswietlaczu :<br />{ <br />PORTC = (1&lt;&lt;1); //wlaczenie pierwszego segmentu<br />PORTD = (cyfra&#91;0&#93;&lt;&lt;4); //wyswietlanie pierwszej cyfry<br />_delay_ms(500); /*opoznienie zeby nie chwycilo dwa razy jednego wcisniecia*/<br />}<br />else <br />{<br />TCNT1 = 0;<br />TIFR = (1&lt;&lt;OCF1A); //zerowanie przez wpisanie jedynki<br />while(!(TIFR &amp; (1&lt;&lt;OCF1A))/*dopuki nie ma flagi*/) {wysw(cyfra);}<br />}<br /><br />}<br />}<br /><br />PORTA ^= (1&lt;&lt;k); //ustawienie jedynki na linii<br />}<br />}<br /><br /><br />PORTA &amp;= ~0x07; // ponowne ustawienie zer na wszyzstkich liniach<br />}<br /><br /><br />int main(void)<br />{<br /><br />DDRD=0xff; //wyswietlacz 7 seg<br />DDRC=0x03; //zasilanie wyswietlacza 7 seg<br />DDRA=0x1f; //4 pierwsze piny to wyjscia klawiatury, 3 ostatnie piny to wejscia<br />PORTA=0xef; //ustawienie podciagniecia do VCC<br /><br />TCCR1B |= (1&lt;&lt;CS11) | (1&lt;&lt;CS10) | (1&lt;&lt;WGM12); //tryb ctc, fcpu/64<br />OCR1A = 7812; // 1/2 sek<br /><br />unsigned char cyfra&#91;2&#93;={6,9};<br />PORTA &amp;= ~0x07;<br />/*obecnie na wszystkich liniach wejsc sa zera zeby wcisniecie ktoregokolwiek przycisku wywolalo funkcje,<br />to ktory przycisk konkretnie zostal wcisniety zostanie okreslone w funkcji wciskaj*/<br /><br />while (1)<br />{<br />wysw(cyfra);<br /><br />if( (~PINA &amp; 0xe0) ) //sprawdzenie czy na ktorejkolwiek kolumnie pojawilo sie 0<br />{<br />wciskaj(cyfra);<br />}<br /><br />}<br /><br /><br />}[/syntax]<br /><br />Gdy zamiast tej pętli sprawdzającej flagę czy timer już się przepełnił :<br />[syntax=c]TCNT1 = 0;<br />TIFR = (1&lt;&lt;OCF1A); //zerowanie przez wpisanie jedynki<br />while(!(TIFR &amp; (1&lt;&lt;OCF1A))/*dopuki nie ma flagi*/) {wysw(cyfra);}[/syntax]<br /><br />wykorzystam pętlę która działa dopóki nie wystąpi przerwanie, to wszystko się sypie :<br />[syntax=c]TCNT1 = 0; <br />koniec = 0;<br />sei(); //globalne zezwolenei na przerwania, cli cofa zezwolenie<br /><br />while(koniec==0) {wysw(cyfra);} //wyjscie z tej petli nastapi pzrez przerwanie<br /><br />cli();[/syntax]<br /><br />zmienna koniec jest zmieniana w przerwaniu na =1 żeby wyjść z pętli, oczywiście dopisałem do jej definicji volatile<br /><br /><br />Cały kod z przerwaniem :<br />[syntax=c]#define F_CPU 1000000L<br />#include &lt;avr/io.h&gt;<br />#include &lt;util/delay.h&gt;<br />#include &lt;avr/interrupt.h&gt; //zaladowanie obslugi przerwan<br /><br />volatile unsigned char koniec; <br /><br />unsigned char cyfra&#91;2&#93;={6,9};<br /><br /><br /><br />void wysw(unsigned char tablica&#91;&#93;) //funkcja obslugujaca wyswietlacz 7 seg<br />{<br />// pierwsza cyfra/segment<br />PORTC = (1&lt;&lt;1);<br />PORTD = (tablica&#91;0&#93;&lt;&lt;4);<br />_delay_ms(5);<br />// droga cyfra/segment<br />PORTC = (1&lt;&lt;0);<br />PORTD = (tablica&#91;1&#93;&lt;&lt;4); //wyswietlanie wcisnietej cyfry<br />_delay_ms(5);<br />}<br /><br /><br /><br /><br />void wciskaj(unsigned char cyfra&#91;&#93;) //wywolywana po wcisnieciu jakiegos klawisza<br />{<br />unsigned char n,j,k;<br /><br />PORTC = 0x00; //wylaczenie wyswietlacza<br />PORTA |=0x07; //ustawienie jedynki na wszystkich 3 liniach klawiatury<br />j=0;<br /><br />while(j&lt;2)<br />{<br />for (k=0 ; k&lt;=2; k++) // zmienic do 3 gdy ostatni rzadek zacznie dzialac<br />{<br />PORTA ^= (1&lt;&lt;k); //ustawienie zera na linii<br />_delay_ms(5);<br /><br />for(n=1;n&lt;=3;n++) //sprawdzenie kolumn (wejsc)<br />{<br />if(bit_is_clear(PINA,n+4)) <br />{<br />cyfra&#91;j&#93;=n+(k*3); <br />j++; <br /><br />if (j==1) //po wcisnieciu pierwszej cyfry pojawi sie ona na wyswietlaczu :<br />{ <br />PORTC = (1&lt;&lt;1); //wlaczenie pierwszego segmentu<br />PORTD = (cyfra&#91;0&#93;&lt;&lt;4); //wyswietlanie pierwszej cyfry<br />_delay_ms(500); /*opoznienie zeby nie chwycilo dwa razy jednego wcisniecia*/<br />}<br />else <br />{<br />TCNT1 = 0; //bo nie wiadomo jaka wartosc moze miec w tej chwili<br />koniec = 0;<br />sei(); //globalne zezwolenei na przerwania, cli cofa zezwolenie<br /><br />while(koniec==0) {wysw(cyfra);} //wyjscie z tej petli nastapi pzrez przerwanie<br /><br />cli(); //zeby przerwania niepotrzebnie nie wystepowaly w trakcie glownego programu i szukania przyciskow<br />}<br /><br />}<br />}<br /><br />PORTA ^= (1&lt;&lt;k); //ustawienie jedynki na linii<br />}<br />}<br /> <br />PORTA &amp;= ~0x07; // ponowne ustawienie zer na wszyzstkich liniach<br /><br />}<br /><br /><br /><br />ISR (TIMER1_COMPA_vect)<br />{<br />koniec = 1;<br />}<br /><br /><br /><br /><br />int main(void)<br />{<br /><br />DDRD=0xff; //wyswietlacz 7 seg<br />DDRC=0x03; //zasilanie wyswietlacza 7 seg<br />DDRA=0x1f; //4 pierwsze piny to wyjscia klawiatury, 3 ostatnie piny to wejscia<br />PORTA=0xef; //ustawienie podciagniecia do VCC<br /><br />TCCR1B |= (1&lt;&lt;CS11) | (1&lt;&lt;CS10) | (1&lt;&lt;WGM12); //tryb ctc, fcpu/64<br />OCR1A = 7812; // 1/2 sek<br />TIMSK |= (1&lt;&lt;OCIE1A); //wlaczenie przerwan od porownania A<br /><br />PORTA &amp;= ~0x07;<br />/*obecnie na wszystkich liniach wejsc sa zera zeby wcisniecie ktoregokolwiek przycisku wywolalo funkcje,<br />to ktory przycisk konkretnie zostal wcisniety zostanie okreslone w funkcji wciskaj*/<br /><br />while (1)<br />{<br />wysw(cyfra);<br /><br />if( (~PINA &amp; 0xe0) ) //sprawdzenie czy na ktorejkolwiek kolumnie pojawilo sie 0<br />{<br />wciskaj(cyfra);<br />}<br /><br />}<br /><br /><br />}[/syntax]<br /><br /><br /><br />Konfiguracja timera jest dokładnie ta sama, tyle że dochodzi uruchomienie przerwań przez TIMSK oraz sei().<br /><br />Wskazywana powyżej pętla while(koniec==0) albo w ogóle się nie wykonuje, albo trwa zdecydowanie krócej niż 0,5 sekundy przez które powinna, zanim pojawi sie przerwanie (nie jestem tego w stanie określić na oko <img src="https://forum.atnel.pl/images/smilies/icon_razz.gif" alt=":P" title="Pokazuje język" />)<br /><br />Naprawdę doprowadza mnie to do białej gorączki, jeżeli pomnożę OCR1A = 7812 razy np 4 (czyli timer liczy do 2 sek) to pętla raz działa dobrze a raz znowu zachowuje się jakby przerwanie występowało po ułamku sekundy. <br /><br />Co jest nie tak ?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=1518">oseri</a> — 27 lip 2013, o 15:46</p><hr />
]]></content>
</entry>
</feed>