Programujeme jednočipy

Kniha předpokládá mírně pokročilou znalost programování (v jazycích C a Python), elektroniky, šestnáctkové soustavy a výpočetní techniky obecně. Příklady jsou psány ve zmíněných dvou jazycích a předpokládá se linuxové prostředí na PC (návody testovány na Ubuntu 8.04). Pokud máte Windows či jiný systém, pravděpodobně se situace nebude moc lišit a s drobnými úpravami můžete příklady z této knihy použít také.

Celá kniha se za účelem jednoduchosti bude zabývat jen jediným typem jednočipového počítače, a to Atmega8 a jeho novější verzí Atmega8A. V obchodě jej koupíte řádově za 50 až 70 Kč pod označením Atmega8A. Kniha je pojata stylem "skoč do vody a nauč se plavat". Za případné zmatky se čtenáři omlouváme a věříme, že si chybějící části domyslí nebo najde jinde. Příklady jsou okomentované a pokud na nich něco není úplně jasné, pokusíme se uvést dostatek odkazů. Namísto klasických schémat zde někdy použijeme přímo nákresy čipů zeshora, aby bylo jasné umístění pinů.

Nebojte se připsat do diskuse k této stránce svoje dotazy, poznámky či požadavky na další kapitolu. Text je v raném stádiu vývoje. Můžete přispět i svými zkušenostmi.

Popis jednočipového počítače Atmega8

editovat
 
Atmega8 ve standardním 28-nohém DIP pouzdře

Atmega8 je tzv. jednočipový počítač, neboli mikrokontroler. V tomto jediném čipu jsou obsaženy všechny komponenty, které jsou potřeba pro běh počítače, byť jsou ve srovnání se stolním PC dosti slabé:

  • mikroprocesor AVR
    • je osmibitový (běžný PC je 32bitový)
    • má tzv. RISC architekturu, která je odlišná od architektury běžně používaných procesorů Intel nebo AMD
    • pracuje na frekvenci 1 MHz, ale lze jej přetaktovat až na 16 MHz
  • 8kB In-System-Programmed FLASH memory
    • tato paměť slouží k nahrání vlastního programu, zachová se i po vypnutí
  • 1kB RAM
    • volně přístupná paměť na provozní data (po vypnutí se smaže)
  • 512B EEPROM
    • trvanlivá paměť na dlouhodobé ukládání provozních dat
  • další zabudované obvody
    • 2x 8bit + 1x16bit čítač/časovač
    • 3x PWM -- obvody pro střídovou modulaci (řízení stejnosměrných motorů apod.)
    • 4x 10bitový A/D, 2x 8bitový A/D -- 6 digitálních voltmetrů (rozlišení 1024, resp 256 hodnot)
    • USART -- komunikace přes sériový port
    • vnitřní oscilátor 1 - 8 MHz -- slouží jako zdroj taktovací frekvence, pokud není čip přetaktován vnějším krystalem nebo RC obvodem
    • watchdog timer -- automatický reset v případě zamrznutí programu

Napájení celého jednočipového počítače je + 5 V. Spotřeba proudu je malá, při frekvenci 1 MHz je to řádově 3 mA. Spotřeba je úměrná frekvenci a lze ji tedy výrazně snížit podtaktováním např. na 1 kHz. Všimněte si, že 8 kB programové paměti je zcela oddělených od 1 kb RAM a za běhu Atmegy se do nich nezapisuje. To se označuje jako Harvardská architektura. V obvodech Atmegy je víc vstupů/výstupů, než je na čipu nožiček. Předpokládá se, že nikdy nevyužijeme všechny vnitřní vývody najednou. Jednotlivé nožičky lze během programování připojit k danému vnitřnímu vodiči a tím určit jejich funkci. V následujících kapitolách se blíže podíváme na vlastnosti a schopnosti čipu a výklad ilustrujeme funkčními návody.

Vstupně výstupní porty

editovat

Atmega8 má tři porty: dva osmibitové PORTB, PORTD a jeden šestibitový PORTC. Jejich jednotlivé piny můžou fungovat jako vstupní nebo jako výstupní. To se určí pro každý pin jednotlivě v registrech DDRA, DDRB, DDRC.

 

U většiny pinů je uvedeno více popisků. Takové piny je možno za běhu mikrokontroleru přepnout mezi tím, zda se chovají jako digitální port, anebo zda budou využívat nějakou speciální funkci, která jim byla přiřazena. (Výjimkou je pin RESET/PC6, který se dá změnit na vstupně/výstupní pin nastavením pojistky RSTDSBL jen během programování.) Výčet speciálních funkcí:

  • RESET -- reset mikrokontroleru, nezbytný pro sériové programování
  • RXD, TXD -- příjem a odesílání dat přes sériové rozhraní
  • INT0, INT1 -- dva zdroje pro externí přerušení
  • T0, T1
  • XCK
  • TOSC1, TOSC2
  • XTAL1, XTAL2 -- možnost připojit externí krystal
  • AIN0, AIN1 -- vstupy analogového komparátoru
  • ICP1
  • OC1A, OC1B, OC2
  • MISO, MOSI, SCK -- automaticky použité během sériového programování (přenos dat dovnitř, ven a taktování)
  • SCL
  • SDA
  • ADC0, ADC1, ADC2, ADC3 -- čtyři 10-bitové analogově-digitální převodníky (ADC)
  • ADC4, ADC5 -- dva 8-bitové ADC

