Forum: Compiler & IDEs Wie kann man USART deaktivieren?


von Egon M. (kpc)


Lesenswert?

Hallo,

ich versuche, USART ohne Interrupt gangbar zu machen. Da gibt es Dinge, 
die ich mir nicht erklären kann:

Ein Codeschnipsel:
  USART_init();          // enth.  UCSRB = (1<<RXEN) | (1<<TXEN);
                               // nebst Baud- u. Frame-Einstellg.
//  get = USART_Receive(); //   ????
  USART_halt();         //    UCSRB = (0<<RXEN) | (0<<TXEN);

  DDRD |=2;              //  Kontrolle, ob PD1 wieder verfügbar ist
  PORTD &= 253;
  _delay_ms(5);
  PORTD |= 2;
  _delay_ms(5);

Ich möchte den USART, der ja PORTD 0 u. 1 belegt, benutzen. Anschließend 
soll aber PD1 wieder low sein.
Daß man nach USART_init nicht einfach den vormals als TX benutzten 
PortD1 manipulieren kann, sehe ich ja ein, deshalb die Zeile mit 
USART_halt, die die Ports erfolgreich freigibt. Was mir aber sonderbar 
vorkommt, ist, daß dies nicht mehr hilft, wenn ich im obigen Beispiel 
die Zeile mit get.... aktiviere (das get- Beispiel steht hier für viele 
Befehle, die mit dem USART zusammenhängen).
Aktiviere ich die Zeile, dann bleibt PD1 high, deaktiviere ich sie 
wieder, dann zeigt der Oszi das gewünschte Muster am PD1.

Ich hatte gedacht, wenn ich RXEN und TXEN auf Null setze, ist das 
erledigt. Muß man sich vielleicht auch noch um die ausgelesenen oder 
nicht ausgelesenen Bytes in den Pufferspeicher kümmern?
Oder was kann sonst noch zu dem eigenartigen Effekt führen?

Schönen Abend noch

Egon

von Matthias L. (Gast)


Lesenswert?

>Ich hatte gedacht, wenn ich RXEN und TXEN auf Null setze, ist das
>erledigt.

Das tuts auch.

Die Frage ist eher:
1
  get = USART_Receive();
2
  USART_halt();

Kann das nicht eher sein, dass der µC in der Zeile get=.. festhängt, 
weil er dort auf ein Zeichen wartet???
Das sollte vielleicht eher per ISR gemacht werden. So kannst du 
jederzeit abschalten. Solltest allerdings das TXC-Flag (letztes Senden 
erfolgreich beendet) vorher prüfen.

