Taster abfrage in C

Gast #3611500
Lesenswert?

Hi

Ich habe diesen Code geschrieben:
1
#include <avr/io.h>
2

3
int main(void)
4
{
5
    DDRA = (1 << DDA0) | (1 << DDA1) | (1 << DDA2) | (0 << DDA3) | (0 << DDA4) | (0 << DDA5) | (0 << DDA6) | (0 << DDA7);
6
  
7
    while(1)
8
    {
9

10

11
        if ( PINA & (1 << PINA3) ) {
12
          PORTA = (1 << PA0);
13
        }
14
        
15
        if ( PINA & (0 << PINA3))  {
16
          PORTA = (0 << PA0);
17
        }
18
  
19

20
    }
21
}
Die LED bleibt angeschaltet, wenn ich den Taster drücke.
Wenn ich den Code so abändere:
1
#include <avr/io.h>
2

3
#include <avr/io.h>
4

5
int main(void)
6
{
7
    DDRA = (1 << DDA0) | (1 << DDA1) | (1 << DDA2) | (0 << DDA3) | (0 << DDA4) | (0 << DDA5) | (0 << DDA6) | (0 << DDA7);
8
  
9
    while(1)
10
    {
11

12

13
        if ( PINA & (1 << PINA3) ) {
14
          PORTA = (1 << PA0);
15
        }
16
        
17
        if (!( PINA & (0 << PINA3) )) {
18
          PORTA = (0 << PA0);
19
        }
20
  
21

22
    }
23
}
Funktioniert es. Warum ist das so?

lgd
Gast #3611510
Lesenswert?

Dario schrieb:
> Funktioniert es. Warum ist das so?

weil (0 << PINA3)

