Forum: Mikrocontroller und Digitale Elektronik UART Empfangs Interrupt funktioniert nicht


von aspire (Gast)


Lesenswert?

Hallo, ich versuche gerade Daten vom PC zum ATMega8 und umgekehrt zu 
senden. Vom Mega8 zum PC klappt es super. Vom PC zum Mega8 noch nicht. 
Empfangen möchte ich mit einem Interrupt realisieren um nicht permannent 
das Register abzufragen ob was drin stehet.
Was bis jetzt passiert:
Ich Schalte mein µC ein und er zeigt mir kurz den Wert des ADC auf dem 
Display an und kurz darauf wird die obere Zeile des Displays komplett 
weis.

entferne ich folgende Zeilen funktioniert das Senden von Mega8 zum PC 
perfekt:
  UCSRB |= (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);  // UART RX, TX und RX 
Interrupt einschalten
  sei();

Ich verwende einen ATMega8-16PU
mit internem 1MHz Osszilator.
Der Empfang auf dem PC wird durch ein in Java Programmiertes Programm 
realisiert. Kann ich bei bedarf auch posten.


Ganzer Code:
//Includes
//--------
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <string.h>
#include "LCD_display.h"
#include "BitUtilities.h"

//Funktions Prototypen
//--------------------
int getAnalogVoltage( short mux, short cycels );
void setPWM( int value );  // value 0(0%) ... 1023(100%)

//Defines
//-------
#define XTAL        1e6 // Noch auf 1e6 stellen
#define F_CPU        XTAL

//Variablen
//---------
char str[4];

//Main
//----
int main()
{
  //Initialisierungen
  _delay_ms(100);
  lcd_init();
  USART_Init();
  UCSRB |= (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);  // UART RX, TX und RX 
Interrupt einschalten
  sei();

  //ADC (ADCSRA S.200, ADMUX S.199)
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Prescaler=8 (1 
MHz/8=125 kHz)
  ADMUX |= (1<<REFS0) | (0<<REFS1);

  //Programm Code
  //-------------
  while (1){

  dtostrf(getAnalogVoltage(0x05,20),4,0,str);

  //Print Spannung
  lcd_set_cursor (1, 0);
  lcd_write(str);

  _delay_ms(100);
  USART_Write(str);
  USART_Write("\n");
  }

  return 0;
}

int getAnalogVoltage( short mux, short cycels ){
  ADMUX &= ~0x0F;            // MUX auf 0000 setzen
  ADMUX |= mux;              // ADC5 auswählen

  int digitalValue = 0;

  for(int i=0;i<cycels;i++){      // Mittelwertbildung
    ADCSRA |= (1<<ADSC);        // single conversion
    while ( ADCSRA & (1<<ADSC) );     // wait for ADC ready
    digitalValue += ADCW;        // add up conversions
  }
  return digitalValue/cycels;
}

void USART_Init( void ){
  // Set baud rate to 9600
  UBRRH = (unsigned char)(12>>8);
  UBRRL = (unsigned char)12;
  // Enable receiver and transmitter
  UCSRB = (1<<RXEN)|(1<<TXEN);
  // Set frame format: 8data, 2stop bit
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
  UCSRA = (1<<U2X);
}

void USART_Transmit(char data ){
  // Wait for empty transmit buffer
  while ( !( UCSRA & (1<<UDRE)) );
  // Put data into buffer, sends the data
  UDR = data;
}

void USART_Write(char *str)
{  while(*str) {USART_Transmit(*str); str++;}
}

ISR(USART_RX_vect)
{
  lcd_set_cursor (2, 0);
  lcd_write("etwas empfangen");
}

von Krapao (Gast)


Lesenswert?

Mehrere Probleme in der ISR(USART_RX_vect):

1/ Die LCD Ausgabe in der ISR ist bad. Artikel Interrupt
2/ Du liest das empfangene Zeichen nicht aus der UART aus. Die Ursache 
des Interrupts bleibt bestehen. Du verlässt die ISR quasi nie mehr.

von aspire (Gast)


Lesenswert?

Okay hab folgendes geändert:

...
char receive;
...

ISR(USART_RX_vect)
{
  receive = UDR;
}

es besteht immernochh das gleiche Problem.

von Krapao (Gast)


Lesenswert?

> ISR(USART_RX_vect)

In meiner Toolchain existiert dieser Vektorname nicht. In meinem 
avr/include/avr/iom8.h heisst es

> /* USART, Rx Complete */
> #define USART_RXC_vect_num    11
> #define USART_RXC_vect    _VECTOR(11)
> #define SIG_UART_RECV      _VECTOR(11)

Beim Übersetzen kommt eine Warnung. Lässt man das dennoch erzeugte 
Programm trotzdem laufen, stürzt es mit jedem empfangenen Zeichen ab. 
Das könnte ein seltsames Bild auf dem LCD erzeugen.

von aspire (Gast)


Lesenswert?

danke! das funktioniert:

ISR(_VECTOR(11))
{
  char unsigned data;

    // Daten auslesen, dadurch wird das Interruptflag gelöscht
    data = UDR;

  lcd_set_cursor (2, 0);
  lcd_write("bla");
}

aber ich verstehe dann nicht warum das hier funktioniert
ISR( INT0_vect ){}

ich meine ist dieser Interrupt definiert und der UART nicht?

von aspire (Gast)


Lesenswert?

an meinem RX Eingang des ATMwegas liegt irgentwie genau das an, was über 
den TX Ausgang meines ATMegas ausgegeben wird.
Ich weis aber auch nicht wirklich wofür der Jumper auf meinem USB 
Wandler ist, ich habe das gefühl das er in einer jumperstellung einfach 
von TX auf RX Spiegelt. er ist auch nicht beschrifttet und ein 
datenblatt gibts natürlich auch nicht (8€ bei ebay)

von Krapao (Gast)


Lesenswert?

> ich meine ist dieser Interrupt definiert und der UART nicht?

USART_RXC_vect ist definiert, USART_RX_vect nicht
        ^                             ^

> TX auf RX Spiegelt

vielleicht ist im PC-Programm Echo eingeschaltet.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.