pátek 2. ledna 2009

Atmega8 - USART

Dneska mě pro změnu vypekla atmega8 v modulu MotorControl. Během dopoledne jsem napsal poměrně univerzální knihovnu pro plánovaný komunikační protokol. Pak jsem celé odpoledne zjišťoval, proč nemůžu přenést mezi dvěma moduly ani jeden jediný byte. Na elektronice je prostě okouzlující ta různorodost chyb. Člověk píše program, škrábe vlasové spoje mezi cestami na desce, opravuje přerušené cesty... No zkrátka sranda. A hlavně je naprosto geniální to, že chyba může být buď v programu, nebo v návrhu elektroniky, nebo v provedení (studeňák atd.), nebo může vznikat kombinací několika chyb (nejlépe z různých jmenovaných oblastí). To je pak zábava :-)

Aby ten zápisek byl k něčemu, zkusím popsat v čem byl zakopaný pes. U atmega8 totiž sdílí registr UBBRH a UCSRC stejnou adresu. Pokud zapisujete do jednoho z těchto registrů, rozhoduje hodnota bitu URSEL o tom, do kterého z nich se bude zapisovat. Viz. citace z datasheetu (strana 152):
The UBRRH Register shares the same I/O location as the UCSRC Register. Therefore some special consideration must be taken when accessing this I/O location.

When doing a write access of this I/O location, the high bit of the value written, the USART Register Select (URSEL) bit, controls which one of the two registers that will be written. If URSEL is zero during a write operation, the UBRRH value will be updated. If URSEL is one, the UCSRC setting will be updated.
Takže jak má správně vypadat nastavení USARTu?


// 9600bd, 8n2
UBRRL = 103;
UBRRH = 0;

UCSRA = (0<<U2X)|(0<<MPCM);
UCSRB = (0<<UCSZ2)|(1<<TXCIE)|(1<<TXEN)|(1<<RXEN)|(1<<RXCIE);
UCSRC = (1<<URSEL)|(1<<USBS)|(0<<UMSEL)|(0<<UPM1)|(0<<UPM0)|(1<<UCSZ1)|(1<<UCSZ0);


Zdánlivě hloupost, ale trochu mě to potrápilo...

2 komentáře:

  1. zajimave, koukal jsem do datasheetu a melo by to byt jak pises...

    ale jak potom vysvetlis ze to v navodu na avrfreaks delaji takto

    http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=45341

    a ja podle toho take bez problemu ovladam seriak.. :D

    OdpovědětVymazat
  2. Ale oni to dělají stejně jako já, jestli teda koukám dobře...

    UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes - URSEL bit set to select the UCRSC register

    OdpovědětVymazat