Forum: Compiler & IDEs Schalter für den Atmega16


von Matze K. (phytomed)


Lesenswert?

Moin,

Ich bin noch ein absoluter Anfänger mit Mikrocontrollern und
möchte zwei Schalter mit dem Atmega16 verwenden.
Dabei habe ich die Schalter an die Pins PB0 und PB1 angeschlossen.
Die Schalter verbinden die Pins mit der Masse und die Pins sind
über einen Widerstand (10 kOhm) mit der Spannung verbunden.

DDRB &= ~(1 << DDB0) | ~(1 << DDB1); /* Pin B0 und B1 als Eingang */

unsigned int Taster1(void){                    //Taster1 ist B0
  unsigned char temp1, temp2;
  unsigned int i;
  unsigned int ret;

  temp1 = !(PINB);                  // read input
  for(i=0;i<65535;i++);
  temp2 = !(PINB);                  // read input
  temp1 = (temp1 & temp2);       // debounce input
  if ( temp1 & (1 << PINB0) ){
    ret=1;
  }else{
    ret=0;
  }
  return ret;
}


main(){

...
      taster1 = Taster1();
      taster2 = Taster2();
      if ((taster1 == 1) || (taster2 == 1)){
  lcd_clrscr();
  lcd_puts("Taster gedrückt:\n");
  lcd_puts("Sehr gut!!");
      }
}

Dieser Code funktioniert für keinen Taster,
was ist daran verkehrt?

Vielen Dank
Matthias

von Rolf Magnus (Gast)


Lesenswert?

> DDRB &= ~(1 << DDB0) | ~(1 << DDB1); /* Pin B0 und B1 als Eingang
> */

Überprüfe mal deine Logik.

~(1 << DDB0) | ~(1 << DDB1) = 0xff

Also wird der gesamte Port B auf Ausgang umgeschaltet.

>   for(i=0;i<65535;i++);

Soll das eine Warteschleife sein? Dann lieber eine entsprechende
Bibliotheksfunktion nutzen. Andernfalls wird der Compiler bei
eingeschalteten Optimierungen diese Schleife komplett entfernen.
}

von Matze K. (phytomed)


Lesenswert?

Moin,

nochma.

@Rolf
> DDRB &= ~(1 << DDB0) | ~(1 << DDB1); /* Pin B0 und B1 als Eingang
> */

Überprüfe mal deine Logik.


Ich habe meine Logik überprüft und es etwas verändert, nach dem
avr-gcc Skript.

DDRB &= ~((1 << PB0)|(1 << PB1)); //Eingänge -> 9.5 im Skript
PORTB &= ~((1 << PB0)|(1 << PB1));//da Pull-Up Widerstände(10kOhm)


Das Entprellen mache ich nun mit _delay_ms(100);

es funktioniert allerdings immer noch nicht.

Für weitere Hilfen bin ich immer noch dankbar.

Matthias

von mthomas (Gast)


Lesenswert?

_delay_ms(100) ist mglw. "zu viel", es gibt einige Randbedingungen
fuer die maximale Wartezeit in Abhaengigkeit vom Takt, vgl. dazu
avr-libc Dokumtentation. Testweise mehrere _delay_ms(x) mit x<max.
Delay hintereinander.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Allerdings braucht man auch keine 100 ms zum Entprellen.  10 oder 20
ms sollten dafür genügen.

Normalerweise pollt man einfach die Schalter im Timer-Interrupt, und
betrachtet sie als gesetzt, wenn sie für N ms ihren Wert nicht mehr
geändert haben.  Ich glaube, Peter Dannegger hat da irgendwo ein Stück
Code, was das macht.

Die ganzen Operationen auf DDRB und PORTB sind übrigens NOPs, da sie
den Reset-Wert von 0 nicht ändern (alle Ports sind nach dem Reset auf
Eingang ohne Pullup geschaltet).

Ansonsten Matze: bitte definiere ,,geht nicht'' etwas näher.

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.