Forum: Mikrocontroller und Digitale Elektronik Zustand der Eingang-PINs


von Andreas (Gast)


Lesenswert?

Hallo,
ich möchte gerne den Zustand bestimmter PINs meines µControllers 
(ATmega8) abfragen. Die Eingänge sind Hardwareseitig durch Pull-Up 
Widerstände auf Vcc gezogen. Also ich möchte gerne wissen wann ein 0 an 
den jeweiligen PINs anliegt!

kann ich das so machen?
1
if (PORTB & (1<<PB0) & (1<<PB1) & (1<<PB2))            
2
Zahl = 0;  
3
4
if (PORTB & (1<<PB0) & (1<<PB1) & (0<<PB2))
5
Zahl = 1;
6
7
if (PORTB & (1<<PB0) & (0<<PB1) & (1<<PB2))
8
Zahl = 2;
9
10
etc...

von Thomas E. (thomase)


Lesenswert?

Andreas schrieb:
> kann ich das so machen?
Nein. Erstmal nicht PORTB sondern PINB. Und wenn ich das richtig 
verstehe, willst du die Zahl vom Port einlesen. Mit deiner Methode 
fragst du aber genau 2 Zustände ab: true oder false.

Dadurch daß die Ports nebeneinander liegen kannst du das ganz einfach 
machen:
zahl = PINB & 0x07;

Wäre das jetzt nicht so, müsstest du noch ein bischen Bitgefriggel 
veranstalten.

mfg.

von Andreas (Gast)


Lesenswert?

> Andreas schrieb:

> Nein. Erstmal nicht PORTB sondern PINB.

Also so:
1
if (PINB & (1<<PB0) & (1<<PB1) & (1<<PB2))            
2
Zahl = 0;

Das Problem ist folgendes: Ich möchte aus 4 nebeneinander stehenden PINs 
eines PORTes mittels BCD-Codierung einen Zahl zwischen 0 und 9 
generieren!

Bin für jede Hilfe Dankbar!

von MagIO (Gast)


Lesenswert?

PINB gibt dir den Zustand des kompletten Ports, also 8 bit.

PINB & (1<<PB0 | 1<<PB1 | 1<<PB2 | 1<<PB3) erzeugt eine Maske (die 
oder-Verknüpfungen). Wenn man nun PINB mit dieser Maske und-Verknüpft, 
dann bleiben nur noch die bits übrig, die den 4 Pins entsprechen. Alle 
anderen bits sind garantiert auf 0.

Nun musst Du nur noch bitweise negieren, da ja deine Eingänge Low-Aktiv 
sind. D.H. aus 0000 wird 1111 = 0, 1110 wird 0001 = 1 .... Mit anderen 
Worten diese 4 bit entsprechen genau dem Wert, den du umständlich mit 
if-Anweisungen ermitteln wolltest.
Zahl = ~PINB & (1<<PB0 | 1<<PB1 | 1<<PB2 | 1<<PB3)

Jetzt hast Du als Ergebnis direkt die Zahl zwischen 0 und 15. Wenn Du 
nur 0-9 brauchst, dann musst Du Dir halt weiter überlegen:
* kann ein solcher Wert überhaupt anliegen? 0101 - 0000
* wenn ja, was soll dann passieren? Fehlerbehandlung?

von Chris H. (hergi)


Lesenswert?

Dann lies doch vielleicht erst die binäre Darstellung so ein:
1
zahlBinaer = PINB & 0x0F;

und berechne dann die BCD Darstellung daraus.


Und übrigens, das (0<<PB2) bringt garnix, solltest vielleicht nochmal 
ins Tutorial gucken.

von Thomas E. (thomase)


Lesenswert?

Andreas schrieb:
> if (PINB & (1<<PB0) & (1<<PB1) & (1<<PB2))
> Zahl = 0;
Nein, so wird das nichts. So wird zahl auf 0 gesetzt, wenn alle Pins 
high sind. Ist irgendeiner low, passiert gar nichts.
Wenn du 4 Pins hast und Zahlen von 0 bis 9 erhalten willst, ist das egal 
ob BCD oder binär. BCD wird erst bei mehreren Stellen interessant. 
Allerdings kannst du mit 4 Bit von 0 bis 15 zählen. Bei >9 brauchst du 2 
BCD-Stellen.

