PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : einfache Protokoll-Implemenation?



Hender
09.03.2006, 15:21
Hallo,
ich suche nach einer möglichst einfachen Variante Daten zwischen meinem Atmega32 und dem Pc auszutauschen.
PC->Atmel:
Es soll möglich sein vom Pc aus einfache Steuerbefehle zu senden, bei denen dann auf dem Atmel einfach eine Funktion ausgerufen wird, z.B.: "res" löst die Funktion reset() aus. Zudem soll es möglich sein konkrete Werte zu senden, die dann auf dem Atmel einer Variable oder einem Register zugewiesen werden, z.B. durch "pwm128" wird dem PWM-Register OCR1AL=128; zugewiesen.
Atmel->PC: (diese Richtung ist weniger das Problem)
Hier soll es möglich sein diverse Statuswerte von Variablen an den PC zu senden, z.B. ADCValue=234.

Ich weiß das es eine Variante gibt, wo man zwei Byte sendet, wobei im ersten Byte das Kommando steht und im zweiten Byte die dazugehörigen Daten. Leider verstehe ich das ganze noch nicht richtig und weiß auch nicht wie die Pakete aussehen müssen, die ich vom PC aus sende. Veilleicht gibt es auch eine andere, vielleicht auch einfachere, Variante.

Es wäre echt nett wenn mir da jemand weiter helfen könnte. Vielleicht kennt jemand ein Tutorial im Netz, wo eine Protokoll-Implemenation erklärt?

Für die Uart-Kommunikation verwende ich den folgenden Code.:


#include "uart.h"
#include <avr/io.h>
#include <avr/signal.h>

/* UART Buffer */
#define UART_RX_BUFFER_SIZE 128 /* 2,4,8,16,32,64,128 or 256 bytes */
#define UART_TX_BUFFER_SIZE 128

#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1 )
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
#error RX buffer size is not a power of 2
#endif

#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1 )
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
#error TX buffer size is not a power of 2
#endif


/* Static Variables */
static uint8_t uart_rxbuf[UART_RX_BUFFER_SIZE];
static volatile uint8_t uart_rxhead;
static volatile uint8_t uart_rxtail;
static uint8_t uart_txbuf[UART_TX_BUFFER_SIZE];
static volatile uint8_t uart_txhead;
static volatile uint8_t uart_txtail;


/* Initialize UART */
void uart_init (uint8_t ubrr)
{
UBRRH = 0;
UBRRL = ubrr; /* Set the baud rate */
/* Enable UART receiver and transmitter, and receive interrupt */
UCSRB = ( (1<<RXCIE) | (1<<RXEN) | (1<<TXEN) );

/* enable 2 stopbits 8bit char size */
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //syncron usart modus UMSEL

/* Flush receive buffer */
uart_rxtail = 0;
uart_rxhead = 0;
uart_txtail = 0;
uart_txhead = 0;
}


/* Interrupt handlers */

/*
* Receive Complete
*/
SIGNAL (SIG_UART_RECV)
{
uint8_t data;
uint8_t tmphead;

data = UDR; /* Read the received data */
/* Calculate buffer index */
tmphead = (uart_rxhead + 1) & UART_RX_BUFFER_MASK;

if (tmphead == uart_rxtail) {
/* ERROR! Receive buffer overflow */
tmphead = uart_rxhead;
}
uart_rxhead = tmphead; /* Store new index */

uart_rxbuf[tmphead] = data; /* Store received data in buffer */
}

/*
* Data Register Empty
*/
SIGNAL (SIG_UART_DATA)
{
uint8_t tmptail;

/* Check if all data is transmitted */
if (uart_txhead != uart_txtail) {
/* Calculate buffer index */
tmptail = ( uart_txtail + 1 ) & UART_TX_BUFFER_MASK;
uart_txtail = tmptail; /* Store new index */

UDR = uart_txbuf[tmptail]; /* Start transmition */
} else {
UCSRB &= ~ _BV (UDRIE); /* Disable UDRE interrupt */
}
}

