PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pinabfrage mehrerer Pins



masterx
07.03.2011, 18:33
Tag zusammen! Ich möchte PORTB 1 bis 4 abfragen?
Habe schon vieles probiert aber nichts hat wirklich funktioniert!

Hier mein letzter versuch:(Und wenn das denn mal geht.... giebt es eine kürzere Möglichkeit???)


int anzahl_Zyl(void) //fragt BP1-PB4 ab und giebt Einstellung Zylinderanzahl zurück
{

DDRB |= 0x00;
int a = 0;
//PORTB 765 4 321 0
if((PINB |= ~(1<<PINB1) && (PINB |= ~(1<<PINB2) && (PINB |= ~(1<<PINB3) && (PINB & (1<<PINB4))a =1; //000 1 000 0
if((PINB |= ~(1<<PINB1) && (PINB |= ~(1<<PINB2) && (PINB & (1<<PINB3) && (PINB |= ~(1<<PINB4))a =2; //000 0 100 0
if((PINB |= ~(1<<PINB1) && (PINB |= ~(1<<PINB2) && (PINB & (1<<PINB3) && (PINB & (1<<PINB4))a =3; //000 1 100 0
if((PINB |= ~(1<<PINB1) && (PINB & (1<<PINB2) && (PINB |= ~(1<<PINB3) && (PINB |= ~(1<<PINB4))a =4; //000 0 010 0
if((PINB |= ~(1<<PINB1) && (PINB & (1<<PINB2) && (PINB |= ~(1<<PINB3) && (PINB & (1<<PINB4))a =5; //000 1 001 0
if((PINB |= ~(1<<PINB1) && (PINB & (1<<PINB2) && (PINB & (1<<PINB3) && (PINB |= ~(1<<PINB4))a =6; //000 0 110 0
if((PINB |= ~(1<<PINB1) && (PINB & (1<<PINB2) && (PINB & (1<<PINB3) && (PINB & (1<<PINB4))a =7; //000 1 110 0
if((PINB & (1<<PINB1) && (PINB |= ~(1<<PINB2) && (PINB |= ~(1<<PINB3) && (PINB |= ~(1<<PINB4))a =8; //000 0 001 0
if((PINB & (1<<PINB1) && (PINB |= ~(1<<PINB2) && (PINB |= ~(1<<PINB3) && (PINB & (1<<PINB4))a =9; //000 1 101 0
if((PINB & (1<<PINB1) && (PINB |= ~(1<<PINB2) && (PINB & (1<<PINB3) && (PINB |= ~(1<<PINB4))a =10; //000 0 101 0
if((PINB & (1<<PINB1) && (PINB |= ~(1<<PINB2) && (PINB & (1<<PINB3) && (PINB & (1<<PINB4))a =11; //000 1 101 0
if((PINB & (1<<PINB1) && (PINB & (1<<PINB2) && (PINB |= ~(1<<PINB3) && (PINB |= ~(1<<PINB4))a =12; //000 0 011 0

return a;

}Und die einzelne Abfrage eines Pins auf logisch 0 habe ich bis jetzt auch nicht gefunden!

Grüße Stephan

Stone
07.03.2011, 20:56
Hallo Stephan,
für die Abfrage eins Pins ist das von dir verwendete Verfahren ok aber da du ja eine genau Vorstellung hast wie der ganze Port ausschauen muss würde ich anders vorgehen.

uint8_t Test=0, a=0;
while(1)
{
Test=PINB; // Das Register in einer Variable speichern
Test &=0b00011110; //unwichtige Bits ausmaskieren

switch(Test) //Switch case Abfrage
{
case 0b00010000: a=1;break;
case 0b00001000: a=2;break;
default: a=199;
}
}Habs grade im Simulator ausprobiert geht 1A

Gruß Matthias

masterx
07.03.2011, 21:27
Erstmal vielen Dank!
Werden durch das Maskieren die bits gesetzt?
Weil auf dem port noch die Abfrage eines Tasters zur Led Beleuchtung liegt und wenn das Bit gesetzt würde geht das LCD immer an und aus weil alles in einer Schleife läuft!

Grüße Stephan

Stone
07.03.2011, 21:52
Nein, du maskierst ja nur die Variable "Test".
Das eigentliche maskieren und Speicher wäre auch in einem Schritt möglich mit
Test= PINB & 0b0011110;
Zur Übersichtlichkeit habe ichs mal in zwei Zeilen geschrieben.

Gruß Matthias

masterx
07.03.2011, 22:02
Jetzt bin ich leider völlig durcheinander!
Was bedeutet den Maskieren??
Bewirkt es ,das nur PB1-PB4 abgefragt werden und dann in Test geschrieben werden???

Also ich stelle mit Jumpern die Zustände an den Pins ein und das Programm sol darauf reagieren....
Es währe sehr schlecht wenn ich bei oder vor der Abfrage Portpins ändere!!!

Tut mir leid ich bin nicht ganz so schnell von kp!!

Viele Grüße Stephan

Felix G
07.03.2011, 22:27
Also beginnen wir mal mit der Abfrage auf logisch 0...
die geht genauso wie die Abfrage auf logisch 1, nur mit einem ! davor

!(PINB & (1<<PINB1))Weiter geht's mit deinem Code, der in dieser Form nicht funktionieren kann (hauptsächlich wegen der fehlerhaften Abfrage auf logisch 0).
Außerdem passen die Kommentare nicht so ganz, daher habe ich versucht das nochmal etwas übersichtlicher darzustellen:


//PORTB 1234
// 0001
// 0010
// 0011
// 0100
// 0101
// 0110
// 0111
// 1000
// 1001
// 1010
// 1011
// 1100Dabei werden 2 Dinge offensichtlich:
1. Das wären die Zahlen von 1 bis 12 im Binärformat...
2. wenn die Bits nicht "rückwärts" angeordnet wären #-o

Kannst du das noch ändern, oder ist die Zuordnung so festgelegt?
Denn falls die Reihenfolge anders wäre, könnte man deine Funktion bis auf das hier reduzieren:


int anzahl_Zyl(void) //fragt BP1-PB4 ab und giebt Einstellung Zylinderanzahl zurück
{
DDRB |= 0x00;
return ((PINB & 0x1E) >> 1);
}

masterx
07.03.2011, 22:46
Habe gerade eine Antwort geschrieben ,aber das System hat mich raus gekickt!
Ich gebe an PB1- BP4 per Jumper einen Binären Wert von 1-12 vor(Anordnung PortB 01234567 auf der Platine), da ich das zählen von rechts nach links gewöhnt bin --->der gedrehte code !
Die Funktion muß diesen Binären Wert dann als Int-Wert zurückgeben!
Die anderen Port-Pins dürfen auf gar keinen Fall mit abgeprüft werden!!!Weil sie sich willkürlich ändern!

Grüße Stephan

Stone
07.03.2011, 22:51
Maskieren bedeutet das Anwenden eine Binären Operation auf ein Byte und einer Definierten Maske(Bitmuster) die nur die Relevanten Bit anzeigt und alle anderen auf 0 (oder 1 je nach Einsatzzweck) setzt.
http://de.wikipedia.org/wiki/Bitmaske


Gruß Matthias

masterx
07.03.2011, 23:11
@Matthias habe deinen Code mal probieert und er funktioniert, dafür erstmal vielen Dank!
@Felix ..habe noch mal den Code wie er funktioniert reingestellt... ich habe das mit dieser für mich tiefgreifenden Bitmanipulation auch wenn es nur ne Abfrage ist, echt noch nicht so gut raus!!! Aber ich arbeite dran! Versprochen.Mich würde noch mal interessieren was Deine Funktion genau macht???

Vielen Dank euch beiden Grüße Stephan

EDIT:


int anzahl_Zyl(void) //fragt BP1-PB4 ab und giebt Einstellung Zylinderanzahl zurück
{

DDRB |= 0x00; //0000 0000 -> 0 TIMER && Z-Interface ZYL 1 ; 1-4 BITs Portabfrage Anzahl Zylinder ,5 LCD on/off , 5-7 ISP
int a = 0;
int test ;


test=PINB; // Das Register in einer Variable speichern
test &=0b00011110; //unwichtige Bits ausmaskieren

switch(test) //Switch case Abfrage
{

case 0b00000010: a=1;break;

case 0b00000100: a=2;break;

case 0b00000110: a=3;break;

case 0b00001000: a=4;break;

case 0b00001010: a=5;break;

case 0b00001100: a=6;break;

case 0b00001110: a=7;break;

case 0b00010000: a=8;break;

case 0b00010010: a=9;break;

case 0b00010100: a=10;break;

case 0b00010110: a=11;break;

case 0b00011000: a=12;break;
}


return a;

}
@Felix : Ich habe es glaube ich verstanden!!?? Dein Code funktioniert auch, habe es gerade getestet!

Felix G
07.03.2011, 23:26
@Felix ..habe noch mal den Code wie er funktioniert reingestellt... ich habe das mit dieser für mich tiefgreifenden Bitmanipulation auch wenn es nur ne Abfrage ist, echt noch nicht so gut raus!!! Aber ich arbeite dran! Versprochen.Mich würde noch mal interessieren was Deine Funktion genau macht???Meine Funktion macht das gleiche, nur kürzer ;)

Ich versuche mal das genauer zu erklären...
Zuerst maskiere ich den Wert von PINB mit 0x1E, wodurch nur die interessanten Bits übrig bleiben

PINB & 0x1E0x1E ist die hexadezimale Schreibweise für 0b00011110, bis hierhin gibt es also noch keine Unterschiede.

Die Bits 1 bis 4 enthalten jetzt schon die gesuchte Zahl, nur leider um 1 nach links verschoben. Daher schiebe ich die Zahl mit >> 1 an die richtige Stelle.


edit:
ehrlicherweise muss ich zugeben, daß es einen kleinen Unterschied gibt: meine Funktion akzeptiert auch die Werte 13, 14 und 15.
Falls das ein Problem ist, müsste man sie also noch um ein if() erweitern

masterx
07.03.2011, 23:42
Das macht nichts denn ich gebe es ja per Jumper vor, kann also nichts schief gehen!Das mit dem verschieben habe ich immer überlesen weil ich es einfach nicht begriffen habe!Werde das wohl so lange durchkauen müssen bis ichs drin habe!
Ich begreife nur nicht wenn doch schon die gesuchte Zahl auf den Plätzen der Maskierten Einsen steht ,warum muß dann noch etwas verschoben werden??
Aber das verstehe ich sicher wenn ich das mit dem Verschieben drauf habe...

Vielen Dank nochmal an Euch für die Mühe, bis dahin viele Grüße Stephan

EDIT: oder besser warum die Zahl um 1 nach links verschoben ist....

Felix G
07.03.2011, 23:54
Aller Anfang ist schwer, aber keine Sorge das wird schon...

Das Verschieben ist notwendig, weil nach dem Maskieren zwar alle "unerwünschten" Bits auf 0 gesetzt sind, aber trotzdem ist das ganze für den µC immernoch eine komplette 8-Bit Zahl (Er kann ja nicht wissen, daß Bit 0 für dich uninteressant ist). Wenn man alle Bits um 1 nach rechts schiebt ist das kein Problem mehr, denn dann stimmt der Wert auch wenn man alle 8 Bit auswertet.

edit:
die Zahl ist um 1 nach links verschoben, weil sie nicht bei Bit 0 beginnt, sondern bei Bit 1

masterx
08.03.2011, 00:04
Ahhhh... also bestimmen die 1sen der Maske welche Bits sich ändern dürfen und weil ne00011110 als zahl in 8 Bit ja 1e ist wird nach dem verschieben dann eine ff daraus....

Der Groschen ist gefallen!

Felix G
08.03.2011, 07:40
also bestimmen die 1sen der Maske welche Bits sich ändern dürfenJa, denn alle Bits die in der Maske 0 sind, werden auch im Ergebnis immer 0 sein. Nur da wo die Maske 1 ist, steht im Ergebnis das entsprechende Bit aus dem maskierten Wert.