von risu (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Egon,

Deiner Beschreibung kann ich nicht 100% folgen; das liegt auch daran, 
dass Du uns Deine Funktionen nicht zeigst. Prinzipiell verhält sich bei 
den AVRs die Freigabe der RXD-Leitung anders als die Freigabe der 
TXD-Leitung. Bei RXEN=0 sollte die RXD-Leitung (fast, siehe nächst. 
Satz) sofort freigegeben werden, bei TXEN=0 dauert die TXD-Freigabe, bis 
die letzte Aussendung komplett ist. Obwohl der RX-Puffer bei RXEN=0 
geleert wird, rät Atmel, dass man ein formelles "flush" durchführt, 
indem man auf RXC=0 wartet (siehe Anlage).

Ich hänge diesem Posting einen Datenblatt-Ausschnitt des ATmega32 zum 
Empfangen an und poste einen Folgebeitrag, der den zugehörigen 
Ausschnitt zum Senden zeigt.

Viele Grüße

  risu

von risu (Gast)


Angehängte Dateien:

Lesenswert?

Anhang zum letzten Beitrag

von Egon M. (kpc)


Angehängte Dateien:

Lesenswert?

Hallo,
vielen Dank

Matthias Lipinsky wrote:
>>Ich hatte gedacht, wenn ich RXEN und TXEN auf Null setze, ist das
>>erledigt.
>
> Das tuts auch.
>
> Die Frage ist eher:
>
1
>   get = USART_Receive();
2
>   USART_halt();
3
>
>
> Kann das nicht eher sein, dass der µC in der Zeile get=.. festhängt,
> weil er dort auf ein Zeichen wartet???
> Das sollte vielleicht eher per ISR gemacht werden. So kannst du
> jederzeit abschalten. Solltest allerdings das TXC-Flag (letztes Senden
> erfolgreich beendet) vorher prüfen.

Glaube ich eher nicht, weil das Programm nicht ewig wartend anhält, 
sondern weiter läuft. Außerdem, wenn ich ein anderes Kommando, z.B. 
ring(); (vgl. angehängtes kpl. Programm) stattdessen hinschreibe, tritt 
der gleich Effekt auf.

> Deiner Beschreibung kann ich nicht 100% folgen; das liegt auch daran,
> dass Du uns Deine Funktionen nicht zeigst. Prinzipiell verhält sich bei

Programm füge ich bei. Und, ich hatte vergessen zu erwähnnen: es handelt 
sich um einen Atmeg16.

> den AVRs die Freigabe der RXD-Leitung anders als die Freigabe der
> TXD-Leitung. Bei RXEN=0 sollte die RXD-Leitung (fast, siehe nächst.
> Satz) sofort freigegeben werden, bei TXEN=0 dauert die TXD-Freigabe, bis
> die letzte Aussendung komplett ist.

> geleert wird, rät Atmel, dass man ein formelles "flush" durchführt,
> indem man auf RXC=0 wartet (siehe Anlage).

> Viele Grüße

>   risu

Genau genommen, geht es mir nur um TX, weil dort PD1 dauernd high 
gehalten wird, was das angeschlossene Händie veranlaßt, auf Netzsuche zu 
gehen.

Viele Grüße
Egon

von risu (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Egon,

> Genau genommen, geht es mir nur um TX, weil dort PD1 dauernd high
> gehalten wird, was das angeschlossene Händie veranlaßt, auf Netzsuche zu
> gehen.
Du setzt doch am Ende Deines Codes PD1 auf Ausgang, 5ms auf L und dann 
5ms auf H:

>  DDRD |=2;     // Kontrolle über PD1: mache zum Ausgang
>  PORTD &= 253; // PD1 auf L
>  //...            5ms warten
>  PORTD |= 2;   // PD1=H

...und da Du (in Deinem Codebeispiel) gar nichts sendest, gilt nach der 
UART-Initialisierung auch TXD=IDLE=H.
Demnach erwarte ich von Deinem Code, dass PD1 etwas über 5ms lang H und 
5ms lang L ist, wenn Du nichts sendest oder empfängst.
Willst Du sagen, Du siehst dieses 100Hz Signal and PD1 nicht auf dem 
Oszi?

Gruß

Fred

von risu (Gast)


Lesenswert?

PS: Wie sieht die Hardware an PD1=TXD aus? Kann es sein, dass der Fehler 
dort liegt?

von Egon M. (kpc)


Lesenswert?

risu wrote:

>
> ...und da Du (in Deinem Codebeispiel) gar nichts sendest, gilt nach der
> UART-Initialisierung auch TXD=IDLE=H.
> Demnach erwarte ich von Deinem Code, dass PD1 etwas über 5ms lang H und
> 5ms lang L ist, wenn Du nichts sendest oder empfängst.
> Willst Du sagen, Du siehst dieses 100Hz Signal and PD1 nicht auf dem
> Oszi?
>
> Gruß
>
> Fred

Da habe ich mich vielleicht zu ungenau ausgedrückt. Das angehängte 
Programm hat mit dem Ziel rein gar nichts zu tun, ich habe es nur, weil 
ich irgendwie sehen wollte, warum das angeschlossene Händie nicht 
reagiert und nach kurzer Zeit auf Netzsuche geht.

Also habe ich eine fliegende Drahtverbindung zwischen PD1 und RX des 
Händies bzw. PD0 und TX am Händie (und natürlich GND). Diese Leitungen 
sind angezapft für den Oszi.

Wenn ich per USART z. B. 'AT' sende, sieht man auf der Leitung ein 
plausibles Signalmuster. Aber, wenn das Programm pausiert, geht das 
Händie auf Netzsuche. Nachdem ich nun den USART-Kram auf das mindeste 
reduziert hatte, habe ich entdeckt, daß PD1 high bleibt und das Händie 
deshalb nach einigen Sekunden Netzsuche startet. Vielleicht hätte es 
lieber 3 statt 5V?




> PS: Wie sieht die Hardware an PD1=TXD aus? Kann es sein, dass der Fehler
> dort liegt?
Wird regelmäßig kontrolliert, so leicht macht es uns die Apparatur 
leider nicht.

Viele Grüße

Egon

von risu (Gast)


Lesenswert?

Hallo Egon,

> Aber, wenn das Programm pausiert, geht das Händie auf Netzsuche.
> Nachdem ich nun den USART-Kram auf das mindeste reduziert hatte,
> habe ich entdeckt, daß PD1 high bleibt ....
Wenn es nicht ein Problem der Pegelanpassung ist, schlage ich vor, Du 
machst es wie im von Dir oben angeführten Beispiel (Deine 
Zahlenkonstanten habe ich hier nur als symbolische Konstanten 
umgeschrieben - finde ich übersichtlicher), um PD1 auf L zu ziehen, 
falls es das ist, was der Empfänger sehen will:

UCSRB &= ~(1<<TXEN);  // TX ausschalten
DDRD  |= (1<<PD1);    // PD1 wird User Ausgang
PORTD &= ~(1<<PD1)    // PD1=L

Dass ein "L" dem seriellen "IDLE" entsprechen soll, ist etwas seltsam, 
denn normalerweise ist das "IDLE"=H. Vielleicht doch ein Pegel-Problem? 
Kommt denn das "AT" korrekt beim Empfänger an (Du sprichst nur von einem 
"plausiblen Signal" auf dem Oszi)? Könnte das Signal invertiert sein?

Gruß

 risu

von Egon M. (kpc)


Lesenswert?

Hallo risu

> risu wrote:

> Wenn es nicht ein Problem der Pegelanpassung ist, schlage ich vor, Du
> machst es wie im von Dir oben angeführten Beispiel (Deine
> Zahlenkonstanten habe ich hier nur als symbolische Konstanten
> umgeschrieben - finde ich übersichtlicher),

außerdem ist offensichtlich UCSRB &= ~(1<<TXEN) besser als
UCSRB &= (0<<TXEN);

> um PD1 auf L zu ziehen,
> falls es das ist, was der Empfänger sehen will:
>
Ich habe eine Funktion
void PD1_low(void)
  {
  UCSRB &= ~(1<<TXEN);
  DDRD |= (1<<PD1);
  PORTD &= ~(1<<PD1);
  }
eingefügt, damit bleibt jetzt PD1 low und die Netzsucherei hat ein Ende. 
Damit ist es nun möglich, längere Zeit auf irgend etwas vom Händie zu 
warten, z.B. einen Anruf.

>
> Dass ein "L" dem seriellen "IDLE" entsprechen soll, ist etwas seltsam,
> denn normalerweise ist das "IDLE"=H. Vielleicht doch ein Pegel-Problem?
> Kommt denn das "AT" korrekt beim Empfänger an (Du sprichst nur von einem
> "plausiblen Signal" auf dem Oszi)?

Wenn ich das irgendwie kontrollieren könnte, wäre ich sehr froh! Es gibt 
aber nur die eine Verbindung AVR - Händie. Ich fürchte mich vor der 
blinden Kommunikation mit dem Händie, wo man nicht weiß, woran man ist. 
Ich werde zunächst wenigstens versuchen, ein 'ok' zu detektieren als 
Antwort auf mein 'AT'. Das müßte ja nun gehen mit dem PD1_low.

Bis hierher erst mal vielen Dank!

Viele Grüße
Egon

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.