www.mikrocontroller.net

Forum: Compiler & IDEs Bytes Nacheinander empfangen


Autor: CNChris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Wie ihr wisst, habe ich ein CNC-Projekt vor.

Nun habe ich in meinem Programmcode anscheinend das Problem, dass die 
Bytes vom Computer einfach nacheinander rausgeschickt werden.
Der Mikrocontroller muss aber die Bytes in eine array schreiben, und 
zwar nacheinander.
Wie kann ich das machen?
Hier mein aktueller Code.





#include <avr/io.h>
#include <util/delay.h>


#define DREHUNG 50

char globalReceiveEnable=0;

unsigned char ReceiveUART(void)   //schreibt die empfangenen Bytes in 
eine Array
{
    unsigned char tempVar;

    for(;;)
    {
        while (!(UCSRA & (1<<RXC)))
        {
            tempVar = UDR;

            return tempVar;
        }
    }
}

unsigned char ReadyForReceive(void)
{
    while (!(UCSRA & (1<<UDRE)))  // warten bis Senden moeglich
      {
     }

      UDR = 0xFF;

}


int goCNC (unsigned char Anzahl,unsigned char Adresse,unsigned char 
Richtung)
{
    int i=0;
    int y=0;
    globalReceiveEnable=0;
    for(; i<=Anzahl;i++)
    {
        if (Adresse == 0)   //frägt: Welcher Motor soll laufen?!
        {
            if (Richtung == 0)
            {
                for(y=0;y<=DREHUNG;y++)
                {
                PORTA = 0x7F;

          _delay_ms( 50 );

            PORTA = 0xBF;

           _delay_ms( 50 );

            PORTA = 0xDF;

          _delay_ms( 50 );

            PORTA = 0xEF;


         _delay_ms( 50 );

                //Zyklus für Motor0/Richtung0
                }
            globalReceiveEnable=1;
            }
            if (Richtung == 1)
            {
                for(y=0;y<=DREHUNG;y++)
                {

          PORTA = 0xEF;
           _delay_ms( 50 );
          PORTA = 0xDF;
          _delay_ms( 50 );
        PORTA = 0xBF;
          _delay_ms( 50 );
        PORTA = 0x7F;
          _delay_ms( 50 );
                //Zyklus für Motor0/Richtung1
                }
            globalReceiveEnable=1;
            }
        }
        if (Adresse == 1)
        {
            if (Richtung == 0)
            {
                for(y=0;y<=DREHUNG;y++)
                {
                _delay_ms(50);
                //Zyklus für Motor1/Richtung0
                }
            globalReceiveEnable=1;
            }
            if (Richtung == 1)
            {
                for(y=0;y<=DREHUNG;y++)
                {
                _delay_ms(50);
                //Zyklus für Motor1/Richtung1
                }
            globalReceiveEnable=1;
            }
        }
        if (Adresse == 2)
        {
            if (Richtung == 0)
            {
                for(y=0;y<=DREHUNG;y++)
                {
                _delay_ms(50);
                //Zyklus für Motor2/Richtung0
                }
            globalReceiveEnable=1;
            }
            if (Richtung == 1)
            {
                for(y=0;y<=DREHUNG;y++)
                {
                _delay_ms(50);
                //Zyklus für Motor2/Richtung1
                }
            globalReceiveEnable=1;
            }
        }
    }
}


int main (void)
{
    char aiParameter[3] ;
    int i=0;
    int go=0;
    UCSRB |= (1<<RXEN) | (1<<TXEN);                         //Empfangen 
aktivieren
    UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);

    UBRRH = 00;                         //Baudrate einstellen 9600 bei 8 
MHz
    UBRRL = 51;

for(;;)
{
    if (UDR != 0)                             //wenn was im UART steht,
    {
        for(;i<=3;i++)
        {
            aiParameter[i] = ReceiveUART();     //schreibe die 
empfangenen Bytes in eine Array
        }
        goCNC(aiParameter[0],aiParameter[1],aiParameter[2]); //...führe 
Fräsprozess durch.


        if (globalReceiveEnable == 1)
        {
            UCSRB |= (1<<RXEN);//empfang aktivieren
            ReadyForReceive();//jetzt muss was an den PC gesendet 
werden, damit er was zurückschicken kann. Controller fordert byte!
            ReceiveUART();    //wenn bereit für Empfang, sendet 
controller "0xFF" . Am PC muss auf 0xFF gewartet werden!
            go=1;
        }
        else
        {
            UCSRB &= ~(1<<RXEN);
        }
    }
}
}




Vielen Dank

Autor: CNChris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also...wenn ich nun mit dem oben genannten code in Visual Basic 3 mal 
0xFF rausschicke, dann dreht sich mein Motor genau einmal und bleibt 
stehen. er sollte aber da schon mal 255 umdrehungen machen ;-)