Co budeme potřebovat

editovat

Návody předpokládají že má čtenář jednak počítač s paralelním portem (Pokud vám žádný z počítače netrčí, nezoufejte, stále je častý interní konektor na základních deskách -označen jako LPT- a vývod vyjde do 80 Kč), jednak základní elektronické vybavení, jako jsou drátky, páječka apod. Konkrétní potřeby závisí na použití Atmegy. Pokud chce čtenář začít s prvními několika návody, měl by navštívit obchod s elektronickými součástkami [1] a koupit v přiměřeném množství:

  • obvody ATMEGA8-16PU
  • nepájivé pole (viz obr.)
  • 28-pinové patice na čipy
  • 10 rezistorů 330 Ohm, 10 rezistorů 1 kOhm, 5 rezistorů 100 Ohm
  • LED diody dle vlastního vkusu, malý sedmisegmentový display
  • LPT kabel (počítač-tiskárna nebo podobný pro stavbu programátoru)

(Dřív nebo později bude stejně něco chybět. Krabice od banánů plná elektronického šrotu k rozpájení je v tomto nenahraditelná.)

Programujeme Atmegu přes paralelní port

editovat

Postup nahrání vlastního programu do FLASH paměti Atmegy může být následující:

  1. Napsat na svém počítači program v jazyce C,
  2. zkompilovat jej v kompilátoru GCC,
  3. pokud jej ještě nemáme, vyrobit si programátor,
  4. připojit Atmegu k programátoru a programátor k paralelnímu portu počítače,
  5. nahrát do paměti Atmegy zkompilovaný program pomocí programu avrdude,
  6. vrátit Atmegu do svého obvodu a spustit ji.

Výroba jednoduchého programátoru stk200

editovat
 
Pozor, paralelní port má v počítači dírky. Nezaměňte jej se širokou verzí sériového portu, který má kolíky.

Hardwarový programátor je zařízení, které slouží k propojení mikrokontroleru a počítače tak, aby se do mikrokontroleru dal nahrát program. Zde si popíšeme, jak jeden jednoduchý vyrobit.

Existuje i praktičtější verze programátoru, usbasp, která se k počítači připojuje se přes USB. Její výrobu si popíšeme níž, ale protože sama obsahuje jeden mikrokontroler, bez tohoto programátoru se neobejdeme.

Velkou výhodou Atmegy je, že k nahrání programu není potřeba žádná složitá elektronika. Pro stavbu programátoru označovaného jako stk200 si vystačíme s:

  • paralelním portem běžného počítače,
  • 4 rezistory (třikrát 330 Ohm, jeden 100 Ohm)
  • standardní paticí na čipy (s 28 děrami) a
  • standardním paralelním kabelem k tiskárně.

Atmega i během nahrávání programu vyžaduje napájení + 5 V. Většina ostatních návodů to řeší pomocí dodatečného stabilizovaného síťového zdroje. Spotřeba proudu je u Atmega8 velmi malá. Pokud k mikrokontroleru není připojena dodatečná zátěž, můžeme použít napájení přímo z paralelního kabelu. Stačí najít nějaký pin, na kterém je během programování trvale zapnuta logická 1, tedy + 5 V. V daném případě jde o pin 14. Pokud se programování nedaří, v prvé řadě pomocí voltmetru zkontrolujte, zda je na daném pinu trvale napětí 5 V a případně programovaný čip napájejte externím zdrojem. Pak nezapomeňte na to, že země musí být společná pro zdroj i pro počítač.

 

Konkrétní provedení ponecháme na čtenáři. Pokud pracujete na nepájivém poli, asi nejpraktičtější je na dotyčné vodiče přímo připájet rezistory a barevné drátky a zajistit je proti zkratu. Patici s rezistory lze zabudovat do krytu konektoru, čímž vznikne velmi kompaktní programátor bez kabelu. Jinou možností je patici zabudovat do stěny papírové krabičky s tiskárenským konektorem, jak ilustrují obrázky.

 
 

Kompilace programu blikajícího diodami v assembleru

editovat


Assembler je nízkoúrovňový jazyk, v němž se píší konkrétní kroky, které má procesor provést. Je vhodný tam, kde je třeba psát velmi úsporný a rychlý kód. K běžnému programování doporučujeme použít jazyk C.

