mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Software Handshake mit Atmega64


Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe eine serielle Verbindung mit meinem ATmega64 zu meinem PC 
aufgebaut (mit Silabs USB-Bridge).
Ich nutze die "Interrupt UART library" von Peter Fleury.
Ich möchte nun ein Software-Handshake unterbringen. Wo genau muss ich 
diese Steuerzeichen unterbringen?
Hier mal die Sende- und Empfangsroutine:
void uart_putc(unsigned char data)
{
    int tmphead;
    
    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
    
    while ( tmphead == UART_TxTail ){
        ;/* wait for free space in buffer */
    }
    
    UART_TxBuf[tmphead] = data;
    UART_TxHead = tmphead;

    /* enable UDRE interrupt */
    UCSR0B    |= (1<<UDRIE0);

}/* uart_putc */

ISR (USART0_RX_vect) {

  // read UART status register and UART data register
  uart_menu_rxdata  = UCSR0A;  // Empty the Status Register
  uart_menu_rxdata  = UDR0;    // Read desired data

  UART_RX_OFF;                 // Kein weiterer Empfang (nur ein Zeichen)
 
  uart_menu_rxflag=1;          // Flag, dass etwas empfangen wurde

}

Nun ist die Frage wo ich den Software-Handshake einbaue. Der 
Software-Handshake macht doch auch nur Sinn, wenn der Sender dauerhaft 
sendet oder?
Dies tue ich aber nicht, ich "trigger" aus LabView heraus den Controller 
mit einem Zeichen und daraufhin wird mir der gewünschte String 
zurückgesendet.
Das Problem ist, dass ich zwei Funkmodule habe (die mein Kabel ersetzen 
sollen), die mit Software-Handshake arbeiten. PC-seitig kann man das ja 
einstellen. Nur wie mache ich das bei meinem Controller?

Ich hoffe ihr könnt mir helfen.

Viele Grüße
Daniel

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel schrieb:

> Ich möchte nun ein Software-Handshake unterbringen. Wo genau muss ich
> diese Steuerzeichen unterbringen?

In möglichst tief liegenden Treiberschichten.

> Hier mal die Sende- und Empfangsroutine:
>
>
> void uart_putc(unsigned char data)
> {
>     int tmphead;
> 
>     tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
> 
>     while ( tmphead == UART_TxTail ){
>         ;/* wait for free space in buffer */
>     }
> 
>     UART_TxBuf[tmphead] = data;
>     UART_TxHead = tmphead;
> 
>     /* enable UDRE interrupt */
>     UCSR0B    |= (1<<UDRIE0);
> 
> }/* uart_putc */

guter Platz. Noch besser wäre es allerdings die Sendefreigabe 
unmittelbar vor Ausgabe des Zeichens ins UDR Register zu prüfen. Da das 
aber im Interrupt passiert, ist das nicht so simpel. Denn im Interrupt 
sollte man nicht warten.
Auf der anderen Seite muss die Gegenstelle nach dem Senden eins XOFF 
sowieso damit rechnen, dass noch ein paar Zeichen eintrudeln werden. Es 
ist nicht spezifiziert wieviele das sein können aber wenn dein 
UART_TxBuf nicht allzugross dimensioniert ist, sollte das eigentlich 
kein allzugroßes Problem sein. Muss man ausprobieren.

Also: Gesendet werden darf nur dann, wenn die Gegenstelle nicht mit 
einem XOFF das Senden unterbunden hat.
Also wirst du in der Empfangsroutine eine Erkennung von XOFF (und XON) 
einbauen. Wird XOFF erkannt, dann wird eine static volatile globale 
Variable SenderAllowsTransmission auf FALSE gesetzt. In der uart_putc 
fragst du ab, ob SenderAllowsTransmission auf TRUE steht und wenn nicht, 
dreht die Sendroutine ihre Runden, solange, bis sie die Freigabe über 
diese Variable bekommt.

> ISR (USART0_RX_vect) {
>
>   // read UART status register and UART data register
>   uart_menu_rxdata  = UCSR0A;  // Empty the Status Register
>   uart_menu_rxdata  = UDR0;    // Read desired data
>
>   UART_RX_OFF;                 // Kein weiterer Empfang (nur ein
> Zeichen)
>
>   uart_menu_rxflag=1;          // Flag, dass etwas empfangen wurde
>
> }
> [/c]

In dieser Funktion wird das empfangene Zeichen angeschaut.
Ist es XOFF, dann wird SenderAllowsTransmission auf FALSE gesetzt, ist 
es XON dann wird selbige Variable auf TRUE gesetzt. Ist es keinen von 
beiden, dann wird mit dem empfangenen Zeichen verfahren wie bisher auch.

> Nun ist die Frage wo ich den Software-Handshake einbaue. Der
> Software-Handshake macht doch auch nur Sinn, wenn der Sender dauerhaft
> sendet oder?

