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
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
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
> 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.
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!
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.
Noch etwas:
>_delay_ms( 50 );
Leider hast du deine Quarzfrequenz nicht angegeben, aber ab 4MHz kannst
du mit _delay_ms maximal 20ms warten.
> 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.
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.
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 | }
|
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
>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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.