Forum: Mikrocontroller und Digitale Elektronik Arrays Vergleichen


von Phillip H. (philharmony)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von tubbu (Gast)


Lesenswert?

vergleiche doch einfach byteweise:

for(unsigned char i=0; i < 16; i++)
{
    if(data[i] != old_data[i])
    {
         send(data);
         break;
    }
}

von Patrick (Gast)


Lesenswert?

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

von Patrick (Gast)


Lesenswert?

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);

von Helmi (Gast)


Lesenswert?

if (!memcmp(data,olddata,16))
 {
    send(data);
    memcpy(olddata,data,16);
 }

Gruss Helmi

von Phillip H. (philharmony)


Lesenswert?

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

von Johannes M. (johnny-m)


Lesenswert?

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.

von Helmi (Gast)


Lesenswert?

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

von Phillip H. (philharmony)


Lesenswert?

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?

von Johannes M. (johnny-m)


Lesenswert?

memcpy wurde doch oben schon erwähnt...

(Helmis Posting von 11:08)

von Phillip H. (philharmony)


Lesenswert?

oh, oohps, nich gesehn...dankeschön

von Phillip H. (philharmony)


Lesenswert?

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«

von helmi (Gast)


Lesenswert?

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

von helmi (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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*

von Phillip H. (philharmony)


Lesenswert?

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...

von Phillip H. (philharmony)


Lesenswert?

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?

von Eddie Current (Gast)


Lesenswert?

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;

von Eddie Current (Gast)


Lesenswert?

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....

von Uhu U. (uhu)


Lesenswert?

> (((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.

von Phillip H. (philharmony)


Lesenswert?

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

von Eddie Current (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.