USART und Interrupt

Gast #1092527
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.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4

5
void delay_ms(int delay) {
6
        int i;
7
        for (i=0;i<=delay;i++) {
8
                _delay_ms(1);
9
        }
10
}
11

12

13
void init_usart(void) 
14
{ 
15
 uint8_t HighByte = (416 >> 8);   // Baudrate 2400
16
 uint8_t LowByte = 416 & 0xFF;
17
 UBRRL |= LowByte;
18
 UBRRH |= HighByte;
19
 UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE);
20
 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
21
}
22

23
void send_char(unsigned char s) 
24
{ 
25
 while (!(UCSRA & (1<<UDRE))); 
26
 UDR = s; 
27
} 
28

29
void send_string(char *s) 
30
{ 
31
 while(*s != '\0') 
32
  { 
33
   send_char(*s); 
34
   s++; 
35
  } 
36
} 
37

38
ISR(USART_RXC_vect) {
39
    uint16_t test;
40
    test = UDR;
41
  send_string("Interrrupt!!!");
42
}
43

44

45
int main(void) 
46
{
47
sei();
48
init_usart();
49
DDRB = 0xFF;
50
while(1)
51
{
52
  send_string("test");
53
  delay_ms(1000);
54
}
55
return 0;
56
}
Gast #1092530
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???
Gast #1092763
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).
Gast #1092995
Lesenswert?

Bin jetzt soweit dass ich eigentlich ganze Strings empfangen sollte,
leider klappt es wieder nicht...
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
#define PUFFER_GROESSE 100
5
volatile char *schreibzeiger;
6
volatile char *lesezeiger;
7
volatile char puffer[PUFFER_GROESSE];
8

9
void delay_ms(int delay) {
10
        int i;
11
        for (i=0;i<=delay;i++) {
12
                _delay_ms(1);
13
        }
14
}
15

16

17
void init_usart(void) 
18
{ 
19
 uint8_t HighByte = (416 >> 8);   // Baudrate 2400
20
 uint8_t LowByte = 416 & 0xFF;
21
 UBRRL |= LowByte;
22
 UBRRH |= HighByte;
23
 UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE);
24
 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
25
}
26

27
void send_char(unsigned char s) 
28
{ 
29
 while (!(UCSRA & (1<<UDRE))); 
30
 UDR = s; 
31
} 
32

33
void send_string(char *s) 
34
{ 
35
 while(*s != '\0') 
36
  { 
37
   send_char(*s); 
38
   s++; 
39
  } 
40
} 
41

42
ISR(USART_RXC_vect) {
43
  *schreibzeiger=UDR;
44
  schreibzeiger++;
45
  if(schreibzeiger==puffer+PUFFER_GROESSE) schreibzeiger=puffer;
46
  
47
}
48

49
int main(void) 
50
{
51
uint8_t datenbyte = 0;;
52
sei();
53
init_usart();
54
lesezeiger=puffer;
55
schreibzeiger=puffer;
56
while(1)
57
{
58
  if(schreibzeiger != lesezeiger) {
59
    datenbyte = *lesezeiger;
60
    lesezeiger++;
61
    if(lesezeiger==puffer+PUFFER_GROESSE) lesezeiger=puffer;
62
    send_string(datenbyte);
63
    }
64

65
  
66
}
67
return 0;
68
}

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.
#1093003
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.
Gast #1093531
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;
}[/]
Gast #1093551
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. ??
#1093611
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.
Gast #1094091
Lesenswert?

Super, geht jetzt! Hier der Code falls jemand mal das gleiche Problem 
hat:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4

5
#define PUFFER_GROESSE 100
6

7
char *volatile schreibzeiger;
8
char *volatile lesezeiger;
9
volatile char puffer[PUFFER_GROESSE];
10

11
void delay_ms(int delay) {
12
        int i;
13
        for (i=0;i<=delay;i++) {
14
                _delay_ms(1);
15
        }
16
}
17

18
void init_usart(void) 
19
{ 
20
 uint8_t HighByte = (416 >> 8);   // Baudrate 2400
21
 uint8_t LowByte = 416 & 0xFF;
22
 UBRRL |= LowByte;
23
 UBRRH |= HighByte;
24
 UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE);
25
 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
26
}
27

28
void send_char(unsigned char s) 
29
{ 
30
 while (!(UCSRA & (1<<UDRE))); 
31
 UDR = s; 
32
} 
33

34
void send_string(char *s) 
35
{ 
36
 while(*s != '\0') 
37
  { 
38
   send_char(*s); 
39
   s++; 
40
  } 
41
} 
42

43
void get_string(char *s) 
44
{ 
45
 while(*s != '\0') 
46
  { 
47
   send_char(*s); 
48
   s++; 
49
  } 
50
} 
51

52
ISR(USART_RXC_vect) {
53
  *schreibzeiger=UDR;
54
  schreibzeiger++;
55
  if(schreibzeiger==puffer+PUFFER_GROESSE) schreibzeiger=puffer;
56
  
57
}
58

59

60
int main(void) 
61
{
62
uint8_t datenbyte = 0;
63
char c;
64
sei();
65
lesezeiger=puffer;
66
schreibzeiger=puffer;
67
init_usart();
68
while(1)
69
{
70
  if(schreibzeiger != lesezeiger) {
71
    cli();
72
    datenbyte = *lesezeiger;
73
    while(*lesezeiger != '\0') {
74
      send_char(datenbyte);
75
        lesezeiger++;
76
      }
77
    if(lesezeiger==puffer+PUFFER_GROESSE) lesezeiger=puffer;
78
    sei();
79
    }
80
  
81
}
82
return 0;
83
}
Gast #1094165
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?
Gast #1094238
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.
Gast #1094363
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...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren