ATmega8 UART ovládanie LED

Nazdar.
Aj v tento sviatočný deň(24.12 :smiley:) sa trápim z programovaním. Viete mi prosím dať príklad ako ovládať LED cez UART?
Mám procesor ATMEGA8 ext kristál 14,7456MHz. Komunikácia medzi ATmegou a PC funguje bez problémov (odošlem SVET vrati sa SVET)

Neviem ale ako mám dorobiť to že keď dám napr. LED zap tak sa LED na porte PD7 rozsvieti a ked dám LED vyp tak zhasne.
Ano skušal som hladať na google ale asi zle lebo žiaden takýto príklad neviem nájsť.

Mám len toto.

[code]#include <avr/io.h>
#include <util/delay.h>

//prijmuti znaku

unsigned char uart_getc( void )

{

//cekani na prijem dat

while ( !(UCSRA & (1<<RXC)) )

;

//vraceni registru UDR

return UDR;

}
// posláni znaku
void uart_putc(unsigned char data )

{
//cekani na odeslani dat
while ( !( UCSRA & (1<<UDRE)) )

;

UDR = data;

}
int main(void)

{

DDRD |= (1 << PD7); //PD7 ako výstupný (LED)

int znak;

  /***** inicializace uart  *****/

  UCSRA = 0x02;

  UBRRH = 0x00;  // nastaveni rychlosti pro krystal 1MHz

  UBRRL = 191;

  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);
  }

}
[/code]

Přečíst znak umíš, odeslat echo taky. Teď už stačí čtené znaky skládat do řetězce a pokud se řetězec shoduje s tím, co potřebuješ, provedeš požadovanou akci. Přeji hezký sváteční den.

sprav si nejake pole, trebars volatile char pole[20]; a donho si ukladaj kazdy znak ktory ti pride. Na konci stringu ktory posielas do atmegy odosli aj “\n”, a ked atmega zachyti tento znak, porovnas prijate znaky so stringom ktory ocakavas pole[0] = "L" pole[1]= "E"... atd Ak to plati tak togglujes ledkou: PORTD ^= (1<<PD7);

Pro začátek můžeš zvolit jednoznakové příkazy.
Např klávesa ‘A’ zapne Led a ‘B’ ji vypne.
Smyčku while(1) pak změň takto:

[code] while(1)
{
znak = uart_getc();

        if ((znak == 'A') || (znak == 'a'))
        PORTD |= (1 << PD7);  // zapni Led
        
        if ((znak == 'B') || (znak == 'b'))
        PORTD &= ~(1 << PD7);  // vypni Led
 } [/code]

Místo
int znak;
použij
unsigned char znak;

Zásada je používat nejmenší vyhovující typ.
A uart přenáší bajt.

Dakujem.
Takto mi to funguje len ajtak sa chcem naučiť tie polia.
Teraz aj ked napisem ahoj tak sa zapne lebo je tam “a”

a tie polia vobec nechapem nijako mi to nefunguje.

Ak nechapes polia tak si sa nevybral spravnou cestou. Nastuduj si zaklady napr. z knihy od Herouta: “Ucebnice jazyka C”.

Je to celkem jednoduché :

unsigned char retezec[100];

Ti nadefinuje proměnnou retezec o délce 100 prvků (0-99) typu unsigned char.
K indexování doporučuji použít opět unsigned char :

unsigned char index;

Můžeš to zapsat i takto :

unsigned char retezec[100], index;

Ještě k tomu přidáme proměnnou pro data a nebude od věci proměnné označit jako volatile :

volatile unsigned char retezec[100], index, data;

Číst pak budeš následovně :

[code]ISR(USART_RXC_vect)
{
// Čtení pomocí přerušení je efektivnější - neplýtváš zbytečně strojovým časem. Stejně se ale funkce dá napsat i pro klasické volání

data=UDR; // Přečíst přijatý byte
UDR=data; // odeslat echo do PC - nemusí být.

if (index<99) index++; // Prodloužit retězec pouze v případě, že ještě nejsme na konci.
retezec[index]=data; // Zapsat přijatý byte do řetězce.
}