Výpis programu v jazyce assembler

.NOLIST
 .INCLUDE "/usr/avr/inc1/m8def.inc" ; odkaz na inc soubor
 .LIST
 
 .DEF tmp = R16 ; tmp - registr pro docasna data
 
 	rjmp RESET ; provede nezbytne nastaveni mikroprocesoru - inicializace
 RESET:
 	LDI tmp,LOW(RAMEND)
 	OUT SPL,tmp
 	LDI tmp,HIGH(RAMEND)
 	OUT SPH,tmp
 	rjmp Start ; nyni spustime vlastni program
 
 
 Start: ; sem není dobre psat prikazy, stane se program spatne citelny
         LDI tmp,$01 ; do tmp nahrajem hodnotu 0b00000001 -> tzn 1
         OUT DDRB,tmp ; a tu pak nahrajem do DDRB - takze urcime vstupy a vystupy
 
 	sbi PortB,0 ; rozsviti LED
 	rcall Cekej ; spusti 1s zpozdeni
 
 	cbi PortB,0 ; zhasne LED
 	rcall Cekej ; opet spusti zpozdeni
 
 	rjmp Start
 cekej:
 	LDI R19,14 ; do registru R19 zapise hodnotu 14 v destkove soustave
 	clr R20 ; vymaze data v registru R20
  	clr R21 ; vymaze data v registru R21
 cekej1:
 	dec R21 ; odecte z registru R21 cislo 1 (zmensi o 1)
 	brne cekej1 ; pokud bude hodnota v R21 rovna 0, pak program pokracuje na dalsi radek, jinak skoci
 
 	dec r20
 	brne cekej1
 
 	dec r19
 	brne cekej1
 
 	ret ;navrat z podprogramu

Nainstalujte si balíčky

gcc-avr avr-libc avra

Provedeme kompilaci programu v assembleru

avra blikajici_LED.asm

Přeložený program se tedy bude jmenovat blikajici_LED.hex

Nahrání programu do Atmegy

editovat

Nainstalujte si balíček avrdude:

sudo apt-get install avrdude

K nahrání vlastního programu do jednočipů existuje pro Linux i pár jiných programů, např. uisp nebo ponyprog. Firma Atmel dodává i kompletní vývojové prostředí AvrStudio, které podporuje programování přes paralelní programátor také. Nebudeme se jimi zde z prostorových důvodů zabývat.

Propojte Atmegu8 a počítač pomocí programátoru stk200 a spusťte příkaz:

sudo avrdude -p m8 -c usbasp -U flash:w:main.hex

Je pravděpodobné, že tento příkaz budete používat často. Můžete si pro něj vytvořit tzv. alias! Přidejte následující řádek na konec souboru ~/.bashrc:

avrload() { sudo avrdude -p m8 -c usbasp -U flash:w:$1; } 

Nyní stačí místo výše uvedeného příkazu spustit jen

avrload main.hex

Přepnutí pojistek

editovat

Atmega8 také obsahuje 16 tzv. pojistek, anglicky fuses. Jsou to 2 byte v EEPROM paměti, označované jako lfuse a hfuse, jejichž hodnota se zachovává při vypnutí obvodu a které určují, které piny mají jakou funkci, jaký zdroj taktovacího signálu Atmega8 použije atp.

Hodnota, na niž se mají přepnout pojistky, se předá programu avrdude jako parametr. Pro výpočet těchto parametrů lze použít: http://www.engbedded.com/fusecalc/

Velmi snadno se stane, že se člověk při programování pojistek splete a buďto nastaví nějaký nepoužitelný zdroj taktování, nebo vypne možnost resetovat čip. Atmega8 s chybným nastavením pak nebude ani fungovat, ani spolupracovat při programování přes ISP. Musí se pak zresetovat pomocí druhého čipu a paralelního programování, které je zdokumentováno v dodatcích. Buďte opatrní při nastavování pojistek.

Usnadnění práce s avrdude na Linuxu

editovat

Otevřete v textovém editoru soubor ~/.bashrc a na jeho konec zkopírujte následující 3 řádky. Platí, pokud budete programovat Atmegu8 s jednoduchým programovacím kabelem "stk200".

avrload() { sudo avrdude -p m8 -c stk200 -U flash:w:$1; }
avrfuseXtal() { sudo avrdude -p m8 -c stk200 -U lfuse:w:0xff:m -U hfuse:w:0xd9:m; }
avrfuseIntOsc() { sudo avrdude -p m8 -c stk200 -U lfuse:w:0xc1:m -U hfuse:w:0xd9:m ; }

Tyto zkratky si samozřejmě můžete přidávat nebo upravovat podle potřeby. Pokud namísto kabelu budete používat usbprogramátor, který je uveden v jedné z následujících kapitol, nahraďte stk200 za usbasp. Dále, pokud nebudete používat obvod Atmega8, ale třeba Atmega16, nahraďte parametr m8 za m16. V příkazu avrload si všimněte řetězce $1, za který se zde doplní první parametr, který uvedete za příkazem avrload.

