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


von Dennis J. (jodel)


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:
1
//main.c
2
#include"uart.h"
3
int main()
4
{
5
  cli();
6
  uart_init(25);
7
  uart_senden('+');
8
9
  char senden[] = "asdf";
10
  sei();
11
  uart_string_senden(senden);
12
  
13
  
14
  for(;;)
15
  {
16
  }
17
    
18
  return 0;
19
}
20
21
22
//uart.h
23
#ifndef __UART_H
24
#define __UART_H
25
26
#include<avr/io.h>
27
#include<avr/interrupt.h>
28
#include<stdbool.h>
29
#include<string.h>
30
#include<stdint.h>
31
32
void uart_init(uint16_t ubrr);
33
void uart_senden(uint8_t zeichen);
34
bool uart_string_senden(const char *daten);
35
bool uart_string_empfangen(const char *daten);
36
37
volatile bool uart_buffer_gesendet;
38
volatile bool uart_string_empfangen;
39
40
volatile uint8_t uart_buffer_senden[32];
41
volatile uint8_t uart_pos_senden;
42
volatile uint8_t uart_buffer_empfangen[32];
43
volatile uint8_t uart_pos_empfangen;
44
45
#include "uart.c"
46
47
#endif
48
49
50
//uart.c
51
#ifndef __UART_C
52
#define __UART_C
53
54
void uart_init(uint16_t ubrr)
55
{
56
  /* Baud Rate */
57
  UBRRH = (unsigned char) (ubrr>>8);
58
  UBRRL = (unsigned char) ubrr;
59
  /* Vorerst nur Senden */
60
  UCSRB = (0 << RXEN) | (1 << TXEN);
61
  /* 8 Datenbits, 1 Stopbit, keine Parität */
62
  UCSRC = (1 << URSEL) |  (0 << USBS) |   (3 << UCSZ0); 
63
  uart_buffer_gesendet = true;
64
}
65
66
void uart_senden(uint8_t zeichen)
67
{
68
  //Auf leeren Datenbuffer warten
69
  while ( !( UCSRA & (1<<UDRE)) );
70
        //senden
71
  UDR = zeichen;
72
}
73
74
75
bool uart_string_senden(const char *daten)
76
{
77
  if(!uart_buffer_gesendet)
78
  {
79
    return  false;
80
  }
81
  strcpy(uart_buffer_senden, daten);
82
  uart_pos_senden = 0;
83
  uart_buffer_gesendet = false;
84
  UCSRB |= (1 << TXCIE);
85
}
86
87
88
void uart_string_empfangen(const uint8_t *daten)
89
{
90
}
91
92
93
IST(USART_TXC_vect)
94
{
95
  uint8_t temp = uart_buffer_senden[uart_pos_senden];
96
  if('\0' != temp)
97
  {
98
    uart_senden(temp);
99
    uart_pos_senden++;
100
  }
101
  else
102
  {
103
    //fertig mit Senden
104
                uart_buffer_gesendet = true;
105
    //Interrupt-Steuerung aus!
106
                UCSRB &= ~(1 << TXCIE );  
107
  }
108
}
109
110
#endif

von gast (Gast)


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

von johnny.m (Gast)


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...

von Karl H. (kbuchegg)


Lesenswert?

... und das Teil heist ISR, nicht IST

von jodel (Gast)


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.

von Karl H. (kbuchegg)


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 ...

von Dennis J. (jodel)


Lesenswert?

Danke für Eure Mühe!

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

von jodel (Gast)


Lesenswert?

Update:

Alle Probleme gelöst! Danke!

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.