zahl = PINB & 0x0F;

char bcd0, bcd1;
bcd0 = zahl % 10;
bcd1 = zahl / 10;

mfg.

von MagIO (Gast)


Lesenswert?

Richtiger ist natürlich :o)
D.H. aus 1111 wird 0000 = 0, 1110 wird 0001 = 1 ....

Was legt denn diese BCD-Zahl an dem Port an?
Ein Logik-Gatter mit BCD-Ausgang? Ein BCD Encoder?

BCD bedeutet 4 bit ergeben eine Ziffer. Wieviele Ziffern? Wenn die 
oberen 4 bit des Ports die Zehner-Stelle einer BCD enthalten, dann geht 
man genauso vor, wie bei der Einer-Stelle, muss nur das Ergebnis nochmal 
schieben und multiplizieren:

Zahl = ~PINB & (1<<PB0 | 1<<PB1 | 1<<PB2 | 1<<PB3)
oder
Zahl = ~PINB & 0x0f
das ist das selbe!

Zahl += (~PINB & 0xf0)>>4 * 10

~PINB & 0xf0 maskiert die bits aus, die für die zehner-stelle gebraucht 
werden.
>>4 schiebt diese 4 bits dann in den Bereich, wo sie den Wert 0-15 haben
*10 macht dann aus den Werten 0-9 eine 0-90 - eben eine Zehner-Stelle.

War mir nur so in den Kopf gekommen ... vielleicht interessiert es ja 
jemanden ;o)

von Andreas (Gast)


Lesenswert?

MagIO schrieb:
> Was legt denn diese BCD-Zahl an dem Port an?
> Ein Logik-Gatter mit BCD-Ausgang? Ein BCD Encoder?

Also ich habe 3 BCD-Kodierschaltern mit denen ich den Zahlenbereich 0 - 
512 abdecken soll!
1. BCD-Kodierschalter >> Einer Stelle
2. BCD-Kodierschalter >> Zehner Stelle
3. BCD-Kodierschalter >> Hunderter Stelle

Zur Verfügung stehen folgende Ports:
PORT-D >> 3 bis 7
PORT-B >> 0 bis 5

Das reicht gerade so, weil ich
4 Pins für BCD-Kodierschalter 1 brauche (Zahlenbereich 0 - 9)
4 Pins für BCD-Kodierschalter 2 brauche (Zahlenbereich 0 - 9)
3 Pins für BCD-Kodierschalter 3 brauche (Zahlenbereich 0 - 5)

Aus der 3 Schaltern muss eine Ziffer zustande kommen. Am besten ein 
Ziffer der Datentyp Integer.

MagIO schrieb:
> Zahl += (~PINB & 0xf0)>>4 * 10

Was sagt mit das += ?

vielen vielen Dank für euer Hilfe :)

von MagIO (Gast)


Lesenswert?

Na im ersten Statement wurde die Einerstelle 'berechnet' und mit = der 
Variablen Zahl zugewiesen. Die Zeile mit += addiert dann die 
Zehnerstelle dazu.

Musst halt in Deinem Falle die Einer-Stelle auf PORTB Pins 0-3 legen,
die Zehner-Stelle auf PORTD Pins 4-7 legen und die Zeile entsprechend 
ändern in:
Zahl += (~PIND & 0xf0)>>4 * 10

Und dann brauchst Du noch ne weitere Zeile für die 100er Stelle.
Aber die bekommst Du ja sicher selbst hin. Das Muster ist das gleiche:
invertieren, maskieren, bits hinschieben, wo sie hin müssen und 
malnehmen mit der Wertigkeit der entsprechenden Stelle.

Wobei es bei der 3. Stelle schon Sinn macht, den Wert erst mal zu 
überprüfen, sonst kann man hier durchaus auch ne 7 eingeben.

von Karl H. (kbuchegg)


Lesenswert?

Andreas schrieb:

> MagIO schrieb:
>> Zahl += (~PINB & 0xf0)>>4 * 10
>
> Was sagt mit das += ?

Vor allen Dingen sagt es uns, dass du ein C-Buch brauchst!


  a += b;

