mikrocontroller.net

Forum: Compiler & IDEs UART - Fehler mit Interrupt / "Zeichensalat"


Autor: Dennis Jekubczyk (jodel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich kämpfe mitlerweile schon seit einigen Tagen an einer kleinen 
UART-Library, die Interrupt-gesteuert Strings empfangen und senden 
können soll.


Mein Problem besteht darin, dass ich mit folgendem Programm zunächst ein 
Testzeichen sende und danach versuche einen String Interrupt-gesteuert 
zu übertragen. Konsequenz daraus ist leider, dass nur massenhaft das 
zuerst gesendete Zeichen den PC erreicht. Wenn ich jedoch TXCIE nicht 
setze, kommt das nicht vor..

Genauso merkwürdig erscheint mir, dass die interrupt-Routine gar nicht 
erst angesteuert wird (habe ich überprüft). Kann mir vielleicht jemand 
sagen wieso?!

Danke erstmal für eure Mühe!

Mein Code:
//main.c
#include"uart.h"
int main()
{
  cli();
  uart_init(25);
  uart_senden('+');

  char senden[] = "asdf";
  sei();
  uart_string_senden(senden);
  
  
  for(;;)
  {
  }
    
  return 0;
}


//uart.h
#ifndef __UART_H
#define __UART_H

#include<avr/io.h>
#include<avr/interrupt.h>
#include<stdbool.h>
#include<string.h>
#include<stdint.h>

void uart_init(uint16_t ubrr);
void uart_senden(uint8_t zeichen);
bool uart_string_senden(const char *daten);
bool uart_string_empfangen(const char *daten);

volatile bool uart_buffer_gesendet;
volatile bool uart_string_empfangen;

volatile uint8_t uart_buffer_senden[32];
volatile uint8_t uart_pos_senden;
volatile uint8_t uart_buffer_empfangen[32];
volatile uint8_t uart_pos_empfangen;

#include "uart.c"

#endif


//uart.c
#ifndef __UART_C
#define __UART_C

void uart_init(uint16_t ubrr)
{
  /* Baud Rate */
  UBRRH = (unsigned char) (ubrr>>8);
  UBRRL = (unsigned char) ubrr;
  /* Vorerst nur Senden */
  UCSRB = (0 << RXEN) | (1 << TXEN);
  /* 8 Datenbits, 1 Stopbit, keine Parität */
  UCSRC = (1 << URSEL) |  (0 << USBS) |   (3 << UCSZ0); 
  uart_buffer_gesendet = true;
}

void uart_senden(uint8_t zeichen)
{
  //Auf leeren Datenbuffer warten
  while ( !( UCSRA & (1<<UDRE)) );
        //senden
  UDR = zeichen;
}


bool uart_string_senden(const char *daten)
{
  if(!uart_buffer_gesendet)
  {
    return  false;
  }
  strcpy(uart_buffer_senden, daten);
  uart_pos_senden = 0;
  uart_buffer_gesendet = false;
  UCSRB |= (1 << TXCIE);
}


void uart_string_empfangen(const uint8_t *daten)
{
}


IST(USART_TXC_vect)
{
  uint8_t temp = uart_buffer_senden[uart_pos_senden];
  if('\0' != temp)
  {
    uart_senden(temp);
    uart_pos_senden++;
  }
  else
  {
    //fertig mit Senden
                uart_buffer_gesendet = true;
    //Interrupt-Steuerung aus!
                UCSRB &= ~(1 << TXCIE );  
  }
}

#endif

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,

schau dir mal den Namen der Interrupt-Routine an. In der Doku zur 
avr-libc finde ich USART_TXC_vect nämlich nicht. Der Name hängt vom 
verwendeten Baustein ab. Eine Möglichkeit: USART0_TXC_vect.

Gruß
Mo

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Vektorname ist für die µCs, die nur einen USART haben, schon 
korrekt. Nicht korrekt ist hingegen das "IST". Das müsste wohl "ISR" 
heißen. Wenn das im Original-Code auch so da steht, müsste das zumindest 
zu einigen Compiler-Warnungen geführt haben, aber Warnungen liest ja eh 
keiner...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... und das Teil heist ISR, nicht IST

Autor: jodel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manchmal hätte einem ne Tasse Kaffee wohl viel Arbeit erspart, danke!

Aber wieso wird dann immer wieder das zuerst gesendete Zeichen 
wiederholt?!

Und ja, der Interrupt sollte stimmen. Ist nen Mega16.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Aber wieso wird dann immer wieder das zuerst gesendete Zeichen
> wiederholt?!

Weil du technisch gesehen keinen Interrupt Handler
installiert hast. Du hast allerdings den Interrupt
freigegeben und der tritt auch auf. Da es aber keinen
Handler dafür gibt, passiert ein 'Reset', d.h. dein
Programm fängt wieder von vorne an. Bis dann der
Interrupt erneut auftritt, welcher zu einem Neustart führt,
etc ...

Autor: Dennis Jekubczyk (jodel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für Eure Mühe!

Ich werd mal nachher probieren, ob das alles war, wenn ich wieder zu 
hause bin..

Autor: jodel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Update:

Alle Probleme gelöst! Danke!

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.