PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Rückfrage: Uart ISR stört die If then abfrage



chrisavr1981
13.01.2014, 20:44
Hallo zusammen,

ist das korrekt, dass die ISR(USART_RXC_vect) eventuell nach mehrfacher Eingabe von
Zeichen über die Tastatur, die Ausgabe einer if then Abfrage "überschreibt"??



#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define F_CPU 7372800
#define BAUD 9600
#define UBRR_VAL F_CPU/16/BAUD-1

volatile unsigned char receive_char;
volatile int buffersize = 8;

ISR(USART_RXC_vect)
{
receive_char = UDR;
}

void init_uart(unsigned int ubrr)
{
UBRRH = (unsigned char)(ubrr>>8);
UBRRL = (unsigned char)(ubrr);
UCSRB = (1 << RXEN) | (1 << TXEN) | (1<<RXCIE);
UCSRC = (1<<URSEL)|(1<<UCSZ0) | (1<<UCSZ1);
}

void send_char(unsigned char data)
{
while (!(UCSRA & (1<<UDRE)));
UDR = data;
}

void send_string(char *data)
{
while (*data)
{
send_char(*data);
data++;
}
}

int main(void)
{
DDRB |= (1<<PB1);
init_uart(UBRR_VAL);
send_string("TESTING");
sei();
PORTB |= (1<<PB1);
_delay_ms(300);
PORTB &=~ (1<<PB1);
uint8_t i;
while (1)
{
//i = strlen(receive_char);

cli();
if (receive_char == 100)
{
send_string("Yes, we wrote e");
}

if (receive_char == 114)
{
send_string("Yes, we wrote r");
}

if (receive_char == 116)
{
send_string("Yes, we wrote t");
}

receive_char = "";
sei();
}
return 0;
}


Erst nach der Definition von cli() und sei() wurde das Ergebnis besser, ist das euch auch schon vorgekommen?

Vielen Dank!

Spectre
14.01.2014, 07:20
Hallo,

Sieht nach einem sehr klaren Fall von einer Race-Condition (http://de.wikipedia.org/wiki/Race_Condition) aus.

Du schreibst mehrere Zeichen über die UART an den Mikrocontroller. Als erstes Zeichen schreibst du ein 'e'. Die erste if-Abfrage evaluiert zu true, folglich wird der String "Yes, we wrote e" über die UART an den PC geschrieben. Da du die UART-Übertragung blockierend implementiert hast, dauert der Aufruf der Funktion send_string("Yes,we wrote e") (1/(Baudrate/10))*AnzahlZeichenVon"Yes,we wrote e". Das ist auf jeden Fall länger, als es dauert bis das nächste Zeichen empfangen wird. Der Effekt: Während deine Hauptprogrammabarbeitung noch in der Funktion send_string "festhängt", werden mehrere Zeichen empfangen, die dann jeweils die Variable receive_char überschreiben. Für dich macht das den Eindruck, als ob die if-Abfrage nicht evaluiert werden würde, da nur das Zeichen evaluiert wird.

Die Verwendung von cli() und sei() verbessert das Verhalten, da damit Interrupts während der Übertragung gesperrt werden, damit kannst du aber ebenso empfangene Zeichen verlieren.

Die beste Methode wäre die Implementierung eines Empfangs- und Sende-Ringbuffers, hierfür verweise ich auf die weiterführende Literatur z.B. hier (http://www.lxrobotics.com/avr-serielle-schnittstelle-arduino-uno) und hier (http://www.mikrocontroller.net/topic/101472#882716) ;)