aber ich bin froh dass er schon mal was macht ;)


Danke

Autor: CNChris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm...hat denn keiner eine Ahnung??

Autor: CNChris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe jetzt mit HTerm herausgefunden, dass es egal ist, wieviele 
Bytes und welche bytes ich rausschicke. Er dreht immer nur einmal eine 
Umdrehung, dann muss er geresetet werden.

Wisst ihr woran das liegt?? (Code)


DAnke

Autor: Rahul Der trollige (rahul)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>    if (UDR != 0)                             //wenn was im UART steht,

Sobald UDR gelesen wird, ist der Inhalt nicht mehr drin.
Du müsstest UDR also vorher in einem Byte sichern oder RXC abfragen.

Autor: TransistorQuäler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was heißt, wenn UDR gelesen wird? Wenn ich es mit der If-Anweisung 
abfrage?

Ansonsten habe ich ja zur Sicherung der Daten die nachfolgende 
for-Schleife, die die Inhalte in eine Array packt.


Danke!

Autor: Torben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wieviele Threads moechtest Du zum gleichen Thema noch eröffnen?

1. Solltest Du dir ein Protokoll endlich ausdenken, weil deine 1. Byte 
sende Methode sehr störempfindlich reagieren kann und bei einer CNC 
Fraese ist das Fatal.
Z.B.

PC sendet:
Startframe, Kommando, Datenlänge, Parameter-x, Endframe, CRC Prüfsumme

Im ersten Moment denkt man der Mikrocontroller muss jetzt soviele Bytes 
empfangen und bearbeiten, aber nachdem der Mikrocontroller alle 
Parameter bekommen hat benötigt er keine weiteren Daten und der UART 
Interrupt stört die Motoransteuerung nicht mehr bzw. den 
Normalenprogrammablauf. Der Uart Interrupt ist relativ schnell durch, 
aber man sendet lieber komplette Blocke als einzelne Bytes.

Du koenntest z.B. so ein komplettes Programm für ein Ausschnitt an den 
Mikrocontroller senden und nachdem alles empfangen arbeitet der 
Mikrocontroller das komplette Programm ab.

Der Mikrocontroller sendet folgende Bestaetigung zurueck bei empfang 
eines kompletten Frames oder bei einem Timeout des Frames:

Startframe, Result, Endframe, CRC Prüfsumme

Im Result koennte folgendes stehen:

0x31 = Busy
0x32 = Timeout fail
0x33 = Kommandofehler

usw.

Um deine Uartroutine zu verbessern sollte ein Empfangsbuffer und 
Sendebuffer angelegt werden. Empfangsbuffer und Sendebuffer baut man als 
Ringbuffer auf.

Bei Codeposting hilft es ungemein diesen in Angang zuhaengen oder den 
Part als C Code zu deklarieren. Wieso?

Weil ein unformatierter Code schlecht zu lesen ist.

Autor: Torben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch etwas:

>_delay_ms( 50 );

Leider hast du deine Quarzfrequenz nicht angegeben, aber ab 4MHz kannst 
du mit _delay_ms maximal 20ms warten.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> was heißt, wenn UDR gelesen wird? Wenn ich es mit der If-Anweisung
> abfrage?

Klar. Woher soll das if denn wissen, ob UDR 0 ist, ohne dessen Wert zu 
lesen? Außerdem bedeutet eine 0 in dem Register nicht, daß nichts 
angekommen ist. Die echte Abfrage, ob überhaupt was gekommen ist, machst 
du erst später in ReceiveUART. Dort wartest du sogar solange, bis was 
angekommen ist.

Autor: CNChris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also meine quarzfrequenz liegt bei 8 MHz.


Jetzt brauch ich aber noch die Funktion die irgendwann eintreffenden 3 
Bytes auszuwerten und in die Array zu schreiben.

Autor: CNChris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier nochmal der Code in formatierter Form:


#include <avr/io.h>
#include <util/delay.h>


#define DREHUNG 50

char globalReceiveEnable=0;

unsigned char ReceiveUART(void)   //schreibt die empfangenen Bytes in
eine Array
{
    unsigned char tempVar;

    for(;;)
    {
        while (!(UCSRA & (1<<RXC)))
        {
            tempVar = UDR;

            return tempVar;
        }
    }
}

unsigned char ReadyForReceive(void)
{
    while (!(UCSRA & (1<<UDRE)))  // warten bis Senden moeglich
      {
     }

      UDR = 0xFF;

}


