UsART Atmega8

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
solar1
-
Posty: 14
Rejestracja: 27 kwie 2008, 8:05
Lokalizacja: Banino

UsART Atmega8

Post autor: solar1 » 27 kwie 2008, 8:20

Jako ze na elektordzie nie znalazlem pomocy - a nie umem sobie sam poradzic .. wiec wkleje watek:

Witam prosze o pomoc w takim oto temacie :
Staram sie odczytac/wyslac dane przez Usart przy pomocy AVR studio (jako ze jestem jeszcze zielony w tym temacie nie moge poradzic sobie z tym problemem sam)
Zapalanie i gaszenie Ledow mam juz za soba i teraz chcialem nauczyc sie rozmawiac z komputerem przez USART
wydukalem taki oto kod - ale niestety symulacja w avr studio blokuje sie w pewnym momecie i nie moge dojsc czemu...

Kod: Zaznacz cały

/Najpierw musisz ustawić odpowiednie parametry 
//np tak Kod: 
//unsigned char odebrane;                   //zmienna globalna - definujemy ja przed wszyskimi funkcjami unsigned - oznacza ze przyjmuje warotsc od 0 do 255 
unsigned char zmienna; 
#include <avr\sfr_defs.h>        //pozwala sterowac bitami code::blocks 
#include <avr\io.h>             //wejscia_wyjscia avr 
#define F_CPU 8000000           // tu definiujesz wartość uzywanego kwarcu 

void PORTY(void)            //Ustawiamy porty 
   { 
   DDRB|=_BV(PB0);          //ustawienie piny PB0 jako wyjscia = zapisz do rejesru 1 
   DDRB&=~_BV(PB1);         // portC0 jako wejscie (zapisz 0 do rejestru DDRC) 
   PORTB|=_BV(PB1);         // wlacz wewnetrzny rezystor podciagajacy do Vcc 
   } 

void InitUSART( unsigned long int baud ) // baud - czyli bitrate portu COM 
{ 
    
   UBRRH = (unsigned char)(((F_CPU/(16UL*baud))-1)>>8); 
   UBRRL = (unsigned char)((F_CPU/(16UL*baud))-1); 
   // Otwarty kanal odbioru i nadawania 
   UCSRB = (1<<RXEN)|(1<<TXEN); 
   // 8bitów, 2bity stopu */ 
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); 
} 

unsigned char ReceiveUSART( void )  // funkcja odbioru bajtu z RS232 
{ 

   while ( !(UCSRA & (1<<RXC)) ); 
   //odebrane = UDR;                 //zmienna odebrane przyjmuje wartosc UDR 
   return UDR; 
} 

void TransmitUSART( unsigned char data )  // funkcja wysłania bajtu po RS232 
{ 
   while ( !( UCSRA & (1<<UDRE)) ); 
   UDR = data; 
} 


void ZAMIANA(void) 
      { 
         PORTB^=_BV(PORTB0);  //zamiana stanu pinu...czyli toggle 
      } 

int main (void)              // glowna petla progamu 
{ 
   PORTY();                // ustaw porty 
   //while(1);            
   ZAMIANA();            //Odwolaj sie do petli bez parametrow 
      for (int i=0;i<200;i++);   // male opoznienie  
      zmienna = ReceiveUSART(); 
return(0); 
}
Cala zrozumiala dla mnie obsluge USARTU znalazlem na forum i powklejalem kawalki kodu do mojego ledomrygacza - usiluje odebrac znak i zapalic diode podpieta pod PB0... jak uda mi sie ta sztuka to po nacisnieciu przyciksu PB1 bede chcial nadac odebrany znak
w bascomie robilem to przy pomocu przerwan (niestety nie znam jeszcze na tyle dobrze C aby przelozyc ten program z bascoma)
w bascomie wygladalo to tak +/-

Kod: Zaznacz cały

...) 
On Urxc Rx232                                                
Set Ucr.4                                                   ' załącz odbiornik UART 
Enable Urxc 
Enable Interrupts 
(...) 
' gdy odebrano znak to: 
Rx232:                                                      ' wywolanie przerwania 
If Usr.3 = 1 Then                                           ' błąd 
  erro = 1                                                 ' ustaw flage erro na 1 
  Elseif Usr.4 = 1 Then                                     ' uszk ramka 
  erroa = 1                                                 ' ustaw flage rserr  na 1 
  Else                                                      ' wszystko poprawnie 
  Slowo = Udr                                               ' przypisz UDR do zmiennej 
  got = 1                                                ' ustaw flage 
  errb = 0                                                 ' flaga bledu 0 
 End If 
