[C] ATmega32 tut nicht was er soll. Tasterabfrage

OP #3658958
Lesenswert?

Hallo Leute

Ich hab hier nen ATmega32, der, wenn die Variable "Wuerfel" auf 1 
gesetzt ist, einen Motor einschalten soll und, wenn PINB,7 gedrückt (auf 
null gesetzt) ist, den Motor wieder ausschalten soll.
Code:
1
  case 4:    // Zucker ausgeben Teil 1
2
        if (wuerfel==0)
3
        {menu = 6;}
4
        if (wuerfel==1)
5
        {menu = 5;}
6
          break;
7
      case 5:    // Teil 2
8
        PORTA = 0x01;    
9
        loop_until_bit_is_clear(PINA,7);  
10
        PORTA = 0x00;    
11
        menu++; 
12
          break;
Wenn wuerfel also null ist wird der Teil (case 5) übersprungen. Das 
macht er auch. Wenn wuerfel aber 1 ist, springt er wie gewollt auch in 
case 5 und schaltet den motor an. Nach schätzungsweise 100ms schaltet er 
ihn aber wieder ab. Egal ob der Taster gedrückt ist oder nicht. Hab mit 
Multimeter und Oszi schon nachgemessen welche Spannung vom Taster kommt. 
Er ist aber nicht dauerhaft gedrückt.

Liegt das Problem am Code?

Mit freundlichen Grüßen
Valentin S.
OP #3658959
Lesenswert?

Wenn ich folgendes Programm ausführe macht er alles 1x richtig und dann 
blinkt nur noch die 1 auf dem Display. den Rest lässt er aus.
1
#include <avr/io.h>
2
#define F_CPU 1000000
3
#include <util/delay.h>
4
#include "lcd-routines.c"
5

6
int main(void)
7
{
8
  lcd_init();
9
  DDRA = 0b00000001;  //Motor an PORTA 0
10
  PORTA = 0b01000000;  //Pullup für Taster
11
    while(1)
12
    {
13
  lcd_setcursor(0,1);
14
  PORTA = 0x01;    //Motor anschalten
15
  loop_until_bit_is_clear(PINA,7);  //Schleife bis PINA 7 gedrückt ist
16
  PORTA = 0x00;    //Motor ausschalten    
17
  _delay_ms(1000);
18
  lcd_string("1");
19
  _delay_ms(1000);
20
  lcd_clear();
21
  
22
  } //while(1)
23
}  //Main
Gast #3658973
Lesenswert?

Hallo,

unabhängig vom schon genannten Problem: wenn der Taster an PinA.7 hängt 
(zweites Programm) und mit der Anweisung

>  PORTA = 0b01000000;  //Pullup für Taster

der Pullup für PinA.6 eingeschaltet wird, passt das auch nicht zusammen 
...
Gast #3658981
Lesenswert?

Löte einen externen Pullup Widerstand an den PA7 (10k oder so),
dann funktioniert dein Programm.
Mit der Anweisung
1
PORTA = 0x01;    //Motor anschalten
schaltest Du den internen Pullup aus. Weil Du das Bit PA7 mit 0 
beschreibst.
Dass es einmal funktionieren soll wundert mich deshalb sehr.
Gast #3658986
Lesenswert?

> funktioniert aber immer noch nicht.

Wird immer schlimmer. Geh mal zurück auf Anfang, vergleich die 
Codezeilen, die ich Dir oben rauszitiert hab, nochmals ∗genau∗ mit den 
mitzitierten Kommentaren und stelle fest, dass die beiden letzteren 
Kommentare FALSCH sind (die kommentieren nicht das, was Du tatsächlich 
machst).

Dann überleg nochmal, was Du machen musst, damit die Kommentare RICHTIG 
werden.
#3659052
Lesenswert?

Valentin S. schrieb:
> A7
Wie soll dann die Abfrage mit B2 funktionieren?

Das Problem sind einfach die Zuweisungen an den Port mittels 
Holzhammermethode. Bitmanipulation wurde ja bereits angesprochen, 
das sollte man sich von Beginn an so angewöhnen, denn gerade wenn man 
unterschiedliche Dinge an den Pins eines Ports hängen hat, wird man mit 
Direktzuweisungen früher oder später wahnsinnig.
#3659072
Lesenswert?

Was wäre so schlimm, das so zu schreiben?
1
#include <avr/io.h>
2
#define F_CPU 1000000
3
#include <util/delay.h>
4
#include "lcd-routines.c"
5

6
int main(void)
7
{
8
  lcd_init();
9
  DDRA  |= 1<<PA0;  //Motor an PORTA 0
10
  PORTA |= 1<<PA7;  //Pullup für Taster
11
    while(1)
12
    {
13
  lcd_setcursor(0,1);
14
  PORTA |= (1<<PA0);    //Motor anschalten
15
  loop_until_bit_is_clear(PINA,7);  //Schleife bis PINA 7 gedrückt ist
16
  PORTA &= ~(1<<PA0);    //Motor ausschalten    
17
  _delay_ms(1000);
18
  lcd_string("1");
19
  _delay_ms(1000);
20
  lcd_clear();
21
  
22
  } //while(1)
23
}  //Main

Wie ist der Motor angeschlossen? Direkt am Mikrocontroller?
#3659078
Lesenswert?

Ich bin davon ausgegangen, dass du einen Taster an A7 hast, der beim 
Drücken den Pfad nach GND schließt. Richtig? Ich kenne den Inhalt der 
Funktion loop_until_bit_is_clear(...) nicht, was passiert, wenn du das 
durch
1
while(PINA & (1<<PA7))

ersetzt?

Freilaufdiode ist vorhanden?

Edit: 70ms sind für den Controller eine Ewigkeit. Das muss reichen.
Gast #3662888
Lesenswert?

> Ach ja?

Ja! Ich zitiere zweckmäßigerweise nochmals eine der bemängelten Zeilen:

> PORTA = 0x00;    //Motor ausschalten

Links (Code) steht im wesentlichen sowas wie 'setzte den gesamten Port 
auf 0 und schalte damit alle Pullups aus (wo auf Eingang konfiguriert) 
bzw. den Ausgang auf low (wo auf Ausgang konfiguriert)'.
Rechts (Kommentar) steht im wesentlichen sowas wie 'mach was an einem 
einzelnen bestimmten Pin uns sonst gar nie nicht nirgens woanders'.

Jetzt klarer? Dann ganz konkret: Der Code schaltet die 
Pull-Up-Widerstände (und den Motor) aus, der Kommentar behauptet er 
würde nur den Motor ausschalten. Das mit den Widerständen wurde 
mittlerweile mehrfach diskutiert, ändert aber nix daran dass im Original 
Code und Kommentare nicht zusammenpassen.

HTH und ich konnte damit alle Unklarheiten beseitigen.

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