Poté, co znovu spustíte terminál, nebo natáhnete upravený ~/.bashrc příkazem source ~/.bashrc, už budete moci snadno nahrát program mujprogram.hex do čipu:

avrload mujprogram.hex

... a přepnout jej na taktování externím krystalem:

avrfuseXtal

nebo vrátit nastavení taktování na zabudovaný 1 MHz oscilátor:

avrfuseIntOsc

Program počítající impulzy

editovat

Výstup na sedmisegmentový display

Použití vstupně/výstupních portů

editovat

Program na jednoduché vypínanie a zapínanie pinov na PORTB.1 tlacidlom na PORTB.0. Sú tu aj vyriešené zákmity tlačidiel a pokračovanie až po pustení tlacidla.

Čtení hodnoty pinu

# include <avr/io.h>
# define F_CPU 8000000UL
# include <util/delay.h>
int main(void)
  {
    DDRB = 0x06;	//riadenie vstupu a vystupu, 1-vystup, log 0-vstup
    PORTB = 0x07;	//výstupný register ak DDR==1 potom PORT sa prenesie na výstup inak pri log 1 pullup-ON, log 0 pullup-OFF
    do{
      if (!bit_is_set(PINB, 0)) 
        {
          _delay_us(500); 
          if (!bit_is_set(PINB, 0)) 
           {
 if (bit_is_set(PINB, 1))
 {PORTB &= ~((1<<1));}
  	     else
              {PORTB |= (1<<1);}
             while(!bit_is_set(PINB, 0))
 {};
           };
        }
    }while(1);
    return (0);	//vrat 0 = ukončení v pořádku
  }

Pro zpoždění běhu programu, které se u mikrokontrolerů využije poměrně často, lze použít funkce _delay_ms() a _delay_us(), jejichž argumentem je doba v milisekundách, resp. mikrosekundách. Doporučujeme, aby byly tyto funkce vždy volány se statickou hodnotou; pokud jim totiž předáváme proměnnou, do programu se nalinkuje i řádově 10 kB knihoven pro matematické počty. Pro správné časování definujte hodnotu F_CPU jako taktovací frekvenci (s koncovkou UL).

Použití A/D převodníků

editovat

Pro jednoduchý analogově-digitální převod je potřeba zapojit piny AVCC (20) a AREF (21) k napájecímu napětí, které předpokládáme 5 V. Následující výsek kódu změří napětí na vstupu ADC0 (pin 23).

	ADMUX = 0; // inicializace A/D prevodniku na kanalu 0 
	ADCSRA |= _BV(ADEN) | _BV(ADPS1) | _BV(ADPS2) ; 

	ADCSRA |= _BV(ADSC); // zahajime mereni
	while  (!(ADCSRA & _BV(ADIF))); // cekame na dokonceni
	ADCSRA |= _BV(ADIF);

A/D převodník má 10bitovou přesnost, tedy hodnota "0" odpovídá 0 V, hodnota "1023" odpovídá 5 V. Spodních 8 bitů se uloží do registru ADCL, horní 2 bity do registru ADCH. Doplníme úsekem kódu, který tuto 10bitovou hodnotu převede na 4místné desetinné číslo ve formátu ASCII a odešleme po sériovém portu.

	UBRRL = 25; // usart init 2400 bps (assuming 1MHz internal clock)
	UCSRB |= _BV(TXEN);
	int VInput;
	VInput = ADCL + 256*(ADCH&3); // 10 bits ADC input
	usart_putchar(0x30 + (VInput % 10000)/1000);
	usart_putchar(0x30 + (VInput % 1000)/100);
	usart_putchar(0x30 + (VInput % 100)/10);
	usart_putchar(0x30 + (VInput % 10));
	usart_putchar(0x0a);	// end of line

Při tom se využívá funkce

void usart_putchar(uint8_t c)/*{{{*/
{
    UDR = c;
    while(bit_is_clear(UCSRA, TXC));
    UCSRA = _BV(TXC) ; 
}

Popis komunikace přes sériový port viz v příslušné kapitole.

Zpřesnění měření

editovat
  • stabilizovat napětí na AVCC (20) a AREF (21) (kondenzátorem a/nebo stabilizátorem LM7805)
  • zpomalit měření - snížení taktovací frekvence ADC

Pokud máme větší nároky, lze také použít externí ADC a číst z něj data přes SPI. Za cca 70 Kč lze pořídit např. 12bitový dvoukanálový převodník MCP3202, který obsahuje i sample-and-hold obvod. Pokud chceme pouzivat vyšší vzorkovací frekvenci, lze vybrat napr. osmibitový AD9280, který vzorkuje s frekvencí až 32 MHz. Data pak je třeba přechodně ukládat do externí paměti (viz [2]).

