ATTINY4313 versus USART

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
epes
Příspěvky: 111
Registrován: 05 srp 2008, 02:00
Bydliště: Praha 5

ATTINY4313 versus USART

#1 Příspěvek 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=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

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#2 Příspěvek 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.

Uživatelský avatar
epes
Příspěvky: 111
Registrován: 05 srp 2008, 02:00
Bydliště: Praha 5

#3 Příspěvek 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

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#4 Příspěvek 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.

Uživatelský avatar
epes
Příspěvky: 111
Registrován: 05 srp 2008, 02:00
Bydliště: Praha 5

#5 Příspěvek 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

Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 01:00

#6 Příspěvek 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?

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#7 Příspěvek 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)

Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 01:00

#8 Příspěvek 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);

Uživatelský avatar
epes
Příspěvky: 111
Registrován: 05 srp 2008, 02:00
Bydliště: Praha 5

#9 Příspěvek 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.

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#10 Příspěvek od FHonza »

a jaký používáš překladač ?

Uživatelský avatar
epes
Příspěvky: 111
Registrován: 05 srp 2008, 02:00
Bydliště: Praha 5

#11 Příspěvek od epes »

překladač se jmenuje Mikro C PRO od "jugoslávské" fy Mikroelektronika.

Uživatelský avatar
epes
Příspěvky: 111
Registrován: 05 srp 2008, 02:00
Bydliště: Praha 5

#12 Příspěvek 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=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.
{

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#13 Příspěvek 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 =

Uživatelský avatar
Ruprecht
Příspěvky: 1114
Registrován: 28 zář 2005, 02:00
Bydliště: ZČ + JM

#14 Příspěvek 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?

Uživatelský avatar
epes
Příspěvky: 111
Registrován: 05 srp 2008, 02:00
Bydliště: Praha 5

#15 Příspěvek 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

Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“