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

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2016-05-12T08:07:27+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=4&amp;t=15363&amp;mode</id>
<entry>
<author><name><![CDATA[JungleMan]]></name></author>
<updated>2016-05-12T08:07:27+01:00</updated>
<published>2016-05-12T08:07:27+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=15363&amp;p=160492#p160492</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=15363&amp;p=160492#p160492"/>
<title type="html"><![CDATA[Odbiór bajtów za pomocą UART'a programowego]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=15363&amp;p=160492#p160492"><![CDATA[
Dzień dobry.<br />Wiem, że temat omawiany w szerokim zakresie. ale chciałem zrobić to sam i niestety jest pewien problem.<br />Program wykonuję na ATmega 1284, chcę odebrać bajty z modułu GPS/GLONASS. Wcześniej udało mi się to zrobić za pomocą hardware'u, jednakże teraz chciałbym skorzystać ze sleep mode'ów i potrzebuję wybudzania na bit UART'a.<br />Do problemu podszedłem w taki sposób, że na początku czekam na zbocze opadające (początek bitu startu) i włączam Timer. Timer liczy ile bitów przeminęło (częstotliwość ustawiona na ~9600Hz) i program czeka na zbocze narastające. Inicjalizuję licznik odebranych bitów wartością -1, aby zignorować bit startu i nie interpretować go jako bit danych. Zastosowałem taki trik, że jeżeli zbocze pojawiło się tuż przed przerwaniem Timer'a to sprawdzam, czy wartość rejestru TCNT jest większa niż 0.9 * OCR (czyli bliskie jest przerwanie z Timer'a). W zależności od zbocza ustawiam bity odebrane: jeżeli stan na pinie wynosi jeden to znaczy, że ostatnie zbocze było narastające i odebrano ostatnio logiczne jedynki; analogicznie dla stanu pinu wynoszącemu zero. Wykrycie całego bajtu zachodzi podczas, gdy zostało wykryte początkowe zbocze bitu stopu lub gdy w przerwaniu Timer'a zostaną naliczone 8 bajtów. Wykrycie zachodzi w przerwaniu Timer'a, gdy ostatni bit danych był logicznym 0.<br /><br />Kod programu:<br />uart.h:<br />[c]<br />#define UART_BAUD_RATE 9600.0<br /><br />/*To change prescaling additional updates in Timer2_init function should be added,<br />according to datasheet.*/<br />#define UART_PRESCALER 8.0<br /><br />#define UART_RX_PIN PD0<br /><br />#define UART_RX_PIN_STATE (PIND &amp; (1&lt;&lt;UART_RX_PIN))<br /><br />#define OCR_UART_CONTENT ((float)F_CPU / UART_PRESCALER / UART_BAUD_RATE + 0.5)<br /><br />#define NEXT_RX_BIT_GATE (0.9 * OCR_UART_CONTENT)<br /><br />#define UART_NUM_DATA_BITS 8<br /><br />#define GENERATE_SOFT_INT (PORTB |= (1&lt;&lt;PB2))<br /><br />inline void Timer2_start() {<br />TCNT2 = 0;<br />TIMSK2 |= (1&lt;&lt;OCIE2A);//Allow interrupt in CTC mode<br />}<br /><br />inline void Timer2_stop() {<br />TIMSK2 &amp;= ~(1&lt;&lt;OCIE2A);//Forbid interrupt in CTC mode<br />TCNT2 = 0;<br />}<br /><br />// RXD0 corresponds to PCINT24 pin, so any hardware change is needed.<br />inline void UART_init() {<br />DDRD &amp;= ~(1&lt;&lt;UART_RX_PIN);<br />PORTD |= (1&lt;&lt;UART_RX_PIN);//PD0 - RXD0 - PCINT24 pin as input - VCC pull up.<br />PCICR |= (1&lt;&lt;PCIE3);//Enable pin change interrupt on PCINT31:24 pins.<br />PCMSK3 |= (1&lt;&lt;PCINT24);//Enable pin change interrupt PCINT24 pin.<br /><br />/*Set PB2 (INT2 pin) as output to generate software interrupt, to move received bytes handling <br />on other level of application.*/<br />DDRB |= (1&lt;&lt;PB2);<br />EICRA |= (1&lt;&lt;ISC21) | (1&lt;&lt;ISC20);//Set rising edge triggering software interrupt.<br />EIMSK |= (1&lt;&lt;INT2);//Enable interrupt generated by INT2 pin.<br />}<br /><br />//Timer 2 is used to count bits in frame.<br />void Timer2_init();[/c]<br /><br />uart.c:<br />[c]//Counter of received bits of the same value.<br />volatile uint8_t cycles_not_int = 0xFF;<br /><br />volatile uint8_t bits_rec_cnt;<br />volatile uint8_t byte_rec;<br /><br />void Timer2_init() {<br />TCCR2A |= (1&lt;&lt;WGM21);// CTC mode<br />TCCR2B |= (1&lt;&lt;CS21);// Prescaler F_CPU/8<br />OCR2A = OCR_UART_CONTENT;// 8000000/8/9600 = 104,1(6)<br />TCNT2 = 0;<br />}<br /><br />ISR(PCINT3_vect) {<br />//Firstly read TCNT content to avoid inconsistency.<br />uint8_t TCNT_content = TCNT2;<br /><br />//If TCNT content is almost equal OCR content it is understood, that next bit was received. <br />cycles_not_int += (TCNT_content &gt; NEXT_RX_BIT_GATE ? 1 : 0);<br /><br />//Start period count timer, when start bit's falling edge detected.<br />if(cycles_not_int == 0xFF) {<br />Timer2_start();<br />return;<br />}<br /><br />//No negation needed, because logical one corresponds to GND voltage level (zero - VCC).<br />if(UART_RX_PIN_STATE) byte_rec |= ((1 &lt;&lt; cycles_not_int) - 1) &lt;&lt; bits_rec_cnt;<br /><br />bits_rec_cnt += cycles_not_int;<br />cycles_not_int = 0;<br /><br />if(bits_rec_cnt == UART_NUM_DATA_BITS) {<br />Timer2_stop();<br />bits_rec_cnt = 0;<br />cycles_not_int = 0xFF; //Initialized with '-1', to avoid interpreting start bit as data bit.<br />uart_byte_rec = byte_rec;<br />byte_rec = 0;<br />GENERATE_SOFT_INT;<br />return;<br />}<br /><br />//Clear TCNT register.<br />TCNT2 = 0;<br />}<br /><br />ISR(TIMER2_COMPA_vect) {<br />//1 bit period ended<br />cycles_not_int ++;<br /><br />//When last bit was logic zero.<br />if(bits_rec_cnt + cycles_not_int == UART_NUM_DATA_BITS &amp;&amp; UART_RX_PIN_STATE) {<br />Timer2_stop();<br />cycles_not_int = 0xFF;<br />bits_rec_cnt = 0;<br />uart_byte_rec = byte_rec;<br />byte_rec = 0;<br />GENERATE_SOFT_INT;<br />}<br />}[/c]<br /><br />Przy odebraniu pełnego bajtu generuję przerwanie programowe, w którym następuje obsługa danych na poziomie bajtów (wyłuskiwanie odpowiednich danych z tekstu).<br /><br />Problem polega na tym, że dostaję &quot;krzaki&quot; i wydaje mi się, że bajtów odbieram mniej niż powinienem, czyli tak jakby nie wykrywane były wszystkie zbocza lub przerwania Timer'a były w nie odpowiednim momencie.<br /><br />Wykonałem testy:<br />[c]ISR(PCINT3_vect) {<br /><br />uint8_t TCNT_content = TCNT2;<br /><br />//cycles_not_int += (TCNT_content &gt; NEXT_RX_BIT_GATE ? 1 : 0);<br /><br />x_itoa_u8((char *)data[i_data], TCNT_content);<br />x_itoa_u8((char *)&amp;data[i_data][4], cycles_not_int);<br />data[i_data][8] = UART_RX_PIN_STATE + 48;<br />i_data = (i_data + 1) % 254;<br /><br />cycles_not_int = 0;<br /><br />TCNT2 = 0;<br />}<br /><br />ISR(TIMER2_COMPA_vect) {<br />//1 bit period ended<br />cycles_not_int ++;<br />}[/c]<br /><br />Ustawiłem Timer2 na częstotliwość 8000000/256 = 31250 Hz:<br />[c]void Timer2_init() {<br />TCCR2A |= (1&lt;&lt;WGM21);// CTC mode<br />TCCR2B |= (1&lt;&lt;CS20);// Prescaler no<br />OCR2A = 255;<br />TIMSK2 |= (1&lt;&lt;OCIE2A);<br />}[/c]<br /> i przy każdym zboczu zapisywałem ile minęło od ostatniego zbocza; to są wyniki:<br />[c]203 001 0<br />002 004 1<br />202 001 0<br />053 007 1<br />000 004 0<br />202 001 1<br />203 001 0<br />000 004 1<br />204 001 0<br />088 008 1<br />227 004 0<br />202 001 1<br />202 001 0<br />001 004 1<br />204 001 0<br />088 008 1<br />225 004 0<br />202 001 1<br />202 001 0<br />002 004 1<br />204 001 0<br />001 004 1<br />000 004 0<br />203 001 1<br />002 004 0<br />002 004 1<br />202 001 0<br />026 007 1<br />202 001 0<br />001 004 1<br />203 001 0<br />201 001 1<br />088 008 0<br />023 007 1<br />203 001 0<br />203 001 1<br />203 001 0<br />162 014 1<br />202 001 0<br />203 001 1<br />203 001 0<br />203 001 1<br />201 001 0<br />203 001 1<br />088 008 0<br />026 007 1<br />204 001 0<br />203 001 1<br />203 001 0<br />087 008 1<br />226 004 0<br />001 004 1<br />203 001 0<br />203 001 1<br />203 001 0<br />088 008 1<br />226 004 0<br />004 004 1<br />204 001 0<br />203 001 1<br />203 001 0<br />088 008 1<br />226 004 0<br />203 001 1<br />201 001 0<br />001 004 1<br />202 001 0<br />088 008 1<br />226 004 0<br />201 001 1<br />202 001 0<br />001 004 1<br />203 001 0<br />088 008 1<br />227 004 0<br />203 001 1<br />203 001 0<br />002 004 1<br />203 001 0<br />088 008 1<br />226 004 0<br />202 001 1<br />204 001 0<br />203 001 1<br />201 001 0<br />001 004 1<br />202 001 0<br />202 001 1<br />201 001 0<br />255 004 1<br />088 008 0<br />220 004 1<br />203 001 0<br />000 004 1<br />053 007 0<br />203 001 1<br />203 001 0<br />255 004 1<br />203 001 0<br />202 001 1<br />202 001 0<br />255 004 1<br />053 007 0<br />001 004 1<br />203 001 0<br />203 001 1<br />203 001 0<br />000 004 1<br />088 008 0<br />226 004 1<br />202 001 0<br />001 004 1<br />203 001 0<br />201 001 1<br />202 001 0<br />203 001 1<br />203 001 0<br />255 004 1<br />204 001 0<br />201 001 1<br />001 004 0<br />000 004 1<br />002 004 0<br />001 004 1<br />202 001 0<br />165 014 1<br />001 004 0<br />001 004 1<br />203 001 0<br />201 001 1<br />201 001 0<br />203 001 1<br />001 004 0<br />107 011 1<br />203 001 0<br />001 004 1<br />200 001 0<br />203 001 1<br />243 001 0<br />088 011 1<br />204 001 0<br />253 004 1<br />203 001 0<br />201 001 1<br />202 001 0<br />001 004 1<br />087 008 0<br />223 004 1<br />203 001 0<br />202 001 1<br />200 001 0<br />000 004 1<br />053 007 0<br />001 004 1<br />203 001 0<br />088 008 1<br />228 004 0<br />203 001 1<br />204 001 0<br />002 004 1<br />201 001 0<br />203 001 1<br />203 001 0<br />000 004 1<br />087 008 0<br />226 004 1<br />203 001 0<br />201 001 1<br />202 001 0<br />000 004 1<br />053 007 0<br />255 004 1<br />201 001 0<br />255 004 1<br />088 008 0<br />169 001 1<br />201 001 0<br />001 004 1<br />203 001 0<br />203 001 1<br />203 001 0<br />001 004 1<br />087 008 0<br />226 004 1<br />203 001 0<br />203 001 1<br />205 001 0<br />001 004 1<br />087 008 0<br />226 004 1<br />203 001 0<br />088 008 1<br />227 004 0<br />202 001 1<br />202 001 0<br />001 004 1<br />203 001 0<br />203 001 1<br />203 001 0<br />087 008 1<br />225 004 0<br />203 001 1<br />201 001 0<br />002 004 1<br />202 001 0<br />001 004 1<br />088 008 0<br />226 004 1<br />203 001 0<br />201 001 1<br />205 001 0<br />001 004 1<br />203 001 0<br />203 001 1<br />203 001 0<br />203 001 1<br />204 001 0<br />004 004 1<br />203 001 0<br />004 004 1<br />004 004 0<br />204 001 1<br />003 004 0<br />005 004 1<br />203 001 0<br />091 008 1<br />172 001 0<br />204 001 1<br />002 004 0<br />003 004 1<br />203 001 0<br />205 001 1<br />204 001 0<br />204 001 1<br />001 004 0<br />113 011 1<br />204 001 0<br />004 004 1<br />203 001 0<br />203 001 1<br />203 001 0<br />113 011 1<br />203 001 0<br />255 004 1<br />088 008 0<br />223 004 1<br />202 001 0<br />202 001 1<br />203 001 0<br />001 004 1<br />087 008 0<br />225 004 1<br />202 001 0<br />000 004 1<br />088 008 0<br />025 007 1<br />204 001 0<br />202 001 1<br />201 001 0<br />088 008 1<br />225 004 0<br />000 004 1<br />202 001 0<br />203 001 1<br />202 001 0<br />088 008 1<br />222 004 0<br />002 004 1<br />202 001 0<br />202 001 1<br />203 001 0<br />088 008 1<br />223 004 0<br />201 001 1<br />202 001 0<br />002 004 1<br />201 001 0<br />088 008 1<br />225 004 0<br />202 001 1<br />204 001 0<br />002 004 1<br />202 001 0<br />089 008 1<br />224 004 0<br />203 001 1<br />202 001 0<br />004 004 1<br />202 001 0<br />088 008 1<br />227 004 0<br />202 001 1<br />202 001 0<br />001 004 1<br />202 001 0<br />088 008 1<br />222 004 0<br />202 001 1<br />202 001 0<br />001 004 1<br />204 001 0<br />088 008 1<br />221 004 0<br />203 001 1<br />203 001 0<br />004 001 1<br />202 001 0<br />255 004 1<br />201 001 0<br />203 001 1<br />201 001 0<br />255 004 1<br />053 007 0<br />254 004 1<br />202 001 0<br />203 001 1<br />201 001 0<br />001 004 1<br />053 007 0<br />253 004 1<br />202 001 0<br />255 004 1<br />203 001 0<br />202 001 1<br />202 001 0<br />202 001 1<br />202 001 0<br />000 004 1<br />203 001 0<br />201 001 1<br />001 004 0<br />255 004 1<br />001 004 0<br />254 004 1<br />201 001 0<br />161 014 1<br />255 004 0<br />001 004 1<br />202 001 0<br />203 001 1<br />200 001 0<br />202 001 1<br />001 004 0<br />107 011 1<br />203 001 0<br />254 004 1<br />202 001 0<br />201 001 1<br />201 001 0<br />108 011 1<br />203 001 0<br />088 008 1<br />168 001 0<br />254 004 1<br />202 001 0<br />255 004 1<br />202 001 0<br />202 001 1<br />051 007 0<br />052 007 1<br />202 001 0<br />201 001 1<br />201 001 0<br />158 014 1<br />202 001 0<br />203 001 1<br />200 001 0<br />202 001 1<br />203 001 0<br />002 004 1<br />203 001 0<br />203 001 1<br />201 001 0<br />001 004 1<br />088 008 0<br />226 004 1<br />203 001 0<br />201 001 1<br />205 001 0<br />001 004 1<br />088 008 0<br />226 004 1<br />203 001 0<br />001 004 1<br />088 008 0<br />246 001 1<br />131 001 0<br />004 004 1<br />202 001 0<br />205 001 1<br />202 001 0<br />005 004 1<br />087 008 0<br />232 004 1<br />203 001 0<br />204 001 1<br />204 001 0<br />003 004 1<br />087 008 0<br />229 004 1<br />204 001 0<br />088 008 1<br />232 004 0<br />204 001 1<br />203 001 0<br />005 004 1<br />203 001 0<br />203 001 1<br />204 001 0<br />002 004 1<br />088 008 0<br />225 004 1<br />203 001 0<br />201 001 1<br />202 001 0<br />001 004 1<br />223 004 0<br />202 001 1<br />161 001 0<br />009 004 1<br />007 004 0<br />006 004 1<br />009 004 0<br />006 004 1<br />206 001 0<br />088 008 1<br />238 004 0<br />207 001 1<br />205 001 0<br />007 004 1<br />207 001 0<br />089 008 1<br />240 004 0<br />206 001 1<br />206 001 0<br />006 004 1<br />208 001 0<br />088 008 1<br />239 004 0<br />205 001 1<br />206 001 0<br />007 004 1<br />205 001 0<br />006 004 1<br />206 001 0<br />009 004 1<br />006 004 0<br />008 004 1<br />205 001 0<br />123 011 1<br />088 008 0<br />240 004 1<br />207 001 0<br />006 004 1<br />206 001 0<br />207 001 1<br />205 001 0<br />206 001 1<br />206 001 0<br />005 004 1<br />205 001 0<br />205 001 1<br />087 008 0<br />184 001 1<br />008 004 0<br />006 004 1<br />205 001 0<br />207 001 1<br />204 001 0<br />088 008 1<br />238 004 0<br />006 004 1<br />206 001 0<br />207 001 1<br />205 001 0<br />206 001 1<br />008 004 0<br />121 011 1<br />205 001 0<br />205 001 1<br />[/c]<br />Lewa kolumna to odczytana wartość rejestru TCNT, środkowa wartość to wartość cycles_not_int a prawa kolumna to stan pinu.<br />Widać, że jest tu jakiś determinizm. Gdy wziąłem powtarzające się wiersz i obliczyłem czasy pomiędzy kolejnymi zboczami, wyszło mi, że wynoszą one 57.25, 128, 227.25, 267, 366.125 [us]. Nie rozumiem dlaczego nie ma tu wartości wielokrotności 104us, czyli 1/9600 (baud rate).<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=3945">JungleMan</a> — 12 maja 2016, o 08:07</p><hr />
]]></content>
</entry>
</feed>