Programujeme jednočipy

Z Wikiknih

Přejít na: navigace, hledání

Obsah

[editovat] Úvod

Kniha předpokládá mírně pokročilou znalost programování (v jazycích C a Python), elektroniky, šestnáctkové soustavya 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. V obchodě jej koupíte řádově za 30 až 40 Kč pod označením Atmega8-16PU. Kniha je pojata stylem "skoč do vody a nauč se plavat", za což 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 schémat zde použijeme 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.

[editovat] Popis jednočipového počítače Atmega8

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 Harwardská 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.

[editovat] Vstupně výstupní porty

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.


Atmega8 pinout.svg

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

[editovat] Co budeme potřebovat

Návody předpokládají že má čtenář jednak počítač s paralelním portem, 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á.)

[editovat] Programujeme Atmegu přes paralelní port

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.

[editovat] Výroba jednoduchého programátoru stk200

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


Velkou výhodou Atmegy je, že k nahrání programu není potřeba žádná složitá elektronika. ObvVystačíme si 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. Ale protože je její spotřeba proudu velmi malá, 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.

Atmega8 lpt programmer.svg

Konkrétní provedení ponecháme na čtenáři -- 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. V krabičce pak jde skladovat hromadu drobného příslušenství a navíc se někdy může hodit snadný přístup k jednotlivým pinům paralelního portu:

Atmega8 programmer box1.jpg
Atmega8 programmer box2.jpg

[editovat] Kompilace programu blikajícího diodami

Tato kapitola je zatím příliš krátká, nebo neobsahuje důležité informace. Pomozte Wikiknihám tím že ji doplníte.

Nainstalujte si balíčky

gcc-avr avr-libc

[editovat] Nahrání programu do Atmegy

Nainstalujte si balíček avrdude:

sudo apt-get install avrdude
Poznámka 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
Poznámka 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

[editovat] Přepnutí pojistek

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/

Upozornění 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.

[editovat] Usnadnění práce s avrdude na Linuxu

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 ; }
Poznámka 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, 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

[editovat] Program počítající impulzy

Tato kapitola je zatím příliš krátká, nebo neobsahuje důležité informace. Pomozte Wikiknihám tím že ji doplníte.

Výstup na sedmisegmentový display

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

Tato kapitola zatím v tomto článku chybí. Můžete Wikiknihám pomoci tím, že ji doplníte.

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

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řitom 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.

[editovat] Zpřesnění měření

  • 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 vyssi vzorkovaci frekvenci, lze vybrat napr. osmibitovy MAX153, ktery vzorkuje s frekvenci 1 MHz a data ukladat do seriove pameti (viz [2]).

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

Tato kapitola zatím v tomto článku chybí. Můžete Wikiknihám pomoci tím, že ji doplníte.

#include <avr/eeprom.h>

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

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

Tato kapitola zatím v tomto článku chybí. Můžete Wikiknihám pomoci tím, že ji doplníte.


http://blog.louic.nl/?cat=24

[editovat] Použití přerušení

Tato kapitola zatím v tomto článku chybí. Můžete Wikiknihám pomoci tím, že ji doplníte.

[editovat] Komunikace s PC přes USART

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.

[editovat] Hardware

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.


[editovat] Firmware Atmegy pro komunikaci přes USART


Počítačový kód
#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); 
    } 
}

[editovat] Software v počítači

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

[editovat] Příkazový řádek Linuxu

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:

Počítačový kód
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ů:

Počítačový kód
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

[editovat] Program v Pythonu

Tato kapitola je zatím příliš krátká, nebo neobsahuje důležité informace. Pomozte Wikiknihám tím že ji doplníte.

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

[editovat] Program v C

http://www.captain.at/electronic-atmega16-serial-port.php

ATmega16 měří signál ze sonaru a konvertuje ho na centimetry, data odesílá na počítač.


Chip type           : ATmega16
Clock frequency     : 12000 MHz
jan.kalenda[at]gmail.com
Počítačový kód
#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include <stdio.h>
//delay
#include <util/delay_basic.h>
#define F_CPU 12000000UL
 