int goCNC (unsigned char Anzahl,unsigned char Adresse,unsigned char
Richtung)
{
    int i=0;
    int y=0;
    globalReceiveEnable=0;
    for(; i<=Anzahl;i++)
    {
        if (Adresse == 0)   //frägt: Welcher Motor soll laufen?!
        {
            if (Richtung == 0)
            {
                for(y=0;y<=DREHUNG;y++)
                {
                PORTA = 0x7F;

          _delay_ms( 50 );

            PORTA = 0xBF;

           _delay_ms( 50 );

            PORTA = 0xDF;

          _delay_ms( 50 );

            PORTA = 0xEF;


         _delay_ms( 50 );

                //Zyklus für Motor0/Richtung0
                }
            globalReceiveEnable=1;
            }
            if (Richtung == 1)
            {
                for(y=0;y<=DREHUNG;y++)
                {

          PORTA = 0xEF;
           _delay_ms( 50 );
          PORTA = 0xDF;
          _delay_ms( 50 );
        PORTA = 0xBF;
          _delay_ms( 50 );
        PORTA = 0x7F;
          _delay_ms( 50 );
                //Zyklus für Motor0/Richtung1
                }
            globalReceiveEnable=1;
            }
        }
        if (Adresse == 1)
        {
            if (Richtung == 0)
            {
                for(y=0;y<=DREHUNG;y++)
                {
                _delay_ms(50);
                //Zyklus für Motor1/Richtung0
                }
            globalReceiveEnable=1;
            }
            if (Richtung == 1)
            {
                for(y=0;y<=DREHUNG;y++)
                {
                _delay_ms(50);
                //Zyklus für Motor1/Richtung1
                }
            globalReceiveEnable=1;
            }
        }
        if (Adresse == 2)
        {
            if (Richtung == 0)
            {
                for(y=0;y<=DREHUNG;y++)
                {
                _delay_ms(50);
                //Zyklus für Motor2/Richtung0
                }
            globalReceiveEnable=1;
            }
            if (Richtung == 1)
            {
                for(y=0;y<=DREHUNG;y++)
                {
                _delay_ms(50);
                //Zyklus für Motor2/Richtung1
                }
            globalReceiveEnable=1;
            }
        }
    }
}


int main (void)
{
    char aiParameter[3] ;
    int i=0;
    int go=0;
    UCSRB |= (1<<RXEN) | (1<<TXEN);                         //Empfangen
aktivieren
    UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);

    UBRRH = 00;                         //Baudrate einstellen 9600 bei 8
MHz
    UBRRL = 51;

for(;;)
{
    if (UDR != 0)                             //wenn was im UART steht,
    {
        for(;i<=3;i++)
        {
            aiParameter[i] = ReceiveUART();     //schreibe die
empfangenen Bytes in eine Array
        }
        goCNC(aiParameter[0],aiParameter[1],aiParameter[2]); //...führe
Fräsprozess durch.


        if (globalReceiveEnable == 1)
        {
            UCSRB |= (1<<RXEN);//empfang aktivieren
            ReadyForReceive();//jetzt muss was an den PC gesendet
werden, damit er was zurückschicken kann. Controller fordert byte!
            ReceiveUART();    //wenn bereit für Empfang, sendet
controller "0xFF" . Am PC muss auf 0xFF gewartet werden!
            go=1;
        }
        else
        {
            UCSRB &= ~(1<<RXEN);
        }
    }
}
}



Autor: CNChris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abgsehen von dem Protokoll was ich dann wirklich machen werde.

Aber welche Änderung muss ich in meinem Code noch vornehmen, damit es so 
funktioniert, wie es sollte?

Also ständig auf 3 Bytes warten, die dreit Bytes dann in eine Array 
schreiben und damit die "goCNC"-Funktion steuern.

@ Rolf Magnus: Danke auch Dir. Aber wie genau soll ich da dann die 
Abfrage für den UDR machen?


Danke

Autor: Torben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Abgsehen von dem Protokoll was ich dann wirklich machen werde.

Das sollte einiges verbessern.

>Also ständig auf 3 Bytes warten, die dreit Bytes dann in eine Array
>schreiben und damit die "goCNC"-Funktion steuern.

Lange programmierst du defentiv noch kein C und deine Kenntnisse in der 
Mikrocontrollerwelt scheint auch noch nicht sehr groß zu sein.

Du solltest dich nochmal zum Anfang bewegegn und Dir das AVR GCC 
Tutorial vornehmen, weil es nix bringt ein Projekt dieser grössen 
Ordnung anzufangen ohne die Grundkenntnisse des Mikrocontrollers und der 
Programmiersprache zu kennen.


Hier findest Du ein Beispiel. Die Auswertungsfunktion muss auf einen 
Zaehler (counter bis 0x02) triggern, weil du 3 Bytes empfangen möchtest.

Beitrag "Auswertung RS232-Befehle"

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.