Forum: Compiler & IDEs UART_TX setzt RX ausser Kraft


von Björn G. (tueftler)


Lesenswert?

Habe hier ein wirklich blödes Problem und denke evtl. habt Ihr ja noch 
ne Idee dazu...

Ich habe eine Routine geschrieben, die so lange "bf1" sendet, bis die 
Gegenstelle mit einem "€"-Zeichen quittiert.

Habe es mit einer while() gelöst.
Diese gibt immer die Zeichenfolge raus aaaber setzt die ISR(RX) total 
ausser kraft.
Selbst wenn ich dort delay´s einbaue oder den TX aus schalten, delay, Tx 
wieder ein, dann gehts auch nicht.
TX-ISR gibt es keine.
Aber wenn ich die While-Schleife durch das nur einmalige Senden der 
Zeichenkette ändere, springt er auch in die ISR!?

Controller: Mega1280 @ 16MHz
1
So funktioniert es komischerweise nicht:
2
3
Aufruf-Funktion:
4
5
extern uint8_t receive_okay;
6
7
void ck2(void)
8
{
9
  while (!(receive_okay))                      //So lange senden, bis ein Eurozeichen (170) zur Quittierung empfangen wurde
10
  {  
11
    uart_puts_safety("bf1");                  //on
12
  }
13
}
14
15
16
UART Funktion:
17
18
extern uint8_t receive_okay;
19
20
void uart_putc(char c)
21
{ 
22
  while(!(_SFR_MEM8(0xC8) & (1<<UDRE1)));              //UCSR1A ist dem Compiler nicht bekannt! Deswegen direkte SFR-Adresse
23
  (_SFR_MEM8(0xCE)) = c;                               //UDR1 ist auch nicht bekannt!
24
}
25
26
27
void uart_puts(char *s)
28
{  
29
  while(*s)
30
  uart_putc(*s++);
31
}
32
33
34
ISR (USART1_RX_vect)
35
{
36
  uint8_t receive_okay_zeichen = UDR1;
37
38
  if (receive_okay_zeichen == 170)
39
  {
40
    receive_okay = 1;
41
  }
42
  else
43
  {
44
    receive_okay = 0;
45
  }
46
}
47
48
---------------------------------------------------------------------------------------------------------------------------
49
50
So springt er auch in die ISR:
51
52
Aufruf-Funktion:
53
54
extern uint8_t receive_okay;
55
56
void ck2(void)
57
{    
58
  uart_puts_safety("bf1");                  //on
59
}
60
61
62
UART Funktion:
63
64
extern uint8_t receive_okay;
65
66
void uart_putc(char c)
67
{ 
68
  while(!(_SFR_MEM8(0xC8) & (1<<UDRE1)));              //UCSR1A ist dem Compiler nicht bekannt! Deswegen direkte SFR-Adresse
69
  (_SFR_MEM8(0xCE)) = c;                               //UDR1 ist auch nicht bekannt!
70
}
71
72
73
void uart_puts(char *s)
74
{  
75
  while(*s)
76
  uart_putc(*s++);
77
}
78
79
80
ISR (USART1_RX_vect)
81
{
82
  uint8_t receive_okay_zeichen = UDR1;
83
84
  if (receive_okay_zeichen == 170)
85
  {
86
    receive_okay = 1;
87
  }
88
  else
89
  {
90
    receive_okay = 0;
91
  }
92
}

Ich hoffe, Ihr könnt mir helfen.
Habe schon so viele verschiedene Möglichkeiten getestet - ohne 
wirklichen Erfolg.

Gruß, Björn

von Jörg X. (Gast)


Lesenswert?

Probier mal
1
//header-Datei, fuer alle:
2
extern volatile uint8_t receive_okay;
3
       ^^^^^^^^
4
//und da, wo 'receive_okay' definiert wird, das 'extern' weglassen:
5
// USART-Quellcode:
6
volatile uint8_t receive_okay;
Steht bestimmt beides im AVR-GCC-Tutorial
Ist also eine ganz alltägliche Frage ;)

hth. Jörg

von Tüftler (Gast)


Lesenswert?

Hi!

Mit "volatile" deklarieren löst das Problem?

Mir wäre es natürlich wirklich recht ;-)

Momentan ist mir noch nicht so ganz klar, warum dies ein Unterschied 
macht - Wenn ich die while() weg lasse geht es ja auch...

Naja, ich probiere es direkt heute früh aus - Bin momentan an einem 
anderen Rechner.

Gute n8 dann mal ;-)
Björn

von Björn G. (tueftler)


Lesenswert?

Morgen!

Hat leider nichts genützt :-(

Igrndwie kommt es mir so vor, als ob der so flott sendet, das die 
RXD-ISR gar keine Zeit bekommt auch etwas zu empfangen.
Aber eigentlich ist gerade das ja nicht der Sinn einer ISR :-)

Also wie gestern auch, wenn ich nicht immer hintereinander sende, 
sondern nur ein einziges mal, empfängt er auch ein Zeichen - sonst 
springt er einfach nicht in die ISR.

Weitere Ideen? ;-)

Björn

von Jörg X. (Gast)


Lesenswert?

Kannst du mal deine USART-Initialisierung hier reinstellen?

Und sind eigentlich diese Kommentare noch aktuell?
> [...] //UCSR1A ist dem Compiler nicht bekannt! Deswegen direkte SFR-Adresse
> [...] //UDR1 ist auch nicht bekannt!
Dann hast du entweder einen alten Compiler (bzw. eine alte avrlibc) oder 
den AVR nicht richtig eingestellt -- mein WinAVR 20071221 kennt die 
MegaX0 Familie nämlich und damit auch deren Register.

hth. Jörg

von Björn G. (tueftler)


Lesenswert?

Hier ist die Konfiguration:

Die sollte aber stimmen.
Habe momentan zu wenig Zeit um nach dem Fehler mit UCSR1A zu suchen...
1
void uart_s_config(void)
2
{
3
  UBRR1H = 0x03;                              //baud
4
  UBRR1L = 0x40;
5
6
  UCSR1A |= (1<<U2X1);
7
  UCSR1B |= (1<<TXEN1) | (1<<RXEN1) | (1<<RXCIE1);                    //TXD & RXD Enabled; RXD_ISR enabled
8
  UCSR1C |= (1<<UCSZ11) | (1<<UCSZ10);                          //8bit
9
}

Björn

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.