Echo-Test zwischen PC und Atmega644p

OP #3052150
Lesenswert?
• ▲
▼
Moin,

ich versuche ein Echo-Test zwischen PC und Atmega644p mit hilfe der 
Interruptsfunktion ISR(USART0_TX_vect) aufzubauen. Der PC sendet über 
RS232 nacheinander Daten zum Atmega644p. Der Atmega644p empfängt über 
USART0 die Daten vom PC und sendet wieder über USART0 die Empfangene 
Daten zum PC zurück.

Momentan ist der Atmega644p in der Lage Daten vom PC zu empfangen. Aber 
der Atmega644p sendet nicht die Daten zum PC zurück. Also,meine 
interruptsfunktion ISR(USART0_TX_vect) funktioniert nicht.

Ich wäre sehr dankbar, wenn jemand mir hilft.

Danke im Voraus.

Code vom Atmega644p:
1
#include <avr/io.h>
2
#include <avr/interrupt.h> 
3
#include <stdio.h>
4
#include <stdlib.h>
5
#include <string.h>
6
#include <avr/pgmspace.h>
7

8
#define F_CPU 3686400UL
9
#define FOSC 7372000 // Clock Speed
10
#define BAUD 9600UL
11

12
// Berechnungen zur Baudrate:
13

14
#define UBRR_VAL ((FOSC+BAUD*8)/(BAUD*16)-1)   // clever runden
15

16
#define usart0_rx_buffer_max_size 50 
17
/***************************************************/
18

19
char usart0_rx_buffer[usart0_rx_buffer_max_size];
20
volatile uint8_t usart0_rx_buffer_size = 0;
21

22
/****************************************************/
23
void USART_Init (unsigned int ubrr)
24
{
25
  UBRR0H = (unsigned char)(ubrr>>8);
26
  UBRR0L = (unsigned char) ubrr;
27
//  UBRR1H = (unsigned char)(ubrr>>8);
28
//  UBRR1L = (unsigned char) ubrr;
29
  
30

31
  UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(0<<TXCIE0)|(0<<UCSZ02)|(0<<UDRIE0);
32
  UCSR0C = (0<<USBS0) | (1<<UCSZ01)|(1<<UCSZ00);// 1 Stopbit, 8 Bits
33
  DDRB = 0b11111111; // Setting PB7-PB0 as output
34
  PORTB = (0<<PB7); // USART0 receive data from pc 
35
} 
36

37
ISR(USART0_RX_vect)
38
{
39
  char data = UDR0;
40
  
41
  if (usart0_rx_buffer_size < usart0_rx_buffer_max_size)
42
  {
43
    usart0_rx_buffer[usart0_rx_buffer_size] = data;
44
    ++usart0_rx_buffer_size;
45
   /* Activation transmission of data, then we have data in the buffer */
46
    UCSR0B |= (1<<TXCIE0);
47
  }
48
}
49

50
ISR(USART0_TX_vect)
51
{
52
  int i;
53
  if (usart0_rx_buffer_size == 0) // If we have no data to send
54
    UCSR0B &= ~(1<<TXCIE0);// we stop transmission
55
  else
56
  {
57
    UDR0 = usart0_rx_buffer[0];
58
    --usart0_rx_buffer_size;
59
    
60
    if (usart0_rx_buffer_size == 0)
61
      UCSR0B &= ~(1<<TXCIE0);
62
    else
63
      // it can be a circular buffer 
64
      for (i = 0; i < usart0_rx_buffer_size; ++i)
65
        usart0_rx_buffer[i] = usart0_rx_buffer[i + 1];
66
  } 
67
}
68

69
int main (void)
70
{ 
71
  USART_Init(UBRR_VAL) ;  // USART Initialisation
72
  
73
  sei();
74
  while(1)
75

76
  {   
77
  }
78

79
}
OP #3052672
Lesenswert?
• ▲
▼
Danke schön für deinen Hinweis Spess.

Ich habe versucht mit folgenden Schritten, der TX-Interrupt auszulösen:

1- TX-Interrupt ist deaktiviert
2- Im RX-Interrupt:
  - Daten in Puffer schreiben
  - UDRE-Interrupt aktivieren(UDRIE0 auf high setzen)
3- Im UDRE-empty-Interrupt:
  - Zeichen übertragen
  - Nach dem Senden des Zeichens, TXC0 löschen und TXCIE0 auf high 
setzen
4- Im TX-Interrupt (Übertragung vom Zeichen abgeschlossen)
  - UDRIE0 auf low setzen.
  - TXCIE0 auf low setzen
5- Im RX-Interrupt wird auf nächste Zeichen gewartet.

Mit meinem aktuellen Code kann ich der TX-Interrupt auslösen, wenn ich 
schritt für schritt der code ausführt. Aber der Echo-Test läuft trotzdem 
nicht. Der Atmega644p sendet nicht die Zeichen zurück.

Was mache ich denn falsch ! Danke im Voraus.
1
ISR(USART0_RX_vect)
2
{
3
  char data = UDR0;
4
  
5
  if (usart0_rx_buffer_size < usart0_rx_buffer_max_size)
6
  {
7
    usart0_rx_buffer[usart0_rx_buffer_size] = data;
8
    ++usart0_rx_buffer_size;
9
   /* Activation transmission of data, then we have data in the buffer */
10
    UCSR0B |= (1<<UDRIE0);
11
  }
12
}
13

14
ISR(USART0_TX_vect)
15
{
16
 UCSR0B &= ~((1<<UDRIE0)|(1<<TXCIE0));
17
}
18

19
ISR(USART0_UDRE_vect)
20
{
21
  int i;
22
  if (usart0_rx_buffer_size == 0) // If we have no data to send
23
  {
24
    UCSR0B &= ~(1<<UDRIE0);// we stop transmission
25
  }
26
  else
27
  {
28
    UDR0 = usart0_rx_buffer[0];
29
    --usart0_rx_buffer_size;
30
    
31
    if (usart0_rx_buffer_size == 0)
32
    {
33
      UCSR0A = (0<<TXC0);
34
      UCSR0B = (1<<TXCIE0; // TX-Interrupt aktivieren
35
    }
36
    else
37
      // it can be a circular buffer 
38
      for (i = 0; i < usart0_rx_buffer_size; ++i)
39
        usart0_rx_buffer[i] = usart0_rx_buffer[i + 1];
40
  } 
41
}
#3052704
Lesenswert?
• ▲
▼
Luffy Monkey schrieb:
> UCSR0A = (0<<TXC0);

Diese Anweisung löscht alle Bits im Register UCSR0A. Willst Du das?


> UCSR0B = (1<<TXCIE0; // TX-Interrupt aktivieren
Mal abgesehen von der fehlenden Klammer, mit dieser Anweisung setzt Du 
zwar das TXCIE0-Bit, alle anderen Bits dieses Registers werden aber 
gelöscht, was unter anderem zur Folge hat, das Transmitter und Receiver 
(TXEN0 und RXEN0) abgeschaltet werden. Kein Wunder, dass Du nichts 
senden kannst.

Wie man Bits richtig setzt und löscht:
http://www.mikrocontroller.net/articles/Bitmanipulation

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.