PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : mega8 über Computer steuern



Slotti
05.02.2010, 16:12
Hi Community

Ich erkläre erstmal mein Vorhaben:
Ich habe vor auf dem PC eine Oberfläche in einer mir bekannten Sprache(c#, Autoit, C) zu erstellen, über welches is dann meinem µC einfache Befehle schicken möchte. Über einen Com-Anschluss verfüge ich leider nicht mehr, habe aber vor mir einen USB-Com Adapter zuzulegen.

Vieleicht noch nebenbei, ich habe keine Ahnung wie ich den Controller zum Programmieren an den PC anschließen muss, da ich ein myAVR (mk2) Lernboard besitze.

Nun würde mich interresieren, wie ich den controller anzuschließen hab und wie ich ihm Befehle senden kann, ich habe bereits herausgefunden, dass man über die console per "echo" befehl, den com port ansteuert, aber nicht wie der controller diese verarbeitet.

Ein beispiel währe: Ich drück nen knopf im prog, das schreibt was in die console, der controller empfängt das signal-->lampe leuchtet.

Ich hoffe ihr könnt mir helfen und habt ein wenig verständniss für meine Unwissenheit, ich stehe noch ganz am Anfang.

THX im vorraus

Che Guevara
05.02.2010, 17:08
Hallo Slotti,

in welcher Sprache möchtest du denn den µC programmieren? Ich kann leider nur Bascom (Basic) und ein bisschen Assembler.

Bei dem USB-Serial Adapter musst du aufpassen! Einige können nur senden, jedoch nicht empfangen.

Zu deiner Frage:
Im Prinzip ist es ganz einfach:
Du sendest mit dem PC einen Befehl, z.B. "LED:01:255". Dieser Befehl wird vom µC empfangen und, wenn nötig, sendet dieser den Befehl zurück, damit du diesen am PC mit dem gesendeten vergleichen kannst, um evtl. Übertragungsfehler zu erkennen und entsprechend darauf zu reagieren. Der Befehl wird dann im µC zerlegt. Hier z.B. so:
"LED"-"01"-"255" --- LED steht dafür, dass du eine LED ansteuern möchtest. Mit "01" gibst du an, dass du LED-Nr. 01 ansteuern möchtest. "255" gibt an, den PWM-Wert (also Helligkeit) dieser LED auf 255 zu setzen.
Der ":" ist dafür, dass der µC merkt, wann ein neuer Befehlsabschnitt kommt.
Das ganze sollte jetzt nur als Beispiel dienen, du kannst natürlich dein eigenes "Protokoll" entwickeln.

Gruß
Chris

Slotti
05.02.2010, 17:48
Hallo Chris, danke für die schnelle Antwort

Deine Antwort hat mich bereits weitergebracht, mir war nicht klar, dass ich über den echo befehl einen string senden kann.

Ich programmiere übrigens in C, aber das dürfte nicht die Hürde sein.

Ich denke mal, dass der Befehl dann in einem Register gespeichert wird, die Frage die sich nun auftut währe dann: Wie heißt das Register und wie merkt der Contoller, dass er einen Befehl bekommen hat? muss ich das per polling überprüfen oder kann man das wie einen Interrupt handhaben?

Gruß Stefan

shedepe
05.02.2010, 18:01
so mal als kleiner hinweis:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART

Che Guevara
05.02.2010, 18:09
Also in Bascom configuriert man ganz am Anfang einen "Uart"-Interrupt. Wenn jetzt ein Zeichen über die Schnittstelle kommt, geht der µC in die ISR und liest das Zeichen ein. Alternativ kannst du auch einen Buffer erstellen, welcher sich solange mit Zeichen füllt, bis entweder der Buffer voll ist oder ein best. Zeichen (z.B. <CR>) empfangen wurde. Bis zu diesem Zeitpunkt passiert das alles im "Hintergrund", du kannst also währenddessen viele andere Sachen machen.
Du kannst natürlich auch den Eingang (RX) permanent abfragen, allerdings finde ich das sehr uneffizient und unelegant. Da sind Interrupts wesentlich besser, da diese nur aufgerufen werden, wenn es nötig ist.
Da die Zeichen dann aber noch im Buffer sind, musst du diese dann aus dem Buffer in eine Variable (in Bascom: String) einlesen. Diese zerlegst du dann in die einzelnen "Befehlsabschnitte". Jetzt kannst du die Daten wirklich nutzen.
Hier mal ein Pseudocode, welcher evtl. hilfreich sein könnte:


'Init-code

mache
...
Hauptschleife

isr_von_uart:
input befehle 'hier werden die Zeichen aus dem Buffer in eine Variable eingelesen
split befehle , ":" ' hier wird der ganze Befehl in einzelne Abschnitte geglidert, jeweils getrennt durch den Doppelpunkt
...
return

Wenn du das nicht verstehst, musst du nochmal fragen. Am besten wäre es aber, wenn du für einen konkreteren Code jemanden fragst, der sich mit C auskennt. Ich kann dir lediglich die Vorgehensweise erklären.

Gruß
Chris

Slotti
05.02.2010, 19:39
Super, genau das was ich gesucht habe...die Funktion ist mir klar, ich werds mal nächste tage ausprobieren und dann einen beispielscode in C posten.
Vieleicht füge ich dann direkt einen c# code bei, um per "GUI" am PC den mega8 anzusteuern.

Danke an alle, die Antworten kamen wirklich schnell und waren sehr präziese.

BurningWave
06.02.2010, 18:03
Wenn du wissen willst, wie man in C auf die serielle Schnittstelle zugreift, kannst du mal "serielle Schnittstelle mit C ansprechen" bei google eingeben, es erscheinen dann viele auf, deine Frage zutreffenden, Antworten.

Ich habe selbst schon ein kleines Terminalprogramm programmiert (in C++) den Code und das Programm habe ich auf meiner Website veröffentlicht. Dort habe ich außerdem beschrieben, wie man den µC genau an die serielle Schnittstelle anschließt. Du kannst es dir mal anschauen, wenn du noch nicht weißt, wie das geht.

mfg

Slotti
07.02.2010, 22:49
Danke _R2D2 für den Hinweis, nur bereitet mir nicht der Anschluss die Probleme, ich besitze, wie oben beschrieben ein myAVR mk2 lernboard mit fertigem USB Adapter, und Daten kann ich über die Entwicklungsumgebungs senden, mein Problem nach langem Lesen und ausprobieren ist nun, dass eine Kontrolllampe auf dem Board sagt, dass Daten empfangen wurden, das kriegt das Programm aber iwie nich mit -.-, hier mal der code, fals es jemanden weiter bringt. Ich bin über jede Hilfe dankbar.

zum Code: Wenn Daten empfangen wurden sollte der Interrupt ausgelöst werden und die Lampe ausgehn, tut sie aber nich-.-.


#define F_CPU 3686400 // Taktfrequenz des myAVR-Boards

#define FOSC 1843200// Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1

#include <avr\io.h> // AVR Register und Konstantendefinitionen
#include <avr/interrupt.h>
#include <avr/iom8.h>

void USART_Init(unsigned int);
unsigned char USART_Receive( void );

main ()
{
cli(); //Global Interrupts deaktivieren

DDRB=0xFF; //PORTB als Schreibport definieren
DDRC=0xFF; //PORTC als Schreibport definieren
DDRD=0xFF; //PORTD lowbytes=Leseports & highbytes=Schreibeports

PORTD=0x80;
PORTB=0xFF;

USART_Init ( MYUBRR );

sei(); //Global Interrupts aktivieren

while(1)
{
USART_Receive();
PORTB=0x00;
}
}

void USART_Init( unsigned int ubrr)
{
/* Set baud rate */
UBRRH = (unsigned char)(ubrr>>8);
UBRRL = (unsigned char)ubrr;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN);//|(1<<TXEN);
/* Set frame format: 8data, 2stop bit */
UCSRC = (1<<USBS)|(3<<UCSZ0);
}