void main(void)
{
// Tady bude inicializace

while(1)
{
sleep(); //
if (retezec[index]==13) // Pokud je poslední načtený znak ENTER, pak se provede následující část programu
{
retezec[index]=0; // Ukončit string pro další zpracování.
if (strcmp (retezec, “LED on”)==0) LED_ON; // Pokud je řetězec “LED on”, LEDku rozsvítí
if (strcmp (retezec, “LED off”)==0) LED_OFF; // Pokud je řetězec “LED off”, LEDku zhasne
if (strcmp (retezec, “LED toggle”)==0) LED_TOG; // Pokud je řetězec “LED toggle”, LEDku přepne
do
{
index–;
retezec[index]=0; // Index je na konci řetězce, tak ho vynulujeme až do nultého znaku.
}
while (index>0);
// V tuto chvíli máme řetězec opět prázdný (s nulovou délkou) a připravený na příjem dalších dat.
}
}
}
[/code]

V programu můžou být chyby pro překlad. Například budeš muset nadefinovat LED_ON, LED_OFF a LED_TOG. Kód jsem neprohnal překladačem, ale principiálně je OK, tak snad se Ti v něm podaří zorientovat a rozběhat ho. Nebo se alespoň inspirovat. Jinak práce s polema je docela důležitá věc. Práce se znaky v řetězci je práce s poli. Řetězec (string) je de-facto jenom jeden typ pole s jednobytovými prvky typu char, pro které jsou v C implementované různé funkce.

Je to myslené takto?
Pri preklade to hodi 1 Error 0 warning.

