UART komunikacia

C,C++,C#

Moderátori: psichac, Moderátori

BaWiX
Okoloidúci
Okoloidúci
Príspevky: 17
Dátum registrácie: 03 Feb 2013, 20:57

UART komunikacia

Príspevok od používateľa BaWiX » 23 Máj 2013, 17:54

Dobrý deň,

potreboval by som pomoc :)
chcem si spraviť ovládanie ATMEGY8 cez UART ale aj tlačítkami :)
aby som mohol ovládať port D7 (zapínanie ledky)
popis si nevsimajte to pre kamaráta bolo :D lebo uz fakt nevem ako :)
plus teraz program mi úplne zmenil text na ;?;?;D?;$?;?;D?;?;?;?;D?;?;?;D?;D?;?;?;?;?;D?;?;D?;?;?;?;?;D?;?;D?;?;D?;$?;D?;D?;?;?;D?;?

pritom jak som mal len tlačítkami mi to fungovalo plus aj z ATMEGY som dostaval pohode text aký mal byt :)


Kód: Vybrať všetko

#include <avr/io.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include "uart.h" //uart 


ISR(INT0_vect){  
    PORTD |= (1 << PD7); // ledku zapnes neee? :D
uart_puts("Zapinam svetlo! \n"); //vypise 
}  
  
ISR(INT1_vect){  
    PORTD &= ~(1 << PD7); // ledku vypnes neee? :D
uart_puts("Vypinam svetlo! \n"); //vypise 
}  

ISR(USART_RXC_vect){
if(UDR=='z')
zapni_led(); 
if(UDR=='v')
vypni_led(); 
}

int zapni_led(void){
 PORTD |= (1 << PD7); // ledku zapnes neee? :D
uart_puts("Zapinam svetlo! \n"); //vypise 
return 0;
}  

int vypni_led(void) {  
    PORTD &= ~(1 << PD7); // ledku vypnes neee? :D
uart_puts("Vypinam svetlo! \n"); //vypise 
return 0;
}  


int main(){
char znak; 
uart_init(9600); //UART rychlost 
  
    DDRD |= (1 << PD7); //PD7 výstup (LED)  
      
    // PD2,PD3 tlacitko ne ?   
    DDRD &= ~((1 << PD2) | (1 << PD3));   
  
    // TA rezistor nutorny ne ?
    PORTD |= (1 << PD2) | (1 << PD3);   
  
    MCUCR |= (1 << ISC01); // dobežná hrana INT0  
    MCUCR |= (1 << ISC11); // dobežná hrana INT1  
    GICR |= (1 << INT1) | (1 << INT0); // povol  od INT1 a INT0  
  
    sei(); //prerusenie 
  
    while(1);
	{
znak=uart_getc();
if(znak=='1')
zapni_led();
else if(znak=='0')
vypni_led();
}
}  


Kód: Vybrať všetko

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <string.h>
#include "uart.h"


#define RX_UKONCENE 1
#define RX_NEUKONCENE 2


#define	BUF_SIZE 128 					// Velkost rx pola
char rx_buff[BUF_SIZE];	//inicializacia rx pola
volatile unsigned char rx_pos,rx_stav = RX_NEUKONCENE;				// ukazovatel pola, stav rx dat


/******************************************************
    inicializacia
    - nastavenie baudRate - ako vstupna premenna
    - zapne vysielac a prijimac
    - 8 datovych a 1 stop bity
******************************************************/

void uart_init(unsigned int baud)
{
    unsigned int ubrr = F_CPU/16/baud-1;

	//nastavenie prenosovej rychlosti v UBRR
	UBRRH = (unsigned char) (ubrr>>8);
	UBRRL = (unsigned char) ubrr;

	//zapni prijmac a vysielac, prerusenie pri prijime noveho znaku
	UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);

	//nastav format ramca: 8data, 1stop bity
	UCSRC = (1<<URSEL)|(3<<UCSZ0);
}

/******************************************************
    odosle bajt (znak)
******************************************************/

void uart_putc(unsigned char data)
{
	//cakaj na vyprazdnenie buffera
	while (!( UCSRA & (1<<UDRE)));

	//vloz data do buffer-a a odosli
	UDR = data;
}

/******************************************************
    odosle retazec bajtov (znakov)
******************************************************/

void uart_puts(char *s)
{
    while (*s)
      uart_putc(*s++);
}

/******************************************************
    prijem bajt-u (znak)
******************************************************/

unsigned char uart_getc(void)
{
	//cakaj na prijatie dat
	while (!(UCSRA & (1<<RXC)));

	//zober data z buffer-a
	return UDR;
}

/******************************************************
    prijem retazca znakov
******************************************************/

