Moin, Ich möchte gerne laufend 128 Schalter über Schieberegister einlesen (refresh(data)), aber nur dann wenn sich der Wert zum vorherigen verändert hat über RS232 verschicken (send(data)). Dazu hatte ich die Idee: data_old=data; refresh(data); if (!(data_old==data)) send(data); Allerdings sind data, sowie data_old in der bisherigen idee char-arrays mit 16 chars. Wie kann ich die inhalte kopieren und dann miteinander vergleichen? Oder gibt es einen 128Bit datentyp? Gruß Phil
@ Phillip Hommel (Firma hs-bremen) (philharmony) >Allerdings sind data, sowie data_old in der bisherigen idee char-arrays >mit 16 chars. Womit du entweder per "Hand" in einer Schleife die Arraysvergleichen musst, oder auf strcmp() zurückgreifen musst. >Wie kann ich die inhalte kopieren und dann miteinander vergleichen? In einer Schleife. >Oder gibt es einen 128Bit datentyp? Nicht auf kleinen Mikrocontrollern. MFG Falk
vergleiche doch einfach byteweise: for(unsigned char i=0; i < 16; i++) { if(data[i] != old_data[i]) { send(data); break; } }
Zwei Arrays sind gleich, wenn jede einzelne Zelle gleich ist. Du könntest eine Schleife machen, die bei jedem Durchgang jede Zellen mit dem gleichen Index vergleicht. ungefähr so:
1 | int i; |
2 | int sendok; |
3 | for (i=0;i<data.length;i++){ |
4 | if (data_old[1]!= data[1]){ |
5 | int sendok = 0; |
6 | i=data.length;} |
7 | else sendok = 1;} |
8 | |
9 | if (sendok) |
10 | send(data); |
Oder so ähnlich
Sorry, natürlich so:
1 | unsigned char i; |
2 | unsigned char sendok; |
3 | for (i=0;i<data.length;i++){ |
4 | if (data_old[i]!= data[i]){ |
5 | sendok = 0; |
6 | i=data.length;} |
7 | else sendok = 1;} |
8 | |
9 | if (sendok) |
10 | send(data); |
if (!memcmp(data,olddata,16)) { send(data); memcpy(olddata,data,16); } Gruss Helmi
is memcmp ein sdandard-c ausdruck der muß ich das irgendwoher importieren? Klingt am einfachsten...Nur wie kann ich dem das gesamte array übergeben? Phil
Phillip Hommel wrote: > is memcmp ein sdandard-c ausdruck der muß ich das irgendwoher > importieren? memcmp, memcpy usw. sind Funktionen aus dem (Standard-Header) string.h.
memcpy und auch memcmp sind Teile der Standart C Bibilothek meistens sind sie in der "string.h" enthalten Du uebergibst nicht das Array sondern einen Pointer auf das Array. Die angabe von 16 in meinem Code heisst das die beiden Arrays 16Byte lang sind -> 128 Bit Daten. Du musst in deinem Programm das Header File string.h inkludieren. #include <string.h> Gruss Helmi
gut, werd ich mal versuchen... Gibt es für das Kopieren von Data nach Data_old auch so ne funktion, oder muß ich das per Schleife machen?
Hmm, gibt ein Problem:
1 | char Data_to_send[16], Data_to_send_old[16], Data_received_LED[16]; |
2 | ...
|
3 | if (!memcmp(Data_to_send,Data_to_send_old,16)) //Vergleichen, ob Änderung |
4 | {
|
5 | Send_To_PC(Data_to_send);//wenn ja, dann an PC senden |
6 | memcpy(Data_to_send_old, Data_to_send, 16);//als "gesendet" ablegen |
7 | }
|
Fehlermeldung: ../Overhead_Board.c:65: Fehler: in Konflikt stehende Typen für »memcpy«
Opps ich hatte einen kleinen Fehler in dem Programm nimm mal das '!' zeichen vor dem memcmp weg. memcpy b.z.w. memcmp funktioniert auf byte (char) ebene if (memcmp(data,olddata,16)) { send(data); memcpy(olddata,data,16); } gruss helmi
Caste die Varibeln mal mit (char*) da könnte deine Fehlermeldung herkommen if (memcmp((char*)data,(char*)olddata,16)) { send(data); memcpy((char*)olddata,(char*)data,16); } Gruss Helmi
helmi wrote: > Caste die Varibeln mal mit (char*) > > da könnte deine Fehlermeldung herkommen > > if (memcmp((char*)data,(char*)olddata,16)) > { > send(data); > memcpy((char*)olddata,(char*)data,16); > } > sollte aber keinen Unterschied machen, da char Data_to_send[16], Data_to_send_old[16], Data_received_LED[16]; und somit der cast implpizit vom Compiler gemacht wird. Wenn schon, dann würde ich mal in der string.h nachschauen wie auf dem System die Funktionen memcmp und memcpy deklariert sind Eventuell ist er in Wirklichkeit ja auf einem C++ Compiler. Dort sind die Argumente als const void* bzw void* deklariert und muss explizit nach void* casten if (memcmp((void*)data,(void*)olddata,16)) { send(data); memcpy((void*)olddata,(void*)data,16); } Wenn mans dann ganz exakt machen will, dann castet man beim memcmp in beiden Fällen nach const void* bzw. beim memcpy das 2. Argument nach const void*
lag an nem syntaxfehler weiter oben...die Fehlermeldungen von AVR-Studio führen manchmal echt in die Irre... Aber hat jemand ne Idee warum das hier nicht funktioniert?
1 | #define Pin_Input (PINC,PINC0) //PIN C0 ist der Input Pin für das Input-Schieberegister
|
2 | #define Input_Load_Shift 2 //PIN C2 als Load-Shift Wähler
|
3 | #define Input_Clock 1 //PIN C1 als Clock am Input Register
|
4 | |
5 | ...
|
6 | |
7 | while (a <16) |
8 | {
|
9 | while(i<8) |
10 | {
|
11 | PORTC |= (1<<Input_Clock); |
12 | _delay_us(10); |
13 | PORTC &= ~(1<<Input_Clock); //1 Clock, um das Register um eine Stelle zu schieben |
14 | Data_to_send[a] &= ~(1<<i); |
15 | Data_to_send[a] |= ((Pin_input)<<i); |
16 | i++; |
17 | }
|
18 | i=0; |
19 | a++; |
20 | }
|
Wenn ich das ganze Simuliere verändert sich der Wert in Data_to_send kein bisschen, egal was ich an PINC mache...
Grmpf Wenn ich anstatt Pin_Input (steht ja für PINC, PINC0) PINC&0x01 einsetze dann gehts. Gibt mir denn die PINC,PINC0-Abfrage keinen Wert zurück?
Naja, mit ((Pin_input)<<i) findet ja auch kein Portzugriff statt. Es wird vom Preprozessor erweitert zu (((PINC,PINC0))<<i) Der C-Compiler nimmt dann PINC als Ergebnis dieses Ausdrucks und schiebt den entsprechend. Schreib doch einfach mal: if ((PINC & (1<<PINC0)) != 0) Data_to_send[a] |= 1<<i; Wenn es aber wirklich Bit 0 von PORTC ist, hast Du Glück und könntest einfacher schreiben: Data_to_send[a] |= (PINC & 1)<<i;
Du hast Dir etwas ausgedacht, was der Compiler übersetzt, aber nicht das macht, was Du willst :-) Du wolltest eine Abfrage, die Dir 1 liefert, wenn Dein Bit auf 1 ist, ansonsten auf 0. Das geht so aber nicht. Dein #define müßte lauten: #define Pin_Input ((PINC & (1<<PINC0)) != 0 ? 1 : 0) Reichlich unübersichtlich....
> (((PINC,PINC0))<<i) > > Der C-Compiler nimmt dann PINC als Ergebnis dieses Ausdrucks und > schiebt den entsprechend. (PINC,PINC0) ist eine comma expression; Resultat ist der letzte Operand.
Puuh, ich glaub ich muß dringend meine C-Kenntnisse erweitern. Danke für die Tips. Da ich die selbe Abfrage eventuell später noch mit anderen Pins als dem 0-ten machen möchte, werde ich Eddie´s Vorschlag mal versuchen. Vielen Dank
Ja, probier's mal. Deine Code läßt sich übrigens perfekt mit for-Schleifen realisieren: unsigned char a,i; for (a=0; a<16; a++) { Data_to_send[a] = 0; // Annahme: Alles ist 0 for (i=0; i<8; i++) { PORTC |= (1<<Input_Clock); _delay_us(10); PORTC &= ~(1<<Input_Clock); Data_to_send[a] >>= 1; // Platz schaffen für's nächste Bit if (PINC & (1<<PINC0)) Data_to_send[a] |= 0x80; // Ggf. Bit setzen } } Der Typ von Data_to_send muss ein unsigned char sein (nicht signed), da sonst beim Rechtsschieben das Vorzeichen erweitert wird. Das gibt schönen Datenmüll. Dein Eingang darf nun auch wieder auf einem beliebigen Bit vom Port liegen. Eine fiese Version einer for-Schleife wäre noch: unsigned char a,i; for (a=0; a<16; a++) { Data_to_send[a] = 0; // Annahme: Alles ist 0 for (i = 1; i; i <<= 1) // Wir schicken ein Bit durch ein Byte, // bis es hinten heraus fällt { PORTC |= (1<<Input_Clock); _delay_us(10); PORTC &= ~(1<<Input_Clock); if (PINC & (1<<PINC0)) Data_to_send[a] |= i; // Ggf. Bit setzen } } So etwas läßt sich gerade für so eine Anwendung wie Deine sehr oft gebrauchen.
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.