Hallo,
ich arbeite derzeit (bzw. bin am Finalisieren) einer API für ein
Buskommunikationsmodul das sich DevComSlave nennt. Es handelt sich dabei
im Wesentlichen um ein Modul, das einen Protokollstack für diverse
Bussysteme auf Master-Slave-Basis (z.B. und hauptsächlich gedacht für
RS485) implementiert, über dessen Protokoll Daten sowie Befehle
ausgetauscht werden können. Im Modul werden Fehlererkennung (&
Behandlung), Acknowledgeing, Buszugriff und einige Befehle verarbeitet,
diese Funktionen sollen vom Applikationsprogrammierer nicht verändert
werden müssen dürfen können.
Ziel ist es, eine API zu schaffen, die - ich sag mal vorsichtig -
annähernd objektorientiert ist und einigermaßen Hardwareunabhängig ist
(vorerst mal auf AVR). Dazu wird eine statische Library erzeugt und über
ein Headerfile ein Interface geschaffen (Bibliothek muss natürlich zum
Projekt dazugebunden werden)
Mir geht es jetzt darum, wie verständlich und gut zu handhaben ihr
angehängte Zugriffsmethoden und Funktionsprinzipien findet. Main.c ist
mit mitgelinkter static Library so voll funktionsfähig.
Headerdatei (also Interfacedefinition) findet sich im Anhang.
Habe jetzt bewusst nicht die gesamte Doku mitgeliefert da es mir um die
Lesbarkeit des Codes geht und ich kenne einige Programmierer die sowieso
nie Doku lesen - also gehts mir auch darum, den Code und Handhabung
halbwegs intuitiv zu halten. Ein Teil der Bibliotheksbeschreibung der im
Wesentlichen das DevCom-Prinzip unabhängig von der Implementierung
beschreibt ist als PDF angehängt. Protokollspezifikation (großteils bis
auf einige Details fertig (Masterimplementierung und paar Kleinigkeiten
fehlen noch)) ebenfalls im Anhang.
Main.c (Initialisiert und startet ein DevComSlave-Module, polled das
Flag, in dem signalisiert wird, dass neue Daten verfügbar sind)
1 | #include <avr/io.h>
|
2 | #include "DevComSlave.h"
|
3 |
|
4 | uint8_t fooCmdHandler(const unsigned char* cmd, unsigned char lastCtrlByte, unsigned char upperBound, unsigned char responseAllowed)
|
5 | {
|
6 | switch(cmd[0])
|
7 | {
|
8 | case 0x0D:
|
9 | // Handle Command 0x0D
|
10 | return(DCS_CMDHANDLER_SUCCESS);
|
11 | break;
|
12 | default: break;
|
13 | }
|
14 | // Command is unknown
|
15 | return(DCS_CMDHANDLER_ERROR);
|
16 | }
|
17 |
|
18 | #include "crc8.h"
|
19 |
|
20 | int main()
|
21 | {
|
22 | DevComSlave_t dc;
|
23 |
|
24 | dcs_setDefaults(&dc,10); // Default, with SA=10. use of dcs_setDefaults recommended..
|
25 | dc.MCAddress = 0x04;
|
26 |
|
27 | // RW-Output
|
28 | dc.RWPort = &PORTD;
|
29 | dc.RW_bp = PD2;
|
30 | dc.RWPolarity = 1;
|
31 |
|
32 | // Commandhandling
|
33 | dc.CommandHandler = fooCmdHandler; // Callbackfunction for user-commands
|
34 |
|
35 | dc.DataUpperBound = 9-1; // Datasets are expected to be 9 Bytes long
|
36 | dc.ID = 0x1234; // Device ID is 0x1234 (e.g. for identification by master application)
|
37 |
|
38 | dcs_atmega88_rw_init(&dc, F_CPU, 500000); // Initialize with 500kbps
|
39 | // DevComSlave-Module now Ready and listening..
|
40 |
|
41 | while(1)
|
42 | {
|
43 | if(dc.NewReceived & DCS_REC_DATA_gm)
|
44 | {
|
45 | // Do something, access Data ranging from dc.Data[0] .. dc.Data[dc.DataUpperBound]
|
46 |
|
47 | dc.NewReceived &= ~(DCS_REC_DATA_gm); // Reset Flags
|
48 | }
|
49 | }
|
50 | }
|
Kurz noch zum Projektstatus:
- Slaveimplementierung für Atmega fertig, für XMegas in Testphase.
Durch. Codegröße: 2500 Bytes derzeit... is aber glaub ich noch was drin
- Masterimplementierung für C# / Managed C++ fertig (läuft über
USB-Serial Umsetzer oder wahlweise TCP-Verbindungen (z.b. Moxa NPORTs)
- Protokollspezifikation gerade in Finalisierung
- Am Multimaster feil ich noch, läuft derzeit nur stabil mit 1 Master im
System
Habe vor das ganze dann open source zu machen, eventuell kanns ja der
ein oder andere brauchen. Bei uns in der Firma wirds erfolgreich
eingesetzt (im Innen- und Außenbereich), Datenübertragungsraten bis zu
1Mbit/s sind bei 20MHz Quarz i.d.R. möglich, 500kbit/s auf jeden Fall.
Bei Interesse stelle ich natürlich gerne weitere Informationen zur
Verfügung.
Zerreist es in der Luft ;)
Vielen Dank schon einmal für eure Mühe
Thomas