Hab wieder mal ein Problem:
Es geht um eine CRC Berechnung.
Über die suche habe ich schon eine passende Funktion gefunden:
Beitrag "CRC Berechnung"
Jetzt wollte ich von einem String den CRC berechnen:
020600000001 CRC: 4839
Dazu habe ich die Routine kopiert und will sie nun folgendermaßen
aufrufen:
1
charbuffer[6];
2
intnum;
3
inttemp,temp2;
4
5
buffer[0]=0x02;
6
buffer[1]=0x06;
7
buffer[2]=0x00;
8
buffer[3]=0x00;
9
buffer[4]=0x00;
10
buffer[5]=0x01;
11
num=checkSum(buffer,6);
12
13
temp=(uint8_t)num;//(Lowbyte. uint8_t oder char typcasten)
14
temp=(uint8_t)(num>>8);// Highbyte
15
uart_puts();
Leider sendet die Schnittstelle gleich 16 Zeichen statt nur die zwei CRC
Werte. Muss ich noch eine typumwandlung vornehmen? Oder wo liegt der
Fehler?
Chris tian schrieb:> Leider sendet die Schnittstelle gleich 16 Zeichen statt nur die zwei CRC> Werte. Muss ich noch eine typumwandlung vornehmen? Oder wo liegt der> Fehler?
du sendest doch überhaupt nichts?
> uart_puts();
zeig mal etwas mehr code.
temp = (uint8_t) num; //(Lowbyte. uint8_t oder char typcasten)
temp = (uint8_t) (num>>8); // Highbyte
ist genauso unsinn, der 2. Anweisung überschreibt die 1.
Dann gibt es die CRC funktion schon in der AVR Lib, die muss man nicht
kopieren.
Chris tian schrieb:> ok das wusste ich nicht. In welcher lib muss ich denn sucehn und wie
schau einfach mal ein den include verzeichniss vom AVR nach, dort liegt
eine crc header dateien rum.
> heißt die funktion?
keine ahung, steht in der header datei
> Es muss CRC (Modbus) sein. wie man hier berechnen kann:
auch keine Ahnung ob sie gleich sein.
Aber das ändert nichts an den Fehlern in deinem Programm, das senden ist
falsch.
Deine Verwendung von
int16_
macht mich nervös.
Wenn du auf Byte-Ebene arbeitest, dann ist der Datentyp der Wahl
praktisch IMMER ein unsigned Wert. Alle 8 Bit sind gleichberechtigt - es
gibt keine Sonderfälle, weil eines der Bits die Sonderrolle eines
Vorzeichenbits hat und anders behandelt werden muss.
uint8_t bzw. uint16_t
Was denkst du, was wohl
crc = crc >> 1;
ergibt, wenn crc den Wert 0xFFFF hat und vom Datentyp int16_t ist? Gut,
um fair zu sein: Das Ergebnis davon ist laut C-Standard undefiniert,
aber auf allen Implementierungen, die 2-er Komplement-Arithmetik
benutzen kommt immer dasselbe raus. Nämlich 0xFFFF. Wodurch sich
automatisch die Frage ergibt: wozu dann überhaupt schieben, wenn das
Ergebnis sowieso wieder identisch zum Ausgangspunkt ist?
Der, von dem du die Funktion abgeschrieben hast, war genauso auf einem
Auge blind und hat sein Heil in der Verwendung eines int32_t(!) gesucht,
anstatt den Stier bei den Hörnern zu packen und sich darüber klar zu
werden, dass Datentypen nicht einfach nur eine 'Verzierung' des Codes
bedeuten sondern dass da etwas dahinter steckt.
Und gewöhn dir sowas
char buffer[6];
..
buffer[0]= 0x02;
buffer[1]= 0x06;
buffer[2]= 0x00;
buffer[3]= 0x00;
buffer[4]= 0x00;
buffer[5]= 0x01;
ab!
char verwendest du, wenn du es mit Strings, also mit Texten, zu tun
hast! Und zu sonst nichts anderem.
Für Byte benutzt du immer und ausschliesslich uint8_t und nichts
anderes. Selbst dann, wenn du von irgendwo Code bekommst, bei dem ein
char als Ersatz für 'Byte' benutzt wird. Dann siehst du den Code durch,
ob es irgendwo ein Anzeichen gibt, ob hier ein char als 'signed'
aufgefasst wird und wenn nicht, dann änderst du das um auf uint8_t.
Am besten du machst es dir zur Regel, dass du 3 'kleine' Datentypen
hast.
int8_t für kleine Zahlen, die ein Vorzeichen brauchen
uint8_t für kleine Zahlen, die kein Vorzeichen haben.
Das ist genau das, was weithin als Byte bekannt ist
char Für Zeichen bzw. Texte.
Benutze die Datentypen sinngemäss nach diesem einfachen Schema und du
hast weniger Probleme.
Danke für deine Hinweise, ich werde versuchen mich daran zu halten.
>>char buffer[6];
hatte ich in späteren posts schon abgeändert.
ICh muss ja auch zugeben das ich keine ahnung von der CRC Berechnung
habe.
Aber eshalb habe ich mir auch vermeintlich lauffähige Funktionen
gesucht, welche ich übernehmen knn und das Rasd nicht nochmal neu
erfinden.
Da ich dachte das die Funktion läuft wie im anderen Threat beschrieben,
habe ich einfach diese genommen.
Da sie aber niciht das macht was sie soll hab ich eben hier gefragt, wo
der Fehler liegt. Da jemand der jeden Tag mit sowas zu tun hat bestimmt
mehr Ahnung hat.
Ich bin den Anweisungen gefolgt aber es kommt immernoch ein falscher
Wert raus.
Kann mir jetzt nochmal jemand helfen das Teil zum laufen zu bringen?
Chris tian schrieb:> Jetzt gibt er mir auch nur noch 2 Zeichen aus., Allerdings sidn das noch> nicht die richtigen
Er macht genau das, was du programmiert hast. putc(c) erwartet als
Parameter ein druckbares Zeichen. Du übergibst aber eine 8-Bit Zahl.
Also entweder die 8 Bit in zwei HEX Werte wandeln oder per itoa() in
einen String wandeln und dann ausgeben.
Georg G. schrieb:> Er macht genau das, was du programmiert hast. putc(c) erwartet als> Parameter ein druckbares Zeichen. Du übergibst aber eine 8-Bit Zahl.> Also entweder die 8 Bit in zwei HEX Werte wandeln oder per itoa() in> einen String wandeln und dann ausgeben.
er will (vermutlich) es aber als binary übertragen und nicht als Text.
Das Problem wird wohl die CRC selber und nicht mehr die übertragung
sein.
Peter II schrieb:> Peter II schrieb:>> erwartet als>>> Parameter ein druckbares Zeichen>> das stimm auch nicht. Er erwartet 8bit und diese werden übertragen.
"putc" steht mit Sicherheit für "put char". Und char bedeutet dabei
Zeichen, wie Karl Heinz dargestellt hat.
Simon K. schrieb:> "putc" steht mit Sicherheit für "put char". Und char bedeutet dabei> Zeichen, wie Karl Heinz dargestellt hat.
es geht aber um die übertragung auf UART und diese kennt keine zeichen.
Hier gibt es um 8bit. Es macht wenig sinn noch eine Extra funktion für
unsigned char zu schreiben. Aus dem Grund kann man hier damit leben das
man der funktion einfach einen uint8 geben kann.
Simon K. schrieb:> Peter II schrieb:>> Peter II schrieb:>>> erwartet als>>>> Parameter ein druckbares Zeichen>>>> das stimm auch nicht. Er erwartet 8bit und diese werden übertragen.>> "putc" steht mit Sicherheit für "put char". Und char bedeutet dabei> Zeichen, wie Karl Heinz dargestellt hat.
Yep.
Wobei ich das historisch sehen würde. Die Funktion ja schon zu Zeiten
Kernighan&Ritchies putc geheissen.
> Es macht wenig sinn noch eine Extra funktion für unsigned char zu> schreiben.
Aber auch nur, weil wir wissen, dass dieses putc zb nach einem CR kein
LF nachschieben wird und zb XON/XOFF nicht ausfiltert.
Ich kann nur jedem raten: Nehmt die Unterscheidung Zeichen-Byte ernst!
Und nur weil man bisher mit ignorieren durchgekommen ist, bedeutet das
nicht, dass das immer so sein wird.
Nun mach doch mal einen ganz simplen Test: Ersetze alle int16_t durch
uint16_t, kompiliere und lass laufen. Und dann freu dich.
(zumindest mein Standard-C Compiler, Borland Museum, gibt dir dann den
gesuchten CRC)
Chris tian schrieb:> Es muss CRC (Modbus) sein. wie man hier berechnen kann:
LOL, über 20 Beiträge, was in einem beantwortet werden kann:
http://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf
Schau dir die Seiten 42 und 43 an, da wird dir eine CRC16 Berechnung auf
Array-Ebene vorgekaut. nur geringfügig anpassen und fertig ist das ganze
Hier sonst noch meine Version (Läuft auf einem STM32 einwandfrei, und
ist auch mit diversen Modbus-Test-Programmen überprüft worden)
Peter II schrieb:> Simon K. schrieb:>> "putc" steht mit Sicherheit für "put char". Und char bedeutet dabei>> Zeichen, wie Karl Heinz dargestellt hat.>> es geht aber um die übertragung auf UART und diese kennt keine zeichen.> Hier gibt es um 8bit. Es macht wenig sinn noch eine Extra funktion für> unsigned char zu schreiben. Aus dem Grund kann man hier damit leben das> man der funktion einfach einen uint8 geben kann.
Du weißt aber doch gar nicht, was putc macht? Vielleicht wandelt es
Zeichen von lowercase nach uppercase oder ähnliches.
Man macht genau das mit der Funktion, wofür sie gedacht ist. Binärbytes
übertragen mit dieser Funktion ist das nunmal nicht.
Chris tian schrieb:> Hier gerade mit der Prüfsumme aus 0202. Funzt prima!
Und nix gelernt aus dem was hier geschrieben wurde. Prima!
EDIT: Karl Heinz Beispiel bzgl. putc mit XON/XOFF ist sogar noch besser
als meines.
Simon K. schrieb:> Man macht genau das mit der Funktion, wofür sie gedacht ist. Binärbytes> übertragen mit dieser Funktion ist das nunmal nicht.
dann bau doch die Lib um wenn du willst. Ich weiss das sie auch
Binärbytes sauber überträgt und verwende sie einfach.
Peter II schrieb:> Simon K. schrieb:>> Man macht genau das mit der Funktion, wofür sie gedacht ist. Binärbytes>> übertragen mit dieser Funktion ist das nunmal nicht.>> dann bau doch die Lib um wenn du willst. Ich weiss das sie auch> Binärbytes sauber überträgt und verwende sie einfach.
Tu das. Nur wunder dich nicht, wenn man über dich flucht, wenn dein
Programm an jemand mit mehr Anspruch an Struktur und Ordnung gerät.
Stichwort defensives Programmieren. Das sollte so mancher mal hier
nachschlagen.