Forum: Mikrocontroller und Digitale Elektronik PIN bei Atmega128 abfragen


von Roman (Gast)


Lesenswert?

Hallo,

ich möchte bei einem Atmega128 den Zustand der PINS am PORTC anfragen. 
Ich setze diese als Eingang mit einem PULL UP und möchte einen von 
extern anliegenden LOW Pegel detektieren.

Habe also folgende Konfiguration:

 PORTC = 0xFF; //High setzen
 DDRC  = 0x00; //Eingang

Und eingentlich sollte es damit funktionieren:

(Für PIN 0 am PORT C)

if(PINC0 == 0)
{}

Leider funktioniert dies nicht.

Und dies hier auch nicht:

if((PINC &(1<<PINC0))== 1)


Wäre sehr dankbar, falls jemand einen Tip hat.

von Karl H. (kbuchegg)


Lesenswert?

Roman wrote:

> Und eingentlich sollte es damit funktionieren:

nicht wirklich

> Und dies hier auch nicht:
>
> if((PINC &(1<<PINC0))== 1)

Das allerdings wäre richtig

> Wäre sehr dankbar, falls jemand einen Tip hat.

Poste doch mal dein komplettes Programm.

von Roman (Gast)


Lesenswert?

Hallo,

vielen Dank für eine schnelle Atnwort,

ich habe im Moment noch nicht viel Code, weil ich genau an der Stelle 
hänge.

void main(void)
{

   int n;
    CLI();  /*disable all interrupts*/
   init_devices();
   //SPI_MasterTransmit16Bit(0XAA, 0x00);
   //SPI_MasterTransmit16Bit(0XAE, 0x00);


   while(1)
   {


if((PINC &(1<<PINC0))== 1)
 {
test1 = 1;
}

 if((PINC &(1<<PINC1))== 1)
{
test2 = 1;
}

if((PINC &(1<<PINC2))== 1)
{
  test3 = 1;
}



}}

von Daniel D. (bademeister)


Lesenswert?

Mal ne evtl blöde Vermutung, aber lass doch mal den Vergleich weg. Evtl 
kommt bei dem UND was anderes als 1 raus..

von Roman (Gast)


Lesenswert?

Sorry,

der Vergleich sollte gar nicht rein. Ist wegen copy paste geblieben.

