przerwanie od UARTU ATMega32
przerwanie od UARTU ATMega32
Witam serdecznie,
mam do napisania program na uC, który w zależności co odbierze z PC przez UART to wykona odpowiednią funkcję / skoczy do innego fragmentu programu. Rozwiązalem to tak:
**************************
int main(void) {
USART_Init(MYUBRR);
while(1)
{
char znak = USART_Receive();
if(znak == '1') { funkcja 1; }
if(znak == '2') P funkcja 2; }
}
}
**************************
problem jest nastepujacy: dana sterujaca programem (znak) wysylam raz na jaksi czas, a w linijce char znak ... program przestaje byc wykonywany AŹ odbierze jakiś znak. Jak to rozwiązać? A może obsługa przerwania? Ale jak umieszcze jakiś kod w SIGNAL(SIG_UART_RECV) { kod } to sie wogóle nie wykonuje. Co robie źle?
Prosze o pomoc, z góry dziękuję i pzodrawiam.
mam do napisania program na uC, który w zależności co odbierze z PC przez UART to wykona odpowiednią funkcję / skoczy do innego fragmentu programu. Rozwiązalem to tak:
**************************
int main(void) {
USART_Init(MYUBRR);
while(1)
{
char znak = USART_Receive();
if(znak == '1') { funkcja 1; }
if(znak == '2') P funkcja 2; }
}
}
**************************
problem jest nastepujacy: dana sterujaca programem (znak) wysylam raz na jaksi czas, a w linijce char znak ... program przestaje byc wykonywany AŹ odbierze jakiś znak. Jak to rozwiązać? A może obsługa przerwania? Ale jak umieszcze jakiś kod w SIGNAL(SIG_UART_RECV) { kod } to sie wogóle nie wykonuje. Co robie źle?
Prosze o pomoc, z góry dziękuję i pzodrawiam.
Zakładając, że masz taką funkcję USART_Receive() jak poniżej:
to zauważ, że ona czeka w pętli while aż w buforze będzie gotowy znak do odebrania,
czyli ciągle obserwuje bit RXC rejestru UCSRA...
można spróbować coś takiego - to wersja nieczekająca:
funkcja zwróci 0x00 gdy znaczka jeszcze nie ma lub odebrany ostatnio znak
ale na nic nie będzie czekać, po prostu sprawdzi co jest w USART i poleci dalej...
tak globalnie oraz to, które jest zgłaszane przy odbiorze znaku przez USART?
tasza
Kod: Zaznacz cały
unsigned char USART_Receive( void ) {
while ( !( UCSRA & (1<<RXC) ) );
return UDR;
}
czyli ciągle obserwuje bit RXC rejestru UCSRA...
można spróbować coś takiego - to wersja nieczekająca:
Kod: Zaznacz cały
unsigned char USART_Receive_NoWait( void ) {
if ( UCSRA & (1<<RXC) ) {
return UDR;
}
else {
return 0x00;
}
}
ale na nic nie będzie czekać, po prostu sprawdzi co jest w USART i poleci dalej...
a czy odblokowałeś przerwania?doctor pisze: Ale jak umieszcze jakiś kod w SIGNAL(SIG_UART_RECV) { kod }
to sie wogóle nie wykonuje. Co robie źle?
tak globalnie oraz to, które jest zgłaszane przy odbiorze znaku przez USART?
tasza
Odblokowlem
Witaj, odblkokowalem przerwania. zrobilem to funkcja sei(), z tego co sie orientuje to jest to samo co SREG |= 1 << 7; Jeszcze cos, odczytalem rejestr SREG po wywolaniu sei(), wynosi 130d, czyli 10000010, 7 bit jest ustawiony, czyli globalnie przerwania sa odblokowane. Zaraz sprawdze ta funkcje no_wait, wielkie dzieki za nia. Dodam jeszcze ze probuje ten program w najprostszy sposob, tj chce aby po odebraniu 1 znaku przez USART zapalila sie dioda. Dolaczam moj kod programu, Pozdrawiam
- Załączniki
-
- signal.zip
- Kod programu
- (914 Bajtów) Pobrany 339 razy
Kod: Zaznacz cały
SIGNAL(SIG_USART_RECV)
{
PORTA |= 1 << PA2; //powinno zapalac diode
_delay_ms(100);
}
mają się wykonywać szybko i zwinnie, ponieważ jak 'ugrzęźniesz' w takim handlerku
jakimś delay-em ( jak u Ciebie _delay_ms(100); ) to jest szansa, że program nie zareaguje na nowe przerwanie...
najlepiej to chyba zrobić zapalającą/gasnącą co znaczek diodę, czyli coś takiego:
Kod: Zaznacz cały
unsigned char bLedState = 0;
SIGNAL( SIG_USART_RECV ) {
bLedState ^= 1;
if ( bLedState ) {
PORTA |= (1 << PA2); //powinno zapalac diode
}
else {
PORTA &= ~(1 << PA2); //powinno gasić diode
}
} // of SIGNAL
i oczywiście diodka zapięta przez rezystor do masy...zapalana stanem H.
aha, w void USART_Init(unsigned int ubrr) brakuje mi zezwolenia, aby UART zgłaszał
przerwanie, jak odbierze znaczek...
czyli linijka
Kod: Zaznacz cały
UCSRB = (1 << RXEN) | (1 << TXEN);Kod: Zaznacz cały
UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);jest niepotrzebne, zakomentuj je...
tasza
[ Dodano: 2006-12-05, 13:46 ]
na tej stronce: https://elportal.pl/index.php?module=Co ... y&ceid=145 masz źródła aplikacji,
która odbiera znaczki w przerwaniach: https://elportal.pl/tasza/lxt/led_tree_avr.zip
może też tam zerknij....
tasza
Pomoglo
Dziekuje za rady. juz sie dioda wlacza jak odbierze dowolny znaczek. Niestety nie idzie jej wylaczyc. Oto kod
***************
char bLedState = 0;
SIGNAL(SIG_USART_RECV)
{
bLedState = !bLedState;
if( !bLedState )
PORTA |= 1 << PA2; //powinno zapalac diode
else
PORTA &= ~(1 << PA2);
}
***************
wiem ze w winavr nie ma zmiennych boolowskich, sprubuje na intach jeszcze
***************
char bLedState = 0;
SIGNAL(SIG_USART_RECV)
{
bLedState = !bLedState;
if( !bLedState )
PORTA |= 1 << PA2; //powinno zapalac diode
else
PORTA &= ~(1 << PA2);
}
***************
wiem ze w winavr nie ma zmiennych boolowskich, sprubuje na intach jeszcze
jak cytujesz kod, używaj proszę tagów CODE, dzięki...
no to tak:
i to powinno działać....
tasza
no to tak:
Kod: Zaznacz cały
typedef unsigned char BOOL;
#define FALSE 0
#define TRUE 1
BOOL bLedState = FALSE;
unsigned char anyChar = 0x00;
SIGNAL( SIG_USART_RECV ) {
//dodane...
anyChar = UDR;
bLedState ^= TRUE; // to co wywołanie zmieni się: true/false/true/false....
if( bLedState == TRUE ) {
PORTA |= 1 << PA2; //powinno zapalac diode
}
else {
PORTA &= ~(1 << PA2);
}
}
tasza
No prawie juz
Za to zrobilem program który klawiszem '5' zapala ta diode, a pozostalymi ja gasi. To juz mnie wlasciwie satysfakcjonuje, ale to ciekawe z jednej strony, bo w przykladzie wyzej tylko ja zapalal, wiec cos bylo ztypem zmiennej, mimo iz byla zadeklarowana globalnie.
*******************
unsigned char keycode;
SIGNAL(SIG_USART_RECV)
{
keycode = UDR;
if( keycode == '5')
PORTA |= 1 << PA2; //powinno zapalac diode
else
PORTA &= ~(1 << PA2);
}
*******************
Pozdrawiam
*******************
unsigned char keycode;
SIGNAL(SIG_USART_RECV)
{
keycode = UDR;
if( keycode == '5')
PORTA |= 1 << PA2; //powinno zapalac diode
else
PORTA &= ~(1 << PA2);
}
*******************
Pozdrawiam
http://www.atmel.com/dyn/resources/prod ... oc2503.pdf
strona 152, topic: Receive Complete Flag and Interrupt
reasumując: przy obsłudze odbierania w przerwaniach, trzeba w procedurze
obsługi odczytywać nadesłany znaczek z rejestru UDR, inaczej nie skasuje się
flaga RXC i nowe przerwanie wywoła się natychmiast po zakończeniu poprzedniego...
i to prawdopodobnie był problem....
oj, coś kiepsko ze mną
pa,
tasza
strona 152, topic: Receive Complete Flag and Interrupt
reasumując: przy obsłudze odbierania w przerwaniach, trzeba w procedurze
obsługi odczytywać nadesłany znaczek z rejestru UDR, inaczej nie skasuje się
flaga RXC i nowe przerwanie wywoła się natychmiast po zakończeniu poprzedniego...
i to prawdopodobnie był problem....
oj, coś kiepsko ze mną
pa,
tasza
Wszystko gra
W datasheecie stoi:
Dzięki wilelkie za pomoc Tasza, megaszacunek.
Pozdrawiam
Mowiac prosciej należało po każdym wystąpieniu przerwania czytać rejestr UDR aby czyścić flagę RXC.przerwanie od USATR'a bedzie wykonywane tak długo dopóki flaga RXC jest ustawiona.
Dzięki wilelkie za pomoc Tasza, megaszacunek.
Pozdrawiam