Return
bede wdzieczny za okazana pomoc :)

snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 27 kwie 2008, 8:25

W funkcji main brakuje inicjalizacji RS'a InitUSART. Skąd procesor ma wiedzieć jak ustawić USART? ;)

ZbeeGin

Post autor: ZbeeGin » 27 kwie 2008, 8:44

solar1 pisze:wydukalem taki oto kod - ale niestety symulacja w avr studio blokuje sie w pewnym momecie i nie moge dojsc czemu...
Mamy zgadywać w którym momencie się ona blokuje?

To może pierwszy strzał:

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

Nie ustawiasz ręcznie RXC w panelu z prawej.

solar1
-
Posty: 14
Rejestracja: 27 kwie 2008, 8:05
Lokalizacja: Banino

Post autor: solar1 » 27 kwie 2008, 9:15

:) dziekuje za tak szybka odpowiedz !!
fakt nie inicjowalem predkosci usartu w mainie <bo pewnie jest to zlepek kodow ktore to znalazlem na elce i innych portalach a niestety http://avr.elektroda.eu/?q=node/16 - cos co powinno by kompendium wiedzy - jest strasznie ale to strasznie nieakutalne>
teraz main u mnie wyglada tak :

Kod: Zaznacz cały

int main (void)  				// glowna petla progamu
{
	PORTY(); 					// ustaw porty
	//while(1);            
	ZAMIANA();				//Odwolaj sie do petli bez parametrow
		for (int i=0;i<200;i++);   // male opoznienie  
		//ReceiveUSART()=zmienna ;
		//zmienna = ReceiveUSART();
	InitUSART(9600); // inicujemy usart z predkoscia nam odpowiadajaca i zgodna z 
					// mozliwosciami zegara
while ( !(UCSRA & (1<<RXC)) ); // 
	ZAMIANA();	
return(0);
}
Rozumem ze "while ( !(UCSRA & (1<<RXC)) ); "
to petla ktora czeka az w rejestrze UCSR 0x01 pojawi sie 1 i program poleci dalej - ale jakt to zrobic w przerwaniach ? ... mowie w bascomie to jakos szlo a tu to totalna nowosc d dla mnie
:D :mrgreen:
btw fajne forum nie takie - zkostniale jak elekda

snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 27 kwie 2008, 9:17

solar1 pisze:fakt nie inicjowalem predkosci usartu w mainie <bo pewnie jest to zlepek kodow ktore to znalazlem na elce i innych portalach a niestety http://avr.elektroda.eu/?q=node/16 - cos co powinno by kompendium wiedzy - jest strasznie ale to strasznie nieakutalne>
Przecież tam jest inicjacja USART'a :> Przypatrz się dokładnie - na początku main'a tyle że u ciebie jest wymagane podanie ustawień RS'a a tam jest to załatwione poprzez stałe zdefiniowane na początku programu.

[ Dodano: 2008-04-27, 10:22 ]
solar1 pisze:ale jakt to zrobic w przerwaniach ?
Masz przerwanie SIG_UART_RECV i jeżeli ono wystąpi to znaczy że zakończył się odbiór.

solar1
-
Posty: 14
Rejestracja: 27 kwie 2008, 8:05
Lokalizacja: Banino

Post autor: solar1 » 27 kwie 2008, 9:31

w avr.elektroda.eu - moze i jest - ja nie wiem czemu ale od jakis 2 lat < z tego co wycztyalem> nie uzywa sie sbi i cbi.. a tam wszyskie przyklady sa oparte wlasnie na tych _makrach_ moim zdaniem to bardzo przeszkadza - poczatkujacym czyli takim jak ja !

ZbeeGin

Post autor: ZbeeGin » 27 kwie 2008, 9:38

teraz main u mnie wyglada tak :
I wygląda jeszcze straszniej.
solar1 pisze:ale jakt to zrobic w przerwaniach ?
Dodać na początku

Kod: Zaznacz cały

#include <avr/interrupt.h>
A potem to już korzystać z podprogramów obsługi przerwań (klamry wypełnić odpowiednią treścią):

Kod: Zaznacz cały

ISR(USART_RXC_vect)          //przy odebraniu znaku
{
}

ISR(USART_TXC_vect)          //przy nadaniu znaku
{
}

ISR(USART_UDRE_vect)          //jeśli bufor pusty
{
}
W programie głownym uaktywnić potrzebne źródła przez ustawienie odpowiednich bitów w rejestrze UCSRB tj. RXCIE, TXCIE, UDRIE oraz włączyć system przerwań przez sei();. To wszystko... (chyba).

Awatar użytkownika
RcTomek
Moderator
Posty: 243
Rejestracja: 27 wrz 2007, 21:15
Lokalizacja: Głogów / Wrocław

Post autor: RcTomek » 27 kwie 2008, 9:46

sbi i cbi to instrukcje asemblerowe ustawiające/zerujące dany bit w rejestrze funkcyjnym. Ich ograniczenie polega na tym, że operują jedynie na dolnej części podstawowej przestrzeni I/O (czyli od 0x20 do 0x3F). Używając tych instrukcji posługujemy się adresami 0d 0x00 do 0x1F (wymagają adresowania z przesunięciem o -0x20).

snow
Użytkownik
Posty: 794
Rejestracja: 16 sty 2007, 3:44
Lokalizacja: lubelskie
Kontakt:

Post autor: snow » 27 kwie 2008, 10:11

solar1 pisze:a tam wszyskie przyklady sa oparte wlasnie na tych _makrach_ moim zdaniem to bardzo przeszkadza - poczatkujacym czyli takim jak ja !
Faktycznie może to komplikować nieco w nowych kompilatorach. Aby te makra stosować można dołączyć do programu bibliotekę

Kod: Zaznacz cały

#include <compat/deprecated.h>
gdy korzysta się z WinAvr.

solar1
-
Posty: 14
Rejestracja: 27 kwie 2008, 8:05
Lokalizacja: Banino

Post autor: solar1 » 27 kwie 2008, 10:59

Nadal twierdze ze to dla "nowych" tylko komplikacja - ktos mial jakis cel w usunieciu Sbi i cbi <ktos opisal czemu > nie wydaje mi sie zeby byl sens w podtrzymywaniu "zlych" nawykow - a przynajmniej ja chcialbym sie nauczyc jak to zrobic poprawnie "po nowemu"
WinAVR uzywam tylko poto aby uruchomic programy napisane w AVR studio w VMLAB .... <chyba ze avr studio moze jakos dzialc z VMLABEM bez koniecznosci uzywania winAVR>
... to co pisze moze dla was jest malo sensowne - ale ja zaczyna i widze problemy ktore dla was sa niezauwazalne tj:
Brak ONline Prostego i przystepnego poradnika - jak zaczac <takiebo bez cbi i sbi>
Brak Online opisu VMlab - konfiguracja i uruchamianie swoich programow w tym symulatorze... bo z tego co widze to jak juz ktos raz nauczyc sie to zrobic nie jest chetny do podzielenia sie swoja wiedza- albo poprostu nie ma czasu i uczy sie czegos nowego...
chyba ze moje poszukiwania w google byly marne i to co pisze jest nieprawda...to prosze mnie poprawic :)


a co do programu mojego tj zapalenie diody przy odebraniu znaku z uart i wyslanie tego odebranego znaku z uartu przy pomocy przycisku wszylo mi cos takiego :

Kod: Zaznacz cały

unsigned char odebrane;                   //zmienna globalna - definujemy ja przed wszyskimi funkcjami unsigned - oznacza ze przyjmuje warotsc od 0 do 255
unsigned char zmienna;
#include <avr\sfr_defs.h>  		//pozwala sterowac bitami 
#include <avr\io.h>    			//wejscia_wyjscia avr
#include <avr\interrupt.h>		// bibloteka przerwan
#define F_CPU 8000000     		// tu definiujesz wartość uzywanego kwarcu 
//#########################Ustawiam sprzet#####################################
void PORTY(void)				//Ustawiamy porty
{
	DDRB|=_BV(PB0); 			//ustawienie piny PB0 jako wyjscia = zapisz do rejesru 1 
	DDRB&=~_BV(PB1);			// portB1 jako wejscie (zapisz 0 do rejestru DDRC)
	PORTB|=_BV(PB1);			// wlacz wewnetrzny rezystor podciagajacy do Vcc
}
//########################Ustawiam predkosc USARtu#############################
void InitUSART( unsigned long int baud ) // baud - czyli bitrate portu COM 
{ 
    
   UBRRH = (unsigned char)(((F_CPU/(16UL*baud))-1)>>8); 
   UBRRL = (unsigned char)((F_CPU/(16UL*baud))-1); 
   // Otwarty kanal odbioru i nadawania 
   UCSRB = (1<<RXEN)|(1<<TXEN); 
   // 8bitów, 2bity stopu */ 
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); 
} 

