ATtiny4313 - příklad programu pro USART, hodnota UDR

Mohl by mi někdo ze znalejšís poradit s tímto problémem?

Příkazy
i=0;
do
{while((UCSRA&(1<<RXC))==0){};
prijato*=UDR;
i++;


}
while i<10

fungují, tak jak jsem očekával.

Zato příkazy
i=0;
do
{
prijato*=UDR;
i++;


}
while((UCSRA&(1<<RXC))==1);
nefungují ani náhodou, včetně různých modifikací. Vypadá to, že bit RXC se nechová tak jak se píše v dokumentaci, anebo dokumentaci vůbec nerozumím, což je asi pravděpodobnější.

Díky

:arrow_right: administrator: přejmenováno z “ATTINY4313 versus USART”**

To samé jako první uvedené příkazy, akorád by nevznikla nekonečná smyčka.

A ty si jako myslíš že výraz >> prijato*=UDR << ví kdy příjde nějaký byte po sériáku a že se má vokopírovat do toho pole ? :slight_smile:*

(UCSRA&(1<<RXC) není nikdy 1 (protože RXC není nultý bit v registru UCSRA.
Je třeba použít buď

while(UCSRA & (1<<RXC));

nebo

while((UCSRA & (1<<RXC)) != 0);

Pokud v uartu není žádný přijatý znak, je hodnota v UDR nula.

i=0; do { prijato*=UDR; i++; .... .... } while((UCSRA&(1<<RXC))!=0);
Tento kód přečte a uloží UDR ať je v něm přijatý znak nebo ne.
Pokud nebyl přijatý znak (RXC=0), opustí while().
Pokud byl přijatý znak, tak po jeho přečtení se RXC vynuluje a opět opustí smyčku dřív než se stačí přijmout případný další znak.

Pokud nechceš aby byl procesor blokovaný čekáním na znak, tak použij

while(1) // hlavní smyčka { if(UCSRA & (1<<RXC)) { prijato* = UDR; i++; } ... ... }
Další možnost je použít přerušení při příjmu znaku.**

To, že (UCSRA&(1<<RXC) není nikdy 1 (protože RXC není nultý bit v registru UCSRA jsem už též pochopil a zkusil jsem tedy toto:

i=0;
while((UCSRA&(1<<RXC))
{
prijato*=UDR;
i++;
delay_ms(xxx);

}

Tento kód se však chová velmi podivně. Do prijato uloží pouze 3 znaky ať je příjmaný řetezec jakkoli dlouhý. Pokud je délka pouze 3 znaky přijmou se správně, pokud je délka přij.řetězce delší, přijmou se první 2 znaky a potom až ten poslední!!! Délka vloženého zpoždění na to nemá vliv.

Bohužel, ze všech pokusů mi zatím funguje jen příkaz
while((UCSRA&(1<<RXC))=0){}; na tom se ale program zasekne jakmilele se přijme celý řetězec.
{*

No je to preto, ze sa obe struktury chovaju principialne inak

Ta prva najprv naozaj caka, kym sa prijme bajt, az potom ho ulozi a az potom caka na dalsi bajt. Ten druhy kod sa naozaj moze spravat nevyspytatelne.

Prvy kod caka na prijem prave 10 bajtov. Pokial ich neprijme, ostane v slucke vysiet. Ten druhy sa uz s poctom prijatych bajtov moc nezapodieva a viac menej si moze robit skoro hocico.

Napriklad podmienka


#define KONCOVY_ZNAK 0x0d // napriklad
#define UVODNY_ZNAK ':'     // napriklad
#define MAX_BUFER 100
static uint8_t prijato[MAX_BUFER], i;


i = 0;
do
{while((UCSRA&(1<<RXC))==0){};
   prijato*=UDR;
   if (prijato[0] == UVODNY_ZNAK) i++;
}
while ((i<MAX_BUFER) && (prijato* != KONCOVY_ZNAK))

if (prijato* == KONCOVY_ZNAK) {
// dobre ukoncena sprava
}
else {
// nejaka blbost sposobila pretecenie bufera
}

by mohla byt omnoho funkcnejsia. Ale neskusal som.
Samozreje do tej podmienky prijmu bajtu sa este da zakomponovat timeout. A pre dany kod je uplne normalne, ze ked raz pride do bodu

while((UCSRA&(1<<RXC))==0){};

tak tam ostane visiet az do skonania svetov, pokial mu medzitym nejaky bajtik nepride.***

Jestli nechceš aby se zasekl, použij něco takového:

[code]main()
{
unsigned char i;

while(1)
{
if(UCSRA & (1<<RXC)) // jestli RXC=1
{
for(i=0;i<10;i++)
{
while((UCSRA & (1<<RXC))==0); // čekej až RXC bude 1
prijato* = UDR;
}
}



}
}
[/code]

Snaž se porozumět co se v kódu děje.

Pokud v uart není přijatý znak, RXC je nula (a v UDR je 0).
Po přijetí znaku se RXC nastaví na 1 a v UDR je přijatý znak.
Jakmile přečteme přijatý znak ( prijato* = UDR;), RXC se hned znovu vynuluje (a UDR také).**

Testování počátečního a koncového bitu jsem se chtěl vyhnout, neboť to o co se pokouším by mělo analyzovat přijatou SMS a u té testovat počátek a konec bude trochu obtížnější protože její přesný formát nebudu schopen zajistit. Nicméně vyzkoušel jsem si následunící kód. Cování je opět trochu nevyzpytatrlné.

while(1)
{
j=strlen(temp);
for(i=0;i<j;i++)temp*=0;
for(i=0;i<7;i++)znak*=0;
k=0;j=0;
for(i=0;i<7;i++)
{ while((UCSRA&(1<<RXC))==0){}
{
znak*=UDR;
k=i+48;
}
if(znak*==’’) break;
}
//odsud
strcat(temp,znak);
delay_ms(100);
Lcd_Out(1,1,znak);
delay_ms(2000);
Lcd_Out(2,1,&k);
delay_ms(2000);
// sem
if(pind6_bit==1)
{ j=strlen(temp);
for(i=0;i<j;i++)
{
while((UCSRA & (1<<UDRE))==0){};
UDR=temp
;
delay_ms(100);
}
}

Pokud se provede příkaz break tak zbytek programu proběhne OK.
Pokud ovšem se cyklus for řádně ukončí, příkazy mezi odtud - sem se neprovedou a program se zablokuje na konci po odeslání temp*.

Ať ten fragment kontroluji sem tam nemohu najít důvod podivného chování. Jestli se něčeho všimnete, budu rád za upozornění.******

Používej tlačítko Code.

Kludne si ten svoj kod odkrokuj v AVR simulatore, snad Ti to pomoze.

Jestli máš na mysli simulátor v AVR Studiu, tak to kupodivu odkrokuje bez problémů a simulátor v mém překladači taktéž.