/* Read and write functions */
uint8_t uart_get_char (void)
{
uint8_t tmptail;

while (uart_rxhead == uart_rxtail) { /* Wait for incomming data */
}
/* Calculate buffer index */
tmptail = (uart_rxtail + 1) & UART_RX_BUFFER_MASK;

uart_rxtail = tmptail; /* Store new index */

return uart_rxbuf[tmptail]; /* Return data */
}

uint8_t tx_buffer_size (void)
{
return (uart_txhead - uart_txtail);
}
uint8_t uart_put_char (uint8_t data)
{
uint8_t tmphead;
/* Calculate buffer index */
tmphead = ( uart_txhead + 1 ) & UART_TX_BUFFER_MASK;
/* Wait for free space in buffer */
while ( tmphead == uart_txtail ) {
}

uart_txbuf[tmphead] = data; /* Store data in buffer */
uart_txhead = tmphead; /* Store new index */

UCSRB |= _BV (UDRIE); /* Enable UDRE interrupt */

return 0;
}

uint8_t uart_data_available (void)
{
/* Return 0 (FALSE) if the receive buffer is empty */
return (uart_rxhead != uart_rxtail);
}


... also uart_get_char() und uart_put_char(data)

Kera
09.03.2006, 17:50
Hallo!

Du könntest für dich selber ein Protokoll definieren, und zwar mit Zeichen: ein Startzeichen, Aktion, Endzeichen, BCC

z.B.: xp128y2

Das BCC erhält man durch EXOR verknüpfen der vorhergegangenen Zeichen, zum überprüfen ob man auch alle Daten richtig empfangen hat.

Du musst zwar jedes Zeichen einzeln senden, dafür ist es zumindest einfach!

Wenn du interesse hast, schreib einfach rein, dann werde ich es dir genauer erklären!!!

MFG

Vogon
09.03.2006, 19:02
Was hältst du von dem Projekt ?

Rnbfra Multi-Thread und Netzwerkfähig mit GUI
https://www.roboternetz.de/phpBB2/viewtopic.php?p=151161#151161

Hender
10.03.2006, 15:02
Hallo,
Danke erst einmal für Eure schnellen Antworten. Das Smirs Protokoll bzw. Telegramm ist wahrscheinlich für mein Vorhaben eher nicht geeignet.
Ich möchte daher sehr gern auf das Angebot von Kera zurückkommen und ein eigenes kleines Protokoll entwickeln.
Bei meinem Projekt handelt es sich um meine Diplomarbeit. Ich möchte einen (evtl. auch zwei) Elektronmagnet(e) über ein (zwei) PWM-Signale vom PC aus steuern und damit ein bewegliche Einheit auf einer kurzen Strecke von 1-2 cm verschieben. Die Position dieser beweglichen Einheit wird mittels eines Potentiometers gemessen. Die Komponenten wie ADC, zwei PWM-Signale, Uart funktionieren auch schon. Im Prinzip muss Folgendes funktionieren:

PC->Atmega32:
- Zuweisen von konkreten Werten für die PWMs, also OCR1AL=xxx und OCR1BL=yyy
- senden von Steuerbefehlen, die eine bestimmte Funktion auslösen, z.b: init(), reset()

Atmega32->PC:
- Senden der Statusdaten von Variablen oder Registern ADCValue, OCR1AL, OCR1BL

Ich möchte den Atmel von meiner .Net-Anwendung (Visual C#) aus steuern. Hier habe ich die folgenden 3 Möglichkeiten Daten an den Atmel zu senden.:
SerialPort.Write (String)
SerialPort.Write (Byte[], Int32, Int32)
SerialPort.Write (Char[], Int32, Int32)

Ich weiß eben auch nicht, in welcher Form ich dann die Daten vom PC aus schicken muss? Wie würde denn ein Paket im konkreten Beispiel aussehen? Sende ich vom PC aus als String?
Auf dem Atmel kann ich jeweils einzelne Zeichen senden bzw. empfangen (siehe Uart-Quelltext im letzten Post).
Eine detailiertere Erklärung und evtl. vor allem Quelltext-Beispiele wären für mich sehr hilfreich.

Vielen Dank für Eure schnelle Hilfe. :)