void nastaveni_casovace();
void sonar_activate_trigger();
void nastaveni_preruseni();
void namereno();
 
void delay(unsigned int num);
 
//USART
void USART_Init( unsigned int baud );
void USART_Transmit( char * data );
unsigned char USART_Receive();
 
char odata=0, *odesilana_data = &odata;
char pdata=0, *prijmute_data = &pdata;
 
#define UBRR 77
 
#define led_potvrzeni_prijmu PORTB |= _BV(PB0)
#define fled_potvrzeni_prijmu PORTB &= ~(_BV(PB0))
#define sonar_pin PIND & 0x08
#define sonar_activate DDRD |= 0x08, PORTD |= _BV(PD3)
#define sonar_deactivate DDRD &= 0xF7, PORTD &= ~(_BV(PD3)), PIND &= 0xF7
#define led_namereno PORTB |= _BV(PB0), DDRB |= 0x01
#define fled_namereno PORTB &= ~(_BV(PB0))
#define zapni_INT1 GICR |= (1<<INT1)
#define vypni_INT1 GICR &= ~(_BV(INT1))
#define zapni_casovac0 TIMSK |= (1<<OCIE0)
#define vypni_casovac0 TIMSK &= ~(_BV(OCIE0))
#define zapni_casovac1 TIMSK |= (1<<OCIE1A)
#define vypni_casovac1 TIMSK &= ~(_BV(OCIE1A))
#define zapni_casovac2 TIMSK |= (1<<OCIE2)
#define vypni_casovac2 TIMSK &= ~(_BV(OCIE2))
 
unsigned int sonar_fr=0,*sonar = &sonar_fr; // 58us = 1cm
unsigned int sonar_vzdalenost_m=0, *sonar_m = &sonar_vzdalenost_m;
 
unsigned int vzdalenost_od_predni_prekazky=0, *vzdalenost = &vzdalenost_od_predni_prekazky;
 
unsigned int timer1_nacasovani = 0, *timer1 = &timer1_nacasovani;
 
int main(void) 
{
	nastaveni_casovace();
	nastaveni_preruseni();
	USART_Init(UBRR);
	sei();
 
//	char msg[100] = "Naměřená vzdálenost je: ";
	char numStr[10];
 
	while(1)
	{	
		if(!(*odesilana_data))
		{
			sprintf(numStr, "%d", *vzdalenost);
			strcat(numStr, " cm "); 
			USART_Transmit(numStr);
		}
	}
 
	return 0;
}
 
void delay(unsigned int num)
{
	unsigned int j;
	for (j = 0; j < num; j++);
}
 
ISR(INT1_vect)
{
	zapni_casovac0;
}
 
 
ISR(TIMER0_COMP_vect)
{
	if(sonar_pin)
	{
		++*sonar;
		if(*sonar == 100)
		{
			++*sonar_m;
			*sonar = 0; 
		}
	}
 
	else
	{
		vypni_casovac0;
	}
}
 
ISR(TIMER1_COMPA_vect)
{
	++*timer1;
	if(*timer1 == 1)
	{
		namereno();
	}
 
	if(*timer1 == 2)
	{
		sonar_activate_trigger();
		*timer1 = 0;
	}
}
 
/*ISR(TIMER2_COMP_vect)
{
 
}*/
 
 
void nastaveni_casovace()
{	
	//Timer0
	TCCR0 |= (9<<WGM01)|(1<<CS00);
	TIMSK |= (1<<OCIE0);
 
	//Timer1 WGM15
	TCCR1A |= (1<<WGM10);
	TCCR1B |= (1<<WGM12)|(5<<CS10);
	OCR1AH = 0xFF;
	OCR1AL = 0xFF;
	TIMSK |= (1<<OCIE1A);
 
	//Timer2
//	TCCR2 |= (9<<WGM21)|(1<<CS20);
//	OCR2 = 0xFF;
}
 
 
void sonar_activate_trigger()
{
	vypni_INT1;
	sonar_activate;
	_delay_loop_1(50);
	sonar_deactivate;
	zapni_INT1;
}
 
