PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Einganssignale am Port Einer Variablen Bitweise zuordnen



paulspiegel
24.12.2006, 20:27
Hallo die Herren,

ich habe ein Problem mit Bitmanipulation und kann mir einfach nicht erklären wo der Fehler ist. Kann mir eventuell jemand weiter helfen?
Ich habe 12 Platinen die alle gleich sind. Auf jeder Platine ist ein Atmega 8 und 8 Ausgangsrelais. Das Eingangssignal liegt an allen 12 Platinen gleichzeitig auf 8 PINS an. Anhand einer HEX Codierung kann ich auswerten für welche Platine welcher Befehl ist. Mit PINC5 werden dann die Daten übernommen und die jeweiligen Relaisausgänge angesteuert.
Auf allen 12 Atmegas soll das gleiche Programm sein. Die Auswahl welche auf welcher Platine welches Unterprogramm mit entprechendem HEX Code läuft wird über einen DIP-Schlater auf der Platine ausgewählt. PINC0 – PINC3 frei Codierbar 4 DIP-Schalter (Platine 1-12).
Wenn einer dieser DIP-Schalter betätigt ist liegen an den Eingangspins 5 V an. Je nach dem wie die PINS Spannung haben habe ich 16 verschiedene Codiermöglichkeiten. Je nach Codierung möchte ich den Zustand der 4 Eingänge abfragen und in ein Byte von Bit 0 Bit 3 schreiben, der Rest des Byte´s soll Null sein (Funktion Platinenerkennung Byte auswahl).
Das jetzt beschriebene Byte soll dann mit Hilfe von switch Case den entsprechenden Wert zurück geben (müsste auch ohne die Switch case nur mit return auswahl funktionieren).

Anhand des Rückgabewertes, wird dann über switch case die Funktion Platine aufgerufen.
Im Programm Platine in der das eigentliche Eingangsdatenübernahmeprogramm läuft.

Mein Gedanke war, dass dies gleich wie bei den Ports funktionieren müsste, aber irgendwie übernimmt er die Bits bei den Bitmanipulationen nicht richtig. Ich hab´s schon mit Bitabfrage direkt und über if Schleife probiert, aber beides geht nicht.

Ich denke beim Einlesen der Signale in die Variable auswahl und Eingang (Hier werden die Anleigenden Einganssignale eingelesen) mache ich beidesmal den gleichen Fehler, was auch immer der Fehler ist. Beim Simulieren überspringt die Simualtion auch jedes Mal Befehlszeilen in den beiden Einlesefunktionen. Muss ich eigentlich auch die Bits in der Variable wieder zurücksetzen wie bei den Ausgängen, bevor mein nächstes Eingangssignal kommt und korrekt eingelesen werden kann?

Kann mir bitte jemand weiterhelfen und sagen was ich falsch mache? Wäre sehr nett

Hubert.G
24.12.2006, 22:14
Hast du bei den Dip-Schalter Pull-Down-Widerstände?

SprinterSB
25.12.2006, 09:05
Versuch mal

// Funktionen
unsigned int Platinenerkennung (void)
{
unsigned int auswahl=0x00; //Byte auswahl deklarieren und auf Null setzen

// Übernahme an 3. Stelle von Byte auswahl des Signalzustands an PINC3
if (PINC & (1 << PINC3)) auswahl |= (1 << 3);
// Übernahme an 2. Stelle von Byte auswahl des Signalzustands an PINC2
if (PINC & (1 << PINC2)) auswahl |= (1 << 2);
// Übernahme an 1. Stelle von Byte auswahl des Signalzustands an PINC1
if (PINC & (1 << PIN33)) auswahl |= (1 << 1);
// Übernahme an 0. Stelle von Byte auswahl des Signalzustands an PINC0
if (PINC & (1 << PI4C3)) auswahl |= (1 << 0);

switch (auswahl)
{
case 0x01: return 1; break; // Rückgabe Platinennummer 1
case 0x02: return 2; break; // Rückgabe Platinennummer 2
case 0x03: return 3; break; // Rückgabe Platinennummer 3
case 0x04: return 4; break; // Rückgabe Platinennummer 4
case 0x05: return 5; break; // Rückgabe Platinennummer 5
case 0x06: return 6; break; // Rückgabe Platinennummer 6
case 0x07: return 7; break; // Rückgabe Platinennummer 7
case 0x08: return 8; break; // Rückgabe Platinennummer 8
case 0x09: return 9; break; // Rückgabe Platinennummer 9
case 0x0A: return 10; break; // Rückgabe Platinennummer 10
case 0x0B: return 11; break; // Rückgabe Platinennummer 11
case 0x0C: return 12; break; // Rückgabe Platinennummer 12
default : return 13; break; // Rückgabe 13 wenn Zahl 0 oder höher als 12
}
}