ISR(USART_RXC_vect)
{
PORTB=0x00;
}

ISR(USART_TXC_vect)
{
PORTB=0x00;
}

unsigned char USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSRA & (1<<RXC)) )
;
/* Get and return received data from buffer */
return UDR;
}



der Code ist so übrigens aus dem Datenblatt, die sfr sind also richtig.

Ceos
08.02.2010, 09:53
du hast das flag RXCIE nicht aktiviert, so dass dein interrupt nicht angesteuert wird

ausserdem was soll bitte die schleife mit dem USART_Receive ? du solltest das byte, wenn du schon ISRs verwendest, auch in der ISR verarbeiten (in einen puffer schreiben, eine puffervariable oder whatever) diese USART_Receive methode blockiert dein programm solange, wie kein byte empfangen wurde

ausserdem provozierrst du hier ein deadlock, obwohl cih mir nicht sicher bin wie die ISR mit dem flag umgeht!

in der regel löscht ein interrupt das flag, durch welches er ausgelöst wurde selber (RXC in dem fall), womit deine methode in der regel NIE ausgeführt wird, jedoch ist noch ein byte im puffer weil es nicht ausgelesen wurde ... trifft jetzt ein byte ein, wird WIEDER die ISR ausgelöst, kommt das bufferoverflow bit weil noch ein bytre im puffer ist ... und dein hauptprogramm steht sich weiterhin die beine in den bauch ...
ausseerdem hast du dir schon einen fehler eingehandelt der unbehandelt bleibt

wenn du schon mit ISRs arbeites, solltest du tunlichst vermeiden im hauptprogramm an den flags herumzuobern die für die ISRs zuständig sind, das kann ganz fies ins auge gehen

Slotti
09.02.2010, 14:38
Wow :-s hatte nicht gedacht, dass da so viel dran falsch ist, danke auf jeden Fall für die Antwort, ich hab letzte Tage meine Vollversion von Workpad plus bekommen und da war ein Beispielcode drin, den Poste ich mal hier und vielleicht bekomm ich das mit den vorherigen Hinweisen auch mit den Interrupts hin...Is en bischen scher, weil wir in der Schule nen komplett anderen µC benutzen.

Danke für alle hilfe und hier der Beispieltext für alle dies auch noch suchen, was der macht ist glaub ich ersichtlich:



#define F_CPU 3686400
#include <avr\io.h>
//----------------------------------------------------------------------
void uartInit()
{
UBRRL = 23; //9600Baud siehe Baudratentabelle
UCSRB = 8 + 16; //Sender enable, Empfänger enable
}
//----------------------------------------------------------------------
char uartGetChar()
{
char data=0;
//warte bis RX-complete RXC UCSRA / USR bei z.B.: AT090S2313
while (!(UCSRA&128));
//empfangen
data=UDR;
return data;
}
//----------------------------------------------------------------------
void uartPutChar(char data)
{
//warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
while (!(UCSRA&32));
//sende
UDR=data;
}
//----------------------------------------------------------------------
main ()
{
uartInit();
while (true) // Mainloop
{
char zeichen;
zeichen=uartGetChar();
uartPutChar(zeichen);
}
}