Forum: Mikrocontroller und Digitale Elektronik Echo-Test zwischen PC und Atmega644p


von Luffy M. (monkeydluffy)


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
}

von spess53 (Gast)


Lesenswert?

Hi

Der TX-Interrupt wird ausgelöst, wenn der TX-Puffer vom ATMega 
vollständig geleert wurde. Wie soll das bei dir passieren? Du sendest ja 
nichts.

MfG Spess

von Luffy M. (monkeydluffy)


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
}

von J.-u. G. (juwe)


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

von Luffy M. (monkeydluffy)


Lesenswert?

Danke schön,
 ich habe deine Anweisungen befoglt und habe das Problem gelöst.

mfg.

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.