Hallo alle zusammen,
ich hab mir mal die mühe gemacht und schnell mal ein einfaches
Nachrichtenprotokoll in C geschrieben, sinn und zweck ist es
Resourcensparend Daten in eine Nachricht zu packen und am anderen ende
wieder einfach lesen zu können.
Ich weis es gibt bereits viele Nachrichtenprotokolle UDP TCP usw. aber
ich hab keines gefunden dass einfach zu bedienen ist, Daten in
Nachrichten verpackt und am Ende die Korrektheit der Daten über eine
Prüfsumme bestimmt.
Das Programm ist aufgrund eines Projekts enstanden indem ich zwischen
einem ATMEGA8 und einem STM32F103 Steuerungsnachrichten übertragen
musste, da diese Nachrichten aus mehreren Bytes bestanden und es mir
nicht möglich war das alles in einer einzigen I2C übertragung zu
übertragen, hab ich das Protokoll geschrieben und auch erfolgreich
verwendet.
Ich habe das Protokoll bisher auf allen µC und CPUs kompiliert ohne
änderung und probleme.
Falls jemand von euch vor einem ähnlichen Problem steht könnt ihr den
Code von meine Github Account runterladen und verwenden, modifizieren
oder was auch immer ihr damit machen wollt.
https://github.com/Freshdouble/SMP/
Peter Kremsner schrieb:> da diese Nachrichten aus mehreren Bytes bestanden und es mir> nicht möglich war das alles in einer einzigen I2C übertragung zu> übertragen
Wie lang ist denn bei dir ein Byte, wenn du es nicht schaffst mehrere
davon in eine I2C Übertragung zu packen?
Prüfbit schrieb:> Wie lang ist denn bei dir ein Byte, wenn du es nicht schaffst mehrere> davon in eine I2C Übertragung zu packen?
8Bit
Das Problem war dass die I2C Schnittstelle automatisch (vermutlich war
sie einfach nur falsch konfiguriert) nach jedem Byte das Stop Signal
gesendet hat und kein repetet start. Somit war die I2C Übertragung immer
nur ein Byte lang war, dann kam das nächste Startsignal die Adresse und
das nächste Byte.
Das Problem war auch dass die Übertragung in einer verrauschten umgebung
statgefunden hat, viele Motoren die mit PWM gesteuert wurden. Somit
waren die Daten nicht immer richtig die beim Slave ankamen damit die
Daten jetzt in Richtiger reihenfolge, die Pakte komplett sind und vor
allem die Daten richtig waren haben wir dann das Programm geschrieben.
Nebenbei haben wir später das Protokoll auch für UART-Schnittstellen
angewandt und die können nur ein Byte pro Übertragung durchführen.
Andreas Schweigstill schrieb:> inkonsistente Schreibweisen des API> - Rechtschreibfehler
ist mir bekannt und werde ich bald ausbessern, das programm war bis
jetzt auch nur in einem privaten Projekt
Andreas Schweigstill schrieb:> - label/goto statt while-Schleife
Kann man eventuel noch verbessern, aber bringt die verwendung einer
while schleife performancevorteile?
Peter Kremsner schrieb:> Kann man eventuel noch verbessern, aber bringt die verwendung einer> while schleife performancevorteile?
Ja, sie erhöht die Debuggingperformance massiv ;)
Hi
>Das Problem war dass die I2C Schnittstelle automatisch (vermutlich war>sie einfach nur falsch konfiguriert) nach jedem Byte das Stop Signal>gesendet hat und kein repetet start.
So falsch kannst du die TWI-Schnittstelle gar nicht konfigurieren.
MfG Spess
Peter Kremsner schrieb:> aber ich hab keines gefunden dass einfach zu bedienen ist, Daten in> Nachrichten verpackt und am Ende die Korrektheit der Daten über eine> Prüfsumme bestimmt.
Zum Beispiel LIN.
?
Hilf mir mal. Irgendwo scheine ich da einen Denkfehler zu haben oder du
hast da einen gewaltigen Bug in der Software
Du unterscheidest zwischen 2 Buffer. So weit so gut. Der in ist der
SMP_OutBuf und der andere der SMP_InBuf.
Wie ist deren Strukturdefinition? Hier sind die beiden
1
typedefstruct__SMP_BUF_T{
2
unsignedchardata[SMP_BUF_SIZE];
3
unsignedintwrIdx;
4
unsignedintrdIdx;
5
}SMP_BUF_T;
6
7
//SMP input buffer
8
typedefstruct__SMP_TBUF_T{
9
unsignedchardata[BUFFER_SIZE];
10
unsignedintwrIdx;
11
unsignedintrdIdx;
12
}SMP_TBUF_T;
13
14
staticvolatileSMP_BUF_TSMP_OutBuf;
15
staticvolatileSMP_TBUF_TSMP_InBuf;
Man beachte, und das ist im weiteren wichtig, dass die beiden Arrays
nicht potentiell gleich gross sind. Der eine hat eine Arraygrößsse von
SMP_BUF_SIZE, der andere eine Arraygröße von BUFFER_SIZE. Wie sind da
die zugehörigen Defitionen.
1
#define BUFFER_SIZE MAX_PAYLOAD * 2 + 4
2
3
...
4
#define MAX_PAYLOAD 64
5
#define SMP_BUF_SIZE 64
So wie das definiert ist, ist BUFFER_SIZE immer um einiges größer als
SMP_BUF_SIZE. Worauf es mir ankommt: wenn man nicht sorgfältig die
Definitionen von MAX_PAYLOAD und SMP_BUF_SIZE aufeinander abstimmt,
dann ergeben sich da verschiedene Werte.
So weit, so gut.
Jetzt kommts.
Hä?
Du kannst doch nicht die Makros, die du dir zur Verwaltung des
Ringbuffers im Output Buffer gemacht hast so mir nichts, dir nichts auf
den Input Buffer anwenden. Wie wir gerade gesehen haben, sind die Arrays
in den beiden Buffern unterschiedlich gross. D.h. aber auch, das alle
Berechnungen, die in den Makros letzten Endes auf SMP_BUF_SIZE beruhen
nicht auf den Input Buffer anwendbar sind. Dessen Array Grösse ist
BUFFER_SIZE und nicht SMP_BUF_SIZE.
spess53 schrieb:>> So falsch kannst du die TWI-Schnittstelle gar nicht konfigurieren.>
Ging nicht um die twi sondern die I2C am stm32
Rudolph schrieb:> Zum Beispiel LIN.
Danke werd ich mir mal ansehen, wussten wir damals leider noch nicht
Danke karl heinz dass ist offensichtlich ein bug.
Hat aber noch nie zu fehlern geführt, der eine buffer wird nur nicht
voll verwendet.
Aber wenn es da ohnehin schon ein fertiges protokoll mit LIN gibt ist
das hier doch ohnehin obsolet.
Peter Kremsner schrieb:> Danke karl heinz dass ist offensichtlich ein bug.>> Hat aber noch nie zu fehlern geführt, der eine buffer wird nur nicht> voll verwendet.
Dann überleg dir mal, was wohl passiert, wenn ich im festen Vertrauen
auf die Konfigurierbarkeit den MAX_PAYLOAD auf, sagen wir mal, 10 setze.
-> und kawumm.
Array Zugriff out of bounds.
Wenn mir wer ein Ringbuffersystem unterjubeln will, und in der
Strukturdefinition des Ringbuffers kommt die Längenangabe des Arrays
nicht als Strukturmember vor, dann werd ich hellhörig und seh mir die
Zugriffsfunktionen bzw. die Strukturdefinitionen etwas genauer an.
Entweder alle Arrays sind dann gleich gross oder in den Zugriffsmakros
wird mit sizeof gearbeitet. Ist beides nicht der Fall, haben wir schon
eine 99% Chance auf einen kapitalen Fehler.
Ich werde es bei gelegenheit noch anpassen
Das programm wurde unter zeitdruck geschrieben und ist natürlich weit
entfernt von perfekt,ich wollte es hier nur mal teilen falls es jemand
verwenden möchte natürlich ohne garantie
Ich kann nur sagen wir haben es verwendet und es hat super funktioniert
Peter Kremsner schrieb:> Ging nicht um die twi sondern die I2C am stm32
Und was ist bitte der Unterschied zwischen TWI und I2C, außer das Atmel
aus bis 2006 relevanten lizenzrechtlichen Gründen die Bezeichnung TWI
eingeführt hat?
Hi
>Und was ist bitte der Unterschied zwischen TWI und I2C, außer das Atmel>aus bis 2006 relevanten lizenzrechtlichen Gründen die Bezeichnung TWI>eingeführt hat?
Es geht ja um die hardwaretechnische Umsetzung. Das Datenblatt des STMs
zeigt aber, das der sehr ähnlich gestrickt ist. In der Initialisierung
gibt es auch keine Einstellung die das o.g. Verhalten hervorrufen kann.
MfG Spess
spess53 schrieb:> Das Datenblatt des STMs> zeigt aber, das der sehr ähnlich gestrickt ist. In der Initialisierung> gibt es auch keine Einstellung die das o.g. Verhalten hervorrufen kann.
Wir haben uns nicht mit der Hadware direkt beschäft und haben eine
CooCox Library verwendet, ich dachte nur dass es von der Hardware her
kommt, kann natürlich auch an der CooCox Library liegen, ich kann
jedenfalls nur sicher sagen dass es so direkt nicht funktioniert hat und
wir desshalb dieses Programm verwendet haben
Hab jetzt die GOTO Anweisung entfernt und den bug den karl heinz
angesprochen hat beseitigt (zumindest denke ich das ^^), hab es aber
noch nicht getestet
Hi
>Wir haben uns nicht mit der Hadware direkt beschäft und haben eine>CooCox Library verwendet, ich dachte nur dass es von der Hardware her>kommt, ...
Du stocherst bei der Hardware und bei der Software im Dunkeln. Meinst du
nicht, das es mal langsam Zeit wäre sich mal mit den Grundlagen zu
beschäftigen?
MfG Spess
Peter Kremsner schrieb:> da diese Nachrichten aus mehreren Bytes bestanden und es mir> nicht möglich war das alles in einer einzigen I2C übertragung zu> übertragen
Ich kann mich dunkel erinnern.
Bist Du es nicht gewesen, der sich standhaft geweigert hat, mit einem
I2C-EEPROM im Page Mode zu überprüfen, ob das Problem schon am Master
oder erst am Slave liegt?
Ein Würg-Around ist niemals eine Lösung und erst recht nichts, was man
guten Gewissens anderen empfehlen kann.
Gehe systematisch vor, finde den Fehler und mache es richtig.
spess53 schrieb:> Du stocherst bei der Hardware und bei der Software im Dunkeln. Meinst du> nicht, das es mal langsam Zeit wäre sich mal mit den Grundlagen zu> beschäftigen?
Ich beschäftige mich seit 4 Jahren mit Mikrocontroler Programmierung
also ich kenne die Grundlagen. Es war aber das erste mal dass ich einen
Cortex-M3 Mikrocontroler vor mir hatte und wir mussten innerhalb von
einer Woche ein fertiges und zumindest ausreichend lauffähiges Programm
haben, aus diesem Grund haben wir uns nicht auf die Hardware an sich
konzentriert sondern haben die CooCox Bibliothek für das I2C Interface
genommen und darauf vertraut dass die Funktioniert, jedenfalls hat es
aber nicht wirklich funktioniert, also haben wir uns die Übertragung am
I2C-Bus mal auf einem Oszi angesehen und erkannt dass da immer ein Stop
Signal gesendet wird.
Wenn wir mehr zeit gehabt hätten dann hätten wir uns mit der Hardware
natürlich mehr beschäftigt und mal nachgesehen ob da ein Fehler in der
Library ist oder eben alles selbst Programmiert.
Am Ende war das Programm nicht mal annähernd Resourcenschonend oder
optimal, denn die CooCox Library hatte einen Buffer für die I2C
Übertragung und danach haben wir ja noch den Buffer in dem SMP File,
aber für eine saubere Implementierung war eben nicht genug Zeit
Peter Dannegger schrieb:> Ich kann mich dunkel erinnern.> Bist Du es nicht gewesen, der sich standhaft geweigert hat, mit einem> I2C-EEPROM im Page Mode zu überprüfen, ob das Problem schon am Master> oder erst am Slave liegt?
Hab bis jetzt noch keinen I2C-EEPROM angesteuert also war ich das sicher
nicht ^^
Peter Kremsner schrieb:> Hab bis jetzt noch keinen I2C-EEPROM angesteuert
Eben.
Denn dann hätte man ja rausgekriegt, obs am Master liegt oder am Slave.
Peter Dannegger schrieb:> Eben.> Denn dann hätte man ja rausgekriegt, obs am Master liegt oder am Slave.
Das Problem war am Master, wir haben die Übertragungen am Oszi geprüft,
das Stopsignal wird eben vom Master gesendet und nicht vom Slave, zudem
hatten wir keinen EEPROM zur Verfügung.
Außerdem konnten wir uns sicher sein dass der Slave funktioniert, das
war nähmlich ein atmega der eine LED-Matrix angesteuert hat und der
hatte eine I2C Schnittstelle zur Verfügung und wurde davor schon mal
verwendet.
Ich hab hier im Forum auch noch nichts bezüglich I2C geschrieben glaub
ich ^^
Sorry für den Repost,
ist ja auch ziemlich egal was wir damals hätten machen können, feststeht
wir habens nicht gemacht.
Das Projekt war es einen einfachen Linear Positionierer zu steuern, wir
hatten dazu dc motoren für die x und y richtung und sensoren die durch
eine Analoge Spannung die Koordinaten in x und y Richtung bestimmen.
Als Controler haben wir den STM32 bekommen.
Der Positionierer hat bereits funktioniert und dann hat der Professor
gemeint wir sollen noch die LED-Matrix anhängen, als kleinen zusatz, die
soll nur Grobe Informationen über den Positionierer anzeigen, also ein
Warndreieck wenn er sich bewegt ein Rufzeichen wenn er an der
Enbegrenzung ist usw.
Die Led Matrix wurde bereits von einer anderen Gruppe mit einem anderen
Atmega8 angesteuert und hatte solche Zeichen schon vorprogrammiert
drinnen.
Die erwartete 0xFF als startzeichen, dann die Nummer des Zeichens und
die Position wo er es anzeigen soll.
Wir haben also das angeschlossen und versucht, hat aber nicht
funktioniert.
Nachdem wir den Sourcecode des LED-Matrix Moduls hatten, haben wir das
SMP an der LED Matrix und am STM32 implementiert und dann hats geklappt.
Aber eigentlich sollte der Thread doch um das Programm gehen falls es
jemand nutzen möchte und nicht warum wir es damals so gemacht haben und
nicht anders.
Hab deinen Code nur überflogen, aber was mir aufgefallen ist:
- auf manche Typedefs kannst Du verzichten und stdint.h einbinden
- bin mir nicht sicher, aber die Makros sind sollten eigentlich
überflüssig sein. Wenn die nur für die Buffers sind, dann schreibe halt
ein eigenes Modul dafür. Es gibt auch inline...
- Wieso zwei gleiche Buffers beschreiben mit unterschiedlichen Namen.
- die zweite Zeile ist doch Unsinn, oder nicht?
mar IO schrieb:> - die zweite Zeile ist doch Unsinn, oder nicht?
Jup isses.
ich hab mir den code selbst nochmal angesehen, ist ohnehin unsinn, ich
werds einfach verwerfen
Thread kann geschlossen werden
Peter Kremsner schrieb:> Ich hab hier im Forum auch noch nichts bezüglich I2C geschrieben glaub> ich ^^
Dann hat vielleicht der andere auch die selbe I2C-Lib benutzt, wie Du.
Das Problem kam mir jedenfalls bekannt vor.
Ich glaube aber nicht wirklich, daß ein so großer Patzer in einer Lib
unbemerkt bleibt.
Ich würde nochmal die Doku gründlich lesen, ob es andere Funktionen für
Blockmode gibt.
In C++ gibt es aber auch die Unsitte, Funktionen zu überlagern. D.h.
eine Funktion mit gleichem Namen macht was völlig verschiedenes in
Abhängigkeit von den Aufrufargumenten. Ich finde nicht, daß Überlagern
die Verständlichkeit von Code erhöht. Ich mag lieber die Unterscheidung
durch aussagekräftige Namen.
Die libs waren in c programmiert war vermutlich wirklich die
konfiguration. Aber das ist schon ein halbes jahr her und das projekt
sowieso abgeschlossn, hab auch keinen zugriff mehr darauf.
Bezüglich der überlagerung kann ich nur sagen dass ich die gut finde,
eine funktion zu schreiben die sich nach den eingabeparametern richtet
ist schon positiv natürlich sollte sie aber im endeffekt das selbe
machen