void nastaveni_preruseni()
{
	//nastavení přerušení INT1, náběžnou hranou.
	MCUCR |= (3<<ISC10);
}
 
void namereno()
{	
	if(*sonar || *sonar_m)
	{
		*vzdalenost = (*sonar + *sonar_m *100)/2.7179;
	}
 
	if(*vzdalenost>10000)
	{
		*vzdalenost=0;
	}
	*sonar=0, *sonar_m=0;
}
 
void USART_Init( unsigned int baud )
{
		// Set the port as the TxD output.
		DDRD |= 0x02;
 
		// Set baud rate
		UBRRH = (unsigned char)(baud>>8);
		UBRRL = (unsigned char)baud;
 
		// Set frame format: 8data, 1stop bit.
		UCSRC = (1<<URSEL)|(3<<UCSZ0);
 
}
 
 
void USART_Transmit( char * data )
{
	if ((!(*odesilana_data)) && (*timer1 == 1))
	{ 
		odesilana_data = data;
 
		// Disable interrupt to receive data and send data to permit
		UCSRB &= 0x7F; // RXCIE 0
		UCSRB |= (1<<UDRIE)|(1<<TXEN);
	}
 
}
 
// Data transfer using interrupt.
ISR(USART_UDRE_vect)
{
	// Put data into buffer, sends the data.
	if(*odesilana_data)
	{
		UDR = *odesilana_data;
		odesilana_data++;
	}
 
	else
	{
		UCSRB &= 0xDF; // UDRIE 0
	}
}
 
 
unsigned char USART_Receive()
{
	// 	If the previous data collected.
	if(!(*prijmute_data))
	{
		// Disable interrupt for data transmit and receiving enable
		UCSRB &= 0xDF; // UDRIE 0
		UCSRB |= (1<<RXCIE)|(1<<RXEN);
	}
 
	if(*prijmute_data)
	{
		char tmp = *prijmute_data;
		*prijmute_data = 0;
		return tmp;
	}
 
	if(!(*prijmute_data))
	{
		return 0;
	}	
}
 
// Data receive using interrupt.
ISR(USART_RXC_vect)
{		
	// Get data from buffer.
	*prijmute_data = UDR;
	UCSRB &= 0x7F; // RXCIE 0
}

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

Tato kapitola zatím v tomto článku chybí. Můžete Wikiknihám pomoci tím, že ji doplníte.

[editovat] Komunikace s PC přes USB

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í)
  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 -- cena asi 130 Kč, řada návodů na internetu

Autor má dobrou zkušenost s použitím první možnosti, tedy ovladačů od Objective Development. Pro nekomerční užití jsou zdarma pod licencí GPL. 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.

[editovat] Stavba USB programátoru

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 avrasp 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.

Poznámka 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

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.

[editovat] Dodatky

[editovat] Stručný slovníček

  • 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. S vyšší rychlostí USB 2.0 už nedokáže atmega8 pracovat.
  • 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.

[editovat] Vysokonapěťové paralelní programování

[editovat] Motivace

K nahrání programu do Atmegy8 a nastavení jejích pojistek jsme použili 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.

[editovat] Potřebný materiál

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ů

[editovat] Nahrání programu doktorovi

Doktorovi nahrajeme následující recept: Programujeme_jednočipy/VnParProg_hex_code:

sudo avrdude -p m8 -c stk200 -U flash:w:atmega8-fuse-repair.hex
Poznámka Pokud program chceme pozměnit nebo pročíst, je k dispozici zde: Programujeme_jednočipy/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

[editovat] Postup opravy pojistek

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

Atmega8 fuses repair.svg

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.

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. 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.

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

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.


Počítačový kód /* 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 ))
Upozornění 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.

[editovat] Užitečné odkazy