mikrocontroller.net

Forum: Compiler & IDEs USART und Interrupt


Autor: Fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich kann erfolgreich DAten versenden mit dem USART, nur mit dem 
Empfangen klappt es noch nicht :( Im folgenden Code wird irgendwie nie 
die Interrupt Routine angesprungen, obwohl der andere µC was schickt, 
ebenfalls mit 2400 Baud.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

void delay_ms(int delay) {
        int i;
        for (i=0;i<=delay;i++) {
                _delay_ms(1);
        }
}


void init_usart(void) 
{ 
 uint8_t HighByte = (416 >> 8);   // Baudrate 2400
 uint8_t LowByte = 416 & 0xFF;
 UBRRL |= LowByte;
 UBRRH |= HighByte;
 UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE);
 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
}

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

void send_string(char *s) 
{ 
 while(*s != '\0') 
  { 
   send_char(*s); 
   s++; 
  } 
} 

ISR(USART_RXC_vect) {
    uint16_t test;
    test = UDR;
  send_string("Interrrupt!!!");
}


int main(void) 
{
sei();
init_usart();
DDRB = 0xFF;
while(1)
{
  send_string("test");
  delay_ms(1000);
}
return 0;
}

Autor: Fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Muss mich korrigieren, es geht nachdem ich eine gemeinsame Masse 
zwischen den beiden COntrollern hergestellt habe... Mein Ziel ist aber 
eine Datenübertragung per Infrarot, da habe ich ja auch keine gemeinsame 
MAsse???

Autor: omfgrtfm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dafür nimmt man dann lichtleichter

Autor: Mike J. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Fragender
Dein Signal vom TX-Pin hat einen Masse-Bezug!
Also der Strom fließt vom TX-Pin nach Masse.

Wenn du den + Pol deiner Autobatterie anfasst bekommst du doch auch 
keine gewischt, es sei denn du hast deine Hand an der Karosserie 
(Masse).

Autor: Fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt,danke!

Autor: Fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bin jetzt soweit dass ich eigentlich ganze Strings empfangen sollte,
leider klappt es wieder nicht...
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define PUFFER_GROESSE 100
volatile char *schreibzeiger;
volatile char *lesezeiger;
volatile char puffer[PUFFER_GROESSE];

void delay_ms(int delay) {
        int i;
        for (i=0;i<=delay;i++) {
                _delay_ms(1);
        }
}


void init_usart(void) 
{ 
 uint8_t HighByte = (416 >> 8);   // Baudrate 2400
 uint8_t LowByte = 416 & 0xFF;
 UBRRL |= LowByte;
 UBRRH |= HighByte;
 UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE);
 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
}

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

void send_string(char *s) 
{ 
 while(*s != '\0') 
  { 
   send_char(*s); 
   s++; 
  } 
} 

ISR(USART_RXC_vect) {
  *schreibzeiger=UDR;
  schreibzeiger++;
  if(schreibzeiger==puffer+PUFFER_GROESSE) schreibzeiger=puffer;
  
}

int main(void) 
{
uint8_t datenbyte = 0;;
sei();
init_usart();
lesezeiger=puffer;
schreibzeiger=puffer;
while(1)
{
  if(schreibzeiger != lesezeiger) {
    datenbyte = *lesezeiger;
    lesezeiger++;
    if(lesezeiger==puffer+PUFFER_GROESSE) lesezeiger=puffer;
    send_string(datenbyte);
    }

  
}
return 0;
}

Die (woanders abgeschaute)Idee dabei ist,dass die empfangenen Daten in 
einen Ringpuffer geschrieben werden, und sobald Lese- und Schreibzeiger 
verschieden sind, ausgegeben werden sollen. Leider kommt gar nichts am 
Pc an, gesendet wird definitiv und der der Interupt wird auch ausgelöst.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1)
send_string(datenbyte);
->
send_char(datenbyte);

2)
Du schreibst in den Puffer, ohne zu überprüfen, ob darin überhaupt noch 
Platz ist.

3)
Du schaltest die Interrupts ein, bevor schreibzeiger initialisiert 
ist.

4)
In main muss der Zugriff auf schreibzeiger vor der Unterbrechung durch 
den Interrupt geschützt werden. Und wenn du den Sourcecode bezüglich 2) 
änderst, auch die Zugriffe auf lesezeiger.

Autor: Fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, hab die SAchen berücksichtigt, bis auf die Paltzfrage im Puffer, 
aber zumindest amAnfang müsste es ja so gehn, gehts aber leider immer 
noch nicht :( Die andere SEite sendet im Sekundentakt "hallo\0"

[c]
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define PUFFER_GROESSE 100

volatile char *schreibzeiger;
volatile char *lesezeiger;
volatile char puffer[PUFFER_GROESSE];

void delay_ms(int delay) {
        int i;
        for (i=0;i<=delay;i++) {
                _delay_ms(1);
        }
}

void init_usart(void)
{
 uint8_t HighByte = (416 >> 8);   // Baudrate 2400
 uint8_t LowByte = 416 & 0xFF;
 UBRRL |= LowByte;
 UBRRH |= HighByte;
 UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE);
 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
}

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

void send_string(char *s)
{
 while(*s != '\0')
  {
   send_char(*s);
   s++;
  }
}

ISR(USART_RXC_vect) {
  *schreibzeiger=UDR;
  schreibzeiger++;
  if(schreibzeiger==puffer+PUFFER_GROESSE) schreibzeiger=puffer;

}