ist dasselbe wie

  a = a + ( b );

von MagIO (Gast)


Lesenswert?

@Karl Heinz Buchegger:

"Vor allen Dingen sagt es uns, dass du ein C-Buch brauchst!"
Wieso müssen diese Seitenhiebe immer sein? Der Rest in dem Post hätte es 
auch getan!

von Karl H. (kbuchegg)


Lesenswert?

@MagIO

Antworte du so wie du das für richtig hältst und ich mach meine Linie 
weiter. OK?

Hast du das Problem mit Jan schon gelöst?
So wie ich das sehe und verfolgt habe: eher nicht.
Und das liegt nicht daran, dass es unmöglich zu lösen ist, sondern 
daran, dass ihr nicht wahrhaben wollt, dass erst mal einen Gang 
zurückschalten und mit den Basics anzufangen die sinnvollere Alternative 
ist.

Wer zur Tour de France mit Stützrädern am Fahrrad antritt, wird vom 
Veranstalter zu Recht nach Hause geschickt um erst mal seine 
Hausaufgaben (aka. lerne Fahrradfahren) zu machen.

von Andreas (Gast)


Lesenswert?

@ MagIO: Sehr nett! vielen vielen Dank! :)

Karl Heinz Buchegger schrieb:

> Vor allen Dingen sagt es uns, dass du ein C-Buch brauchst!

Schreibt mal bitte ganz oben neben "www.mikrocontroller.net"
Diese Seite ist nur für "Profis"... Anfänger sind hier unerwünscht!

von Thomas E. (thomase)


Lesenswert?

Andreas schrieb:
> Diese Seite ist nur für "Profis"... Anfänger sind hier unerwünscht!
Profis wissen, wie man BCD-Zahlen dekodiert.

Aber von einem Anfänger kann man zumindest erwarten, daß er eine klare 
Frage stellt bzw. sein Problem erläutert. Und nicht scheibchenweise 
damit rüberkommt. Im ersten Post waren es 3 Eingänge, die abgefragt 
werden sollten, im zweiten waren es dann 4 Eingänge und es sollte 
BCD-kodiert werden. Jetzt sind es 11 Eingänge und es soll dekodiert 
werden.
Hättest du das gleich geschrieben, hättest du heute vormittag noch deine 
Lösung gehabt.
Aber jetzt habe ich da keine Lust mehr zu.

mfg.

von Karl H. (kbuchegg)


Lesenswert?

Irgendwie hab ich den Eindruck ich bin im falschen Film.

Was erwartet ihr von einem Forum?
In einem Forum geht es nicht darum, jemandem die absoluten Grundlagen 
beginnend bei 0 beizubringen. Dazu gibt es Bücher! Ist es wirklich so 
viel verlangt, die 20 oder 30 Euro zu investieren und sich in einer 
Buchhandlung ein Buch zu kaufen, welches dir den Stoff in geordneter 
sinnvoller Folge beibringt, anstatt in einem Forum, dass aufgrund von 
Platz und Darstellungsproblemen schon mal überhaupt nicht in der Lage 
ist, dir das, was du in einem Buch auf 15 Seiten erklärt bekommst in 3 
Sätzen beizubringen?

Die Regulars sehen hier jeden Tag wohin es führt, wenn sich Leute ihr 
Viertelwissen (denn Halbwissen kann man das alles noch nicht mal nennen) 
in Foren zusammenschnorren, anstatt dass sie die 20 Abende aufbringen 
und sich in ihrem Buch einfach mal die ersten paar Kapitel reinziehen. 
Im Endeffekt dauert dann alles x-mal so lange, als wenn derjenige 
einfach mal seine Hausaufgaben gemacht hätte. Und hinten nach kommt nix 
gscheites raus, wenn überhaupt etwas rauskommt (siehe: Jan)

> Diese Seite ist nur für "Profis"... Anfänger sind hier unerwünscht!

Das Forum heißt aber auch nicht: Grundschule für C-Programmierer. Macht 
euch keine Sorgen, hier werden sie geholfen. Sie brauchen nix wissen, 
wir erledigen alles für sie.

