ATTINY4313 versus USART
Moderátor: Moderátoři
ATTINY4313 versus USART
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
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
Správně je to takhle (dle datasheetu):
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.
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;
}
Dobře je jenom ten tvůj první příklad, ostatní nemůžou fungovat.
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)
Správně jedině
(UCSRA & (1<<RXC)) != 0
nebo (zbytečně složitě)
(UCSRA & (1<<RXC)) == (1 << RXC)
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);
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.
{
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.
{
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.
Pak také testuj příznaky chyb z registu USCRA (nulují se čtením UDR). Hlavně příznak ztráty znaku DOR.
ti chybí jedno =...zatím funguje jen příkaz
while((UCSRA&(1<<RXC))=0){};...
ATTINY pracuje s frekvencí 8MHz, přenosovou rychlost jsem dle dokumentace zvolil 9600 - teoreticky 0% chybovost.
Nastavení USART je toto:
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
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
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;
Kód: Vybrat vše
while((UCSRA&(1<<RXC))==0){}
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