zu 99.99% Unsinn ist und keinen sinn ergibt. Denn ist es 0

  if ( PINA & (0 << PINA3))  {

und wenn man eine 0 mit irgendetwas verundet kommt immer 0 raus.

Auch das ist fehlerhaft:

>  PORTA = (0 << PA0);
auch wenn es hier funktioniert. Es macht aber viel mehr als ein Pin zu 
löschen und führt später Problemen.
Gast #3611540
Lesenswert?

Der 2. Code muss natürlich:
#include <avr/io.h>

int main(void)
{
    DDRA = (1 << DDA0) | (1 << DDA1) | (1 << DDA2) | (0 << DDA3) | (0 << 
DDA4) | (0 << DDA5) | (0 << DDA6) | (0 << DDA7);

    while(1)
    {


        if ( PINA & (1 << PINA3) ) {
          PORTA = (1 << PA0);
        }

        if (!( PINA & (1 << PINA3) )) {
          PORTA = (0 << PA0);
        }


    }
}
lauten.
#3611651
Lesenswert?

Dario schrieb:
> Der 2. Code muss natürlich:
> #include <avr/io.h>
>
> int main(void)
> {
>     DDRA = (1 << DDA0) | (1 << DDA1) | (1 << DDA2) | (0 << DDA3) | (0 <<
> DDA4) | (0 << DDA5) | (0 << DDA6) | (0 << DDA7);
>
>     while(1)
>     {
>         if ( PINA & (1 << PINA3) ) {
>           PORTA = (1 << PA0);
>         }
>         if (!( PINA & (1 << PINA3) )) {
>           PORTA = (0 << PA0);
>         }
>     }
> }
> lauten.

Das funktioniert auch nicht. Und wenn doch, dann spätestens wenn an der 
Nordseeküste die nächste Flut einsetzt, nicht mehr. Es sei denn, du hast 
an PA3 einen Pullup gelötet.
1
#include <avr/io.h>
2
 
3
int main(void)
4
{
5
     DDRA = (1 << DDA0) | (1 << DDA1) | (1 << DDA2);
6
     PORTA |= (1 << 3);
7
     while(1)
8
     {
9
         if ( PINA & (1 << PINA3) ) 
10
         {
11
         //  PORTA = (1 << PA0);
12
             PORTA |= (1 << PA0);
13
         }
14
         if (!( PINA & (1 << PINA3) ))
15
         {
16
           //PORTA = (0 << PA0);
17
           PORTA &= ~(1 << 0);
18
         }
19
     }
20
}

Das ist aber immer noch nichts Dolles. Das lässt sich auch mit einem 
Taster alleine lösen. Ganz ohne Controller.
Für den nächsten Schritt, einmal Drücken EIN, nochmal Drücken AUS, muß 
dein Taster entprellt werden. Aber verinnerliche erstmal das Thema 
Bitmanipulation.

mfg.
#3611683
Lesenswert?

Dario schrieb:
> Ich habe einen 10k Pullup Wiederstand an PA3.
Wohl eher einen Widerstand. Dann hat sich das mit der Flut erledigt.
Der Widerstand ist aber unnötig, da der Controller Pullups eingebaut hat 
und der entsprechende mit
1
PORTA |= (1 << 3);
aktiviert wird.

Guck dir die letzte Zeile in meiner Version an und vergleiche sie mit 
deiner auskommentierten darüber. Wenn das nur Stirnrunzeln bei dir 
verursacht:

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Ausg.C3.A4nge

mfg.
#3611723
Lesenswert?

Dario schrieb:
> Ich verstehe das Problem immer noch nicht.


Es gibt einen fundemantalen Unterschied zwischen

1
     1 << PA_irgendwas

und

1
     0 << PA_irgendwas


0 um eine ANzahl Bits nach links geschoeben, ist immer noch 0!

Das ist dasselbe wie in der Mathe
1
  1 * 1   = 1
2
  1 * 2   = 2
3
  1 * 3   = 3
4
  1 * 4   = 4
5
  ...
ABER
1
  0 * 1   = 0
2
  0 * 2   = 0
3
  0 * 3   = 0
4
  0 * 4   = 0
5
  ...

egal womit du 0 multiplizierst, das Ergebnis ist immer (in allen Fällen) 
0. Im Falle das du 1 multiplzierst kriegst du jeweils ein anderes 
Ergebnis. Aber nicht bei 0., Die Ergebnisse sind alle gleich, nämlich 0

Nimm den binären Wert 1 her
1
   0000 0001

und verschieb den um 5 Stellen nach links
1
   0000 0001   << 5
2

3
-> 0010 0000

das Ergebnis ist ein binärer Wert, der genau an der Bitposition 5 ein 
1-Bit hat. Genau darauf zielt man ja mit 1 << xxx ab: einen Wert zu 
kriegen, der genau an der Bitposition xxx ein 1 Bit aufweist.

Aber:
Das funktioniert, wenn man eine 1 schiebt.
Aber bei einer 0, so wie in 0 << PA0, ergibt die Operation keinen Sinn. 
Denn eine binäre 0 kannst du nach links schieben so oft du willst
1
   0000 0000   << 5
das Ergebnis ist wieder einfach nur
1
   0000 0000


Daher ist
1
   PORTA = (0 << PA0);
in allen Belangen völlig gleichwertig zu
1
   PORTA = 0;

Dass du da in deinem Ausdruck PA0 drinnen stehen hast, ist zwar nett, 
aber komplett irrelevant, weil es nichts bewirkt. De Facto hast du 
einfach nur an PORTA eine 0 zugewiesen.
Gast #3611767
Lesenswert?

Danke für die tolle Erklärung!
Um das zu verinnerlichen wollte ich so eine LED zum Blinken bringen. 
Aber ich
finde den Fehler nicht :(
#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 1000000

int main(void)
{
  DDRA = 0;
  DDRA |= (1 << 0) | (1 << 1) | (1 << 2);

    while(1)
    {
    PORTA |= (1 << 0);
    _delay_ms(1000)
    PORTA &= ~(1 << 0);
    }
}
Gast #3611785
Lesenswert?

#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 1000000

int main(void)
{
  DDRA = 0;
  DDRA |= (1 << 0) | (1 << 1) | (1 << 2);

    while(1)
    {
    PORTA |= (1 << 0);
    _delay_ms(1000);
    PORTA &= ~(1 << 0);
    }
}
Das ; bei _delay_ms hat gefehlt. Es blinkt trotzdem nicht :(
#3611788
Lesenswert?

Dario schrieb:
> Danke für die tolle Erklärung!
> Um das zu verinnerlichen wollte ich so eine LED zum Blinken bringen.
> Aber ich
> finde den Fehler nicht :(
> #include <avr/io.h>
> #include <util/delay.h>
>
> #define F_CPU 1000000
>
> int main(void)
> {
>   DDRA = 0;
>   DDRA |= (1 << 0) | (1 << 1) | (1 << 2);
>
>     while(1)
>     {
>     PORTA |= (1 << 0);
>     _delay_ms(1000)
>     PORTA &= ~(1 << 0);
>     }
> }

1
     while(1)
2
     {
3
       PORTA |= (1 << 0);
4
       _delay_ms(1000);
5
       PORTA &= ~(1 << 0);
6
       //du mußt dir hier auch eine Sekunde gönnen
7
       _delay_ms(1000);
8
     }

mfg.
Gast #3611825
Lesenswert?

Ich habe mein Ziel erreicht:
1
#include <avr/io.h>
2

3
#define F_CPU 1000000
4

5
int main(void)
6
{
7
  DDRA = 0;
8
  DDRA |= (1 << 0) | (1 << 1) | (1 << 2);
9
  
10
    while(1)
11
    {
12
    if ( PINA & (1 << PA3)) {
13
      PORTA |= (1 << PA0);
14
    }
15
    if ( PINA | (1 << PA3)) {
16
      PORTA &= ~(1 << PA0);
17
    }
18
      
19
    }
20
}
#3611828
Lesenswert?

Dario schrieb:
> Ich habe mein Ziel erreicht:

Nope

>
1
>
2
>     if ( PINA | (1 << PA3)) {
3
>
4
>

ganz sicher nicht.

Was ist denn so schwer dran

Abfrage, ob ein Pin auf 1 ist
1
  if( PINx & ( 1 << PinNr ) )
2
     ...

Abfrage ob der Pin auf 0 ist
1
  if( !( PINx & ( 1 << PinNr ) ) )


Oder in deinem speziellen Fall
1
    if ( PINA & (1 << PA3)) {
2
      PORTA |= (1 << PA0);
3
    }
4
    else {
5
      PORTA &= ~(1 << PA0);
6
    }
... da stellt sich dann die Fragestellung gar nichgt mehr. Denn wenn der 
Pin nicht auf 1 war (erstes if), dann ist automatisch klar, dass er auf 
0 sein muss. Eine andere Möglichkeit existiert gar nicht mehr. Der Pin 
ist entweder 1 oder er ist 0. Sobald klar ist, dass er nicht 1 ist, MUSS 
er 0 sein.
Gast #3611840
Lesenswert?

Okay

#include <avr/io.h>

#define F_CPU 1000000

int main(void)
{
  DDRA = 0;
  DDRA |= (1 << 0) | (1 << 1) | (1 << 2);

    while(1)
    {
    if ( PINA & (1 << 3)) {
      PORTA |= (1 << PA0);
    }
    if (!( PINA & (1 << 3)) ){
      PORTA &= ~(1 << PA0);
    }
    }
}
oder
#include <avr/io.h>

#define F_CPU 1000000

int main(void)
{
  DDRA = 0;
  DDRA |= (1 << 0) | (1 << 1) | (1 << 2);

    while(1)
    {
    if ( PINA & (1 << 3)) {
      PORTA |= (1 << PA0);
    }
    else{
      PORTA &= ~(1 << PA0);
    }
    }
}
Jetzt müsste es richtig sein. Wie kann ich den Code in ein Codefenster 
schreiben?(so wie Ihr)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren