Forum: Mikrocontroller und Digitale Elektronik USART RS485 Daten empfangen über ISR


von Droid E. (eedroid)


Lesenswert?

Hallo,

ich möchte gerne Daten über die USART (RS485) Schnittstelle empfangen. 
Das senden der Daten funktioniert Prima! Als IDE verwende ich Microchip 
MPLAB X IDE 5.45

Hier die Initialisierung der UART Schnittstelle:
1
#ifndef __AVR_ATtiny3217__
2
    #define __AVR_ATtiny3217__
3
#endif
4
5
#define F_CPU 3333333UL
6
7
#include <avr/io.h>
8
#include <avr/interrupt.h>
9
10
#define USART0_BAUD_RATE(BAUD_RATE) ((float)(F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)
11
12
void uart_init()
13
{
14
    USART0.BAUD = (uint16_t)USART0_BAUD_RATE(9600);
15
16
    USART0.CTRLA =
17
        (1 << USART_RXCIE_bp)   /* Receive Complete Interrupt */
18
      | (0 << USART_TXCIE_bp)   /* Transmit Complete Interrupt */
19
      | (0 << USART_DREIE_bp)   /* Data Register Empty Interrupt */
20
      | (0 << USART_RXSIE_bp)   /* Receiver Start Frame Interrupt */
21
      | (0 << USART_LBME_bp)    /* Loop-back Mode Enable */
22
      | (0 << USART_ABEIE_bp)   /* Auto-baud Error Interrupt Enable */
23
      | USART_RS485_INT_gc;
24
25
    USART0.CTRLB =
26
        (1 << USART_RXEN_bp)    /* Reciever enable */
27
      | (1 << USART_TXEN_bp)    /* Transmitter enable */
28
      | (0 << USART_SFDEN_bp)   /* Start Frame Detection */
29
      | (0 << USART_ODME_bp)    /* Open Drain Mode */
30
      | USART_RXMODE_NORMAL_gc  /* Normal mode */
31
      | (0 << USART_MPCM_bp);   /* Multi-processor Communication Mode */
32
33
    USART0.CTRLC =
34
        USART_CMODE_ASYNCHRONOUS_gc /* Asynchronous Mode */
35
        | USART_PMODE_EVEN_gc       /* Even Parity */
36
        | USART_SBMODE_1BIT_gc      /* 1 stop bit */
37
        | USART_CHSIZE_8BIT_gc;     /* Character size: 8 bit */
38
}

Sowie das Senden der Daten:
1
void uart_send(char c)
2
{
3
    while (!(USART0.STATUS & USART_DREIF_bm))
4
        ;
5
6
    USART0.TXDATAL = c;
7
}

Und der Empfang der Daten:
1
ISR(USART0_RXC_vect)
2
{
3
    while (!(USART0.STATUS & USART_RXCIF_bm))
4
        ;
5
6
    char c = USART0.RXDATAL;
7
    
8
    uart_send(c);
9
}

Und die kurze Hauptroutine:
1
int main(void)
2
{
3
    uart_init();
4
5
    uart_send('R');
6
    uart_send('e');
7
    uart_send('a');
8
    uart_send('d');
9
    uart_send('y');
10
    
11
    sei();
12
13
    while (1)
14
    {
15
    }
16
17
    return 0;
18
}

- RS485 Modus ist aktiviert
- USART_RXCIE_bp ist gesetzt
- USART_RXEN_bp ist gesetzt
- sei() aktiviert die ISR

Anscheinend habe ich noch etwas vergessen oder doch noch etwas 
grundlegendes nicht verstanden!?

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Droid E. schrieb:
> Anscheinend habe ich noch etwas vergessen

Ja, zum Beispiel die Angabe um welchen Mikrocontroller es geht.

Worauf wartest du im USART0_RXC_vect?

Wenn dein Wecker klingelt, stehst du dann auf und wartest nochmal 
darauf, dass er klingelt?

Bist du sicher dass es kein Hardware-Problem ist? Wo wird denn die 
Übertragungsrichtung deines RS485 Transceivers umgeschaltet?

Ich würde mal einen USB-UART Adapter direkt an den µC anschließen und 
mit einem Terminalprogramm testen.

von Droid E. (eedroid)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ja, zum Beispiel die Angabe um welchen Mikrocontroller es geht.

Es handelt sich um den ATtiny3217

> Worauf wartest du im USART0_RXC_vect?
>
> Wenn dein Wecker klingelt, stehst du dann auf und wartest nochmal
> darauf, dass er klingelt?

Ich verstehe nicht was du damit meinst.

> Bist du sicher dass es kein Hardware-Problem ist? Wo wird denn die
> Übertragungsrichtung deines RS485 Transceivers umgeschaltet?

Mit dem Bit USART_RS485_INT_gc:
These bits enable the RS-485 and select the operation mode. Writing 
RS485[1] to ‘1’ enables the RS-485 mode which automatically sets the TXD 
pin to output one clock cycle before starting transmission and sets it 
back to input when the transmission is complete.

> Ich würde mal einen USB-UART Adapter direkt an den µC anschließen und
> mit einem Terminalprogramm testen.

Wenn es ein Hardware-Problem wäre, dann würde das senden wohl nicht ohne 
Probleme funktionieren?

von Dirk (Gast)


Lesenswert?

Gruss zum Abend

Nehme an der µC ist ein ATtiny3217, so ein neuer
mit reduziertem EEPROM(256byte) bei 32k u. 2k.


Dirk St

von Droid E. (eedroid)


Lesenswert?

Dirk schrieb:
> Gruss zum Abend
>
> Nehme an der µC ist ein ATtiny3217, so ein neuer
> mit reduziertem EEPROM(256byte) bei 32k u. 2k.
>
>
> Dirk St

Guten Abend Dirk,

ja - deine Angaben stimmen aber was hat dass mit der RS485 UART 
Schnittstelle zu tun ;) ?

von S. Landolt (Gast)


Lesenswert?

So ad hoc vermute ich auch ein Hardwareproblem; ich würde probeweise den 
uC löschen und dann PB2 mit PB3 verbinden - was passiert dann am PC, 
kommt ein Echo?