Analog für Eingangsbyteeinlesen. PIN33 und PI4C3 sind Tippfehler?

paulspiegel
25.12.2006, 14:00
Hallo Hubert G,

ich habe an den DIP Schaltern keine Widerstände. Die 5 V Eingansspannung geht direkt über die DIP Schalter auf die 4 Eingangspins des Atmega8. Jedoch hat der Atmega8 nach meinen Infos automatisch seine integrierten PULL Down Widerstände aktiv, wenn ich den Pull UP Widerstand nicht Softwaremäßig aktiviere.

paulspiegel
25.12.2006, 14:27
Hallo Gerog-Johann,

ich habs versucht, jedoch funktionierts bei der Simulation irgendwie nicht. Bei der Abfrage der Platinenerkennung springt er jetzt wenigstens in jede der 4 if Abfragen. Wenn es dann an das Eingansbyte geht, überspringt er mir die erste if Abfrage: if (PINC&(1<<PINC4)) Eingang |= ( 1 << 6); // 6. Stelle von Byte auswahl auf PINC4
und fängt sofort bei der zweiten an.
Ich hänge nochmal das ganze Programm als Attachment dran.

paulspiegel
25.12.2006, 14:32
Attachment hat irgendwie nich geklappt. Bin zum ersten mal hier im Forum. Probiers nochmal.

SprinterSB
25.12.2006, 15:23
Mit |= werden die Bits nur gelöscht, du musst sie vorher auf 0 setzen (anfangs Eingabe=0 oder so).

Hubert.G
25.12.2006, 16:36
Also das mit den automatischen Pull-Down musst du mir mal in der Doku zeigen(Datenblatt Seite 49), ich habe das noch nicht gelesen. Die Eingänge sind hochohmig und floaten wenn kein externer Pegel anliegt oder der interne Pull-Up eingeschaltet ist.

Hubert

linux_80
25.12.2006, 16:37
Hoppala,
was muss ich da lesen, mit |= werden normalerweise die entsprechenden Bits gesetzt !

@paulspiegel
der AVR hat keinen Pulldown, dH. wenn der Pullup nicht gesetzt ist hängt das Signal in der Luft, und es gibt evtl. Zufallswerte an den Eingängen.
Eine mögliche Lösung wäre, die Pullups zu aktivieren, und dann nach den DIP-Schaltern die Leitung auf Masse zu legen, dann brauchts keine externen Widerstände !

Du stellst deine Werte aber auch etwas kompliziert zusammen, wenn die Eingänge so schön beieinander liegen könnte man das auch zB. so machen:


unsigned int Platinenerkennung (void)
{
unsigned int auswahl = 0x00;
auswahl = PINC & 0x0F; // die unteren 4 Bits einlesen
if ((auswahl == 0) || (auswahl > 12)) {
auswahl = 13;
}
return auswahl;
}


Evtl. wäre es noch praktisch, nicht einen Integer zu verwenden sondern nur ein Byte bzw. char, denn ein Port kann sowieso nur ein Byte gross werden !
also unsigned char auswahl ...

paulspiegel
25.12.2006, 21:45
Hallo,

vielen Dank an alle, ihr habt mir sehr weitergeholfen. Mein Fehler lag darin, dass ich die Variable nicht mehr auf Null gesetzt habe. Der nächste Fehler war, dass ich wenn ich den PORT gesetzt habe z.B. PORTD |= Eingang geschrieben habe. Ich muss jedoch PORTD = Eingang schreiben. Dadurch hat das ganze nur im ersten Durchgang funktioniert. Der Tipp von Linux_80 ist auch super. Das Problem ist, ich schreibe das erste mal ein Programm auf einem Atmega 8 und bin eigentlich den Infinieon C167 gewohnt. Da kann man Prima alles mit Variablen machen und brauch keine komplizierten Bitbefehle schreiben und beachten.

Also nochmals vielen Dank.

SprinterSB
26.12.2006, 10:57
Hoppala,
was muss ich da lesen, mit |= werden normalerweise die entsprechenden Bits gesetzt !

:oops: Danke für die Richtigstellung!