www.mikrocontroller.net

Forum: Compiler & IDEs UART_TX setzt RX ausser Kraft


Autor: Björn G. (tueftler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe hier ein wirklich blödes Problem und denke evtl. habt Ihr ja noch 
ne Idee dazu...

Ich habe eine Routine geschrieben, die so lange "bf1" sendet, bis die 
Gegenstelle mit einem "€"-Zeichen quittiert.

Habe es mit einer while() gelöst.
Diese gibt immer die Zeichenfolge raus aaaber setzt die ISR(RX) total 
ausser kraft.
Selbst wenn ich dort delay´s einbaue oder den TX aus schalten, delay, Tx 
wieder ein, dann gehts auch nicht.
TX-ISR gibt es keine.
Aber wenn ich die While-Schleife durch das nur einmalige Senden der 
Zeichenkette ändere, springt er auch in die ISR!?

Controller: Mega1280 @ 16MHz
So funktioniert es komischerweise nicht:

Aufruf-Funktion:

extern uint8_t receive_okay;

void ck2(void)
{
  while (!(receive_okay))                      //So lange senden, bis ein Eurozeichen (170) zur Quittierung empfangen wurde
  {  
    uart_puts_safety("bf1");                  //on
  }
}


UART Funktion:

extern uint8_t receive_okay;

void uart_putc(char c)
{ 
  while(!(_SFR_MEM8(0xC8) & (1<<UDRE1)));              //UCSR1A ist dem Compiler nicht bekannt! Deswegen direkte SFR-Adresse
  (_SFR_MEM8(0xCE)) = c;                               //UDR1 ist auch nicht bekannt!
}


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


ISR (USART1_RX_vect)
{
  uint8_t receive_okay_zeichen = UDR1;

  if (receive_okay_zeichen == 170)
  {
    receive_okay = 1;
  }
  else
  {
    receive_okay = 0;
  }
}

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

So springt er auch in die ISR:

Aufruf-Funktion:

extern uint8_t receive_okay;

void ck2(void)
{    
  uart_puts_safety("bf1");                  //on
}


UART Funktion:

extern uint8_t receive_okay;

void uart_putc(char c)
{ 
  while(!(_SFR_MEM8(0xC8) & (1<<UDRE1)));              //UCSR1A ist dem Compiler nicht bekannt! Deswegen direkte SFR-Adresse
  (_SFR_MEM8(0xCE)) = c;                               //UDR1 ist auch nicht bekannt!
}


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


ISR (USART1_RX_vect)
{
  uint8_t receive_okay_zeichen = UDR1;

  if (receive_okay_zeichen == 170)
  {
    receive_okay = 1;
  }
  else
  {
    receive_okay = 0;
  }
}

Ich hoffe, Ihr könnt mir helfen.
Habe schon so viele verschiedene Möglichkeiten getestet - ohne 
wirklichen Erfolg.

Gruß, Björn

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probier mal
//header-Datei, fuer alle:
extern volatile uint8_t receive_okay;
       ^^^^^^^^
//und da, wo 'receive_okay' definiert wird, das 'extern' weglassen:
// USART-Quellcode:
volatile uint8_t receive_okay;
Steht bestimmt beides im AVR-GCC-Tutorial
Ist also eine ganz alltägliche Frage ;)

hth. Jörg

Autor: Tüftler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Mit "volatile" deklarieren löst das Problem?

Mir wäre es natürlich wirklich recht ;-)

Momentan ist mir noch nicht so ganz klar, warum dies ein Unterschied 
macht - Wenn ich die while() weg lasse geht es ja auch...

Naja, ich probiere es direkt heute früh aus - Bin momentan an einem 
anderen Rechner.

Gute n8 dann mal ;-)
Björn

Autor: Björn G. (tueftler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Morgen!

Hat leider nichts genützt :-(

Igrndwie kommt es mir so vor, als ob der so flott sendet, das die 
RXD-ISR gar keine Zeit bekommt auch etwas zu empfangen.
Aber eigentlich ist gerade das ja nicht der Sinn einer ISR :-)

Also wie gestern auch, wenn ich nicht immer hintereinander sende, 
sondern nur ein einziges mal, empfängt er auch ein Zeichen - sonst 
springt er einfach nicht in die ISR.

Weitere Ideen? ;-)

Björn

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst du mal deine USART-Initialisierung hier reinstellen?

Und sind eigentlich diese Kommentare noch aktuell?
> [...] //UCSR1A ist dem Compiler nicht bekannt! Deswegen direkte SFR-Adresse
> [...] //UDR1 ist auch nicht bekannt!
Dann hast du entweder einen alten Compiler (bzw. eine alte avrlibc) oder 
den AVR nicht richtig eingestellt -- mein WinAVR 20071221 kennt die 
MegaX0 Familie nämlich und damit auch deren Register.

hth. Jörg

Autor: Björn G. (tueftler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ist die Konfiguration:

Die sollte aber stimmen.
Habe momentan zu wenig Zeit um nach dem Fehler mit UCSR1A zu suchen...
void uart_s_config(void)
{
  UBRR1H = 0x03;                              //baud
  UBRR1L = 0x40;

  UCSR1A |= (1<<U2X1);
  UCSR1B |= (1<<TXEN1) | (1<<RXEN1) | (1<<RXCIE1);                    //TXD & RXD Enabled; RXD_ISR enabled
  UCSR1C |= (1<<UCSZ11) | (1<<UCSZ10);                          //8bit
}

Björn

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.