Stránka 1 z 2

ATTINY4313 versus USART

Napsal: 10 led 2014, 14:09
od epes
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[i]=UDR;
i++;
....
....
}
while i<10

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

Zato příkazy
i=0;
do
{
prijato[i]=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

Napsal: 10 led 2014, 14:36
od FHonza
Kvůli buferování se musí číst USCRA před čtením UDR. V té nefunkční části to máš přesně přesně obráceně, proto to nefunguje. Čtením registru UDR dojde k vynulování příznaku RXC.

Napsal: 10 led 2014, 14:44
od epes
Díky za radu.
Ale!!! jeden z mých pokusů vypadal takto:

while((UCSRA&(1<<RXC))==1);
{ ...
PRIJATO(I)=UDR
...
i++;
}

a nefungoval též. Raději to jdu zkusit znovu a dám vědět.
Díky

Napsal: 10 led 2014, 15:01
od FHonza
Správně je to takhle (dle datasheetu):

Kód: Vybrat vše

unsigned char USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSRA & (1<<RXC)) )
;
/* Get and return received data from buffer */
return UDR;
}


Musíš testovat výsledek na (ne)nulovost, ne na jedničku. Bit RXC je v byte UCSRA 7. bit. Takže když je nastaven, je výsledkem (UCSRA & (1 << RXC)) == 0b10000000. A ne 0b00000001.

Dobře je jenom ten tvůj první příklad, ostatní nemůžou fungovat.

Napsal: 10 led 2014, 15:08
od epes
Ajaj, tak to je ono! Teď už to vidím i já. Ještě bych se zeptal je-li možné testovat pouze bit RCX. Zkoušel jsem to, ale test byl vždy kladný i po přečtení UDR, což by být neměl.
Díky

Napsal: 10 led 2014, 15:18
od AB1
je-li možné testovat pouze bit RCX. Zkoušel jsem to, ale test byl vždy kladný i po přečtení UDR,

A jak jsi ho testoval?

Napsal: 10 led 2014, 15:30
od FHonza
Testovat RCX lze donekonečna, nuluje se jenom přečtením UDR. Ale opravdu musíš testovat jenom tento bit. Máš-li i zapnut vysílač, tak je v registru UCSRA nahozen i bit UDRE, který indikuje že vysílací buffer je prázdný. Takže test (UCSRA != 0) je špatně.
Správně jedině
(UCSRA & (1<<RXC)) != 0
nebo (zbytečně složitě)
(UCSRA & (1<<RXC)) == (1 << RXC)

Napsal: 10 led 2014, 15:46
od AB1
V avr-gcc můžeš použít (snad) srozumitelnější

Kód: Vybrat vše

  if(bit_is_set(UCSRA,RXC))            //jestliže bit = 1
  if(bit_is_clear(UCSRA,RXC))
  loop_until_bit_is_set(UCSRA,RXC);    //čekej až bit bude 1
  loop_until_bit_is_clear(UCSRA,RXC);

Napsal: 10 led 2014, 16:21
od epes
Tak to můj kompilátor neumí a jak postupně zjišťuji, neumí toho víc. Zase má pjřívětivé IDE. Holt něco za něco.
V každé, případě díky za rady.

Napsal: 10 led 2014, 16:28
od FHonza
a jaký používáš překladač ?

Napsal: 10 led 2014, 18:53
od epes
překladač se jmenuje Mikro C PRO od "jugoslávské" fy Mikroelektronika.

Napsal: 11 led 2014, 11:00
od epes
Přes noc jsem vyzkoušel nově nabyté a poznatky a bohužel jsem přesně tam, kde jsem byl včera. Zkusil jsem třeba toto:

i=0;
while((UCSRA&(1<<RXC))
{
prijato[i]=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.
{

Napsal: 13 led 2014, 12:49
od FHonza
Zkus ještě napsat jak USART inicializuješ a jak máš nastaveny parametry přenosu. Zda jde o (a)synchronní komunikaci. Zkontroluj také jestli není příliš rozdílná rychlost přijímaného signálu a vnitřního generátoru přenosové rychlosti (jak nastavuješ UBRR a jaký je kmitočet uPC). Zvláště u asynchronního režimu je rozdíl rychlostí poměrně kritický a určitě by neměl být vyšší jak 3% - nefunguje pak rekonstrukce hodin. Posuvný registr přijímače je tříúrovňový, takže přijaté tři znaky na něco takového možná ukazují.
Pak také testuj příznaky chyb z registu USCRA (nulují se čtením UDR). Hlavně příznak ztráty znaku DOR.

...zatím funguje jen příkaz
while((UCSRA&(1<<RXC))=0){};...

ti chybí jedno =

Napsal: 13 led 2014, 16:26
od Ruprecht
98% chyb sériové komunikace je způsobeno špatnou rychlostí. Hodiny procesoru jsou z krystalu? Zvolená rychlost komunikace (stejná na obou stranách) má při daném krystalu nulovou chybu?

Napsal: 14 led 2014, 08:54
od epes
ATTINY pracuje s frekvencí 8MHz, přenosovou rychlost jsem dle dokumentace zvolil 9600 - teoreticky 0% chybovost.
Nastavení USART je toto:

Kód: Vybrat vše

 BAUD=(((8000000 / (9600 * 16))) - 1);
  UCSRC |=  (1 << UCSZ0) | (1 << UCSZ1);
 UCSRB |= (1 << RXEN) | (0 << TXEN |1<<RXCIE);
  UBRRH = BAUD >>8;
  UBRRL = BAUD;


Chybové příznaky jsem ještě netestoval, to ještě zkusím. V minulých dvou dnech jsem sice dosáhl částečného vítězství nad atmelovskými a céčkařskými mocnostmi, zjistil jsem ale, že to co se píše v datašítu, v reálu tak jednoduché není. Např. přečtením UDR se hned RXC ani UDR nenuluje, nejspíše v MCU musí ještě něco proběhnout. Proto asi bez problémů funguje jedině smyčka s počátečním testem

Kód: Vybrat vše

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

Já jsem nakonec použil tento příkaz a vložil jsem do něj časový test a test na koncovýznak.

Závěrem bych se ještě rád zeptal,jestli někdo neznáte C příkaz pro zjistění frekvence použitého MCU. Neboť F_CPU můj Překladač nezná?
(((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

Díky