int main(void)
{
uint8_t datenbyte = 0;;
sei();
lesezeiger=puffer;
schreibzeiger=puffer;
init_usart();
while(1)
{
  if(schreibzeiger != lesezeiger) {
    cli();
    datenbyte = *lesezeiger;
    lesezeiger++;
    if(lesezeiger==puffer+PUFFER_GROESSE) lesezeiger=puffer;
    send_char(datenbyte);
    sei();
    }
}
return 0;
}[/]

Autor: Fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass Schreibzeiger immer auf den Anfang vom Array zeigt? 
wenn ich in der ISR direkt send_string(*schreibzeiger) einfüge,bekomme 
ich hallo, dann hallohallo, dann hallohallohallo etc. ??

Autor: Fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach und wenn ich in der ISR send_char einfüge,kommt es nur einmal, die 
if-schleife in der main-funktion wird trotzdem nciht angesprungen

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Deklaration von schreibzeiger ist falsch. Der Zeiger selber muss 
volatile sein, nicht das Ziel.

volatile char *schreibzeiger;
->
char * volatile schreibzeiger;

(die beiden anderen volatiles sind im aktuellen Code übrigens 
überflüssig)


> wenn ich in der ISR direkt send_string(*schreibzeiger) einfüge

"send_string(*schreibzeiger)" ist schlicht Unsinn, genau wie das 
"send_string(datenbyte)" im vorigen Code.

Autor: Fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super, geht jetzt! Hier der Code falls jemand mal das gleiche Problem 
hat:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define PUFFER_GROESSE 100

char *volatile schreibzeiger;
char *volatile lesezeiger;
volatile char puffer[PUFFER_GROESSE];

void delay_ms(int delay) {
        int i;
        for (i=0;i<=delay;i++) {
                _delay_ms(1);
        }
}

void init_usart(void) 
{ 
 uint8_t HighByte = (416 >> 8);   // Baudrate 2400
 uint8_t LowByte = 416 & 0xFF;
 UBRRL |= LowByte;
 UBRRH |= HighByte;
 UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE);
 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
}

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

void send_string(char *s) 
{ 
 while(*s != '\0') 
  { 
   send_char(*s); 
   s++; 
  } 
} 

void get_string(char *s) 
{ 
 while(*s != '\0') 
  { 
   send_char(*s); 
   s++; 
  } 
} 

ISR(USART_RXC_vect) {
  *schreibzeiger=UDR;
  schreibzeiger++;
  if(schreibzeiger==puffer+PUFFER_GROESSE) schreibzeiger=puffer;
  
}


int main(void) 
{
uint8_t datenbyte = 0;
char c;
sei();
lesezeiger=puffer;
schreibzeiger=puffer;
init_usart();
while(1)
{
  if(schreibzeiger != lesezeiger) {
    cli();
    datenbyte = *lesezeiger;
    while(*lesezeiger != '\0') {
      send_char(datenbyte);
        lesezeiger++;
      }
    if(lesezeiger==puffer+PUFFER_GROESSE) lesezeiger=puffer;
    sei();
    }
  
}
return 0;
}

Autor: Fragender (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Arg,noch eine letzte Frage: Leider scheint der Zeiger nicht zum ANfang 
zurückzuspringen, nachdem der Puffer voll ist... D.h. wird hallo\0 
gesendet, kommt es bei puffer_groesse 50 9mal richtig an und beim 10. 
mal nur ein teil und dann nicht mehr richtig. muss ich da auch was 
anders deklarieren?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das liegt daran, dass du in main lesezeiger nicht richtig verwaltest. 
Spiel mal durch, was passiert, wenn bei Eintritt in den if-Block 
lesezeiger auf ein '\0' zeigt.

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieso finde ich die Arbeitsweise mit Pointern bei einem Ringpuffer nur 
so umständlich?
Mit ein paar Variablen, die einfach die Indizes hochzählen, finde ich es 
wesentlich leichter. Zumindest funktionieren meine Ringpuffer-Routinen 
einwandfrei ohne Pointer-Operationen.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Natürlich ginge es mit einem Index einfacher, insbesondere wenn er als 
Puffergröße auch noch eine 2er-Potenz wählen würde. Er wollte ja aber 
wissen, warum sein Ansatz nicht geht, und die Antwort darauf lautet ja 
nicht "mit Zeigern geht es gar nicht, nimm einen Index".

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>und die Antwort darauf lautet ja nicht "mit Zeigern geht es gar nicht, nimm 
>einen Index".

Wohl wahr.
Klar geht es mit Zeigern. Nur sollte man schon etwas sicherer beim 
Umgang damit sein...

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
STK500-Besitzer wrote:
> Wieso finde ich die Arbeitsweise mit Pointern bei einem Ringpuffer nur
> so umständlich?

Weil sie es ist.


> Mit ein paar Variablen, die einfach die Indizes hochzählen, finde ich es
> wesentlich leichter.

Und wenn ein Byte (0..255) als Index reicht, ist das sogar effizienter 
(weniger Code, schneller):

Beitrag "AVR-GCC: UART mit FIFO"


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst wrote:
> insbesondere wenn er als
> Puffergröße auch noch eine 2er-Potenz wählen würde.

Das spart gerade mal einen Befehl ein, lohnt also nicht.


Peter

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.