Vogon
10.03.2006, 17:14
Das RN Projekt zur Kuommunikation zwischen Robotern und PC geht sicher weit über deine Aufgabe hinaus.
Mein Tip:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=67997#67997
Hier und auch in einigen weiteren Beiträgen (Suchfunktion) findest du jede Menge Lösungen per IR-Fernbedinung dem Roboter Anweisungen zu übermitteln.
Ob du das per RS232, IR, US, Funk usw machst ist eigendlich egal.

Kera
11.03.2006, 12:36
Hallo!

So ein zufall, ich bin auch gerade bei einer Diplomarbeit dabei!!

1. Dein Protokoll sollte klar definiert sein, d.h.: du solltest immer ein Start und ein End zeichen haben, welches sonst nicht vorkommt! UNd zur sicherheit solltest du auch noch ein Zeichen mitsenden(BCC)!
z.B.: [Start] initA[Ende][BCC]
Ich habe z.B: als Start zeichen x und als endzeichen y verwendet!! Es bleibt dir überlassen!!!
Wenn du nun etwas an deine Platine schickst, solltest du einen Receive Interrupt verwenden, und immer wenn dieser ausgelöst wird, überprüfst welche Daten es sind zwischen [Start] und [ende]!! Je nach dem setzt du eine Variable(Flak). In deinem Hauptprogramm wo du siche reine while(1) haben wirst, fragst du dann einfach mittels IF oder SWITCH anweisung ab, und machst dann dies und das,....!


2. senden vom PC
Es ist egal ob du einen ganzen String oder nur jedels Zeichen einzeln schickst, bei mir wurde gleich der ganze String vom PC runtergeschickt!!
Auf der Platine musst du dann so wie so jedes Zeichen einzeln herauslesen!!!

3. senden von Platine
Ich habe bei mir nicht die Standardfunktionen wie printf und scanf verwendet, diese fressen unmengen von SPeicher!!!
Ich habe selber kleine Unterprogramme geschrieben wo ich jedes Zeichen einzeln herauslese, und ein weiteres UP wo ich die Zeichen wieder einzeln hinaufschicke!!!

4. OCR1a...;
Wir haben zuerst beim PC die Zahl für OCR1A umgewandelt auf Ziffern.: z.B.: 512 --> 5, 1, 2, und danach unten bei der Platine eine Programm geschrieben, welches diese einzelnen Zeichen wieder zu einer Zahl zusammenfügt!!!

5. BSP.:
Schau mal auf
https://www.roboternetz.de/phpBB2/viewtopic.php?p=164982#164982
dort ist mein Programm!!
Wenn du Fragen hast, du weist wo du mich findest!!

6. BCC rechner!!!
als Attachment ist noch ein selbstprogrammierter BCC rechner!!!
einfach alles eingeben: z.B: xinitAy --> BCC= "!

Hender
13.03.2006, 15:31
Hallo Kera,

danke für Deine Hinweise. Ich werde mir Deinen Quelltext in der nächsten Zeit mal näher ansehen und mein Protokoll daraus entwickeln. Bei Fragen werde ich auf Dich zukommen. :-)

Ich kann übrigens das Attachment nicht finden?

6. BCC rechner!!!
als Attachment ist noch ein selbstprogrammierter BCC rechner!!!
einfach alles eingeben: z.B: xinitAy --> BCC= "!

Danke erstmal bis dahin.

Kera
13.03.2006, 16:11
Oh, stimmt!!

Ich versuchs nochmal!!!

So jetzt funktionierts aber!!

MFG

Hender
13.03.2006, 17:23
Nochmals Hallo,

ich kann die Exe bei mir leider nicht starten, da mir die Datei vcl60.bpl fehlt.