von Droid E. (eedroid)


Lesenswert?

S. Landolt schrieb:
> So ad hoc vermute ich auch ein Hardwareproblem; ich würde probeweise den
> uC löschen und dann PB2 mit PB3 verbinden - was passiert dann am PC,
> kommt ein Echo?

Das geht so einfach mit dem RS485? Senden funktioniert ohne Probleme!

: Bearbeitet durch User
von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

S. Landolt schrieb:
> So ad hoc vermute ich auch ein Hardwareproblem; ich würde probeweise den
> uC löschen und dann PB2 mit PB3 verbinden - was passiert dann am PC,
> kommt ein Echo?

Es würde mich wundern, wenn ein Echo käme, denn bei dem vorgeschlagenen 
Test aktiviert niemand das Transmit-Enable des RS485-Tranceivers.

Vielleicht sollte der TO erst mal kleine Brötchen backen und auf den 
Interrupt verzichten. Wenn das Senden mit Polling erfolgt, spricht doch 
nichts dagegen auch das Empfangen zu pollen.

Grüßle
Volker

von S. Landolt (Gast)


Lesenswert?

Gute Frage, Sie haben mich erwischt: ich weiß es nicht. Probieren würde 
ich es trotzdem - funktioniert es, liegt es doch am Programm, 
funktioniert es nicht, muss man weitersuchen.

von Dirk (Gast)


Lesenswert?

Gruss

Der Typ steht doch im Programm.
Ich wollte nur darauf hin weisen.
Bin selbst mit den Schnittstellen beschäftigt, bei Atmega, multi.
Aber einen von den Neueren hatte ich noch nicht auf dem Tisch, geschw. 
Datenblatt


Dirk St

von Droid E. (eedroid)


Lesenswert?

Wenn ich polle, dann sieht das Programm so aus:
1
void uart_send(char c)
2
{
3
    while (!(USART0.STATUS & USART_DREIF_bm))
4
        ;
5
6
    USART0.TXDATAL = c;
7
}
8
9
char uart_read()
10
{
11
    while (!(USART0.STATUS & USART_RXCIF_bm))
12
        ;
13
14
    return USART0.RXDATAL;
15
}
16
17
int main(void)
18
{
19
    //...
20
21
    while (1)
22
    {
23
        PORTB.OUT &= ~PIN4_bm;
24
25
        c = uart_read();
26
        uart_send(c);
27
28
        PORTB.OUT |= PIN4_bm;
29
30
        c = uart_read();
31
        uart_send(c);
32
    }
33
    return 0;
34
}

Wobei ich im uart_init den USART_RXCIE_bp gelöscht habe und das sei im 
main habe ich auch entfernt. Das USART_RXEN_bp ist gesetzt ist weiterhin 
gesetzt.

Ergebnis: Bleibt leider wie gehabt, es kommt kein Zeichen zurück.

: Bearbeitet durch User
von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Droid E. schrieb:

> Ergebnis: Bleibt leider wie gehabt, es kommt kein Zeichen zurück.

Nun ja, dann kann ich wohl nichts für Dich tun, da mir, wie bereits beim 
Vorgängerthread, Deine Be- oder besser Verschaltung unbekannt ist und 
ich leider nach wie vor nicht des Hellsehens mächtig bin :-/

Da Du der Einzige bist, der über die nötigen Informationen verfügst, 
solltest Du prüfen, ob Dein PC-USB-RS485-Adapter wirklich auch den 
RS485-Transceiver aktiviert, also ob der entspechende Pin beschaltet.

Dann das selbe auf der MCU-Seite des RS485-Busses aber diesmal mit dem 
Receiver-Enable.

Ein Oszilloskop wäre ebenfalls hilfreich...

Grüßle
Volker.

von Spess53 (Gast)


Lesenswert?

Hi

Warum machst du zum gleichen Thema

Beitrag "ATtiny3217 UART Schnittstelle"

einen 2.Thread auf?

Dort hast du nicht auf meinen Einwurf geantwortet.

Beitrag "Re: ATtiny3217 UART Schnittstelle"

MfG Spess

von oh weh (Gast)


Lesenswert?

Volker B. schrieb:
> Nun ja, dann kann ich wohl nichts für Dich tun, da mir, wie bereits beim
> Vorgängerthread, Deine Be- oder besser Verschaltung unbekannt ist und
> ich leider nach wie vor nicht des Hellsehens mächtig bin :-/

Da kommt dabei mir schon stark der Eindruck nach Beratungsresistenz
auf. Hier wird offensichtlich gedacht und gehandelt nach dem
Motto: was nicht sein darf kann nicht sein.

von Droid E. (eedroid)


Angehängte Dateien:

Lesenswert?

Spess53 schrieb:
> Hi
>
> Warum machst du zum gleichen Thema
>
> Beitrag "ATtiny3217 UART Schnittstelle"
>
> einen 2.Thread auf?
>
> Dort hast du nicht auf meinen Einwurf geantwortet.
>
> Beitrag "Re: ATtiny3217 UART Schnittstelle"
>
> MfG Spess

Weil es in dem ersten Thread um das Senden ging, und hier geht es nun um 
das empfangen. Anbei meine neue Beschaltung. Unterschied zu vorher, A 
und B vertauscht und Masse angeschlossen ;)

von oh weh (Gast)


Lesenswert?

Spess53 schrieb:
> Dort hast du nicht auf meinen Einwurf geantwortet.

D.h. noch mehr aufkommende Beratungsresistenz. Einfach nur das
lesen was man hören will. Eingehen auf einen Dialog unerwünscht.

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Droid E. schrieb:

> Weil es in dem ersten Thread um das Senden ging, und hier geht es nun um
> das empfangen. Anbei meine neue Beschaltung. Unterschied zu vorher, A
> und B vertauscht und Masse angeschlossen ;)

So und jetzt bitte noch die Dokumentation des kleinen Adapterchens am 
USB-RS232-Converter. Meine leider nicht sehr ausgeprägten 
hellseherischen Fähigkeiten sagen mir, dass der Transmitter über eines 
der Handshakesignale der Rs232 aktiviert werden will. Leider sehe ich 
aber nicht, welches -- und ich sehe auch nicht, ob Du das auch wirklich 
machst...