Auch einem Anfänger ist zuzumuten, dass er sich erst mal auf eigene 
Faust mit Grundlagenwissen versorgt! Wenn er dann Fragen dazu hat, 
gerne, immer her damit. Aber erst mal muss er in die Vorleistung gehen 
und lernen.

Die Profis sind Profis geworden, weil Literatur lesen zu ihrem Alltag 
gehört hat! Durch Fragen in einem Forum ist noch nie jemand zu einem 
Profi geworden. Dazu reicht deine Lebenszeit nämlich nicht aus.
Und selbst wenn das gar nicht angestrebt wird (was ok ist), gehört 
ausreichende Grundlagenliteratur selbst für einen Amateur mit dazu. 
Kaufst du dir halt an 3 Freitagen jeweils 1 Bier in der Diso weniger und 
du hast die Kosten für ein Buch herinnen. Und am Anfang bist du mit 
einem Buch völlig ausreichend versorgt, in dem man auch mal etwas 
nachschlagen kann.

von Oliver (Gast)


Lesenswert?

Andreas schrieb:
> Schreibt mal bitte ganz oben neben "www.mikrocontroller.net"
> Diese Seite ist nur für "Profis"... Anfänger sind hier unerwünscht!

Das hier ist das Forum
>Für alle Fragen rund um Mikrocontroller und Elektronik.

Die allereinfachsten Grundlagen der Syntax irgend einer 
Programmiersprache gehören wohl nicht dazu. Dafür gibt es a) Bücher oder 
b) andere Foren.

Oliver

von High Performer (Gast)


Lesenswert?

@Karl Heinz:

ich kann Dir teilweise zustimmen. Allerdings war die Frage nach dem += 
so in etwa "bin zu faul, google anzuwerfen". Das ist es, was mich 
persönlich an solchen Fragen stört.

Klar ist ein Buch optimal, aber auch im Internet gibt es ja zahlreiche 
Quellen für die C-Grundlagen.

von Karl H. (kbuchegg)


Lesenswert?

High Performer schrieb:
> @Karl Heinz:
>
> ich kann Dir teilweise zustimmen. Allerdings war die Frage nach dem +=
> so in etwa "bin zu faul, google anzuwerfen". Das ist es, was mich
> persönlich an solchen Fragen stört.
>
> Klar ist ein Buch optimal, aber auch im Internet gibt es ja zahlreiche
> Quellen für die C-Grundlagen.

Ich bin ja auf das += auch nur angesprungen, weil noch jeder der in 
einem Kurs oder in der Literatur rausgefunden hat, dass es das gibt, 
sofort darauf anspringt und ab sofort immer und überall auf Biegen und 
Brechen ein += einsetzen will. Das war zu meiner Lernzeit auch nicht 
anders :-)

Von daher kann man davon ausgehen, dass jeder der unter Anleitung lernt 
+= kennt. Bzw. im Umkehrschluss: wer += nicht kennt, versucht sich auf 
eigene Faust irgendwie durchzuschlagen. Und das geht zu99% in die Hose.

von Andreas (Gast)


Lesenswert?

Sinnlos!

von Karl H. (kbuchegg)


Lesenswert?

Wie auch immer.

Hast du jetzt verstanden, wo das Problem bei
1
if (PINB & (1<<PB0) & (1<<PB1) & (1<<PB2))

liegt?

(Denn das ist eine völlig legitime Anfängerfrage, gegen die nichts 
einzuwenden ist. Bitverknüpfungen sind in den üblichen Büchern eher 
stiefmütterlich behandelt)

von Andreas (Gast)


Lesenswert?

Das Problem bei der ganze Sache ist, dass in meiner Schaltung der 2. BCD 
Codierer auf Port-D und Port-B verteilt ist!
1 Kontakt geht auf PB7 und 3 Kontakte gehen auf PB0, PB1, PB2

kann man das so machen:
1
void Adresse (void)
2
{
3
  int Zahl;
4
5
  Zahl = ~PIND & (1<<PD3 | 1<<PD4 | 1<<PD5 | 1<<PD6);
6
  Zahl += ~PIND & PINB (1<<PD7 | 1<<PB0 | 1<<PB1 | 1<<PB2) >>4 * 10;
7
  Zahl += ~PINB (1<<PB3 | 1<<PB4 | 1<<PB5) *100;
8
  
9
}