Die Anwendung konnte nicht gestartet werden, weil vcl60.bpl nicht gefunden wurde. Neuinstallation der Anwendung könnte das Problem beheben.
Damit das bei mir funktioniert, müßtest Du Deine Compiler bzw. Linkeroptionen nochmal überprüfen.

options|linker|use dynamic RTL deaktivieren und
options|packages|build with runntime package deaktivieren

oder

Projektoptionen -> Packages
[_ ] Laufzeit Packages verwenden <-- den Haken entfernen....

Danke.

Kera
13.03.2006, 19:27
So ich hab es dir als .rar File upgeloadet, jetzt brauchst du nur zu entpacken und dann hast du das File rechner.exe!!!

MFG

Hender
14.03.2006, 11:38
Danke für das nochmalige hochladen, aber ich kann rechner.exe immer noch nicht starten, da mir die Datei vcl60.bpl fehlt (siehe letzter Post von mir). Das ist irgendeine Laufzeitbiliothek, die ich nicht auf meinem Computer habe. Rechner.exe hatte ich auch schon beim letzten Mal, nachdem ich das jpg in exe umbenannt hatte.
Damit ich das bei mir starten kann, mußt Du wie gesagt, das Programm neu kompilieren. Dabei müßtest Du Deine Compiler- und Linkeroptionen nochmal überprüfen. Das ganze muß beim Compilieren statisch gelinkt werden. Die Exe-datei wird danach zwar etwas größer, aber dafür läuft das Porgramm auch auf anderen Computern. Ich weißt nun nicht, ob Du Borland C++ Builder oder Visual C++ nutzt.
Also um nicht außer die Exe zu haben musst du in den Projektoptionen:
1. Compiler / Endgültig anklicken
2. Packages / Mit Laufzeit Packages compilieren abwählen
3. Linker / Dynamische RTL verwenden abwählen

Wofür steht eigentlich "BCC"? Ich konnte dafür nichts im WWW finden. Es ist ja sowas wie CRC. Wie funktioniert denn der Algorithmus von zum erstellen des BCC aus einer Zeichenfolge? Gibts dazu irgendwas im WWW?

Vielen Dank nochmals.

SprinterSB
14.03.2006, 19:38
BCC = Borland C-Compiler?

ruediw
14.03.2006, 21:42
Danke für das nochmalige hochladen, aber ich kann rechner.exe immer noch nicht starten, da mir die Datei vcl60.bpl fehlt (siehe letzter Post von mir). Das ist irgendeine Laufzeitbiliothek, die ich nicht auf meinem Computer habe. Rechner.exe hatte ich auch schon beim letzten Mal, nachdem ich das jpg in exe umbenannt hatte.
Damit ich das bei mir starten kann, musst Du wie gesagt, das Programm neu kompilieren. Dabei müßtest Du Deine Compiler- und Linkeroptionen nochmal überprüfen. Das ganze muß beim Compilieren statisch gelinkt werden. Die Exe-datei wird danach zwar etwas größer, aber dafür läuft das Porgramm auch auf anderen Computern. Ich weißt nun nicht, ob Du Borland C++ Builder oder Visual C++ nutzt.
Also um nicht außer die Exe zu haben musst du in den Projektoptionen:
1. Compiler / Endgültig anklicken
2. Packages / Mit Laufzeit Packages compilieren abwählen
3. Linker / Dynamische RTL verwenden abwählen

Wofür steht eigentlich "BCC"? Ich konnte dafür nichts im WWW finden. Es ist ja sowas wie CRC. Wie funktioniert denn der Algorithmus von zum erstellen des BCC aus einer Zeichenfolge? Gibts dazu irgendwas im WWW?

Vielen Dank nochmals.

Er verwendet vermutlich Delphi6 oder den C-Builder von Borland.

BCC ist die Abkürzung für "Block Check Code" und verwandt mir CRC.

fambi_mail
22.03.2006, 12:34
Ich arbeite ebenfalls an einem Protokoll.

Sie auch https://www.roboternetz.de/phpBB2/viewtopic.php?t=17875