ATmega32 - USART

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
hcmateusz
-
Posty: 4
Rejestracja: 11 mar 2008, 12:50
Lokalizacja: Inowrocław

ATmega32 - USART

Post autor: hcmateusz » 28 maja 2008, 12:47

Witam. Mam problem. Napisalem program do wysylania danych przez RS z plytki ZL10AVR z mikrokontrolerem ATmega32. Dodatkowo w programie LabView na PC zrobilem odczyt jak i wysyl danych. Na dzien dzisiejszy program dziala tak, ze po wcisnieciu odpowiedniego przycisku na klawiaturze 4x4 wysylana zostaje odpowiednia dana (np: "1"). Na PC LabView odbiera oraz rozpoznaje dana. Wysylanie z ATmegi oraz odbior przez PC (LabView) odbywa sie swietne. Problem mam z odbiorem danych na ATmedze. Program LabView wydaje mi sie ze wysyla dana "A" do ATmelca, jednak wydaje mi sie ze zle uzywam funkcji USART_in. Prosze o pomoc. Program powinien odczytac z RS wyslana wczeniej dana z PC. Jezeli odbierze to na wyswietlaczu LED zapala sie wszystkie diody. Prosze o pomoc. Czekam na odpowiedz co robie zle.

Kod: Zaznacz cały

#include <avr/io.h> 
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include <stdlib.h>

#define CPU_Hz   8000000         
#define OSC    8               
#define BAUD   9600           
#define MYUBRR  CPU_Hz/16/BAUD-1  




// **** fukcje dla RS232 **** 
void UART_init(unsigned int ubrr)      
{ 
   UBRRH = (unsigned char) (ubrr>>8);   
   UBRRL = (unsigned char) ubrr; 
   UCSRB = (1<<RXEN)|(1<<TXEN);         
   UCSRC = (1<<URSEL)|(3<<UCSZ0);      
} 


void USART_out (unsigned char data)    // wysłanie znaku 
{ 
   while (!(UCSRA & (1<<UDRE))); 
   UDR = data; 
} 


unsigned char USART_in (void)    // odebranie znaku 
{ 
   while (!(UCSRA & (1<<RXC))); 
   return UDR; 
} 


// **** funkcja czasowa **** 
void waitms(unsigned char czas) 
{ 
   unsigned char a, b;                // zmnienne licznikowe 
   for( ; czas > 0; --czas)                // ta pętla zostanie wykonana x-razy 
      for(b = 10; b > 0; --b)          // a ta 10 razy 
         for(a = 25 * OSC; a > 0; --a)    // natomiast ta 100 razy 
            __asm("nop");             // dodatkowa instrukcja opóźniająca o 1 cykl
		 
}

int button1={0B00000110};
int button2={0B01011011};
int button3={0B01001111};
int button4={0B01100110};
int all={0B01111111};

//**** program glowny
int main(void) 
{


DDRD=0x00; //klawa ustawiona jako wejscie 00000000
PORTD=0xFF;//port ustawiony jako wyjscie 11111111

   int i; int j; int x; int z;
   char przycisk1; //inicjacja na przycisk 1
   char przycisk2; //inicjacja na przycisk 2
   char przycisk3; //inicjacja na przycisk 3
   char przycisk4; //inicjacja na przycisk 4

   przycisk1=49;	przycisk2=50;	przycisk3=51;	przycisk4=52;



//----------------------
char odbiorA; 
   odbiorA=65; //dana "A"
//----------------------




DDRA = 0xFF;
DDRB = 0xFF;
PORTA = 0xFF;
PORTB = 0x01;


while (1) {
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);


if (PIND==0xFE){
PORTB = 2;
PORTA = button1;
_delay_ms(8);
UART_init(MYUBRR);
USART_out(przycisk1);

}



if (PIND==0xFD){
PORTB=2;
PORTA=button2;
_delay_ms(8);
UART_init(MYUBRR);
USART_out(przycisk2);
}



if (PIND==0xFB){
PORTB=2;
PORTA=button3;
_delay_ms(8);
UART_init(MYUBRR);
USART_out(przycisk3);

}



if (PIND==0xF7){
PORTB=2;
PORTA=button4;
_delay_ms(8);
UART_init(MYUBRR);
USART_out(przycisk4);

}

char temp;
temp=USART_in();
if (temp==odbiorA) {
PORTB=8;
PORTA=all; }

}
}

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

Post autor: snow » 29 maja 2008, 6:32

Zrób obsługę odbioru danych na przerwaniu.

hcmateusz
-
Posty: 4
Rejestracja: 11 mar 2008, 12:50
Lokalizacja: Inowrocław

Post autor: hcmateusz » 29 maja 2008, 6:43

snow pisze:Zrób obsługę odbioru danych na przerwaniu.
No dziekuje za odp. Ale moze Pan mi podpowiedziec jak mam to zrobic. Wie Pan, od niedawna bawie sie AVR i po prostu nie znam tego jezyka na tyle dobrze, zeby zrozumiec co Pan mi napisal. Moze Pan poprawi kod. Bylbym wdzieczny.

alaris
Użytkownik
Posty: 530
Rejestracja: 21 lut 2006, 14:56
Lokalizacja: Gorzow/Poznan

Post autor: alaris » 29 maja 2008, 10:43

gaweł pisze:RTFM czyli poczytać książki.
gaweł pisze:lub literaturę w języku polskim:
Nie ma to jak kryptoreklama...

tasza
Użytkownik
Posty: 1391
Rejestracja: 21 lut 2005, 15:02

Post autor: tasza » 29 maja 2008, 12:43

alaris pisze:Nie ma to jak kryptoreklama...
Jeżeli jakieś książki, artykuły lub linki do stron są wartościowe a ich podanie nie narusza
regulaminu Forum - to się o nich wspomina. Komentarz jak w cytacie uważam za cokolwiek
nie na miejscu i dlatego uprzedzam: jakakolwiek kontynuacja tego off-topu będzie skutkowała
usuwaniem/edycją postów bądź zamknięciem wątku ze szkodą dla Autora tematu.

------------------------------------------

:arrow: hcmateusz
Myślę, że dobrze Ci zrobi lektura "Sztuki programowania..." szczególnie drugiego tomu.
To jest assemblerowy hardcore - ale jak przez to przebrniesz, to Cię już wiele nie zadziwi...
http://btc.pl/?id_prod=3086800 oraz http://btc.pl/?id_prod=4040000
hcmateusz pisze:Program LabView wydaje mi sie ze wysyla dana "A" do ATmelca,
Skoro Ci się tylko wydaje - to sprawdź - zepnij dwa porty szeregowe GND do GND, Txd do Rxd, Rxd do Txd
czyli null-modem i porozmawiaj z aplikacją LV jakimś terminalem.
Jak będzie ok - kaszkę masz w programie na kontroler.
W/g mnie niepotrzebnie tyle razy wywołujesz funkcję uart_init(), to się robi raz, gdzieś na początku
programu, aby odpalić te bloki procesora, które obsługują port szeregowy.
Co do wspomnianych przerwań - to dobry trop, ponieważ (tak na pierwszy rzut oka w Twój kod)
jest duża szansa, że przesypiasz nadsyłane przez LV znaczki, czyli - LV coś wysyła, a ty "śpisz"
w jakimś wait... jeżeli odbieranie znaczków zrobisz w przerwaniach, to nic Ci nie zginie,
ponieważ gdy nadejdzie znak z portu, zostanie on schowany do tymczasowego bufora, program
główny zainteresuje się nim kiedy będzie miał ku temu sposobność.

W tym projekcie wykorzystałam przerwania od portu szeregowego:
https://elportal.pl/index.php?module=Co ... y&ceid=145
popatrz na kod źródłowy dla AVR, wprawdzie to dużo starszy procesor, ale idea pozostaje ta sama:
https://elportal.pl/tasza/lxt/led_tree_avr.zip

hcmateusz
-
Posty: 4
Rejestracja: 11 mar 2008, 12:50
Lokalizacja: Inowrocław

Moze lepiej by bylo tak:

Post autor: hcmateusz » 30 maja 2008, 6:29

Dobrze dziekuje za wszystkie odpowiedzi. Ostatnie pytanie - w sumie porada. Co do tych przerwan to moge napisac mniej wiecej w taki sposob? :

Kod: Zaznacz cały

SIGNAL (SIG_UART_RECV) 
{ 
   unsigned char byte; 
   byte = UDR; 
  
   if (byte=='A')   // lub if (byte==odbiorA)
   { 
PORTB=8;
PORTA=all; 
   } 
}
Oczywiscie uzylbym tego kodu zamiast tego:

Kod: Zaznacz cały

char temp; 
temp=USART_in(); 
if (temp==odbiorA) { 
PORTB=8; 
PORTA=all; }
Czy ta wersja jest poprawna? Czy nie istnieje potrzeba jakiejś inicjacji przerwań wcześniej w programie. Oczywiście wiem że biblioteki #include <avr/interrupt.h>
#include <avr/signal.h> są konieczne.

Dodam ze uzywam AVR Studio z modułem WinAVR w celu umożliwienia kompilacji C.

Pozdrawiam wszystkich forumowiczow.

ODPOWIEDZ