Ich entschuldige mich nochmal, wenn die Fragen etwas nervig sind und 
rechne mit euer Hilfe.

Vielen vielen Dank!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Andreas schrieb:
> kann man das so machen:
Das kann man schon. Es kommt aber nichts Sinnvolles dabei raus...
Das kommt ja nicht mal der Compiler ohne Fehler durch!

Andreas schrieb:
> kann man das so machen:
Mach das doch einfach mal selber im Simulator oder auf einem Blatt 
Papier durch. So hätte ich das (habe ich das) seinerzeit gemacht. Diesen 
(durchaus zeit- und nervenaufreibenden) Prozess nennt man Lernen...

von Karl H. (kbuchegg)


Lesenswert?

Lothar Miller schrieb:

> Mach das doch einfach mal selber im Simulator oder auf einem Blatt
> Papier durch. So hätte ich das (habe ich das) seinerzeit gemacht. Diesen
> (durchaus zeit- und nervenaufreibenden) Prozess nennt man Lernen...

Ich unterstütze diesen Vorschlag aufs wärmste.

Einfach mal ein Bitmuster für PIND und PINB annehmen (es ist vernünftig, 
wenn du dir im Vorfeld überlegst, was das bedeutet und was dein Programm 
damit herausbekommen müsste) und dann den Code durchspielen. Mein 
Favorit ist dabei immer: Auf dem Papier durchspielen. Überlegt man 
selbst, was da passiert und macht man die Verknüpfungen selber im Kopf, 
dann bleibt da oft viel mehr Wissen und Verständnis hängen, als wie wenn 
man nur irgendwelchen Anzeigen beim Wechseln zusieht.

Du wirst dazu das hier
http://www.swansontec.com/sopc.html
brauchen (C Operator Precedence Table).

Darin ist festgehalten, wie die Reihung der Operatoren ist. Also im 
Grunde das, was du aus der Mathematik als Punkt vor Strich Regel kennst 
und was regelt wie  2 * 3 + 5 auszuwerten ist. Die oberen Gruppen in 
dieser Tabelle haben höhere Priorität. Innerhalb einer Gruppe wird von 
links nach rechts ausgewertet.

Die Tabelle ist zb wichtig, weil irgendwie geregelt werden muss, welche 
Argumente zb in
1
Zahl += ~PIND & PINB (1<<PD7 | 1<<PB0 | 1<<PB1 | 1<<PB2) >>4 * 10;
zusammengehören. So wie  2 * 3 + 5 als (2 * 3) + 5 oder als 2 * (3 + 5) 
angesehen werden kann und die Punkt vor Strich Regel da eine klare 
Auswahl aus den beiden Möglichkeiten trifft.

Man muss nicht alle Einträge dieser Operator Precedence auswendig 
kennen. Aber ein paar wichtige sollten es schon sein und den Rest macht 
man dann mit expliziten Klammern.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb im Beitrag
> Man muss nicht alle Einträge dieser Operator Precedence auswendig
> kennen. Aber ein paar wichtige sollten es schon sein und den Rest macht
> man dann mit expliziten Klammern.
Und wenn man dann immer noch nicht durchblickt, dann kann man schon mal 
so eine einzelne Zeile in 4 oder 5 Zeilen aufteilen. Der Compiler muss 
das sowieso tun, da läuft nicht zwingend 1 Zeile 4 mal so schnell ab wie 
4 Zeilen...

von Karl H. (kbuchegg)


Lesenswert?

Und Andreas:
Weil du da oben so schön 'sinnlos' gesagt hast als Antwort auf den 
Vorschlag sich ein C-Buch zuzulegen.
Ja, auch eine Operator-Precedence-Table samt zugehöriger Erklärung (und 
noch viele hundert andere Dinge, die du als C-Programmierer wissen 
musst) findet sich in jedem noch so grindigem C-Buch.
Die Betonung liegt dabei auf "noch viele andere hundert Dinge, die du 
als C-Programmierer wissen musst". Du kannst dir viel Zeit und Nerven 
sparen, wenn du den Prozess abkürzst, einfach in die Vorleistung gehst 
und zu lesen anfängst.

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.