ATTINY4313 versus USART
Moderátor: Moderátoři
ATTINY4313 versus USART
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
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.
Správně jedině
(UCSRA & (1<<RXC)) != 0
nebo (zbytečně složitě)
(UCSRA & (1<<RXC)) == (1 << RXC)
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);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.
{
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 =
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