void main(void)
{

   int n;
    CLI();  /*disable all interrupts*/
   init_devices();
   //SPI_MasterTransmit16Bit(0XAA, 0x00);
   //SPI_MasterTransmit16Bit(0XAE, 0x00);


   while(1)
   {


if(PINC &(1<<PINC0))
 {
test1 = 1;
}

 if(PINC &(1<<PINC1))
{
test2 = 1;
}

if(PINC &(1<<PINC2))
{
  test3 = 1;
}



}

von Roman (Gast)


Lesenswert?

Und wieder ein copy fehler, ich möchte ja auf LOW Abfragen, also sollte 
es auch  if((PINC &(0<<PINC1))== 1) heißen.

Funktioniert leider nicht:


void main(void)
{

   int n;
    CLI();  /*disable all interrupts*/
   init_devices();
   //SPI_MasterTransmit16Bit(0XAA, 0x00);
   //SPI_MasterTransmit16Bit(0XAE, 0x00);


   while(1)
   {


if((PINC &(0<<PINC0))
 {
test1 = 1;
}

 if((PINC &(0<<PINC1))
{
test2 = 1;
}

if((PINC &(0<<PINC2))
{
  test3 = 1;
}



}

von Daniel D. (bademeister)


Lesenswert?

Mach aus dem (PINC & (1<<PINC0)) ein (!(PINC &(1<<PINC0)))
Das sollte klappen..

von Sebastian (Gast)


Lesenswert?

Hi,

& macht eine Binärverknüpfung, das heißt Du bekommt 128, 64, 32, ... als 
Ergebnis, probiere doch mal:

(PINC & (1<<PINC0)) > 0

<< shiftet nach links, 0<<PINCx geht also nicht, da shiftest Du ja eine 
0, Du willst aber eine 1, also 1<<PINCx

Sebastian

von Daniel D. (bademeister)


Lesenswert?

Also das mit > 0 sollte das gleiche machen wie der Ausdruck, den ich 
oben gepostet habe. Denn ohne Vergleich wie z.B. == 1 wird die Klammer 
als Ergebnis eines Vergleiches angenommen. Sprich ist der Inhalt größer 
0 ist die Bedingung erfüllt und die Anweisungen ausgeführt.

Ist vom Sinn her das gleiche wie while(1) eine Endlosschleife ist.

von Karl H. (kbuchegg)


Lesenswert?

Sebastian wrote:
> & macht eine Binärverknüpfung, das heißt Du bekommt 128, 64, 32, ... als
> Ergebnis, probiere doch mal:
>
> (PINC & (1<<PINC0)) > 0


Mit dem > (größer) bin ich unglücklich.
Da lieferst du dich immer gewissen signed/unsigned Problemen aus. Wenn 
man das im Hinterkopf hat ist es an und für sich kein Problem, aber wenn 
es eine einfachere Lösung gibt ...

Alles was man wissen will ist doch:
Wenn ich nur dieses eine Bit vom Eingangs-Port übrig lasse, kommt dann 0 
raus (heist der Eingangs-Pin ist ebenfalls 0) oder nicht (dann bleibt 
als Zahlenwert, wie du richtig sagst 128, 64, 32, 16... raus, wobei der 
exakte Wert im Grunde nicht wirklich interessiert)
Die Frage, die sich stellt lautet also: Bleibt nach der Maskierung 0 
übrig oder nicht.
1
   if( ( PINC & ( 1 << PINC0 ) ) == 0 )
2
     // der Eingangspin war 0
bzw
1
   if( ( PINC & ( 1 << PINC0 ) ) != 0 )
2
     // der Eingangspin war 1, da er ja nicht 0 war
und da 0 signed und unsigned die gleiche Repräsentierung hat, ist man 
damit alle signed/unsigned Probleme los.

von Karl H. (kbuchegg)


Lesenswert?

Aber was anderes:
Bei Mega128 und Port C: gabs da nicht irgendein Problem mit den Fuse 
Bits, die man setzen musste um den Port als Eingang zu aktivieren

(Sorry: war ein halbes Jahr weg von AVR und mein Gedächtnic ist auch 
nicht mehr das was es mal war)

von Roman (Gast)


Lesenswert?

Hallo, das mit

if( ( PINC & ( 1 << PINC0 ) ) == 0 )

funktioniert wunderbar. Vielen dank für die Tips und sehr schnelle 
Reaktion !!

PS. Tatsächlich funktioniert es beim PORTC mit PIN0 nicht, aber andere 
PINS des C Ports funktionieren.

von STK500-Besitzer (Gast)


Lesenswert?

>Bei Mega128 und Port C: gabs da nicht irgendein Problem mit den Fuse
>Bits, die man setzen musste um den Port als Eingang zu aktivieren

Mega103-Kompatibiltät lässt grüßen. Ich hätte eher an JTAG gedacht, aber 
laut Datenblatt ist der Betrieb des PortC nur als Ausgang möglich, wenn 
die Mega103-Compatible-Mode-Fuse gesetzt ist. Und die ist im 
Auslieferungszustand gesetzt.
JTAG hängt an PortF...(kann man auch ausschalten).

>if( ( PINC & ( 1 << PINC0 ) ) == 0 )

Kürzer:

If (!(PINC & (1<<PINC0)))

>if((PINC &(1<<PINC2))== 1)
Wenn PINC2 gesetzt ist, würde die Abfrage trotzdem nicht erfüllt werden, 
weil das Ergebnis von PINC & (1<<PINC2) nicht 1, sondern 4 wäre.
Sowas kann man gut dazu benutzen, wenn man nachgucken will, ob sich 
mehreren Port-Pins etwas getan hat:

if ((PINC & ((1<<PINC0) | (1<<PINC1) | (1<<PINC2)) == ((1<<PINC0) | 
(1<<PINC1) | (1<<PINC2))))
Dmit würde man feststellen, ob einer der Pins auf 0 gezogen wurde.

von Roman (Gast)


Lesenswert?

Tatsächlich, weil man eigentlich dann den falschen Bitwert abfragt.

Es funktioniert also nur zufälligerweise dann, wenn der abzufragender 
Bitwert Bit 0 ist.

Wie kann ich dann andere Bitstellen bzw. Port auf 0 Abfragen?

Wieso funktioniert eigentlich nicht folgende Abfrage:

if (PINC2 == 1)

oder

if (PINC2 == 0)

wäre doch ein logischer Zustand, der Abgefragt ist. Leider funktiniert 
es nicht im Contoller. Erkennt er die Zustände der einzelner Bits nicht?

von Karl H. (kbuchegg)


Lesenswert?

Roman wrote:

> Wie kann ich dann andere Bitstellen bzw. Port auf 0 Abfragen?

mit 0 kannst du immer vergleichen.
Entweder das was nach der Maskierung übrig bleibt ist 0 oder es ist 
nicht 0. Welcher Wert dann genau übrig bleibt, hängt davon ab welches 
Bit du testest. Hab ich aber weiter oben schon ausgeführt

>
> Wieso funktioniert eigentlich nicht folgende Abfrage:
>
> if (PINC2 == 1)


Weil PINC2 ein Makro ist, welches schlicht und ergreifend zu 2 
expandiert.
Damit steht dann da

  if( 2 == 1 )

und das wird ja wohl nie wahr


Diese PINxx Makros sind einzig und alleine dazu gedacht Bit-Positionen 
an einem Port durchzuzählen und dafür einen schöneren Namen als einfach 
nur 2 zu geben. Mehr nicht. Insbesondere haben sie mit dem Port oder Pin 
Register nich das geringste zu tun. Es sind einfach nur symbolische 
Namen für konstante Zahlen.

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.