c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr4/crtm8.o:(.init9+0x0): undefined reference to `main'

[code]#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> //Knihovna přerušení
//prijmuti znaku

unsigned char LED_ON;
unsigned char LED_OFF;

volatile unsigned char retezec[100], index, data;

unsigned char uart_getc( void )

{

void LED_ON()

{
PORTD |= (1 << PD7); // zapni LED

}

ISR(USART_RXC_vect);
{
// Čtení pomocí přerušení je efektivnější - neplýtváš zbytečně strojovým časem. Stejně se ale funkce dá napsat i pro klasické volání

data=UDR; // Přečíst přijatý byte
UDR=data; // odeslat echo do PC - nemusí být.

if (index<99) index++; // Prodloužit retězec pouze v případě, že ještě nejsme na konci.
retezec[index]=data; // Zapsat přijatý byte do řetězce.
}

void main(void)

{

  /***** inicializace uart  *****/

  UCSRA = 0x02;

  UBRRH = 0x00;  // nastaveni rychlosti pro krystal 14.7456MHz

  UBRRL = 191;

  UCSRB = 0x18;  // povolit vysilani a prijem

  UCSRC = 0x86;  // ramec dat:  8 datovych, 1 stop bit, bez parity
   
    DDRD |= (1 << PD7); //PD7 ako výstupný (LED)   

while(1)
{
sleep(); //
if (retezec[index]==13) // Pokud je poslední načtený znak ENTER, pak se provede následující část programu
{
retezec[index]=0; // Ukončit string pro další zpracování.
if (strcmp (retezec, “LED on”)==0) LED_ON; // Pokud je řetězec “LED on”, LEDku rozsvítí
if (strcmp (retezec, “LED off”)==0) LED_OFF; // Pokud je řetězec “LED off”, LEDku zhasne

  do 
  { 
    retezec[index]=0;  // Index je na konci řetězce, tak ho vynulujeme až do nultého znaku. 
    index--; 
  } 


  while (index>0); 
  // V tuto chvíli máme řetězec opět prázdný (s nulovou délkou) a připravený na příjem dalších dat. 
}

}
}
}
[/code]

  1. main asi má mít návratovou hodnotu int, ale to by asi mělo hodit jenom warn.
  2. Máš nadefinovanou pouze funkci unsigned char uart_getc( void ). Všechno ostatní je její součástí - zkontroluj si zápis. A hlavně, pokud si projdeš program, zjistíš, co tam nechat a co vyhodit.
  3. ISR(???) je funkce obsluhující přerušení.
  4. V inicializaci USARTu Ti chybí povolení přerušení od USARTu.

Pak Ti tam chybí ještě povolení globálního přerušení. Ale Cčko Tě tady učit nebudu, musíš si o tom něco najít. Ukázal jsem Ti směr a napsal podstatnou část kódu. Definici LED_ON a LED_OFF jsi evidentně nepochopil. Nápověda : projdi si direktivy překladače #define. Jde to samozřejmě i jinak, ale právě na #define jsem to směroval. Nejenom kvůli zjednodušení zápisu pro rozsvícení a zhasnutí LEDky, ale i třeba pro definici konstant používané při překladu. Tím nemyslím jenom čísla, ale třeba i pozice signálu na portu apod.

Ok trocha som to prerobil ale skusim to až zajtra.
ešte tam treba to prerusenie od UARTu

[code]#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> //Knihovna přerušení

volatile unsigned char retezec[100], index, data;

//*******************************************************************************//

ISR(USART_RXC_vect)
{
// Čtení pomocí přerušení je efektivnější - neplýtváš zbytečně strojovým časem. Stejně se ale funkce dá napsat i pro klasické volání

data=UDR; // Přečíst přijatý byte
UDR=data; // odeslat echo do PC - nemusí být.

if (index<99) index++; // Prodloužit retězec pouze v případě, že ještě nejsme na konci.
retezec[index]=data; // Zapsat přijatý byte do řetězce.
}

//********************************************************************************//

void LED_ON()

{
PORTD |= (1 << PD7); // zapni LED
}

void LED_OFF()

{
PORTD &= ~(1 << PD7); // vypni LED
}

//********************************************************************************//

int main(void)

{

  /***** inicializace uart  *****/

  UCSRA = 0x02;

  UBRRH = 0x00;  // nastaveni rychlosti pro krystal 14.7456MHz

  UBRRL = 191;

  UCSRB = 0x18;  // povolit vysilani a prijem

  UCSRC = 0x86;  // ramec dat:  8 datovych, 1 stop bit, bez parity

  UCSRB |= (1 << RXCIE);

sei();								//Povol prerušenia.

   
    DDRD |= (1 << PD7); //PD7 ako výstupný (LED)   

while(1)
{

if (retezec[index]==13) // Pokud je poslední načtený znak ENTER, pak se provede následující část programu 
{ 
  retezec[index]=0;  // Ukončit string pro další zpracování. 
  if (strcmp (retezec, "LED on")==0) LED_ON;  // Pokud je řetězec "LED on", LEDku rozsvítí 
  if (strcmp (retezec, "LED off")==0) LED_OFF;  // Pokud je řetězec "LED off", LEDku zhasne 

  do 
  { 
    retezec[index]=0;  // Index je na konci řetězce, tak ho vynulujeme až do nultého znaku. 
    index--; 
  } 


  while (index>0); 
  // V tuto chvíli máme řetězec opět prázdný (s nulovou délkou) a připravený na příjem dalších dat. 
}

}
}
[/code]

  1. Přepiš

retezec[index]=0; // Index je na konci řetězce, tak ho vynulujeme až do nultého znaku. index--;

na

index--; retezec[index]=0; // Index je na konci řetězce, tak ho vynulujeme až do nultého znaku.

nebo na

retezec--index]=0; // Index je na konci řetězce, tak ho vynulujeme až do nultého znaku.

Měl jsem tam chybu. Sice jsem jí opravil, ale byl jsi rychlejší - zkus přiít na to jakou.

  1. Pořád jsi ještě nepovolil RXC přerušení od USARTu (já vím - psal jsi to, ale do shrnutí to patří).

  2. Pořád ještě nemáš nadefinované LED_ON a LED_OFF.

  1. Ta chyba je že sme sa nedostali na koniec reťazcu alenajprv sme ho nulovali?

  2. ešte otázka na čo slúži?

   sleep();  // 

stímto mi to nejde komprimovať.

3)Nerozumiem tomu nadefinované LED_ON a LED_OFF.
To mám dať

#define LED_ON PD7 #define LED_OFF PD7

som myslel že LED_ON volá

[code]void LED_ON()

{
PORTD |= (1 << PD7); // zapni LED
} [/code]

a LED_OFF

[code]void LED_OFF()

{
PORTD &= ~(1 << PD7); // vypni LED
} [/code]

alebo takto?

char retezec = "LED on" char retezec = "LED off"

V programu jsem našel ještě další chybu, takže by Ti to takhle nikdy nefungovalo, neboť řetězec i přes zápis dat z USARTu zůstává trvale prázdný. Chyba je v rutině obsluhy přerušení. To byla malá nápověda a pokud na ní nepřijdeš, tak se k ní vrátíme později a vysvětlím Ti co a jak. Abys mne správně pochopil - nechci Ti psát tupě funkční kód. Vidím, že se snažíš Cčko naučit, tak se Tě snažím navést. A teďka k jednotlivým bodům :



  1. Musíš si především uvědomit, jaký je obsah jednotlivých proměnných v okamžiku, kdy se mcu dostane do dané části programu.
    Jaký je tedy stav :
    mcu se dostane do zpracování řetězce v tuto chvíli :

if (retezec[index]==13) // Pokud je poslední načtený znak ENTER, pak se provede následující část programu
Tedy v okamžiku, kdy v proměnné retezec na pozici index je hodnota 13 => ENTER.
Následují tyto akce :

retezec[index]=0; // Ukončit string pro další zpracování.

Do proměnné retezec na pozici index se místo hodnoty 13 zapíše hodnota 0 (nikoliv znak ‘0’). Je to z toho důvodu, že řetězce se v Cčku ukončují právě nulou.

V tuto chvíli je tedy v proměnné retezec to, co jsi poslal po USARTu, ale už bez toho znaku ENTER. Následuje kontrola načteného textu a akce.
V proměnné index je pozice právě toho ukončovacího znaku (té 0) za řetězcem.

V původním kódu je toto :

do { retezec[index]=0; // Index je na konci řetězce, tak ho vynulujeme až do nultého znaku. index--; } while (index>0);

Tedy - do řetězce na pozici index dám ukončovací znak a index snížím o 1. Pokud je index>0, akci opakuju. No jo, jenže jakmile je index nula, tak se akce pro retezec[0] už neprovede a v řetězci zbyde první znak a délka řetězce na konci nebude 0 znaků, ale 1 znak. Z toho důvodu bylo nutné přehodit pořadí příkazů => nejdřív odečíst 1 od proměnné index, pak zapsat 0 do řetězce a pak teprve provést kontrolu index na 0. Výsledek je toto :

do { retezec--index]=0; // Index je na konci řetězce, tak ho vynulujeme až do nultého znaku. } while (index>0);

V tomto okamžiku je na konci výsledek takový, že řetězec obsahuje 0 znaků a index=0.

Ale POZOR ! Když napíšeš retezec[index–]=0; místo **retezec–index]=0; ** nebude to fugnovat správně. Rozdíl je v tom umístění (platí i pro ++).

Pokud napíšeš --X, provede se nejdřív dekrementace X a pak teprve operace s proměnnou.
Pokud napíšeš X–, provede se nejdřív operace s proměnnou X a pak teprve dekrementace.

Tedy:
A=0;
X=5;
A=++X; není totéž jako A=X++;

V případě A=++X; se provede : X=X+1; A=X; => výsledek je A=6, X=6
V případě A=X++; se provede : A=X; X=X+1; => výsledek je A=5, X=6



  1. sleep(); je správně sleep_cpu();. Je to funkce pro uspání procesoru. Najdi si sleep modes a co vlastně dělá. V drtivé většině programů není nutné, aby mcu běžel trvale, ale může se v každém cyklu nekonečné smyčky po provedení všech akcí uspat. Procesor se ze sleepu budí jakýmkoliv povoleným přerušením. Vetšinou to bývá přerušení od timeru, ale třeba i externím přerušením (obsluha tlačítek nebo nějakého čidla) atd.


3)Direktiva #define Ti pomáhá při spoustě různých definic.

a) LED_ON ani LED_OFF nic nevolá (nejsou tam () závorky).

b) Deklaraci funkcí

[code]void LED_ON()

{
PORTD |= (1 << PD7); // zapni LED
}
[/code]

máš špatně - jaké jsou parametry funkce ? To překladač neví.

Ale vraťme se k direktivě #define :

Místo LED_ON dosaď to, co máš v direktivě :

#define LED_ON PD7 if (strcmp (retezec, "LED on")==0) LED_ON; // Pokud je řetězec "LED on", LEDku rozsvítí
Výsledek je nesmysl :

if (strcmp (retezec, "LED on")==0) PD7; // Pokud je řetězec "LED on", LEDku rozsvítí

Můžeš tam samozřejmě napsat místo LED_ON volání tvé funkce, ale místo jedné instrukce tam můžeš mít i 3 a více (v závislosti na nastavení optimalizace překladače). Minimálně call+provedení_akce+ret. S optimalizací tam může být jen to provedení akce, ale taky tam může být nasypáno volání podprogramu plus nějaké uschovávání registrů atd. Direktiva #define musí být tedy zapsaná tak, aby výsledný kód byl :

if (strcmp (retezec, "LED on")==0) PORTD |= (1 << PD7); // Pokud je řetězec "LED on", LEDku rozsvítí
Jak tedy bude direktiva vypadat zkus dát dohromady sám.

Direktiva se používá ke spoustě definic. Například :

#define CERVENA_LED PB1 #define ZELENA_LED PB0 #define ZLUTA_LED PB4 #define LED_PORT PORTB #define LED_PIN PINB #define LED_DDR DDRB

V programu pak můžeš napsat :

LED_PORT|=(1<<ZLUTA_LED);

Pokud se pak rozhodneš, že žlutou LEDku dáš z PB4 na PB7 (třeba kvůli zjednodušení DPS), tak v programu stačí přesat 1 místo a nemusíš hledat, kde všude jsi v programu napsal PORTB|=(1<<PB4), abys to upravil.

A pro svoje pohodlí můžeš jít ještě dál, když do výše zmíněných definic přidáš :

#define CERVENA_ON LED_PORT|=(1<<CERVENA_LED) #define CERVENA_OFF LED_PORT&=~(1<<CERVENA_LED) #define ZELENA_ON LED_PORT|=(1<<ZELENA_LED) #define ZELENA_OFF LED_PORT&=~(1<<ZELENA_LED) #define ZLUTA_ON LED_PORT|=(1<<ZLUTA_LED) #define ZLUTA_OFF LED_PORT&=~(1<<ZLUTA_LED)

V kódu pak můžeš psát :

CERVENA_ON; ZLUTA_OFF;



Teď Tě nechám ještě přemýšlet nad tou chybou v příjmu dat z UARTu. Je to velmi jednoduhá oprava, nicméně bez ní to fungovat nebude. Abych Tě nasměroval, chyba je podobná té, co byla v nulování řetězce.

Aj mám obavu či to robím dobre :slight_smile: .

Každopádne sa chcem poďakovať za to že si nachádzate na mňa čas ma niečo naučiť aj keď som asi beznádejný prípad. Neplánujem sa živiť programovaním ,ale ma to dosť zaujíma pre vlastné potreby a radosť (HOBBY).

Teraz k veci.

Priznávam. Toto som len tak tresol a je to zle. Je to ten Príjem z UARTu

Ak je index<99 pripočítame 1.
na koniec zapiseme data do retazca

[code]ISR(USART__RXC_vect)
{

data=UDR; // Přečíst přijatý byte
UDR=data; // odeslat echo do PC - nemusí být.

if (index<99) index++;  // Prodloužit retězec pouze v případě, že ještě nejsme na konci. 
    retezec[index]=data;  // Zapsat přijatý byte do řetězce.

} [/code]

Celí kód so upravil takto. V inicializácií je doplnené aj to prerušenie.

[code]
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> //Knihovna přerušení

#define LED_PORT PORTD
#define LED_DDR DDRD
#define LED_PIN PIND

#define LED_1 PD7

#define LED_1_ON LED_PORT|=(1<<LED_1) //LED1 zapne.
#define LED_1_OFF LED_PORT&=~(1<<LED_1) //LED1 vzpne.

//*****************************************************************************//

volatile unsigned char retezec[100], index, data;

//*******************************************************************************//

ISR(USART__RXC_vect)
{
// Čtení pomocí přerušení je efektivnější - neplýtváš zbytečně strojovým časem. Stejně se ale funkce dá napsat i pro klasické volání

data=UDR; // Přečíst přijatý byte
UDR=data; // odeslat echo do PC - nemusí být.

if (index<99) index++;  // Prodloužit retězec pouze v případě, že ještě nejsme na konci. 
    retezec[index]=data;  // Zapsat přijatý byte do řetězce.

}

//********************************************************************************//

int main(void)
{

/**************************** inicializace uart *****************************/

  UCSRA = 0x02; 

  UBRRH = 0x00;  // nastaveni rychlosti pro krystal 14.7456MHz 

  UBRRL = 191; 

  UCSRB = 0x18;  // povolit vysilani a prijem 

  UCSRC = 0x86;  // ramec dat:  8 datovych, 1 stop bit, bez parity 

  UCSRB |= (1 << RXCIE); 

sei(); //Povol prerušenia.

   LED_DDR |= (1 << LED_1); //PD7 ako výstupný (LED)  

//***********************************************************************************//

while(1)
{

if (retezec[index]==13) // Pokud je poslední načtený znak ENTER, pak se provede následující část programu 
{ 
  retezec[index]=0;  // Ukončit string pro další zpracování. 
  if (strcmp (retezec, "LED on")==0) LED_1_ON;  // Pokud je řetězec "LED on", LEDku rozsvítí 
  if (strcmp (retezec, "LED off")==0) LED_1_OFF;  // Pokud je řetězec "LED off", LEDku zhasne 

  do 
  { 
    index--; 
    retezec[index]=0;  // Index je na konci řetězce, tak ho vynulujeme až do nultého znaku. 
  } 


  while (index>0); 
  // V tuto chvíli máme řetězec opět prázdný (s nulovou délkou) a připravený na příjem dalších dat. 
} 

}
}[/code]

OK. #define jsi pochopil (nebo alespoň použil) správně. Ještě by nebylo od věco použít názvy signálů i v inicializacích.

Například místo

UCSRC = 0x86; // ramec dat: 8 datovych, 1 stop bit, bez parity

použít

UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // ramec dat: 8 datovych, 1 stop bit, bez parity

K přidání RXCIE jsi to použil. UCSRB můžeš klidně zapsat jedním zápisem včetně povolení přerušení.

Teďka k chybě v přerušení :

[code]ISR(USART__RXC_vect)
{

data=UDR; // Přečíst přijatý byte
UDR=data; // odeslat echo do PC - nemusí být.

if (index<99) index++;  // Prodloužit retězec pouze v případě, že ještě nejsme na konci.
retezec[index]=data;  // Zapsat přijatý byte do řetězce.

}
[/code]

  1. Pokud je index<99, pak připočteme 1 je správně.
  2. Tady jsem Tě možná jenom nepochopil správně, ale data na konec zapíšeme VŽDY.

Chyba je jinde. Pokud máš prázdný řetězec, máš index=0. To je správně. Jenže, když nejprve hodnotu zvýšíš na 1 a pak teprve zapíšeš data, pak bude 1. znak řetězce VŽDY nulový. Z tohoto důvodu bude řetězec VŽDY prázdný a nezáleží na tom, jakou hodnotu bude mít index a kolik znaků bude načtených. Chyb v programu je několik, které musíme odstranit. První chybou tedy je, že se nám čtený řetězec ukládá od druhé, nikoliv od **první **pozice v proměnné retezec.

Toho dosahneme touto úpravou :

[code]ISR(USART__RXC_vect)
{

data=UDR; // Přečíst přijatý byte
UDR=data; // odeslat echo do PC - nemusí být.

if ((index<98)&&(retezec[0]!=0)) index++;  // Prodloužit retězec pouze v případě, že ještě nejsme na konci a zárověň už je zapsaný první znak řetězce (pozice 0)
retezec[index]=data;  // Zapsat přijatý byte do řetězce.

}
[/code]

Navíc jsem si uvědomil, že stá pozice (retezec[99]) musí být VŽDY 0. To proto, že řetězec musí být ukončen a ukončovací znak je součástí řetězce. Proto byla snížena maximállní hodnota indexu na 98.

A teď ještě opravit další chybu, na kterou jsem přišel :

do { index--; retezec[index]=0; // Index je na konci řetězce, tak ho vynulujeme až do nultého znaku. } while (index>0);

Kód je funkční, ale pokud z PC přijde pouze ENTER, pak se nejdříve sníží index z 0 na 255 (je to unsigned char) a v tu chvíli saháme do paměti až ZA oblast vyhrazenou pro proměnnou retezec. Je potřeba vyhodnocovat proměnnou index před cyklem a ne až po něm. Zkus přijít na to jak.

Tak inicializacia je upravená takto:

[code]/**************************** inicializace uart *****************************/

  UCSRA = (1<<U2X); 

  UBRRH = 0x00;  // nastaveni rychlosti pro krystal 14.7456MHz 

  UBRRL = 191; 

  UCSRB = (1<<RXEN) | (1<<TXEN) | (1 << RXCIE);	//prijem, vyslanie   

  UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // ramec dat:  8 datovych, 1 stop bit, bez parity 

  sei();                        //Povol prerušenia. 

  LED_DDR |= (1 << LED_1); //PD7 ako výstupný (LED.)  

//***********************************************************************************//
[/code]

Z tvojho popísu som pochopil že bi to nemalo fungovať keď sa dá len ENTER a nič iné, no ono to funguje zapnem terminál odošlem (nič) len ENTER a potom dám LED on a ledka sa rozsvieti LED off led zhasne.

Ďalej čo ma zaujíma je že vždy ked niečo odošlem z terminalu tak sa to iste vráti naspäť.
Kde sa nachádza funkcia na to odoslanie?
To je:

odošlem LED on
Vráti sa LED on
LED sa rozsvieti.

Mas to aj okomentovane v kode:

UDR=data;  // odeslat echo do PC - nemusí být.

Aha vďaka nevedel som že je to toto.

Takže kod funguje. Uvidím čo napíše ešte Balů na ten ENTER no mne sa zdá že to funguje dobre.

Takže ďakujem vám a najme Balů ovi patrí VELKÉ ĎAKUJEM.

Nepsal jsem, že to nebude fungovat. Jenom jsem psal, že když pošleš samostatný ENTER, tak se přepíše oblast, ležící ZA místem vyhrazeným pro proměnnou retezec. To znamená, že vynuluješ celkem 256 bytů RAM. Proměnnou retezec a všechny proměnné, ležící v oblasti dalších 156 bytů za touto oblastí. To, že v tuto chvíli mažeš i proměnnou index, která je v tomto okamžiku nulová, proměnnou data, která se v přerušení naplní hodnotou UDR registru, tudíž nevadí, že se v tuto chvíli smaže a dalších 154 bytů, kde nic není, ještě neznamená, že kód funguje korektně. V okamžiku, kdy budeš mít více proměnných a budeš si je přepisovat, případně si smažeš kus zásobníku a program bude zamrzat nebo se Ti bude mcu při příjmu samotného ENTERu restartovat, budeš těžko hledat, proč to zlobí, když to bude třeba týden v pohodě fungovat, pak náhodně odešleš samostatný ENTER a máš vymalováno…

No dobre idem bádať ako nato. No keďže neviem overiť či to čo spravím je dobre tak to bude ťažké.