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?
Mir fällt bei den Quellen auf: - inkonsistente Schreibweisen des API - Rechtschreibfehler - label/goto statt while-Schleife
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 | typedef struct __SMP_BUF_T { |
2 | unsigned char data[SMP_BUF_SIZE]; |
3 | unsigned int wrIdx; |
4 | unsigned int rdIdx; |
5 | } SMP_BUF_T; |
6 | |
7 | //SMP input buffer
|
8 | typedef struct __SMP_TBUF_T{ |
9 | unsigned char data[BUFFER_SIZE]; |
10 | unsigned int wrIdx; |
11 | unsigned int rdIdx; |
12 | } SMP_TBUF_T; |
13 | |
14 | static volatile SMP_BUF_T SMP_OutBuf; |
15 | static volatile SMP_TBUF_T SMP_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.
1 | int smp_send(byte *buffer,int length) |
2 | {
|
3 | byte message[BUFFER_SIZE]; |
4 | int i, offset = 0; |
5 | int d; |
6 | unsigned short crc = 0; |
7 | |
8 | if(length > MAX_PAYLOAD) |
9 | return 0; |
10 | |
11 | if((length + 4) > BUF_FREE_SPACE(SMP_InBuf)) |
12 | |
13 | ....
|
und
1 | #define BUF_COUNT(cdcBuf) (SMP_BUF_MASK & (cdcBuf.wrIdx - cdcBuf.rdIdx))
|
2 | ....
|
3 | #define BUF_FREE_SPACE(cdcBuf) (SMP_BUF_SIZE - BUF_COUNT(cdcBuf))
|
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.
:
Bearbeitet durch User
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
"Timo danaos et dona ferrentes." :-) OK. Ich baue hier im Forum manchmal auch ganz schönen Mist. Aber machen wir doch einen Review-Thread daraus.
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.
:
Bearbeitet durch User
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?
1 | bytesToRead = length; |
2 | bytesToRead = (bytesToRead < (length)) ? bytesToRead : (length); |
3 | // = (length < length ) ? length : length ; |
- Bei deiner Beschreibung: Hast Du eigentlich etwas gegen einen Punkt bei Satzende. - ...
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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.