//unsigned char ReceiveUSART( void )  // funkcja odbioru bajtu z RS232 
//{ 
 //  while ( !(UCSRA & (1<<RXC)) ); 
  // odebrane = UDR;
 //  return UDR; 
//} 

void TransmitUSART( unsigned char data )  // funkcja wysłania bajtu po RS232 
{ 
   while ( !( UCSRA & (1<<UDRE)) ); 
   UDR = data; 
}
//#######################Uruchomienie usartu w przerwaniach#####################
void ActUSART(void)
 {
	UCSRB = (1<<RXCIE)|(1<<TXCIE)|(1<<UDRIE);
 }

//#######################Gdy odbiore znak#######################################
ISR(USART_RXC_vect)          //przy odebraniu znaku 
{ 
ZAMIANA();				    // zmien stan leda
//ReceiveUSART();
odebrane = UDR;
} 
//########################Co zrobic gdy nadam znak
ISR(USART_TXC_vect)          //przy nadaniu znaku 
{ 
} 
//########################Gdy nic nie odbieram##################################
ISR(USART_UDRE_vect)          //jeśli bufor pusty 
{ 
}
//#########################Mrygaie ledem #######################################
void ZAMIANA(void)
		{
			PORTB^=_BV(PORTB0);  //zamiana stanu pinu...czyli toggle
		}
//###########################Glowny program#####################################
int main (void)  				// glowna petla progamu
{
	PORTY(); 					// ustaw porty            
	InitUSART(9600);           // inicujemy usart z predkoscia nam odpowiadajaca i zgodna z 
	ActUSART();					//aktywoj usart via przerwania
	sei();						//uruchom przerwania

					// mozliwosciami zegara
	//	for (int i=0;i<2000;i++);   // male opoznienie  
	while(1)
	{
		
	  if (bit_is_clear(PINB, 1)) //jezeli na pinie B 1 jest stan niski to
			{
			TransmitUSART(odebrane);   // zmienna odebrana przypisz    do   transmisji
			}
	}
	return(0);
}
w symulatorze avr studio wyglada ze dziala to poprawnie odklikujac flagi w Usarcie program przechodzi do odpowiednich podprogramow .. wlasnie staram sie to uruchomic w vmlab z wirtualnym terminalem

ZbeeGin

Post autor: ZbeeGin » 27 kwie 2008, 11:24

Drobna uwaga. Nie powinieneś umieszczać tu pustego przerwania UDRE - przecież go nie używasz, a będzie one zgłaszane nieustannie. Nie aktywuj go i nie pisz procedury ISR(USART_UDRE_vect).
solar1 pisze:WinAVR uzywam tylko poto aby uruchomic programy napisane w AVR studio w VMLAB .... <chyba ze avr studio moze jakos dzialc z VMLABEM bez koniecznosci uzywania winAVR>
.
Trochę to dziwnie "zakręcone". Programy piszesz w AVRStudio, które on kompiluje z wykorzystaniem wtyczki AVRGCC za pomocą WinAVR, a potem importujesz wszystko do VMLab. Po co? Wystarczy program napisać w Programmers Notepad, określić co trzeba w pliku makefile (z reguły tylko 2 linijki do porawy) i z poziomu tegoż edytora skompilować - takie funkcje są tam już standardowo. Jestem pewien, że prędzej dałoby się ożenić Programmers Notepad z VMLab, gdyż ma on bardzo duże możliwości konfiguracji narzędzi.

A o integracji AVR Studio z VMLab nie słyszałem.

Co do jego opisu to znalazłem m.in. to: http://www.tkdami.net/~voytek/vmlab.html i chyba da się wszytko robić z poziomu VMLab.

[ Dodano: 2008-04-27, 12:52 ]
I właściwie się udało twój program skompilować przez WinAVR z poziomu VMLab. Zatem chyba to nie takie straszne.

solar1
-
Posty: 14
Rejestracja: 27 kwie 2008, 8:05
Lokalizacja: Banino

Post autor: solar1 » 27 kwie 2008, 11:53

udalo mi sie znalesc inny symulator ktory dziala z avrstudio <ale i tak wymaga winavr>
http://www.helmix.at/hapsim/#hapsimdownload
- jako symulator wyglda swietnie i z tego co widze nie trzba modyfikowac kodu tak jak to wymaga vmlab
Jest to calkowicie oddzielna aplikacja ktora dziala z avr studio :)

