Forum: Mikrocontroller und Digitale Elektronik Weiterleitung von Daten


von Sabine F. (Gast)


Lesenswert?

Hallo,

habe eine Hardware - UART Schnittstelle und möchte nun die Empfangen 
Daten dieser Schnittstelle über die Software - UART Schnittstelle 
weiterleiten (sprich senden).

Ich kann Daten empfangen und senden, aber alles nur getrennt. Wie muss 
ich vorgehen, damit ich die empfangenen Daten weiter senden kann?

von Tom M. (Gast)


Lesenswert?

Sabine F. schrieb:
> Ich kann Daten empfangen und senden, aber alles nur getrennt.

Was meinst du mit "getrennt"?

> Wie muss
> ich vorgehen, damit ich die empfangenen Daten weiter senden kann?

Ich würde am ehesten:

- eine Timer gesteuerte Senderoutine verwenden für die SW UART, die 
einfach Daten aus einem Sendepuffer rausschiebt
- den "UART RX Complete Interrupt" (sofern vorhanden) nutzen, um Daten 
in den Sendepuffer zu übergeben

Oder wenn's einfach werden soll:

- eine andere MCU derselben Familie nehmen, die 2 Hardware UARTs besitzt 
:D

von Sabine F. (Gast)


Lesenswert?

Tom M. schrieb:
> Was meinst du mit "getrennt"?

Ich kann sowohl Zeichen empfangen, welche ich über den Terminal an den 
Mikrocontroller sende, als wie auch Zeichen an den Terminal senden.

Daten werden im Terminal eingegeben und werden an den µC gesendet, 
dieser sollte sie danach weiterschicken an einen anderen Terminal.

Das Emfangen geschieht ohne Interrupts über die Hardware - UART, das 
Senden über die Software - UART mit Interrupt.
Funktioniert die Kombination von mit und ohne Interrupt?

von Noname (Gast)


Lesenswert?

Hi Sabiner,

das sollte eigentlich ohne Probleme gehen. Der Teufel wird wie immer im 
Detail stecken. Etwa unterschiedliche Baudraten ohne Puffer etc.
Beschreibe mal ausführlich was Du geschrieben hast und poste den 
Quellcode.

von Tom M. (Gast)


Lesenswert?

Sabine F. schrieb:
> Das Emfangen geschieht ohne Interrupts über die Hardware - UART,
> das Senden über die Software - UART mit Interrupt.

Klingt gut, sollte funzen. Wo hakt's noch?

von Sabine F. (Gast)


Lesenswert?

1
#include <avr/io.h>
2
#include "main.h"
3
#include "suart.h"
4
#include <avr/power.h>
5
6
int i;
7
char satz[2000];
8
9
int main( void ) {
10
  uart_init();
11
  uartRx();
12
  clock_prescale_set(clock_div_1);
13
  suart_init();
14
  DDRB = 0x02;
15
  PORTB = 0x02;
16
 
17
  sei();
18
  for(i=0; satz[i] != 0; i++) {
19
    sputs(satz[i]);    
20
    }
21
    for (;;) {        // main loop
22
      sputchar( '-' );
23
      while (! kbhit());      // wait until byte received
24
      sputchar (sgetchar () + 1);    // sent byte + 1
25
    }
26
}
27
28
void uart_init(void) {
29
    UBRR0H = 0x00;
30
  UBRR0L = 0x17;    
31
32
 
33
    UCSR0B = (1<<TXEN0) | (1<<RXEN0);  // UART TX und RX einschalten
34
    UCSR0C = (1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);  // Asynchron 8N2 
35
}
36
37
void uartRx() {
38
  satz[0] = 1;
39
  for(i=0; satz[i] != 0; i++) {
40
      while(!(UCSR0A & (1<<RXC0))) {
41
    }
42
    satz[i] = UDR0;                   
43
  }
44
}



Hier wird die Software UART initalisiert.
1
#include "main.h"
2
#include "suart.h"
3
4
5
6
#define BIT_TIME  (u8)((XTAL / BAUD) / PRESCALE)
7
8
9
volatile u8 stx_count;
10
u8 stx_data;
11
12
volatile u8 srx_done;
13
u8 srx_data;
14
u8 srx_mask;
15
u8 srx_tmp;
16
17
18
void suart_init( void )
19
{
20
  SBIT(PORTD,STX) = 1;
21
  // OCR0A = TCNT0 + 1;    // force first compare
22
  // TCCR0A = 0;        // Default: Normal port operation
23
  TCCR0B = 1 << CS01 | 1<<CS00;  // clk/64
24
  // TIFR0 = 1<<ICF1;      // clear pending interrupt
25
  TIMSK0 = 1 << OCIE0A;    // enable output compare interrupt
26
27
  EICRA = 1 << ISC01;      // falling edge
28
  EIMSK = 1 << INT0;      // enable edge interrupt
29
30
  stx_count = 0;        // nothing to sent
31
  srx_done = 0;            // nothing received
32
  STXDDR |= 1 << STX;      // TX output
33
}
34
35
36
u8 sgetchar (void)      // get byte
37
{
38
  while (!srx_done);      // wait until byte received
39
  srx_done = 0;
40
  return srx_data;
41
}
42
43
44
ISR (INT0_vect)    // rx start
45
{
46
  OCR0B = TCNT0 + (u8)((BIT_TIME * 3) / 2);// scan 1.5 bits after start
47
48
  srx_tmp = 0;        // clear bit storage
49
  srx_mask = 1;        // bit mask
50
  if( !(SRXPIN & 1<<SRX))  {  // still low
51
    EIMSK &= ~(1 << INT0);      // disable edge interrupt
52
    TIMSK0 = 1<<OCIE0A^1<<OCIE0B;  // wait for first bit
53
}
54
  TIFR0 = 1<<OCF0B;      // clear pending interrupt ? why does that output compare int occur?
55
EIFR |= (1 << INTF0);    // clear any pending edge interrupt
56
}
57
58
59
ISR (TIMER0_COMPB_vect)
60
{
61
  u8 in = SRXPIN;      // scan rx line
62
  // PORTB = 0x00;
63
  if (srx_mask) {
64
      if (in & 1 << SRX)
65
      srx_tmp |= srx_mask;
66
    srx_mask <<= 1;
67
    OCR0B += BIT_TIME;      // next bit slice
68
  } else {
69
    srx_done = 1;      // mark rx data valid
70
    srx_data = srx_tmp;      // store rx data
71
    // TIFR0 = 1<<ICF1;      // clear pending interrupt
72
    TIMSK0 = 1<<OCIE0A;        // enable tx and wait for start
73
    EIFR |= (1 << INTF0);    // clear any pending edge interrupt: This hinders the in0-vect from beeing triggerd again just now which may occur by falling edges in the serial data bits
74
    EIMSK = 1 << INT0;  // reenable edge interrupt
75
  }
76
    // PORTB = 0x02;
77
}
78
79
80
void sputchar (u8 val)      // send byte
81
{
82
  while (stx_count);      // until last byte finished
83
  stx_data = ~val;      // invert data for Stop bit generation
84
  stx_count = 10;      // 10 bits: Start + data + Stop
85
}
86
87
88
void sputs (u8 *txt)      // send string
89
{
90
  while (*txt)
91
    sputchar (*txt++);
92
}
93
94
95
ISR (TIMER0_COMPA_vect)    // tx bit
96
{
97
  u8 dout;
98
  u8 count;
99
100
  OCR0A += BIT_TIME;      // next bit slice
101
  count = stx_count;
102
103
  if (count) {
104
    stx_count = --count;    // count down
105
    // ??? dout = 1<<COM0A1;      // set low on next compare
106
    dout = 0;
107
    if (count != 9) {      // no start bit
108
      if (!(stx_data & 1))    // test inverted data
109
        //??? dout = 1<<COM0A1^1<<COM0A0;  // set high on next compare
110
        dout = 1;
111
          stx_data >>= 1;      // shift zero in from left
112
    }
113
    // TCCR0A = dout;
114
    // STX = (dout == 0) ? 1 : 0;
115
    SBIT(PORTD,STX) = dout;
116
  }
117
}

von Karl H. (kbuchegg)


Lesenswert?

Am einfachsten ist es, wenn du das ganze Gedöns mit dem 'satz' wieder 
vergisst.
Kommt ein Zeichen an der Hardware UART an, schickst du es gleich wieder 
auf der Software UART weiter.

Dazu brauchst du dann eine Funktion, die auf 1 Zeichen an der Hardware 
UART wartet
1
uint8_t uartRx()
2
{
3
  while(!(UCSR0A & (1<<RXC0)))
4
  {
5
  }
6
7
  return UDR0;                   
8
}

eine Funktion, die ein einzelnes Zeichen auf der Software UART 
rausschickt hast du ja schon. Und in der Hauptschleife in main() ist der 
verbindende 'Kitt'
1
int main()
2
{
3
  ....
4
5
6
  for(;;) {        // main loop
7
    Zeichen = uartRxChar();
8
    sputchar( Zeichen );
9
  }
10
}

dann überlegst du noch, was von dem Zeugs, das jetzt überflüssig ist, du 
nicht brauchst, schmeisst es raus und bist fertig.

von Sabine F. (Gast)


Lesenswert?

Tom M. schrieb:
> Klingt gut, sollte funzen. Wo hakt's noch?

Bei der Übertragung wird nur ein -o- übertragen, anstatt des textes.

von Noname (Gast)


Lesenswert?

Sag mal was über die Baudraten, bitte.

von Tom M. (Gast)


Lesenswert?

Sabine F. schrieb:
> Bei der Übertragung wird nur ein -o- übertragen, anstatt des textes.

Jo, was anderes tust du ja nicht in deiner main():

Sabine F. schrieb:

>     for(i=0; satz[i] != 0; i++) {
>       sputs(satz[i]);
>     }
>     for (;;) {        // main loop
>       sputchar( '-' );
>       while (! kbhit());      // wait until byte received
>       sputchar (sgetchar () + 1);    // sent byte + 1
>     }

von Max1989 (Gast)


Lesenswert?

Danke für eure bisherigen Antworten!!

Kann noch immer keine Zeichenkette versenden :(, hat jemand eine Idee?
1
#include "main.h"
2
#include "suart.h"
3
#include <avr/power.h>
4
5
char satz[2000];
6
int i = 0;
7
8
int main( void ) {
9
  clock_prescale_set(clock_div_1);
10
  suart_init();
11
12
  sei();
13
  while(1) {
14
  uartRxChar();
15
  sputs(satz[i]);  
16
  }
17
  for (;;) {        // main loop
18
    sputchar( '-' );
19
    while (! kbhit());      // wait until byte received
20
    sputchar (sgetchar () + 1);    // sent byte + 1
21
  }
22
}
23
24
void uartRxChar() {
25
      satz[0] = 1;
26
  for(i=0; satz[i] != 0; i++) {
27
      while(!(UCSR0A & (1<<RXC0))) {
28
    }
29
    return satz[i] = UDR0;                   
30
  }
31
}

von Karl H. (kbuchegg)


Lesenswert?

Max1989 schrieb:
> Danke für eure bisherigen Antworten!!
>
> Kann noch immer keine Zeichenkette versenden :(, hat jemand eine Idee?

Die Programmiersprache lernen.
Mit zusammenkopiertem unverstandenem Code hat noch keiner bei 0 
beginnend programmieren gelernt.

von Sabine F. (Gast)


Lesenswert?

Warum funktioniert es nicht, wenn ich das empfangene Zeichen in ein Char 
- Array an Stelle i speichere und dann die Stelle i wieder ausgib?

von UART (Gast)


Lesenswert?

Sabine,
Das wird so nichts.
Programmiere Dir erst mal eine UART library (oder nimm die eine vom 
Netz), bei der die empfangenen bzw. die zu sendenden Daten mittels 
Interrupt in eine Queue gespeichert werden.  Dann können die Daten aus 
der RxQueue bequem abgeholt, bearbeitet, und in die TxQueue geschoben 
werden.  Die Vermischung von UART Funktionalität und Bearbeitung in der 
Main loop führt ins Chaos.

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.