Forum: Compiler & IDEs Bytes Nacheinander empfangen


von CNChris (Gast)


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

von CNChris (Gast)


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

von CNChris (Gast)


Lesenswert?

Hmm...hat denn keiner eine Ahnung??

von CNChris (Gast)


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

von Rahul D. (rahul)


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.

von TransistorQuäler (Gast)


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!

von Torben (Gast)


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.

von Torben (Gast)


Lesenswert?

Noch etwas:

>_delay_ms( 50 );

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

von Rolf Magnus (Gast)


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.

von CNChris (Gast)


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.

von CNChris (Gast)


Lesenswert?

Hier nochmal der Code in formatierter Form:

1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
5
#define DREHUNG 50
6
7
char globalReceiveEnable=0;
8
9
unsigned char ReceiveUART(void)   //schreibt die empfangenen Bytes in
10
eine Array
11
{
12
    unsigned char tempVar;
13
14
    for(;;)
15
    {
16
        while (!(UCSRA & (1<<RXC)))
17
        {
18
            tempVar = UDR;
19
20
            return tempVar;
21
        }
22
    }
23
}
24
25
unsigned char ReadyForReceive(void)
26
{
27
    while (!(UCSRA & (1<<UDRE)))  // warten bis Senden moeglich
28
      {
29
     }
30
31
      UDR = 0xFF;
32
33
}
34
35
36
int goCNC (unsigned char Anzahl,unsigned char Adresse,unsigned char
37
Richtung)
38
{
39
    int i=0;
40
    int y=0;
41
    globalReceiveEnable=0;
42
    for(; i<=Anzahl;i++)
43
    {
44
        if (Adresse == 0)   //frägt: Welcher Motor soll laufen?!
45
        {
46
            if (Richtung == 0)
47
            {
48
                for(y=0;y<=DREHUNG;y++)
49
                {
50
                PORTA = 0x7F;
51
52
          _delay_ms( 50 );
53
54
            PORTA = 0xBF;
55
56
           _delay_ms( 50 );
57
58
            PORTA = 0xDF;
59
60
          _delay_ms( 50 );
61
62
            PORTA = 0xEF;
63
64
65
         _delay_ms( 50 );
66
67
                //Zyklus für Motor0/Richtung0
68
                }
69
            globalReceiveEnable=1;
70
            }
71
            if (Richtung == 1)
72
            {
73
                for(y=0;y<=DREHUNG;y++)
74
                {
75
76
          PORTA = 0xEF;
77
           _delay_ms( 50 );
78
          PORTA = 0xDF;
79
          _delay_ms( 50 );
80
        PORTA = 0xBF;
81
          _delay_ms( 50 );
82
        PORTA = 0x7F;
83
          _delay_ms( 50 );
84
                //Zyklus für Motor0/Richtung1
85
                }
86
            globalReceiveEnable=1;
87
            }
88
        }
89
        if (Adresse == 1)
90
        {
91
            if (Richtung == 0)
92
            {
93
                for(y=0;y<=DREHUNG;y++)
94
                {
95
                _delay_ms(50);
96
                //Zyklus für Motor1/Richtung0
97
                }
98
            globalReceiveEnable=1;
99
            }
100
            if (Richtung == 1)
101
            {
102
                for(y=0;y<=DREHUNG;y++)
103
                {
104
                _delay_ms(50);
105
                //Zyklus für Motor1/Richtung1
106
                }
107
            globalReceiveEnable=1;
108
            }
109
        }
110
        if (Adresse == 2)
111
        {
112
            if (Richtung == 0)
113
            {
114
                for(y=0;y<=DREHUNG;y++)
115
                {
116
                _delay_ms(50);
117
                //Zyklus für Motor2/Richtung0
118
                }
119
            globalReceiveEnable=1;
120
            }
121
            if (Richtung == 1)
122
            {
123
                for(y=0;y<=DREHUNG;y++)
124
                {
125
                _delay_ms(50);
126
                //Zyklus für Motor2/Richtung1
127
                }
128
            globalReceiveEnable=1;
129
            }
130
        }
131
    }
132
}
133
134
135
int main (void)
136
{
137
    char aiParameter[3] ;
138
    int i=0;
139
    int go=0;
140
    UCSRB |= (1<<RXEN) | (1<<TXEN);                         //Empfangen
141
aktivieren
142
    UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);
143
144
    UBRRH = 00;                         //Baudrate einstellen 9600 bei 8
145
MHz
146
    UBRRL = 51;
147
148
for(;;)
149
{
150
    if (UDR != 0)                             //wenn was im UART steht,
151
    {
152
        for(;i<=3;i++)
153
        {
154
            aiParameter[i] = ReceiveUART();     //schreibe die
155
empfangenen Bytes in eine Array
156
        }
157
        goCNC(aiParameter[0],aiParameter[1],aiParameter[2]); //...führe
158
Fräsprozess durch.
159
160
161
        if (globalReceiveEnable == 1)
162
        {
163
            UCSRB |= (1<<RXEN);//empfang aktivieren
164
            ReadyForReceive();//jetzt muss was an den PC gesendet
165
werden, damit er was zurückschicken kann. Controller fordert byte!
166
            ReceiveUART();    //wenn bereit für Empfang, sendet
167
controller "0xFF" . Am PC muss auf 0xFF gewartet werden!
168
            go=1;
169
        }
170
        else
171
        {
172
            UCSRB &= ~(1<<RXEN);
173
        }
174
    }
175
}
176
}

von CNChris (Gast)


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

von Torben (Gast)


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"

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.