[ Dodano: 2008-05-04, 08:09 ]

Kod: Zaznacz cały

//Najpierw musisz ustawić odpowiednie parametry 
//np tak Kod:
unsigned char odebrane;                   //zmienna globalna - definujemy ja przed wszyskimi funkcjami unsigned - oznacza ze przyjmuje warotsc od 0 do 255
unsigned char zmienna;
#include <avr\sfr_defs.h>  		//pozwala sterowac bitami code::blocks
#include <avr\io.h>    			//wejscia_wyjscia avr
#include <avr\interrupt.h>		// bibloteka przerwan
#include <avr\pgmspace.h>
//#include <string.h>
//#include "bool.h"
#define F_CPU 8000000     		// tu definiujesz wartość uzywanego kwarcu 

// bin2hex macro: convert a binary nibble (0..f) into its ASCII-HEX digit '0'..'f'
#define bin2hex(dat)	(dat = (dat>9)? dat+'a'-10: dat+'0')

void UART_Transmit0(uint8_t data)
{
	while(!(UCSRA & _BV(UDRE)));	// wait for empty transmit buffer
	UDR = data;
}


//#########################Ustawiam sprzet#####################################
void PORTY(void)				//Ustawiamy porty
{
	DDRB|=_BV(PB0); 			//ustawienie piny PB0 jako wyjscia = zapisz do rejesru 1 
	DDRB&=~_BV(PB1);			// portB1 jako wejscie (zapisz 0 do rejestru DDRC)
	PORTB|=_BV(PB1);			// wlacz wewnetrzny rezystor podciagajacy do Vcc
}
//########################Ustawiam predkosc USARtu#############################
void InitUSART( unsigned long int baud ) // baud - czyli bitrate portu COM 
{ 
    
   UBRRH = (unsigned char)(((F_CPU/(16UL*baud))-1)>>8); 
   UBRRL = (unsigned char)((F_CPU/(16UL*baud))-1); 
   // Otwarty kanal odbioru i nadawania 
   UCSRB = (1<<RXEN)|(1<<TXEN); 
   // 8bitów, 2bity stopu */ 
   UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); 
} 

unsigned char ReceiveUSART( void )  // funkcja odbioru bajtu z RS232 
{ 
   while ( !(UCSRA & (1<<RXC)) ); 
   odebrane = UDR;
   return UDR; 
} 

void TransmitUSART( unsigned char data )  // funkcja wysłania bajtu po RS232 
{ 
   UDR = data;
   while ( !( UCSRA & (1<<UDRE)) ); 
}
//#######################Uruchomienie usartu w przerwaniach#####################
void ActUSART(void)
 {
	UCSRB = (1<<RXCIE)|(1<<TXCIE)|(1<<UDRIE);
 }

//#######################Gdy odbiore znak#######################################
ISR(USART_RXC_vect)          //przy odebraniu znaku 
{ 
ZAMIANA();				    // zmien stan leda
//ReceiveUSART();
odebrane = UDR;
} 
//########################Co zrobic gdy nadam znak
ISR(USART_TXC_vect)          //przy nadaniu znaku 
{ 
} 
//########################Gdy nic nie odbieram##################################
//ISR(USART_UDRE_vect)          //jeśli bufor pusty 
//{ 
//}
//#########################Mrygaie ledem #######################################
void ZAMIANA(void)
		{
			PORTB^=_BV(PORTB0);  //zamiana stanu pinu...czyli toggle
		}
//###########################Glowny program#####################################
int main (void)  				// glowna petla progamu

{

    PORTY(); 					// ustaw porty            
	InitUSART(9600);           // inicujemy usart z predkoscia nam odpowiadajaca i zgodna z 
	ActUSART();					//aktywoj usart via przerwania

	sei();						//uruchom przerwania
					// mozliwosciami zegara
	//	for (int i=0;i<2000;i++);   // male opoznienie  
	for ( ; ; ){
		
	        if (bit_is_clear(PINB, 1)) //jezeli na pinie B 1 jest stan niski to
			{
			//TransmitUSART("P");   // zmienna odebrana przypisz do transmisji
			UART_Transmit0("P");
			}
	}
}
Doszedlem do takiego kodu - jednak nieskaczona petla <tak mowi mi ksiazka > ciagle wyskakuje poza siebie, poza tym transmitowany znak jest zupelnie inny staram sie wyslac P a w odpowiedzi dostaje `

ODPOWIEDZ