unsigned char uart_gets(char* rx_pole){
	
	// ak je prijimanie retazca znakov ukoncene...
	if(rx_stav == RX_UKONCENE) {
		// skopiruj buffer do pola
		strcpy(rx_pole, rx_buff);
		//zacni prijimanie retazca znova
		rx_stav = RX_NEUKONCENE;
		rx_pos = 0;
		// navratova hodnota, boli prijate data	
		return 1;	

	}else{
		// data neboli prijate...
		rx_pole = 0;
		return 0;	
	}

}


/******************************************************
prerusenie rx complete
******************************************************
ISR(USART_RXC_vect)
{

	// ak pretieklo rx pole tak ho vynuluj
	if (rx_pos == BUF_SIZE) rx_pos = 0;

	// ak neprisiel ukoncovaci znak
	if(rx_stav != RX_UKONCENE){
		
		rx_buff[rx_pos] = UDR;	// ulozenie znaku do buffer-a
	
		//ak prisiel ukoncovaci znak
		if ((rx_buff[rx_pos] == '\r') | (rx_buff[rx_pos] == '\n')){	
			rx_buff[rx_pos+1] = '\0';	// ukoncenie retazca
			rx_stav = RX_UKONCENE;	
		}else{			
			rx_pos++;	 // inkrementuj pocitadlo
		}
	}
}
*/
/******************************************************
    vycistenie buffer-a
******************************************************/

void uart_flush(void)
{
	unsigned char dummy;

	while ( UCSRA & (1<<RXC) ) dummy = UDR;
}

0

peterple
Ultimate člen
Ultimate člen
Príspevky: 2328
Dátum registrácie: 25 Jún 2013, 21:06
Bydlisko: Krajné
Vek: 57
Kontaktovať používateľa:

Re: UART komunikacia

Príspevok od používateľa peterple » 28 Jún 2013, 20:59

Ahoj.
tak na tomto si ani neviem predstaviť ako to funguje. Máš tam dve funcie ktoré riešia prerušenie pri príjme znaku. Kedy ti to fungovalo tie výpisy? Keď si tam ešte nemal tie tlačítka?
0
Ukáž múdremu chybu a on sa ti poďakuje. Ukáž chybu hlupákovi a on sa urazí.

Používateľov profilový obrázok
sharebell
Stály člen
Stály člen
Príspevky: 292
Dátum registrácie: 07 Máj 2013, 17:17
Bydlisko: HC a NR
Vek: 28

Re: UART komunikacia

Príspevok od používateľa sharebell » 28 Jún 2013, 21:10

Kód: Vybrať všetko

ISR(USART_RXC_vect)
{
if(UDR=='z')
zapni_led();
if(UDR=='v')
vypni_led();
}
toto si zmen na

Kód: Vybrať všetko

ISR(USART_RXC_vect)
{
if(UDR=='z' || UDR==1)
zapni_led();
if(UDR=='v' || UDR==0)
vypni_led();
}
a daj si odtial prec celu tu slucku

krom toho ako pise kolega hore v kniznici uartu mas 1. krat definovane prerusenie USART_RXC_vect tak si ho tam bud okomentuj alebo ho vymaz
0
RED OR BLUE ?

peterple
Ultimate člen
Ultimate člen
Príspevky: 2328
Dátum registrácie: 25 Jún 2013, 21:06
Bydlisko: Krajné
Vek: 57
Kontaktovať používateľa:

Re: UART komunikacia

Príspevok od používateľa peterple » 29 Jún 2013, 11:42

Kód: Vybrať všetko

ISR(USART_RXC_vect)
{
if(UDR=='z' || UDR==1)
zapni_led();
if(UDR=='v' || UDR==0)
vypni_led();
}
?? nechápem ako má toto pomôcť. Prečo by sa mal v UDR objaviť znak s ascii kódom 1 a 0. Ale keď už si to načal tak je to pekná zrada na programátora. UDR je totiž dvobajtová FIFO a tak sa ti môže stať že vyberieš zo sériaka dva znaky čo tam čakajú na spracovanie. Za tú dobu čo sa vo vypni_led() blokuje prerušenie na 20ms kludne môže prísť aj 10 znakov nie len dva. Tu mám štyri doporučenia:
1. znak presunúť do dočasnej premennej a potom testovať
2. obsluhy prerušení robiť čo najkratšie a neblokovať ich nejakými výpismi.
3. ten kto písal tie funkcie na obsluhu sériaka vedel čo robí. Vidno to aj podľa komentárov ktoré majú informačnú hodnotu. Ten kto to použil zjavne nepochopil prečo to tak je a pustil sa nebezpečnou cestou písania vlastných ISR funkcii na čo doplatil. Teda riešiť celú vec v hlavnom programe a nekaziť to čo je tam urobené dobre.
4. To isté platí pre INT0 a 1. Nie sú tam ošetrené zákmity tlačítka. Tiež to bude fungovať veľmi nevyspytateľne.
0
Ukáž múdremu chybu a on sa ti poďakuje. Ukáž chybu hlupákovi a on sa urazí.

Napísať odpoveď
  • Podobné témy
    Odpovedí
    Zobrazení
    Posledný príspevok