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.
> 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.
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"