Nö.
Ein Handshake kann immer Sinn machen, wenn die Gegenstelle zeitweise 
nicht aufnahmebereit ist. Das kann viele Ursachen haben, zb. weil eine 
längere Berechnung im Gange ist, und die Gegenstelle nicht aufnahmefähig 
ist. Oder weil die Gegenstelle befürchtet, dass wenn du weitersendest 
ihr Eingangspuffer überlaufen wird.
Hint: Das ist auch das Stichwort wann dein Programm an die Gegenstelle 
ein XOFF schicken könnte. Wobei dann natürlich die paradoxe Situation 
enstehen kann, dass die Gegenstelle ihrerseits bereits mittels XOFF 
mitgeteilt hat, dass sie zur Zeit nicht belästigt zu werden wünscht :-). 
Wenn also die Gegenstelle bereits einen XOFF geschickt hat, darfst du 
ihr dann deinerseits einen XOFF schicken (denk logisch nach)

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnelle Antwort.
Funktioniert perfekt:
Quellcode:
#define XON 0x11
#define XOFF 0x13

volatile int8_t SenderAllowsTransmission

void uart_putc(unsigned char data)
{
    int tmphead;
    
    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
    
    while ( tmphead == UART_TxTail ){
        ;/* wait for free space in buffer */
    }
    while ( SenderAllowsTransmission == -1){
      ; //solange hier bleiben, bis Sendefreigabe erfolgt
    }
    UART_TxBuf[tmphead] = data;
    UART_TxHead = tmphead;

    /* enable UDRE interrupt */
    UCSR0B    |= (1<<UDRIE0);

}/* uart_putc */

ISR (USART0_RX_vect) {

  // read UART status register and UART data register
  uart_menu_rxdata  = UCSR0A;  // Empty the Status Register
  uart_menu_rxdata  = UDR0;    // Read desired data

  if ( uart_menu_rxdata == XOFF ) 
    SenderAllowsTransmission = -1; // false, kein Senden erlaubt
  else if ( uart_menu_rx_data == XON)
    SenderAllowsTransmission = 1; // True --> Senden erlaubt

  UART_RX_OFF;                 // Kein weiterer Empfang (nur ein Zeichen)
 
  uart_menu_rxflag=1;          // Flag, dass etwas empfangen wurde

}

Das war ja wirklich einfacher als gedacht.
Vielen Dank!

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich hab da noch ein Problem. Ich weiß nicht genau ob es mit dem 
vorherigen Problem zusammenhängt, aber es trat erst jetzt auf.

Ich habe obigen Quellecode geflasht. Via AVR-Studio (AVR-Prog). Nach dem 
Flashen lasse ich die Spannung am Controller vom USB-Port, stecke das 
Empfängermodul an den Rechner und lasse mir was schicken -> 
funktioniert.
Sobald ich den USB-Stecker ziehen und somit auch die Spannung und auf 
meine externe Spannungsquelle umstelle, funktioniert die 
Datenübertragung nicht mehr.
Abhängig von der USB-Spannung ist das Problem offenbar nicht, da ich 
meine externe Spannungsquelle parallel dran hatte und dann die 
USB-Spannung entfernt hatte. Dann klappte es auch noch. Nachdem ich dann 
aber die externe Spannungsquelle entfernt habe und wieder angeschlossen 
habe, funktionierte die Verbindung nicht mehr.
Kann das ein Pegelproblem sein?
Und AVR-Prog führt doch automatisch einen Reboot des Controllers durch, 
der doch auch durchgeführt wird, wenn die Spannungsversorgung des 
Controllers nicht mehr da ist oder?
Die andere Frage ist, ob ich dem Funkmodul controllerseitig ein XOFF 
bzw. XON schicken muss? Wenn ja, wo sollte ich das machen? Bisher 
verarbeite ich ja nur die Empfangenden Zeichen am Controller. Das wird 
aber nicht mit dem obigen Problem zusammenhängen denke ich.

Autor: Wolfgang Beppler (Firma: Wolftec GmbH) (wbeppler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ganz schoen heftig !

was funktioniert nicht mehr wenn du die spannung kappst ?
laeuft der prozessor weiter ? (blinkled zur kontrolle oder so was, 
lebensbit)

mach mal die masse irgendo gegen. das funkmodul koennte schwingen, also 
noch senden, nur eben so dass es keiner mehr versteht

wie ist das aufgebaut ?

die kapazitaet des netzteils ist ja riesig, vieleicht ist die der 
anderen versorgung zu keil ?


wegen dem xon/xoff:

welche baudrate ? womit kommunizierst du ? und wie wichtig sind die 
daten ?
wiederholende daten, z.b. messwerte, kannst auf der empfaengerseite auch 
auf plausibilitaet pruefen, also wenn werte kommen 100, 102, 101, 17, 
104 koenntest die 17 ja erkennen da die abweichung zu gross ist.

da wuerd ich kein handshake bauen, wenn es aber daten sind wie z.b. ein 
nc-programm und eine achse gesteuert wird, da wuerd ich mich nicht mal 
auf das handshake verlassen, sondern ne pruefsumme einbauen (ist 
einfacher)

generell ist handshake von 3 faktoren abhaengig damit es funktioniert
1. puffergroesse
2. baudrate
3. reaktionsgeschwindigkeit der gegenstelle

da ich selber kaum erfahrung mit atmel habe und in zukunft auch solche 
probleme bekommen werde wuerd es mich freuen wenn du mir das ergebnis 
hier wieder kund tust

gruss

w. :-)

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Problem gelöst.

Nach der Initialisierung des UART schicke ich an das Funkmodul ein XON.
Scheinbar ist das Flashen mit AVR-Prog was anderes als der Reboot des 
Controllers wenn man die Spannung weg nimmt.

@wolfgang
Ich muss leider den Software-Handshake nutzen, da die Funkmodule, die 
ich habe, das voraussetzen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.