Grüßle
Volker

: Bearbeitet durch User
von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Droid E. schrieb:
> Ich verstehe nicht was du damit meinst.

Du brauchst im Empfangs-Interrupt nicht darauf warten, dass etwas 
empfangen wurde. Weil: genau das signalisiert der Interrupt doch 
bereits!

> Bit USART_RS485_INT_gc  ...

Ach so. Ich kenne diesen µC nicht, deswegen dachte ich an einen externen 
Transceiver an RxD und TxD, der einen DIR Eingang haben müsste.

> Wenn es ein Hardware-Problem wäre, dann würde das
> senden wohl nicht ohne Probleme funktionieren?

Bei einem externen Transceiver könnte das DIR Signal mangels Ansteuerung 
immer auf "senden" stehen. Dann wäre logisch, dass du nichts empfängst.

Dirk schrieb:
> Der Typ steht doch im Programm.

Facepalm. Oder hast du das nachträglich ergänzt?

Das Foto vom Aufbau zeigt eindeutig einen externen Transceiver, und ich 
sehe dass du es auf Half-Duplex gejumpert hast. Irgendwie musst du 
dessen Übertragungsrichtung steuern, und auf PC Seite ebenso.

In der Doku von dem RS485 Board steht:
5 GPIO1_RTS Driver Enable to RS485 Transceiver
6 GPIO2_CTS Receiver Enable to RS485 Transceiver

Du musst diese Pins ansteuern. Offenbar hat der µC dazu einen XDIR 
Ausgang, welcher den Transmitter einschaltet. Aber wer schaltet den 
Receiver ein?

von Droid E. (eedroid)


Angehängte Dateien:

Lesenswert?

Stefan ⛄ F. schrieb:
> Du musst diese Pins ansteuern. Offenbar hat der µC dazu einen XDIR
> Ausgang, welcher den Transmitter einschaltet. Aber wer schaltet den
> Receiver ein?

Der ATtiny3217 Xplained Pro hat einen XDIR Pin (PB0), dieser ist aber 
nicht mit dem DE/RE Pin von der RS485 Xplained Pro Platine verbunden, 
sondern der gewöhnliche PB7.

Dann muss der PB7 immer auf 1 gesetzt werden, damit der AT3217 empfangen 
kann, es sei denn ich möchte senden, dann muss ich diesen vorher auf 0 
gesetzt werden.

Ich habe das Zusammenspiel von XDIR (PB0) und von den beiden RS485-Bits 
in dem Register USART0.CTRLA wohl überhaupt nicht verstanden!

von Stefan F. (Gast)


Lesenswert?

Ich sehe, das du das jetzt alleine hin bekommst.

von Droid E. (eedroid)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich sehe, das du das jetzt alleine hin bekommst.

