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 #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;
}[/]
#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
}
#1094522
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

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