Další informace jsou v datasheetu a na stránce http://www.avrbeginners.net/architecture/adc/m8_adc_example.html .

Zápis a čtení interní EEPROM paměti

editovat


#include <avr/eeprom.h>

eeprom_read_block(data, eeprom_offset, len);
eeprom_write_block(data, eeprom_offset, len);

Přetaktování na vyšší frekvenci s krystalem

editovat


Použití přerušení

editovat


Komunikace s PC přes USART

editovat

Atmega8 je vybavena obvodem USART, který se stará o komunikaci přes sériový port. Pro odeslání a příjem dat z počítače díky tomu stačí jen několik málo příkazů. Pokud počítač nemá sériový port, lze jej různými způsoby nahradit pomocí USB portu, čemuž se věnují některé z následujících kapitol.

Hardware

editovat

Sériový port (v tomto případě) bude využívat jen tři vodiče: zemi, odesílání dat a příjem dat. Protože při přesunu dat nepoužíváme hodinový signál, který by upozornil na příchod každého nového bitu, musí být v počítači i čipu přesně určena společná přenosová rychlost.

Tyto frekvence ("baudrate") jsou standardizované. V daném příkladu předpokládáme, že je použit interní oscilátor Atmegy na 1 MHz a použijeme přenosovou rychlost 2400 bit/s. Pokud bychom použili taktování Atmegy krystalem o frekvenci 4 MHz, použili bychom namísto toho 9600 bit/s.

Atmega8 používá napěťové úrovně TTL (0 V / 5 V). Sériový port počítače používá podstatně jiné napěťové úrovně (-12 V / +12 V). K převodu mezi těmito úrovněmi je třeba použít obvod MAX232, který vyžaduje připojení dodatečných čtyř kondenzátorů. Koupíme tedy obvod MAX232CPE (cca 19 Kč) a k němu 4x elektrolytický kondenzátor 1 uF/20 V.


Firmware Atmegy pro komunikaci přes USART

editovat

# include <avr/io.h>

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

// send char
void uart_putc(unsigned char data )
{
    while ( !( UCSRA & (1<<UDRE)) ) 
        ; 
    UDR = data; 
}

int main(void)
{
    char znak; 

    /***** inicializace uart  *****/ 
    UCSRA = 0x00; 
    UBRRH = 0x00;  // nastaveni rychlosti pro krystal  1 MHz  
    UBRRL = 25;    // (v pripade taktovani 8 MHz zde pouzijte  UBRRL = 0x33; )
    UCSRB = 0x18;  // povolit vysilani a prijem 
    UCSRC = 0x86;  // ramec dat:  8 datovych, 1 stop bit, bez parity 

    while(1) 
    { 
        znak=uart_getc(); 
        uart_putc(znak); 
    } 
}

Software v počítači

editovat

Popíšeme si 3 prostředí, v nichž lze komunikovat s Atmegou. Které z nich je nejvýhodnější, závisí na použití.

  1. příkazový řádek Linuxu (zápis do na zařízení /dev/ttyS1)
  2. program v Pythonu
  3. program v C

Příkazový řádek Linuxu

editovat

Příjem dat ze zařízení sériového portu, přístupného jako soubor /dev/ttyS0 či /dev/ttyS1. Pokud budete mít štěstí, půjde z něj rovnou číst data:

cat /dev/ttyS0

Přijímaná data se sypou na standardní výstup, jak je zvykem.

Pokud to nefunguje, čtení z portu asi vyžaduje doplnění pár parametrů:

stty -F /dev/ttyS0 clocal cread -crtscts cs8 -cstopb hup -parenb parodd -brkint -icrnl ignbrk \
   -igncr ignpar imaxbel -inlcr inpck -istrip -iuclc -ixany ixoff -ixon bs0 cr0 ff0 nl0 -ocrnl \
   -ofdel -ofill -olcuc -onlcr -onlret onocr -opost tab0 vt0 -crterase crtkill -ctlecho -echo \
   -echok -echonl -echoprt -icanon -iexten -isig -noflsh -tostop -xcase time 5 min 1 2400

Todo: odesílání dat

Program v Pythonu

editovat

Pro příjem dat v Pythonu existuje snadno použitelná knihovna uspp, kterou bude asi třeba doinstalovat (sudo apt-get install python-uspp).

Pokročilejší řešení komunikace přes sériový port

editovat

Firmware zajišťující kompletní USART komunikaci s použitím přerušení.


Chip type           : ATmega16
Clock frequency     : 12MHz
# include <avr/io.h>
# include <avr/interrupt.h>
# include <string.h>

# define rdataSize 100
 
//USART
void USART_Init( unsigned int divisor );
void USART_Transmit( char * data );
void usart_busy_wait();
 
char tdata=0, *transmitted_data = &tdata;
char rdata[rdataSize], *received_data = rdata;

 
# define UBRR 77

int main(void)
{
	USART_Init(UBRR);
	sei();

	while(1)
	{
                usart_busy_wait();
		USART_Transmit(rdata);
	}
 
	return 0;
}
 
void USART_Init( unsigned int divisor )
{
	// Set the port as the TxD output.
	DDRD |= 0x02;

	// Set baud rate
	UBRRH = (unsigned char)(divisor>>8);
	UBRRL = (unsigned char)divisor;

	// Set frame format: 8data, 1stop bit.
	UCSRC = (1<<URSEL)|(3<<UCSZ0);
	//Enable Receiver and Transmitter
	UCSRB |= (1<<RXEN)|(1<<TXEN);
	UCSRB |= (1<<RXCIE);
 
}
 
void usart_busy_wait()
{
	/* Wait for empty transmit buffer */
	while(transmitted_data != NULL);
	while ( !( UCSRA & (1<<UDRE)) );
}

 
void USART_Transmit( char * data )
{
	transmitted_data = data;
	if (*transmitted_data)
	{
		//Enable Data register empty interupt
		UCSRB |= (1<<UDRIE);
	}
 
}
 
// Data transfer using Data register empty interrupt.
ISR(USART_UDRE_vect)
{
	// Put data into buffer, sends the data.
	if(*transmitted_data)
	{
		UDR = *transmitted_data;
		transmitted_data++;
	}
 
	else
	{
		//Disable Data register empty interupt
		UCSRB &= ~(_BV(UDRIE));
	}
}
// Receive data using USART Receive Complete interupt
ISR(USART_RXC_vect)
{
	if(received_data != &rdata[rdataSize])
	{
 *received_data = UDR;
 //UDR = *received_data;
 received_data++;
	}
	else
	{
		received_data = rdata;
	}
}

Záznam dat do SD paměťové karty

editovat

http://www.mikrozone.sk/pluginy/content/content.php?content.43

Komunikace s PC přes USB

editovat