Um ehrlich zu sein habe ich jetzt absolut keine Ahnung wie ich den 
ATtiny3217 jetzt konfigurieren muss :(

von Stefan F. (Gast)


Lesenswert?

J101 gehört auf Position 2+3 (Half Duplex)

Du musst PB7 "zu Fuß" auf HIGH setzen, bevor du sendest.
Du musst PB7 "zu Fuß" danach wieder auf LOW setzen, um zu empfangen.

Setze ihn nicht zu früh auf LOW, denn das Senden dauert länger, als der 
Schreibzugriff auf das Register USART0.TXDATAL.

> Ich habe das Zusammenspiel von XDIR (PB0) und von den beiden
> RS485-Bits in dem Register USART0.CTRLA wohl überhaupt nicht
> verstanden!

Offenbar kannst du diese XDIR Funktion nicht nutzen, weil diese Leitung 
nicht mit dem RS485 Transceiver verbunden ist.

Bei solchen Sachen merke ich (immer wieder), dass die "neuen" ATtinies 
ebenso wie die Xmegas zum Anfangen ebenso schlecht geeignet sind, wie 
die STM32 Controller. Sie haben super viele Funktionen, das macht ihre 
Anwendung super komplex. Ich weiß nicht, warum du ausgerechnet diese 
Boards ausgewählt hast. Vielleicht magst du dich vorher mit den 
klassischen AVR Controllern der zweiten Generation vertraut machen, da 
kommt man viel leichter rein:
1
     8 Pins: ATtiny 25, 45, 85
2
    14 Pins: ATtiny 24, 44, 84
3
    20 Pins: ATtiny 261, 461, 861
4
    28 Pins: ATmega 48, 88, 168, 328
5
    40 Pins: ATmega 164, 324, 644, 1284

Bei Chip45 gibt es kannst du das Crumb644 Board kaufen 
(https://www.chip45.com/atmega644-usb-rs485-modul.html?language=de). Es 
ist dem Arduino Nano ähnlich, nur etwas größer und mit RS485 
Transceiver. Auch dort musst du die Richtungsumschaltung "zu Fuß" 
machen.

von Pieter (Gast)


Lesenswert?

moin,

wenn bei RS485 eine Seite sendet ist die Leitung in einem definierten 
Zustand. Schaltet der Sender auf Empfang um, ist die Leitung in einem 
undefinierten Zustand. Der Rx kann irgendwas "empfangen".
Abhilfe: Mit 2 BaisWiderständen die Leitung vorspannen.

5V - R - A - 120|120 - B - R - GND
R : Die Baiswiderstände, so auslegen das die Spannung A-B ca. 1V hat, 
wenn beide Seiten auf Empfang stehen.

VG
Pieter

von Dirk (Gast)


Lesenswert?

Ja, und Gruss

Ein Schönes Entwicklungsboard mit dazugehörigem RS von Microchip hast Du 
da.
Die einzelnen Attiny 3217 gibt es erst ab Mai, August bei Mouser (+5€! 
bei etwa 0.8€).
Dann mal viel Spaß.

Dirk St

von Dirk (Gast)


Lesenswert?

Noch einen Gruss

Die pdf Info von Microchip dazu ist anscheinend
unvollständig, zumindest bei mir kommt die pdf
nicht vollständig an, so das Bild dazu.

Internet:
Getting started with USART
ww1.microchip.com
http://ww1.microchip.com/downloads/en/DeviceDoc/Getting-Started-with-USART-90003216A.pdf

Dirk St

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Droid E. schrieb:
1
#ifndef __AVR_ATtiny3217__
2
    #define __AVR_ATtiny3217__
3
#endif

Das kann in die Hose gehen - nämlich, wenn Du in der IDE einen anderen 
µC eingestellt hast.

Wenn Du dort den richtigen eingestellt hast, dann sind die Zeilen jedoch 
überflüssig.

Fazit: In beiden Fällen gehören die nicht in den Source.

: Bearbeitet durch Moderator
von Droid E. (eedroid)


Lesenswert?

Ich weiß dass sowohl senden als auch empfangen funktionieren. Aber ich 
bekomme es leider immer noch nicht hin, ich komme einfach nicht weiter 
:(
1
#define F_CPU 3333333UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
#define USART0_BAUD_RATE(BAUD_RATE) ((float)(F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)
7
8
void uart_init()
9
{
10
    USART0.BAUD = (uint16_t)USART0_BAUD_RATE(9600);
11
12
    USART0.CTRLA =
13
        (0 << USART_RXCIE_bp)   /* Receive Complete Interrupt */
14
      | (0 << USART_TXCIE_bp)   /* Transmit Complete Interrupt */
15
      | (0 << USART_DREIE_bp)   /* Data Register Empty Interrupt */
16
      | (0 << USART_RXSIE_bp)   /* Receiver Start Frame Interrupt */
17
      | (0 << USART_LBME_bp)    /* Loop-back Mode Enable */
18
      | (0 << USART_ABEIE_bp)   /* Auto-baud Error Interrupt Enable */
19
      | USART_RS485_EXT_gc;
20
21
    USART0.CTRLB =
22
        (1 << USART_RXEN_bp)    /* Reciever enable */
23
      | (1 << USART_TXEN_bp)    /* Transmitter enable */
24
      | (0 << USART_SFDEN_bp)   /* Start Frame Detection */
25
      | (0 << USART_ODME_bp)    /* Open Drain Mode */
26
      | USART_RXMODE_NORMAL_gc  /* Normal mode */
27
      | (0 << USART_MPCM_bp);   /* Multi-processor Communication Mode */
28
29
    USART0.CTRLC =
30
        USART_CMODE_ASYNCHRONOUS_gc /* Asynchronous Mode */
31
        | USART_PMODE_EVEN_gc       /* Even Parity */
32
        | USART_SBMODE_1BIT_gc      /* 1 stop bit */
33
        | USART_CHSIZE_8BIT_gc;     /* Character size: 8 bit */
34
}
35
36
void uart_send(char c)
37
{
38
    while (!(USART0.STATUS & USART_DREIF_bm))
39
        ;
40
41
    USART0.TXDATAL = c;
42
}
43
44
char uart_read()
45
{
46
    while (!(USART0.STATUS & USART_RXCIF_bm))
47
        ;
48
49
    return USART0.RXDATAL;
50
}
51
52
int main(void)
53
{
54
    char c1,c2 = 0;
55
56
    PORTB.DIR |= PIN4_bm;     // output
57
    //PORTB.OUT |= PIN4_bm;   // led off
58
    PORTB.OUT &= ~PIN4_bm;    // led on
59
60
    PORTB.DIR |= PIN7_bm;
61
    //PORTB.OUT &= ~PIN7_bm;  // receive works
62
    //PORTB.OUT |= PIN7_bm;   // nothing works
63
64
    uart_init();
65
66
    while (1)
67
    {
68
        // receiving
69
        PORTB.OUT &= ~PIN7_bm;
70
71
        c1 = uart_read();
72
        PORTB.OUT |= PIN4_bm;
73
74
        c2 = uart_read();
75
        PORTB.OUT &= ~PIN4_bm;
76
77
        // sending
78
        PORTB.OUT |= PIN7_bm;
79
80
        _delay_ms(500);
81
        PORTB.OUT &= ~PIN4_bm;
82
83
        uart_send('X');
84
85
        PORTB.OUT |= PIN4_bm;
86
        _delay_ms(500);
87
    }
88
89
    return 0;
90
}

von Stefan F. (Gast)


Lesenswert?

Droid E. schrieb:
> Ich weiß dass sowohl senden als auch empfangen funktionieren.

Woran erkennst du das?

> Aber ich bekomme es leider immer noch nicht hin

Was bekommst du nicht hin?

> #define F_CPU 3333333UL

Bist du sicher, das das stimmt? Wo und wie hast du denn die 
Taktversorgung konfiguriert?

Es wäre hilfreich, die Signale am UART (Rx, Tx und PB7) mit einem Logic 
Analyzer aufzuzeichnen, damit das Raten ein Ende hat.

Wenn du noch keinen hast, kaufe dir einen. Und zwar schnell. Du wirst 
ihn noch öfter brauchen. Für 10€ kannst du noch diese Woche einen 
geliefert bekommen.

Warum benutzt du eine einzelne LED zum Debuggen? Du hast doch einen 
Debugger (hoffe ich) und die Möglichkeit, aussagekräftige Texte seriell 
auszugeben.

von Droid E. (eedroid)


Lesenswert?

Stefan ⛄ F. schrieb:
> Woran erkennst du das?

Wenn ich folgendes in uart_init vertausche: USART_RS485_INT_gc anstatt 
USART_RS485_EXT_gc. Dann funktioniert senden aber nicht empfangen, weil 
laut Datenblatt das für eine One-Wire Lösung ist.

Wenn ich USART_RS485_EXT_gc benutze, dann läuft vom AVR der PB0 ins 
leere, weil dieser für XDIR vorgesehen ist, aber das sollte doch egal 
sein!?

Wenn ich bei USART_RS485_EXT_gc den Fall "PORTB.OUT &= ~PIN7_bm" habe, 
dann kann ich im Programm Haltepunkte setzen und mir "c1 = uart_read()" 
und "c2 = uart_read() angucken, die Werte passen.

Wenn ich jetzt bei "USART_RS485_EXT_gc" Daten senden möchte, passiert 
leider nichts erkennbares. "PORTB.OUT |= PIN7_bm" und auch "PORTB.OUT &= 
~PIN7_bm" haben kein Auswirkung. Davor und danach hatte ich sogar einen 
delay eingebaut.

von Stefan F. (Gast)


Lesenswert?

Es kann nur im Modus EXT oder OFF funktionieren, weil dein externer 
Transceiver mit zwei separaten Leitungen (Rx und Tx) an den µC 
angebunden ist. Die Zusammenführung von Transmitter und Receiver findet 
auf der Zusatz-Platine hinter dem Transceiver statt.

EXT ist für dich nutzlos, weil PB0 nicht mit den Steuereingängen des 
Transceivers verbunden ist. Also nimmst du sinnvollerweise den Modus 
OFF.

Es würde aber auch mit EXT funktionieren.

> "PORTB.OUT |= PIN7_bm" und auch "PORTB.OUT &= ~PIN7_bm"
> haben kein Auswirkung

Aber die LED an PB4 lässt sich ansteuern? Und eine LED an PB7 reagiert 
nicht? Dann ist der Pin vielleicht kaputt gegangen.

von Droid E. (eedroid)


Lesenswert?

Stefan ⛄ F. schrieb:
> Aber die LED an PB4 lässt sich ansteuern? Und eine LED an PB7 reagiert
> nicht? Dann ist der Pin vielleicht kaputt gegangen.

Haben keinen Einfluss auf das senden. Mit "PORTB.OUT &= ~PIN7_bm" kann 
ich das Empfangen aber sehr wohl einschalten bzw. mit "PORTB.OUT |= 
PIN7_bm" das Empfangen ausschalten.

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Stefan ⛄ F. schrieb:

>> #define F_CPU 3333333UL
>
> Bist du sicher, das das stimmt? Wo und wie hast du denn die
> Taktversorgung konfiguriert?

Initialwerte nach dem Reset: 20MHz RC-Oszillator und Takteiler 6

> Es wäre hilfreich, die Signale am UART (Rx, Tx und PB7) mit einem Logic
> Analyzer aufzuzeichnen, damit das Raten ein Ende hat.

Ich schlage ihm schon seit seinem ersten Thread zu diesem Thema vor die 
Signale zu oszillografieren... :-/

Hilfreich wäre auch zu wissen, welche Enable-Signale des Transceivers 
nun wirklich mit welchen Portpins der MCU verbunden sind.

Außerdem wundere ich mich, warum in diesen Experimenten der Tx-Pin des 
USARTs nicht mehr als Ausgang konfiguriert wird. Wir sehen hier ein 
extremes Beispiel von Lernresistenz und ich werde mich hier nicht mehr 
äußern. So dermaßen dämlich kann sich doch kein Mensch anstellen!

Grüßle
Volker

: Bearbeitet durch User
von Droid E. (eedroid)


Lesenswert?

Volker B. schrieb:
> Außerdem wundere ich mich, warum in diesen Experimenten der Tx-Pin des
> USARTs nicht mehr als Ausgang konfiguriert wird.


Bits 1:0 – RS485[1:0] RS-485 Mode
These bits enable the RS-485 and select the operation mode. Writing 
RS485[0] to ‘1’ enables the RS-485 mode which automatically drives the 
XDIR pin high one clock cycle before starting transmission and pulls it 
low again when the transmission is complete. Writing RS485[1] to ‘1’ 
enables the RS-485 mode which automatically sets the TXD pin to output 
one clock cycle before starting transmission and sets it back to input 
when the transmission is complete.

Die _beiden_ Felder RS485 Bits in USART0.CTRLA waren in meinem Fall 
die Lösung, nicht "entweder, oder"

EDIT: Könnt ihr mir zu guter Letzt noch einen Logic Analyzer für solche 
Fälle empfehlen :)

Vielen Dank!

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Droid E. schrieb:
> Haben keinen Einfluss auf das senden. Mit "PORTB.OUT &= ~PIN7_bm" kann
> ich das Empfangen aber sehr wohl einschalten bzw. mit "PORTB.OUT |=
> PIN7_bm" das Empfangen ausschalten.

Dann ist vielleicht der Transmitter kaputt. Kannst du das nicht 
nachmessen? Hast du weder Logic Analyzer noch Oszilloskop? Du könntest 
wenigstens LEDs an sämtliche Signale (auch zwischen den beiden Boards) 
hängen und mit niedriger Baudrate testen. Dann kann man sie flackern 
sehen (oder eben nicht).

Wie bereits vorher empfohlen würde ich auch erstmal den RS485 
Transceiver weg lassen und nur UART testen. Dann hast du gleich mehrere 
Baustellen weniger offen.

Erst wenn UART klappt, macht der nächste Schritt mit dem RS485 
Transceiver Board Sinn.

von Droid E. (eedroid)


Lesenswert?

Stefan ⛄ F. schrieb:
> Hast du weder Logic Analyzer noch Oszilloskop?

Es funktioniert jetzt, ich musste im "USART0.CTRLA" schon das richtige 
Bit setzen:
1
    USART0.CTRLA =
2
        (0 << USART_RXCIE_bp)   /* Receive Complete Interrupt */
3
      | (0 << USART_TXCIE_bp)   /* Transmit Complete Interrupt */
4
      | (0 << USART_DREIE_bp)   /* Data Register Empty Interrupt */
5
      | (0 << USART_RXSIE_bp)   /* Receiver Start Frame Interrupt */
6
      | (0 << USART_LBME_bp)    /* Loop-back Mode Enable */
7
      | (0 << USART_ABEIE_bp);   /* Auto-baud Error Interrupt Enable */
8
9
    USART0.CTRLA |= ((0 << 0) | (1 << 1));

von Droid E. (eedroid)


Lesenswert?

Stefan ⛄ F. schrieb:
> UART testen

Ok, dann geht das aber mit einem UART-USB Adapter?

von Stefan F. (Gast)


Lesenswert?

Droid E. schrieb:
> Es funktioniert jetzt

Na endlich. bestelle dir trotzdem einen Logic Analyzer. Und wo du gerade 
dabei bist, auch ein Oszilloskop. Wenn es billig sein muss, dann ein 
DSO150. So ein Spielzeug ist immer noch 100x besser als gar keins zu 
haben.

> ich musste im "USART0.CTRLA" schon das richtig Bit setzen:

> USART0.CTRLA = ...
>     USART0.CTRLA |= ((0 << 0) | (1 << 1));

Wo ist da jetzt der Unterschied zu:

> USART0.CTRLA = ...
>     | USART_RS485_EXT_gc;

Welchen Wert hat USART_RS485_EXT_gc? Gibt es auch USART_RS485_EXT_bm?

Droid E. schrieb:
> UART testen
> Ok, dann geht das aber mit einem UART-USB Adapter?

Ja klar.

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Stefan ⛄ F. schrieb:

>> USART0.CTRLA = ...
>>     USART0.CTRLA |= ((0 << 0) | (1 << 1));
>
> Wo ist da jetzt der Unterschied zu:
>
>> USART0.CTRLA = ...
>>     | USART_RS485_EXT_gc;
>

Ich weiß, der Blick in das Datenblatt wird hier nicht gern gesehen, aber 
ich erlaube mir mal zu zitieren:

Microchip schrieb im Datenblatt des ATtiny3217:
> Bits 1:0 – RS485[1:0] RS-485 Mode
> These bits enable the RS-485 and select the operation mode.
>
> Value Name Description
> 0x0   OFF  Disabled.
> 0x1   EXT  Enables RS-485 mode with control of an external line
>            driver through a dedicated Transmit Enable (TE) pin.
> 0x2   INT  Enables RS-485 mode with control of the internal
>            USART transmitter.

Anmerkung: der TE-Pin ist an der MCU der bereits mehrfach erwähnte 
XDIR-Pin.

Da der TO zumindest im ersten Beitrag einen externen Transceiver 
verwendete, sollte er tunlichst den EXT-Mode aktivieren.

Der INT-Mode "emuliert" einen Pseudo-RS485-Bus (auf nur einer Leitung) 
direkt am TxD-Pin des USARTs, d.h. der USART will dann auch vom TxD-Pin 
lesen und nicht vom RxD-Pin.

Aber, wenn der TO meint, dass nun alles funktioniert, dann darf er das 
gerne glauben...

Stefan ⛄ F. schrieb:
> Welchen Wert hat USART_RS485_EXT_gc? Gibt es auch USART_RS485_EXT_bm?

_bm gibts nur für einzelne Bits, _gc für mehrere. Da hier zwei Bits 
verwendet werden, gibts keine _bm Bitmaske.

Grüßle
Volker

: Bearbeitet durch User
von Droid E. (eedroid)


Lesenswert?

Volker B. schrieb:
> Aber, wenn der TO meint, dass nun alles funktioniert, dann darf er das
> gerne glauben...

Hallo Volker,

es ist nicht so das ich das Datenblatt nicht gelesen hätte oder ich hier 
eine fertige Lösung suche die einfach nur funktioniert. Aber du hast 
dennoch recht, ich habe es immer noch nicht verstanden, nicht mal 
Ansatzweise. Ich möchte nur gerne wissen, was ich falsch mache. Wenn du 
möchtest kann ich dir gerne die Hardware senden, müsste ich nur danach 
wieder zurück haben!

Anbei der Quellcode, aus meiner Sicht mit dem falsch konfigurierten 
USART0.CTRLA.

Ist-Zustand, nach meiner Meinung falsch konfiguriert:
1
    USART0.CTRLA =
2
      | USART_RS485_INT_gc;     // (0x02<<0) - RS485 Mode Internal drive
3
      //| USART_RS485_EXT_gc;   // (0x01<<0) - RS485 Mode External drive
4
      //| USART_RS485_OFF_gc;   // (0x00<<0) - RS485 Mode disabled

Soll-Zustand, nach meiner Meinung falsch konfiguriert::
1
    USART0.CTRLA =
2
      //| USART_RS485_INT_gc;   // (0x02<<0) - RS485 Mode Internal drive
3
      | USART_RS485_EXT_gc;     // (0x01<<0) - RS485 Mode External drive
4
      //| USART_RS485_OFF_gc;   // (0x00<<0) - RS485 Mode disabled
1
#define F_CPU 3333333UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
#define USART0_BAUD_RATE(BAUD_RATE) ((float)(F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)
7
8
void uart_init()
9
{
10
    USART0.BAUD = (uint16_t)USART0_BAUD_RATE(9600);
11
12
    USART0.CTRLA =
13
        (0 << USART_RXCIE_bp)   /* Receive Complete Interrupt */
14
      | (0 << USART_TXCIE_bp)   /* Transmit Complete Interrupt */
15
      | (0 << USART_DREIE_bp)   /* Data Register Empty Interrupt */
16
      | (0 << USART_RXSIE_bp)   /* Receiver Start Frame Interrupt */
17
      | (0 << USART_LBME_bp)    /* Loop-back Mode Enable */
18
      | (0 << USART_ABEIE_bp)   /* Auto-baud Error Interrupt Enable */
19
      | USART_RS485_INT_gc;     // (0x02<<0) - RS485 Mode Internal drive
20
      //| USART_RS485_EXT_gc;   // (0x01<<0) - RS485 Mode External drive
21
      //| USART_RS485_OFF_gc;   // (0x00<<0) - RS485 Mode disabled
22
23
    USART0.CTRLB =
24
        (1 << USART_RXEN_bp)    /* Reciever enable */
25
      | (1 << USART_TXEN_bp)    /* Transmitter enable */
26
      | (0 << USART_SFDEN_bp)   /* Start Frame Detection */
27
      | (0 << USART_ODME_bp)    /* Open Drain Mode */
28
      | USART_RXMODE_NORMAL_gc  /* Normal mode */
29
      | (0 << USART_MPCM_bp);   /* Multi-processor Communication Mode */
30
31
    USART0.CTRLC =
32
        USART_CMODE_ASYNCHRONOUS_gc /* Asynchronous Mode */
33
        | USART_PMODE_EVEN_gc       /* Even Parity */
34
        | USART_SBMODE_1BIT_gc      /* 1 stop bit */
35
        | USART_CHSIZE_8BIT_gc;     /* Character size: 8 bit */
36
}
37
38
void uart_send(char c)
39
{
40
    while (!(USART0.STATUS & USART_DREIF_bm))
41
        ;
42
43
    USART0.TXDATAL = c;
44
}
45
46
char uart_read()
47
{
48
    while (!(USART0.STATUS & USART_RXCIF_bm))
49
        ;
50
51
    return USART0.RXDATAL;
52
}
53
54
int main(void)
55
{
56
    char c = 0;
57
58
    //PORTB.DIR |= PIN0_bm;
59
    PORTB.DIR |= PIN7_bm;
60
61
    uart_init();
62
63
    while (1)
64
    {
65
        // receiving
66
        PORTB.OUT &= ~PIN7_bm;
67
        c = uart_read();
68
        
69
        _delay_ms(100);
70
71
        // sending
72
        PORTB.OUT |= PIN7_bm;
73
        uart_send(c);
74
75
        _delay_ms(100);
76
    }
77
78
    return 0;
79
}

__:(__

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Droid E. schrieb:

> (...)  Aber du hast
> dennoch recht, ich habe es immer noch nicht verstanden, nicht mal
> Ansatzweise. Ich möchte nur gerne wissen, was ich falsch mache. Wenn du
> möchtest kann ich dir gerne die Hardware senden, müsste ich nur danach
> wieder zurück haben!

Ich glaube nicht, dass ich die Hardware benötige. Wichtig wäre zu 
wissen, wie Du Deine Hardware beschaltet und gejumpert hast.
Mein Vorschlag: Drucke die Schaltpläne von MCU-Board und RS485-Board 
aus. Schneide die Schaltpläne aus und klebe beide gemeinsam auf ein 
Blatt. Nun zeichnest Du die Verbindungen ein, die den gesetzten Jumpern 
und dem   Steckverbinder ziwschen MCU- und Rs485-Board entsprechen. Dann 
scannst Du den Plan oder fotografierst ihn und stellst ihn hier wieder 
ein. Damit hätten alle Beteiligten die Chance nachzuverfolgen, wie Deine 
Hardware nun wirklich beschaltet ist.

Mein Lösungsansatz wäre:
* TxD-Pin auf high setzen und als Ausgang konfigurieren.
* auf dem RS485-Board den Jumper setzen, der Transmit-Enable und
  Receive-Enable am Transceiver brückt.
* Dann konfigurierst Du den MCU-Pin, der mit Transmit-Enable und
  Receive-Enable verbunden ist als Ausgang und initialisiert ihn so,
  dass das Transmit-Enable inaktiv ist.
* USART0.CTRLA = USART_RS485_EXT_gc und USART-Transmitter und Receiver
  aktivieren
* Bevor Du das erste Byte sendest, aktivierst Du Transmit-Enable.
* Nachdem Du das letzte Byte ins Senderegister des USART geschrieben
  hast, wartest Du bis der Sendevorgang beendet ist und dann
  deaktivierst Du das Transmit-Enable. Nun kann der USART über
  seinen RxD-Pin Daten vom Bus lesen.

Einfacher wäre es natürlich, wenn Du das Umschalten von Transmit- und 
Receive-Enable vom USART durchführen lassen würdest. Dazu müstest Du 
eine Brücke ziwschen dem XDIR-Pin der MCU und dem besagten Transmit- und 
Receive-Enable-Signal herstellen un XDIR als Ausgang konfigurieren (der 
parallelgeschaltete MCU-Pin muss dann natürlich als Eingang konfiguriert 
werden.
Warum Micorchip das nicht vorgesehen hat, musst Du die Kollegen fragen. 
Ich verstehe das auf jeden Fall nicht... :-/

Grüßle
Volker

: Bearbeitet durch User
von Droid E. (eedroid)


Lesenswert?

Volker B. schrieb:
> * TxD-Pin auf high setzen und als Ausgang konfigurieren.
> * auf dem RS485-Board den Jumper setzen, der Transmit-Enable und
>   Receive-Enable am Transceiver brückt.
> * Dann konfigurierst Du den MCU-Pin, der mit Transmit-Enable und
>   Receive-Enable verbunden ist als Ausgang und initialisiert ihn so,
>   dass das Transmit-Enable inaktiv ist.
> * USART0.CTRLA = USART_RS485_EXT_gc und USART-Transmitter und Receiver
>   aktivieren
> * Bevor Du das erste Byte sendest, aktivierst Du Transmit-Enable.
> * Nachdem Du das letzte Byte ins Senderegister des USART geschrieben
>   hast, wartest Du bis der Sendevorgang beendet ist und dann
>   deaktivierst Du das Transmit-Enable. Nun kann der USART über
>   seinen RxD-Pin Daten vom Bus lesen.

Volker, du bist ein Schatz!

berichtige mich bitte, wenn ich in meinen folgende Sätzen Unsinn 
schreibe!

Mein USART0.CTRLA steht jetzt auf USART_RS485_EXT_gc! Ich habe die 
beiden Pins PB0 (XDIR) und PB7 gebrückt, PB7 ist Initial auf Input, kann 
daher nicht dazwischen funken. Und der Mikrocontroller übernimmt das 
saubere Umschalten.

Jetzt das Entscheidende beim uart_init, also Einmalig:
- XIDR muss auf Output gestellt werden: PORTB.DIRSET = PIN0_bm
- TXD muss auf Output gestellt werden: PORTB.DIRSET = PIN2_bm
- RXD steht initial auf Input

War aus meiner Sicht gar nicht mal so einfach ;)

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Es freut mich, dass es nun doch noch funktioniert. Und siehst Du, wenn 
man einmal verstanden hat, wie der RS485-Bus funktioniert, dann kann man 
das auch ganz einfach implementieren.

Droid E. schrieb:

> Mein USART0.CTRLA steht jetzt auf USART_RS485_EXT_gc! Ich habe die
> beiden Pins PB0 (XDIR) und PB7 gebrückt, PB7 ist Initial auf Input, kann
> daher nicht dazwischen funken. Und der Mikrocontroller übernimmt das
> saubere Umschalten.
>
> Jetzt das Entscheidende beim uart_init, also Einmalig:
> - XIDR muss auf Output gestellt werden: PORTB.DIRSET = PIN0_bm
> - TXD muss auf Output gestellt werden: PORTB.DIRSET = PIN2_bm

Das lässt sich auch zu einer einzigen Anweisung zusammenfassen, was auch 
der Sinn der .xSET- und  .xCLR-Register ist:
PORTB.DIRSET = PIN0_bm|PIN2_bm

> - RXD steht initial auf Input
>
> War aus meiner Sicht gar nicht mal so einfach ;)

Naja, so ähnlich hatte ich das bereits vorgeschlagen. Leider nicht in 
meinen ersten Postings dieses Threads, da mir dort noch nicht bewußt 
war, dass Du über RS485 senden willst. Außerdem hätte ich erwartet, dass 
Microchip Hardware ausliefert, die auch die vorgesehene Betriebsart der 
MCU, also den XDIR-Pin, unterstützt. Dazu wäre lediglich ein Jumper auf 
dem MCU-Board erforderlich. Du kannst Den Brüdern ja mal einen 
Verbesserungsvorschlag senden.

Du siehst nun aber auch, wie wichtig es ist, sämtliche Informationen 
kompakt und übersichtlich zu präsentieren, wenn man zielführende Hilfe 
erhalten will. Zukünftig würdest Du auch schneller kompetente Hilfe 
bekommen, wenn Du in Deinem Posting Dokumente mit den Schaltplänen 
Deiner Hardware verlinken würdest.

Grüßle
Volker

von Spess53 (Gast)


Lesenswert?

Hi

>Jetzt das Entscheidende beim uart_init, also Einmalig:
...
>- TXD muss auf Output gestellt werden: PORTB.DIRSET = PIN2_bm
>- RXD steht initial auf Input

Diese Einstellungen werden  automatisch gemacht wenn du RXEN und TXEN 
einschaltest. Dein Gefummel an den Portpins ist total unsinnig.

MfG Spess

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Spess53 schrieb:

> Diese Einstellungen werden  automatisch gemacht wenn du RXEN und TXEN
> einschaltest. Dein Gefummel an den Portpins ist total unsinnig.

So ein Schwachsinn! Hast Du jemals mal in ein Datenblatt der ATtiny0- 
bzw. -1-Familie geguckt?

Grüßle
Volker

von Spess53 (Gast)


Lesenswert?

Hi

>So ein Schwachsinn! Hast Du jemals mal in ein Datenblatt der ATtiny0-
>bzw. -1-Familie geguckt?

Datenblatt ATtiny3217/ATtiny1617:

Bit 7 – RXEN Receiver Enable
Writing this bit to ‘1’ enables the USART receiver. The receiver will 
override normal port operation for the RxD pin when enabled.

Bit 6 – TXEN Transmitter Enable
Writing this bit to ‘1’ enables the USART transmitter. The transmitter 
will override normal port operation for the TxD pin when enabled

MfG spess

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Spess53 schrieb:

> Datenblatt ATtiny3217/ATtiny1617:
>
> Bit 7 – RXEN Receiver Enable
> Writing this bit to ‘1’ enables the USART receiver. The receiver will
> override normal port operation for the RxD pin when enabled.
>
> Bit 6 – TXEN Transmitter Enable
> Writing this bit to ‘1’ enables the USART transmitter. The transmitter
> will override normal port operation for the TxD pin when enabled

Merkwürdig.
Datenblatt ATtiny1617/3217, 2019, 24.3.1 Initialization:
> For setting the USART in Full-Duplex mode, the following initialization
> sequence is recommended:
> 1. Set the TxD pin value high, and optionally set the XCK pin low
>    (OUT[n] in PORTx.OUT).
> 2. Set the TxD and optionally the XCK pin as an output (DIR[n] in
>    PORTx.DIR).
> 3. Set the baud rate (in the USARTn.BAUD register) and frame format.
> 4. Set the mode of operation (enables XCK pin output in Synchronous
>    mode).
> 5. Enable the transmitter or the receiver, depending on the usage.

Erstaunlicherweise funktionierten meine Experimente mit den neuen Tinys 
erst, nachdem ich TxD als Ausgang konfigurierte.
Ich würde mal wieder einen der zahllosen Copy-&-Paste-Fehler im 
Datenblatt vermuten. :-(

Grüßle
Volker

von Droid E. (eedroid)


Lesenswert?

Volker B. schrieb:
> Erstaunlicherweise funktionierten meine Experimente mit den neuen Tinys
> erst, nachdem ich TxD als Ausgang konfigurierte.

Kann ich so bestätigen! Habe alle Einstellungen in den letzten Tagen 
exzessive durchgetestet! Ich muss den XDIR als auch den TXD als Ausgang 
definieren, sonst funktioniert es nicht!

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Droid E. schrieb:
> Volker B. schrieb:
>> Erstaunlicherweise funktionierten meine Experimente mit den neuen Tinys
>> erst, nachdem ich TxD als Ausgang konfigurierte.
>
> Kann ich so bestätigen! Habe alle Einstellungen in den letzten Tagen
> exzessive durchgetestet! Ich muss den XDIR als auch den TXD als Ausgang
> definieren, sonst funktioniert es nicht!

Absatz 24.3.2.3 "Data Transmission - USART Transmitter" im zitierten 
Datenblatt sagt aus:
> When the transmitter has been enabled, the normal port operation of the
> TxD pin is overridden by the USART and given the function as the
> transmitter's serial output. The direction of the pin n must be
> configured as output by writing the Direction register for the
> corresponding port (PORTx.DIR[n]). If the USART is configured for
> one-wire operation, the USART will automatically override the
> RxD/TxD pin to output, when the transmitter is enabled.

Grüßle
Volker

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.