USB má oproti sériovému portu vyšší přenosovou rychlost a je podporován i u nových počítačů. Také obsahuje napájecí vodič (5 V, 500 mA). Podstatnou nevýhodou je složitost komunikace, kterou zařízení po USB vedou. Existuje několik možností, jak propojit mikrokontroler s počítačem:

  1. implementovat USB protokol do Atmegy softwarově -- k tomu existuje řada nezávislých projektů
    1. http://www.obdev.at/products/avrusb/index.html -- přehledné a poměrně snadno použitelné funkce pro komunikaci přes USB včetně řady příkladů, podporují různé mikrokontrolery a různé frekvence, pro komerční účely zpoplatněno
    2. http://www.cesko.host.sk/IgorPlugUSB/IgorPlug-USB%20(AVR).htm -- populární (a jeden z prvních) projektů USB na mikrokontrolerech Atmel, převodník RS232-USB
    3. http://smrz.chrudim.cz -- dobrý popis komunikace přes USB, ale konkrétní návody vyžadují mnoho vlastního úsilí
    4. http://www.volny.cz/elecon/cz/usb/usb_m.html
    5. http://www.marktmarshall.com/doku.php?id=projects:avr-hid
  2. použít mikrokontroler, který má USB rozhraní zabudované (to Atmega8 není, tyto mikrokontrolery bývají podstatně dražší)
  3. použít dodatečný obvod, který zajistí převod mezi USB a RS232 (sériové rozhraní RS232 už Atmega8 podporuje)
    1. FT232BL (http://www.datasheetsite.com/datasheet/FT232BL) stojí asi 130 Kč a lze s ním dosáhnout komunikace okolo 2 Mbit/s, což je podstatně více, než lze softwarovým USB ovladačem. Řada návodů k FT232BL je na internetu.

Autor má dobrou zkušenost s použitím první možnosti. Pro svoje pokusy zvolis USB ovladače od Objective Development. Pro nekomerční užití jsou zdarma pod licencí GPL. Chcete-li je vyzkoušet, stáhněte a rozbalte jejich zdrojové kódy ve formátu zip a prozkoumejte příklady.

Pro jednoduchou komunikaci s počítačem je vhodná např třída zařízení HID-DATA. Osvědčilo se zapojení obvodu se Zenerovými diodami (uvedeno také ve zmíněném archivu). Další popis komunikace přes USB je nad rámec této wikiknihy.

Stavba USB programátoru

editovat

V jedné z úvodních kapitol byla popsána stavba jednoduchého programátoru stk200, využívajícího paralelní port. Protože některé počítače již paralelní port nemají, existuje řada návodů na stavbu programátoru, který se připojí přes USB. Některé z nich mají pokročilé funkce jako je paralelní programování, podpora širokého množství čipů, debugování apod.

Pro většinu účelů ale bude stačit jednoduchý programátor usbasp podle stránky http://www.fischl.de/usbasp/. Slouží k sériovému programování vícero mikrokontrolerů od Atmelu (včetně Atmegy8 a Atmegy16). Schéma i program je uveden v archivu na stránce autora, programátor lze během několika desítek minut zprovoznit na nepájivém poli.

Autor měl potíže s novější verzí avrasp z roku 2009. [http://www.fischl.de/usbasp/usbasp.2007-10-23.tar.gz

  • atmega8
  • krystal 12,000 MHz
  • LED
  • 5x 330 ohm, 2x 33 ohm, 2x 100 ohm, 1x 1k
  • USB B konektor nebo ustřižený konec USB kabelu, který se dá zapojit do počítače

Atmegu8 je třeba přepnout na taktování externím krystalem a naprogramovat. Nemáte-li tedy ani paralelní port, ani půjčený programátor, je třeba se obrátit na někoho, kdo vám nahraje program.

Dodatky

editovat

Stručný slovníček

editovat
  • Atmega8 - mikrokontroler střední třídy vyráběný firmou Atmel, patří do rodiny AVR
  • Atmel - jedna z mnoha firem vyrábějících mikrokontrolery, mimo jiné vyrábí i Atmegu8, jíž se zabývá tato kniha
  • AVR - rodina procesorů z výrobní řady firmy Atmel. Patří mezi ně i Atmega8.
  • AVRStudio - bohaté vývojové prostředí pro jednočipy Atmel, viz [3]
  • avrdude: program k nahrávání programu do jednočipů řady AVR
  • EEPROM: elektronicky přepisovatelná paměť, podobná flash (u Atmegy8 512 B použitých na uložení dat)
  • FLASH: elektronicky přepisovatelná paměť, podobná flash (u Atmegy8 8 kB k uložení programu)
  • fuse: zde jeden z několika bitů v trvalé paměti mikrokontroleru, který určuje jeho chování (česky též "pojistka")
  • ISP - in system programming: sériové programování pomocí 4 datových vodičů, obvykle bez nutnosti vyndat mikrokontroler z přístroje, který řídí
  • JTAG: rozhraní pro ladění programu nahraného do mikrokontroleru (též ICE)
  • LPT: paralelní port
  • mikrokontroler: programovatelný integrovaný obvod schopný samostatné činnosti bez další složité elektroniky, podobný svou logickou stavbou velmi zmenšenému počítači
  • programátor: zde označuje obvod, pomocí kterého se do mikrokontroleru nahrávají data a nastavení z počítače
  • RS232: sériový port
  • sériový port: starší port, ještě se občas vyskytující u stolních počítačů. Data se přenášejí jedním vodičem tam a druhým zpět (celkem 3 vodiče, pro některé účely i více). Používá napěťové úrovně +/- 12 V, které neodpovídají běžně používaným napětím u digitálních obvodů.
  • stk200: velmi jednoduchý programátor sestávající z kabelu a 4 rezistorů, připojuje se k paralelnímu portu
  • uisp: program k nahrávání programu do jednočipů řady AVR, podobný avrdude
  • USART - Universal Synchronous or Asynchronous Receiver and Transmitter: součást mikrokontroleru, hardwarově zajišťující komunikaci po sériovém portu
  • USB - Universal Serial Bus: velmi populární port u současných stolních počítačů, k němuž se lze připojit také z jednočipových počítačů, a to s použitím
  • USB 1.1: starší standard USB, který pracuje s přenosovou rychlostí 1,5 Mbit/s nebo 12 Mbit/s. Rychlostí 1,5 Mbit/s lze komunikovat i za pomoci softwarového ovladače v mikrokontroleru; vyšší rychlosti potřebují specializovaný obvod.
  • usbasp: poměrně jednoduchý programátor, připojuje se k USB
  • Watchdog timer: nezávislý obvod, předcházející zatuhnutí běhu mikrokontroleru. Pokud přestane být periodicky "krmen", považuje to za kolaps programu a resetuje obvod.

Vysokonapěťové paralelní programování

editovat

Motivace

editovat

K nahrání programu do Atmegy8 a nastavení jejích pojistek jsme dosud používali sériové programování. (Byty se v něm přenášejí sériově po 3 vodičích, ačkoli se u počítače použije paralelní port.) Také se označuje jako in system programming, protože se často dá provést, aniž by se Atmega8 vyndávala z obvodu.

V některých případech je potřeba použít složitější vysokonapěťové paralelní programování:

  • jsou chybně nastavené pojistky, což může znemožnit sériové programování
    • může být vynulovaná pojistka RSTDSBL, která způsobí, že pin PC6 přestane sloužit jako reset
    • nebo jsou zmateně naprogramované pojistky zdroje taktování (přičemž taktování je při ISP potřeba)
  • chceme číst nebo zapsat data v EEPROM
  • chceme vymazat data v čipu, který je zamčený proti zápisu (jsou nastavené lock bity)

V následujícím návodu se budeme zabývat prvním a nejčastějším případem, kdy jsme chybně nastavili pojistky a čip už nejde přepsat pomocí ISP. Tento nemocný čip označíme jako pacienta. Pomocí druhé atmegy8 čip vyresetujeme tak, aby jej šlo znovu programovat pomocí ISP.

Potřebný materiál

editovat

K paralelnímu programování nelze použít prostý paralelní port počítače, protože nemá dost pinů. Namísto toho opatříme

  • druhou, funkční Atmegu8. Budeme ji označovat jako doktora. (Její pojistky ponecháme ve výchozím stavu, tj. interní taktování na 1 MHz.)
  • stabilizovaný zdroj 11,5 - 12,5 V
  • 1 NPN tranzistor, 1 PNP tranzistor
  • 4 rezistory 10 kOhm
  • běžné vybavení používané dříve, tj. nepájivé pole, sériový programátor, stabilizovaný zdroj 5 V a hromadu drátků

Nahrání programu doktorovi

editovat

Doktorovi nahrajeme následující recept: VnParProg hex code:

sudo avrdude -p m8 -c stk200 -U flash:w:atmega8-fuse-repair.hex

Pokud program chceme pozměnit nebo pročíst, je k dispozici zde: VnParProg c code. V tom případě jej zkompilujte klasickými příkazy a nahrajte jej výše uvedeným způsobem.

avr-gcc -g -Wall -O1 -mmcu=atmega8 -c atmega8-fuse-repair.c -o atmega8-fuse-repair.o
avr-gcc -g -Wall -O1 -mmcu=atmega8 atmega8-fuse-repair.o    -o atmega8-fuse-repair.elf
avr-objcopy -j .text -j .data -O ihex atmega8-fuse-repair.elf atmega8-fuse-repair.hex

sudo avrdude -p m8 -c stk200 -U flash:w:atmega8-fuse-repair.hex

Postup opravy pojistek

editovat

Obě Atmegy8 umístíme na nepájivé pole blízko sebe. Většinu pinů propojíme přímo, PB0 na PB0 atd. Takto vytvoříme PB0 - PB6, PC0 - PC2, PD1 - PD7, celkem 17 přímých propojek, které jsou na schématu kresleny sloučené v tlustou čáru:

 

Výstup PC3 připojíme na vstup spínače +12 V. Výstup spínače připojíme přes 10 kOhm rezistor na PC6 pin pacienta. Na schématu je návrh s tranzistory, ale protože 12 V signál je zapnut po dobu programování, lze obvod s tranzistory nahradit ručním spínačem a jediným resistorem.

Oba čipy, doktora i pacienta, zapojíme podle výše uvedeného schématu. Doporučujeme pak postupovat následovně:

  1. připojíme RESET doktora k zemi
  2. připojíme stabilizované 12 V a 5 V napájení
  3. (pokud jsme zjednodušili schéma odstraněním tranzistorů, připojíme 12 V k reset pinu pacienta)
  4. odpojíme RESET a sledujeme svítivou diodu, měla by asi na vteřinu bliknout

Nyní by měl být pacient vyléčen. Odpojíme napájení, vyndáme jej a zkusíme jej naprogramovat běžným, sériovým rozhraním.

Přímý zápis na paralelní port v Linuxu

editovat

Nesouvisí to přímo s Atmegou, ale může se to hodit. Následující program lptout (napsaný v C pro Linux) nastaví na paralelním portu počítače číslo určené jako 1. parametr. Na Windows (XP) lze na paralelní port zapisovat také, ale vyžaduje to dodatečnou instalaci ovladačů. Zápis na LPT funguje, jen je-li spuštěn s rootovskými právy.


/* lptout - sets given value on parallel port */
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/io.h>
 #define base 0x378           	/* printer port address */
 int main(int argc, char **argv) 
 {
    int value;
    if (ioperm(base,1,1)) {fprintf(stderr, "Could not get permission for the port 0x%x.\n", base), exit(1);}
    if (argc < 2) {fprintf(stderr, "Please specify the value to be set. \n"); exit(2);}
    if (sscanf(argv[1], "%i", &value) == 1) {outb((unsigned char)(value), 0x378);} 
       else {fprintf(stderr, "1st parameter must be an integer between 0 - 255. \n", base), exit(3);}
    return 0;
 }

Kompilace a příklad použití k nastavení pinů nastřídačku:

g++ lptout.c -o lptout
sudo ./lptout $(( 1*1 + 0*2 + 1*4 + 0*8 + 1*16 + 0*32 + 1*64 + 0*128 ))

Buďte opatrní při práci s paralelním portem! Obvody počítače jsou citlivé na přepětí a statickou elektřinu. U paralelního portu je riziko poškození i v případě zkratu.

Užitečné odkazy

editovat