Forum: Mikrocontroller und Digitale Elektronik Anfänger Frage zu variable hochzählen


von Huber M. (michael_h784)


Lesenswert?

Hallo,

ich möchte während ich den taster an PA0 drücke die variable a immer um 
+1 hochzählen. wenn ich ihn erneut drücke soll die Variable a wieder um 
+1 hoch gezählt werden. also drücken a=1 ,erneut drücken a=2, erneut 
drücken a=3 usw...


aber was habe ich hier nicht beachtet es scheint so als würde er mir 
nicht richtig hochzählen (willkürlich). Taster mit kondensator 
entprellt.

grüsse huber

1
/*
2
 * GccApplication5.c
3
 *
4
 * Created: 17.09.2016 09:47:49
5
 *  Author: Daniela Weinhart
6
 */ 
7
#define F_CPU 1000000UL
8
#include <util/delay.h>
9
#include <avr/io.h>
10
11
int main(void)
12
{ // EIN und Ausgänge konfigurieren
13
  PORTA = (1<<PA0);
14
  DDRA = (1<<PA1);
15
  
16
    while(1)
17
    {   // Taster 1
18
    int a = 0;
19
    
20
    while( a <=5)
21
    {
22
      if (!(PINA & (1<<PA0)))
23
      {  
24
        a = a+1;
25
      } 
26
      
27
      
28
      if (a == 2)
29
      {
30
        PORTA |= (1<<PA1);
31
      }
32
      
33
      if (a == 3)
34
      {
35
       PORTA &= ~(1<<PA1);
36
          
37
      }
38
        
39
      if (a == 5)
40
      {
41
        a = 0;
42
      }
43
      
44
    }
45
    
46
        
47
    }
48
}

: Verschoben durch User
von Thomas E. (picalic)


Lesenswert?

Servus Hubert,

Du darfst die Variable nicht hochzählen, solange der Taster sich im 
gedrückten Zustand befindet, sondern nur, wenn er vom nicht-gedrückten 
in den gedrückten übergeht!

von Wolfgang (Gast)


Lesenswert?

Huber M. schrieb:
> Taster mit kondensator entprellt.

Taster mit Software entprellen. (s. Artikel Entprellung)

Für nicht genutzten Flash-Speicher gibt es kein Geld zurück.

von Einer K. (Gast)


Lesenswert?

Wolfgang schrieb:
> Taster mit Software entprellen. (s. Artikel Entprellung)
>
> Für nicht genutzten Flash-Speicher gibt es kein Geld zurück.

Software Entprellung benötigt auch Ram.
Oder es wird Zeit in delays verplempert.

von Huber M. (michael_h784)


Lesenswert?

bin ich hier auf dem richtigen weg?
denn es macht nicht was es soll.

-ich drücke, lasse los, dann zählt er um eins hoch, also a = 1 ? noch 
keine Funktion?
-ich drücke erneut. lasse los,zählt wieder um eins hoch, also a = 2? 
jetzt müsste er mir doch PA1 Einschlten?
1
/*
2
 * GccApplication5.c
3
 *
4
 * Created: 17.09.2016 09:47:49
5
 *  Author: Daniela Weinhart
6
 */ 
7
#define F_CPU 1000000UL
8
#include <util/delay.h>
9
#include <avr/io.h>
10
11
int main(void)
12
{ // EIN und Ausgänge konfigurieren
13
  PORTA = (1<<PA0);
14
  DDRA = (1<<PA1);
15
  
16
    while(1)
17
    {   // Taster 1
18
    int a = 0;
19
    
20
    while( a <=5)
21
    {
22
      if (!(PINA & (1<<PA0))==0)
23
      {  
24
         a++;
25
      } 
26
      
27
      
28
      if (a == 2)
29
      {
30
        PORTA |= (1<<PA1);
31
      }
32
      
33
      if (a == 3)
34
      {
35
       PORTA &= ~(1<<PA1);
36
          
37
      }
38
        
39
      if (a == 5)
40
      {
41
        a = 0;
42
      }
43
      
44
    }
45
    
46
        
47
    }
48
}

von Wolfgang (Gast)


Lesenswert?

Arduino F. schrieb:
> Software Entprellung benötigt auch Ram.
> Oder es wird Zeit in delays verplempert.

Die wenigen RAM-Bytes werden wohl noch irgendwo zu finden sein.

Wer sein Timing auf solchen Zeitskalen mit delay() macht, hat allerdings 
schnell verloren, wenn sich der µC auch noch um andere Dinge kümmern 
soll. Falls die einzige Aufgabe allerdings ist, auf eine Taste 
aufzupassen, ist es egal, womit er die Zeit verplempert. Irgendwie muss 
er sie rum kriegen ;-)

von Top S. (topsoft)


Lesenswert?

Du musst dir den alten Tastenzustand merken. Hier ein Beispiel. Mal 
schnell nebenbei und ungetestet. Allerdings solltest du das Konzept 
überdenken. So macht man das nicht.

1
int main(void){
2
    PORTA = (1 << PA0);
3
    DDRA = (1 << PA1);   
4
    uint8_t a = 0, taste_old = PINA & (1<<PA0);
5
    while(1){
6
        if(!(PINA & (1<<PA0))){
7
            if(taste_old){
8
                if(a < 6)
9
                    a++;
10
                else
11
                    a = 0;
12
                if(a==2)
13
                    PORTA |= (1 <<PA1);
14
                else if(a==3)
15
                    PORTA &= ~(1 << PA1);
16
                taste_old = 0;
17
            }
18
        }
19
        else
20
            taste_old = (1 << PA0);
21
    }
22
}

: Bearbeitet durch User
von Holger L. (max5v)


Lesenswert?

Als ganz einfachen Test könntest du in dem If- Block der Tasterabfrage 
gegen das Prellen _delay_ms() einsetzen.
Tasterabfrage Taster gedrückt, kurz warten.
Schleife,
Tasterabfrage Taster nicht gedrückt, kurz warten.

Um die Ergebnisse zu überprüfen würde ich an deiner Stelle mit einer Led 
einen Blinkcode ausgeben, damit ist die ganze Geschichte deutlich besser 
überschaubar.
1
// Blinken
2
void blink_led_x(uint8_t anzahl)
3
{
4
  for (; anzahl > 0; anzahl--)
5
  {
6
    PORTA &=~ (1 << PA1); // Ausschalten
7
    _delay_ms(150);
8
    
9
    PORTA  |= (1 << PA1); // Einschlten
10
    _delay_ms(350);
11
  }
12
  PORTA &=~ (1 << PA1); // Ausschalten
13
}

von c-hater (Gast)


Lesenswert?

Arduino F. schrieb:

> Software Entprellung benötigt auch Ram.

Das stimmt. Ein ganzes sattes Byte für bis zu acht Tasten. Wer zum 
Teufel kann sich solcherart Verschwendung heutzutage denn noch leisten?

von W.S. (Gast)


Lesenswert?

Huber M. schrieb:
> bin ich hier auf dem richtigen weg?
> denn es macht nicht was es soll.

Geh mal ganz systematisch und ohne Programmiersprache an das Problem 
heran. Stell dir dazu einen Beamten vor, der in seinem Amt alle Arbeiten 
machen muß. (jaja im Gedankenexperiment gibt es sowas...)

Dieser Beamte kommt in das Zimmer für die Taste, setzt sich an den 
Schreibtisch und guckt auf das Arbeitsbuch auf dem Tisch, wo draufsteht, 
was er zuletzt gemacht hat.

Also:
Fall 1: auf dem Zettel steht: kein aktueller Vorgang am Laufen, die 
Taste war zuletzt aus.
Jetzt guckt er nach der Taste und stellt fest:
a) die ist immer noch aus. Also steht er auf und geht an seine nächste 
Arbeit.

b) die Taste ist jetzt gedrückt. Also schreibt er auf nen Zettel: "Taste 
wurde gedrückt, bitte Vorgang bearbeiten" und steckt ihn in die 
amtsinterne Post. Anschließend schreibt er in das Arbeitsbuch: "Vorgang 
ist am Laufen" und "Entprellzeit = 100 Bewertungen". Danach geht er an 
seine nächste Arbeit.

Fall 2: auf dem Zettel steht:"Vorgang ist am Laufen".
Jetzt guckt er nach der Taste und stellt fest:
a) die Taste ist ungedrückt. Jetzt liest er im Arbeitsbuch: 
"Entprellzeit = xxx Bewertungen". (xxx steht für eine Zahl) Er radiert 
die Zahl aus und schreibt Zahl-1 hinein. Wenn das nun Null ergibt, dann 
radiert er den gesamten Vorgang aus und schreibt "kein aktueller Vorgang 
am laufen". Danach geht er an seine nächste Arbeit.

b) die Taste ist immer noch gedrückt. Also radiert er die Zahl für die 
Entprellzeit aus und schreibt "100" hinein. Danach geht er an seine 
nächste Arbeit.

So. Ist dir jetzt klar, wie man an solche Dinge herangehen kann? Die 
Story dürfte sich selbst für einen ungeübten Programmierer ohne Probleme 
in eine beliebige Programmiersprache übersetzen lassen.

Und nochwas: Eigentlich reicht es dem Beamten ja aus, zu sehen, ob die 
Zahl auf dem Arbeitsbuch Null ist oder nicht.

W.S.

von Huber M. (michael_h784)


Lesenswert?

also, jetzt habe ich es mal so geschrieben, aber was mir einfach nicht 
einleuchtet, warum er mir den druckzaehler nicht um eins höher zählt. 
liegt das hier an der while schleife.

mir geht es hauptsächlich jetzt mal darum, das mir das mit dem zählen 
endlich mal einleuchtet.

1
/*
2
 * GccApplication6.c
3
 *
4
 * Created: 17.09.2016 14:55:12
5
 *  Author: Daniela Weinhart
6
 */ 
7
#define F_CPU 1000000UL
8
#include <util/delay.h>
9
#include <avr/io.h>
10
11
int main(void)
12
{   // Aus und Eingänge konfigurieren
13
  DDRA = (1<<PA1);
14
  PORTA = (1<<PA0);
15
  
16
    while(1)
17
    {
18
    int tasterstatus = 0;
19
    int druckzaehler = 0;
20
    
21
    if (!(PINA &(1<<PA0)))
22
    {  _delay_ms(15);
23
      tasterstatus = 1 ;
24
    }
25
    if (tasterstatus ==1)
26
    {
27
      druckzaehler++;
28
    } 
29
    else
30
    {
31
      if (druckzaehler == 1)
32
      {
33
        PORTA |= (1<<PA1);
34
        _delay_ms(250);
35
        PORTA &= ~(1<<PA1);
36
        _delay_ms(250);
37
        PORTA |= (1<<PA1);
38
        _delay_ms(250);
39
        PORTA &= ~(1<<PA1);
40
        _delay_ms(250);
41
        PORTA |= (1<<PA1);
42
        
43
      }
44
      if (druckzaehler == 2)
45
      {
46
        PORTA |= (1<<PA1);
47
        
48
      }
49
      else
50
      {
51
        if (druckzaehler==3)
52
        {
53
          PORTA &= ~(1<<PA1);
54
        }
55
        
56
        if(druckzaehler == 4)
57
        {
58
          druckzaehler = 0;
59
        }
60
      }
61
    }
62
    
63
  }
64
}

von Tippgeber (Gast)


Lesenswert?

Der Ablauf von Deinem Programm sollte etwa folgender sein:

  - Variablen und Hardware vorbereiten und einstellen
  - Wiederhole für immer:
    - Warte auf "Taste nicht gedrückt"
    - Warte auf "Taste gedrückt"
    - Zähle um Eins hoch


Wie Du siehst, kommt zweimal "Warte auf irgendwas" vor. So ein Warte 
könnte man folgendermaßen programmieren:

  - Weil "irgendwas" nicht wahr ist, wiederhole:
    - Mache nichts


Verstanden?

von ASDFGHJKL (Gast)


Lesenswert?

Ueberleg, was passiert, wenn der Taster gedrueckt und nicht wieder 
losgelassen wird.

ASDFGHJKL

von Huber M. (michael_h784)


Lesenswert?

dann ist das signal 1 also wahr Boolsche regel. mein problem ist nicht 
das ich grundsätzlich nicht schalten kann, sondern ich bin zu blöd zum 
hochzählen.

int tasterstatus = 0;
int zähler = 0;

if (tastergedrückt)

setze mir den tasterstatus auf 1

wenn der tasterstatus 1 ist


zähle mir den zähler um eins rauf

von Peter D. (peda)


Lesenswert?

Huber M. schrieb:
> if (!(PINA &(1<<PA0)))
>     {  _delay_ms(15);

Das kann bestenfalls ein Gamer oder der Sieger im Schnellschreiben.
Ein typischer Nutzer benötigt 300ms zum Drücken und 300ms zum Loslassen.
Die universelle Lösung ist daher ein Timerinterrupt, der das Entprellen 
und die Flankenerkennung im Hintergrund erledigt. Die Mainloop liest 
dann einfach nur das Drück-Flag und löscht es.

von Holger L. (max5v)


Lesenswert?

http://www.c-howto.de/tutorial-verzweigungen-if-else.html

Die Variable "druckzaehler" wird nach jedem Durchlauf wider auf 0 
gesetzt, kann dementsprechend niemals größer als 1 werden.

Die "else if (druckzaehler == 1)" kann nicht ausgeführt werden solange 
"if (tasterstatus ==1)" wahr ist.

Wenn "if (tasterstatus ==1)" unwahr ist wurde "druckzaehler" bereits 
wider auf 0 gesetzt.

von Thomas E. (picalic)


Lesenswert?

Huber M. schrieb:
> dann ist das signal 1 also wahr Boolsche regel. mein problem ist nicht
> das ich grundsätzlich nicht schalten kann, sondern ich bin zu blöd zum
> hochzählen.

Du hast Dich verrant und suchst an der falschen Stelle!
Benutze den Debugger und führe damit das Programm Schritt für Schritt 
aus! Damit kannst Du es genau verfolgen und wirst sehen, wo das Programm 
etwas anderes tut, als Du Dir vorstellst.

: Bearbeitet durch User
von W.S. (Gast)


Lesenswert?

Huber M. schrieb:
> mein problem ist nicht
> das ich grundsätzlich nicht schalten kann, sondern ich bin zu blöd zum
> hochzählen.

Ich würde das etwas anders formulieren: Du hast Schwierigkeiten, die 
ganze Sache rein logisch zu verstehen und dir eine geeignete Lösung dazu 
zu erarbeiten. Und verstehendes Lesen ist dir auch nicht wirklich 
genehm.

Vielleicht dazu noch ein Rat: Programmierer sein, heißt nicht, in irgend 
einer Programmiersprache etwas syntaktisch richtiges hinschreiben zu 
können, sondern es heißt, gute Algorithmen zum Lösen von Problemen 
erarbeiten und formulieren zu können.

W.S.

von Aufpasser (Gast)


Lesenswert?

Huber M. schrieb:
~~~~~~~~

>  *  Author: Daniela Weinhart
              ~~~~~~~~~~~~~~~~


Ja mei, abgekupfert ist es auch noch...

von Huber M. (michael_h784)


Lesenswert?

das ist nicht abgekupfert sondern der laptop meiner freundin.

von Jobst M. (jobstens-de)


Lesenswert?

1
           start
2
             |
3
             +<-------,
4
             |        |
5
          taster      |
6
         gedrückt?    |
7
         ja   nein    |
8
          |     |     |
9
          |     '-->--+
10
          +<-------,  |
11
          |        |  |
12
       taster      |  |
13
      gedrückt?    |  |
14
      nein  ja     |  |
15
       |     |     |  |
16
       |     '-----'  |
17
      N++             |
18
       |              |
19
       '------->------'


Gruß

Jobst

von W.S. (Gast)


Lesenswert?

Jobst M. schrieb:
> start

Nun ja, geht, aber das ist blockierend konstruiert. Außerdem vertraut es 
auf hardwaremäßige Entprellung.

So langsam müßte unser TO endlich in die Puschen kommen.

W.S.

von Peter D. (peda)


Lesenswert?

W.S. schrieb:
> Nun ja, geht, aber das ist blockierend konstruiert.

Außerdem läuft die gewünschte Aktion erst nach Loslassen ab.
Man möchte aber die Reaktion schon beim Drücken haben.

von Jobst M. (jobstens-de)


Lesenswert?

W.S. schrieb:
> Nun ja, geht, aber das ist blockierend konstruiert.

War nicht gefordert, dass es nicht so ist.


Peter D. schrieb:
> Man möchte aber die Reaktion schon beim Drücken haben.

Huber M. schrieb:
> -ich drücke, lasse los, dann zählt er um eins hoch


Gruß

Jobst

von Dieter F. (Gast)


Lesenswert?

W.S. schrieb:
> So langsam müßte unser TO endlich in die Puschen kommen.

Ihm ist schon in x Threads empfohlen worden, mal ein C-Buch in die Hand 
zu nehmen, zu Lesen bzw. das Tutorial durchzuarbeiten ...

Er lässt sich das wohl lieber erklären / vormachen ...

von Huber M. (michael_h784)


Lesenswert?

Dieter F. schrieb:
> Ihm ist schon in x Threads empfohlen worden, mal ein C-Buch in die Hand
> zu nehmen, zu Lesen bzw. das Tutorial durchzuarbeiten ...




Ich muss mir erst noch eines für C99  bestellen, denn ich habe zwei, 
aber aus meiner unwissenheit sind diese für arduino und arduino und C 
gewesen, denn ich will nicht mit forgefertigten platinen arbeiten, 
sondern ich will mir selbst welche bauen. Deshalb dachte ich mir das der 
arduino nicht das richtige für mich ist,Und habe in bei seite gelegt. 
Und habe mir attiny24a, atmega8 zugelegt. und einen isp mk2 programmer 
original.Und ja das grundprinzip ist das gleiche, aber dann für mich 
auch irgendwie doch nicht.

Dieter F. schrieb:
> Ihm ist schon in x Threads empfohlen worden, mal ein C-Buch in die Hand
> zu nehmen, zu Lesen bzw. das Tutorial durchzuarbeiten ...


>
> Er lässt sich das wohl lieber erklären / vormachen ...

das stimmt nicht, ich frage nur wenn ich etwas nicht weiss oder 
verstehe.

von Huber M. (michael_h784)


Lesenswert?

jetzt habe ich schon mal ein buch, aber ich bin immer noch nicht 
gescheiter.
1
#define F_CPU 1000000UL
2
#include <util/delay.h>
3
#include <stdbool.h>
4
#include <avr/io.h>
5
#define led (1<<PC0)
6
#define ein PORTC |=
7
#define aus PORTC &= ~
8
9
bool tastergedrueckt = true;
10
11
int main(void)
12
{ DDRC = (1<<PC0);
13
  PORTD =(1<<PD0);
14
  
15
  
16
  void ledblink()
17
  {
18
   PORTC |= (1<<PC0);
19
   _delay_ms(400);
20
   PORTC &= ~(1<<PC0);
21
   _delay_ms(400); 
22
   PORTC |= (1<<PC0);
23
   _delay_ms(400);
24
   PORTC &= ~(1<<PC0);
25
   _delay_ms(400);
26
  }
27
  
28
  
29
  
30
    while(1)
31
    {
32
    
33
    
34
    
35
   if (!(PIND&(1<<PD0)))
36
   {   _delay_ms(300);
37
     tastergedrueckt = true;
38
   } 
39
   else
40
   {
41
     tastergedrueckt = false;
42
   }
43
      
44
   if (tastergedrueckt == true)
45
   {
46
     PORTC |= (1<<PC0);
47
    
48
     
49
   }
50
   int a = 0;
51
   if (tastergedrueckt == false)
52
   {
53
     PORTC &= ~(1<<PC0);
54
     a=a+1;
55
   }
56
   if (a >= 5)
57
   {
58
     ledblink();
59
   }
60
   
61
   
62
   
63
    }
64
}

von Jobst M. (jobstens-de)


Lesenswert?

Huber M. schrieb:
> jetzt habe ich schon mal ein buch, aber ich bin immer noch nicht
> gescheiter.

Es reicht nicht, es zu haben.


Gruß

Jobst

von Manfred (Gast)


Lesenswert?

Jobst M. schrieb:

>            start
>              |
>              +<-------,
>              |        |
>           taster      |
>          gedrückt?    |
>          ja   nein    |
>           |     |     |
>          N++    '-->--+
>           +<-------,  |
>           |        |  |
>        taster      |  |
>       gedrückt?    |  |
>       nein  ja     |  |
>        |     |     |  |
>        |     '-----'  |
>        |              |
>        |              |
>        '------->------'

So zählt er schon beim drücken hoch. ;-)

von Jobst M. (jobstens-de)


Lesenswert?

Manfred schrieb:
> So zählt er schon beim drücken hoch. ;-)

Super, kam schon jemand anders drauf. Ist aber genau das, was der TO 
nicht möchte:

Huber M. schrieb:
> -ich drücke, lasse los, dann zählt er um eins hoch


Gruß

Jobst

von Manfred (Gast)


Lesenswert?

Huber M. schrieb:


Das stimmt so aber nicht. Das war der erste Satz des TO

> Hallo,
>
> ich möchte während ich den taster an PA0 drücke die variable a immer um
> +1 hochzählen.

von Jobst M. (jobstens-de)


Lesenswert?

Dann soll er sich das aussuchen ...

von Murmelchen (Gast)


Lesenswert?

Hallo Michael,

würdest Du dein Programm Schritt für Schritt durchgehen und zudem auch 
noch zumindest halbwegs verstehen, was Du da geschrieben hast, dann 
solltest Du eigentlich auch erkennen, was mit deinem Zähler, also der 
Variablen a, innerhalb deiner Endlosschleife passiert und warum es nicht 
gut ist, eine Variable, die ja innerhalb dieser Endlosschleife nur 
aufgrund eines bestimmten Ereignisses inkrementiert werden soll, auch 
gleichzeitig (immer wieder) in dieser Schleife zu initialisieren.

Schau, wo deine Endlosschleife beginnt und wie weit sie geht und 
überlege Dir dann einfach mal, was durch den Ausdruck  int a = 0; 
innerhalb dieser Endlosschleife bewirkt wird.

Apropos, auch das
1
#define led (1<<PC0)
2
#define ein PORTC |=
3
#define aus PORTC &= ~

ist zwar ein ganz netter Ansatz bezüglich besserer Lesbarkeit, aber so 
auch noch ziemlich verdreht, zumal es bisher ja auch noch gar keine 
Verwendung in deinem Programm findet. Das aber auch nur so am Rande. Auf 
dein Zählerproblem hat es keinen Einfluss.


Mit besten Grüßen

Murmelchen

von Thomas E. (picalic)


Lesenswert?

Murmelchen schrieb:
> würdest Du dein Programm Schritt für Schritt durchgehen

am Besten mit einem Debugger - @Michael: warum benutzt Du den nicht?

von Huber M. (michael_h784)


Lesenswert?

Thomas E. schrieb:
> Murmelchen schrieb:
>> würdest Du dein Programm Schritt für Schritt durchgehen
>
> am Besten mit einem Debugger - @Michael: warum benutzt Du den nicht?

so wie bei emmbedded workbench (MSP430) die locals dann ansehen. Das 
wäre ein Traum!!!!!. Da komme ich seit Wochen nicht drauf, wie man das 
(bei ATMEl Studio 6.2) einstellt, das er mir dann die int Werte im 
(local fenster) anzeigt und die berechneten ergebnisse.

das Inkrmentieren ist ja eigentlich so einfach das es schon wieder 
kompliziert ist.

ich glaube mein Hauptproblem ist ganz einfach, und zwar verwirrt mich 
irgendwie das, wie ich dem Taster an Port D0 (PD0) einer int variable 
zuweise die halt dann eben 0 oder 1 ist.


im embedded workbench ist das ganz easy P1IN der Variable taster 
zuweisen, schon ist die Variable im gedrückten Zustand bei 1.
1
 
2
3
int taster =P1IN; // so funktionierts bei MSP430 embedded workbench
4
int druckzaehler = 0;
5
 while(1)
6
 {
7
   if(taster == 0)
8
   {
9
   druckzaehler++;
10
   }
11
12
 }
13
  return 0;
14
 
15
}


und da ich es mir bei Atmel studio 6.2 im debugger nicht anschauen kann. 
sind wohl meine Gedanken komplett aus den ruder gelaufen und dann kamen 
solche Code beispiele wie oben raus, weil ich nicht mehr wusste was ich 
tun soll.

wie weisst man jetzt eigentlich richtig den PD0 einer int Variable 
namens taster zu, das sie dann eben 0 oder 1 ist.

grüsse huber

von Arduinoquäler (Gast)


Lesenswert?

Huber M. schrieb:
> wie weisst man jetzt eigentlich richtig den PD0 einer int Variable
> namens taster zu, das sie dann eben 0 oder 1 ist.

Du fragst den betreffenden Port ab (lesen), damit hast du
8 Bit. Aus diesen 8 Bit maskierst du das Bit aus das deinen
Tastenzustand beinhaltet und prüfst ob es 1 oder 0 ist.
Wenn es 1 ist weist du deiner Zustandsvariablen 1 zu, wenn
es Null ist weist du deiner Zustandsvariablen 0 zu. Oder
genau umgekehrt, je nachdem ob dein Taster eine aktive 1
oder eine aktive Null generiert.

Merke: das entsprechende Maskierte Bit der Taste ist nicht
gleich dem Wert der Zustandsvariable deiner Taste.

Huber M. schrieb:
> Taster mit kondensator entprellt.

Das funktioniert nur bedingt. Eine vernünftige Entprell-
Schaltung braucht einen Kondensator und zwei Widerstände.
Bei deinem Herumexperimentieren fällst du evtl schon wegen
dem Prellen auf die Schnauze.

von Huber M. (michael_h784)


Lesenswert?

> int taster =P1IN; // so funktionierts bei MSP430 embedded workbench

warum funtioniert das dann bei mir nicht mit atmel, ich dachte man macht 
das so:

//
PORTD = (1<<PD0); // oder 0b00000001; // oder 0x0x

wenn ich das so mache:
1
int taster = (1<<PD0);

da ich mir den debugger bei Atmel Studio noch nicht so einstellen kann, 
das ich mir die locals ansehen kann, kann ich es auch nicht kontrolieren 
ob er 1 oder null macht. Und da ich mir nicht sicher bin ob die 
zuweisung in diesem fall so korrekt ist. macht mir das riesige probleme.

von M.A. S. (mse2)


Lesenswert?

W.S. schrieb:
> Nun ja, geht, aber das ist blockierend konstruiert.
Wenn der Mikrocontroller nur ganz einfache Dinge tun muss, ist das 
völlig ok.
Kompliziertere Dinge wird der TO zur Zeit noch nicht hinkriegen, wenn er 
mit so einfacher Programmierlogik schon Probleme hat.

von Arduinoquäler (Gast)


Lesenswert?

Huber M. schrieb:
> da ich mir den debugger bei Atmel Studio noch nicht so einstellen kann,
> das ich mir die locals ansehen kann, kann ich es auch nicht kontrolieren
> ob er 1 oder null macht.

Eine Tasten-Variable lokal zu deklarieren macht ja auch wenig
Sinn da die Taste ja für die ganze Software gültig sein soll.
Also deklariere sie global. Im übrigen macht es auch wenig Sinn
diese als Integer zu deklarieren. uint8_t reicht aus und macht
die Operationen damit übersichtlicher, durchsichtiger.

Lokale Variablen sind übrigens dann nicht sichtbar wenn sie
durch eine Optimierungsstufe des Compilers weg-optimert werden.

von Huber M. (michael_h784)


Lesenswert?

Mahlzeit,
ich verstehe nicht warum das ganze nicht Funktioniert das kann nur am 
tasterpin einlesen liegen? Nur mal zum verständnis, wenn ich das ganze 
so(nachfolgend) schreibe, macht es ja auch was es soll. oder bin ich da 
komplett verkehrt
1
 
2
3
  int anton = 1;
4
  int berta = 0;
5
 
6
  while(1)
7
 {
8
   if(anton > 0)
9
   {
10
   berta++;
11
   }
12
   if (berta == 5)
13
   {
14
   berta = 0;
15
    }
16
 }
17
18
und hier mein Aktueller Code
[]/*
 * GccApplication27.c
 *
 * Created: 20.09.2016 16:33:10
 *  Author: Huber
 */

#define F_CPU 1000000UL
#include <util/delay.h>
#include <stdbool.h>
#include <avr/io.h>



int main(void)
{
  // EIN u. AUSGÄNGE konfigurieren

  PORTD = (1<<PD0); // Eingang
  DDRC = (1<<PC0);// Ausgang

 // eigen funktion erstellen

 void blinkled()
 {
   PORTC|= (1<<PC0);
   _delay_ms(300);
   PORTC&= ~(1<<PC0);
   _delay_ms(300);
 }
    int taster = PIND0; // Lese an PIND0 ob high or low
    int druckzaehler = 0;
    while(1)
    {
      if(taster > 0 )
      {
        druckzaehler++;
      }
      if (druckzaehler == 5)
      {

        PORTC |= (1<<PC0);
      }

    }

  }

[]

von Huber M. (michael_h784)


Lesenswert?

Arduinoquäler schrieb:
> Lokale Variablen sind übrigens dann nicht sichtbar wenn sie
> durch eine Optimierungsstufe des Compilers weg-optimert werden.

den habe ich unter optimize auf none -O0 gestellt

von Arduinoquäler (Gast)


Lesenswert?

Huber M. schrieb:
> int main(void)

Das sind soviele Macken drin dass man dir wirklich nur
raten kann die Sprache C von Grund auf zu lernen.

von lalala (Gast)


Lesenswert?

vielleicht 'taster=PIND0;' in die while(1) -Schleife hineinpacken? 
Ansonsten muss die Taste beim Starten gedrückt sein.
Schreib doch mal auf was genau passieren soll; das Anton-Berta Ding 
sieht auch ganz schön verkehrt aus. (Da kannst Du Anton auch weglassen).

von Huber M. (michael_h784)


Lesenswert?

Arduinoquäler schrieb:
> Huber M. schrieb:
>> int main(void)
>
> Das sind soviele Macken drin dass man dir wirklich nur
> raten kann die Sprache C von Grund auf zu lernen.

das setzt das atmel studio schon als standard automatisch hin.

von Arduinoquäler (Gast)


Lesenswert?

Huber M. schrieb:
> das setzt das atmel studio schon als standard automatisch hin.

Man versteht ja schon deine Ausdrucksweise nicht. Sorry.
Und dass sich meine Aussage auf den ganze geposteten Code
bezieht hast du wohl auch nicht verstanden.

von Huber M. (michael_h784)


Lesenswert?

ich wollte eigentlich einfach nur per Tasterdruck (ohne dass, das die 
Standard mässige vorgehensweise ist) eine Variable hochzählen ohne  das 
es einen grossen Sinn macht, denn ich bin jetzt einfach noch mal an den 
Anfang gegangen, wo Rechnen mit

int a + int b und int c = c / a+b usw...und

if ( a <= b)
{
 d= d+1;

}
if( d == 5)
{

d = 0;
}

zur übung steht.

das kann man auch mit nem texas instrument board machen. und dort wenn 
ich zb. int a = P1IN; hinschreibe dann liest er den pin ein. zeigt halt 
im debugger 0 oder 1 an.

ich dachte mir das muss doch mit dem im Atmelstudio mit dem Atmega8a 
auch gehen, da lag ich wohl falsch. da sollte mir halt wenn d == keine 
ahnung halt 5 ,ist die led an pc4 anschalten.

von lalala (Gast)


Lesenswert?

Huber M. schrieb:
> zb. int a = P1IN;

aber in der while(1) Schleife drin, und nicht draußen.

von Huber M. (michael_h784)


Lesenswert?

Huber M. schrieb:
> zb. int a = P1IN;

aber in der while(1) Schleife drin, und nicht draußen.

Ja, das habe ich schon gemacht, das ändert aber nichts. In
IDE ATMEL STUDIO 6.0 und Atmega8a muesste es ja dann so heissen oder?
>int a = PIND;
>int a = (1<<PD0);

das > zb. int a = P1IN; ist eine andere IDE embedded workbench

von LostInMusic (Gast)


Lesenswert?

Wenn Du den Unterschied zwischen
1
int main(void)
2
  {
3
  int taster = PIND;
4
 
5
  while(1)
6
    {
7
    ...
8
    <irgendwas mit taster anstellen>
9
    ...
10
    }
11
  }
und
1
int main(void)
2
  {
3
  int taster;
4
 
5
  while(1)
6
    {
7
    taster = PIND;
8
    ...
9
    <irgendwas mit taster anstellen>
10
    ...
11
    }
12
  }
verstanden hast, bist Du schon ein großes Stück weitergekommen.

von Einer K. (Gast)


Lesenswert?

Huber M. schrieb:
> IDE ATMEL STUDIO 6.0 und Atmega8a muesste es ja dann so heissen oder?
>>int a = PIND;
>>int a = (1<<PD0);

Nein.
Eher so:
>uint8_t a =  PIND|(1<<PD0);

von Ralf G. (ralg)


Lesenswert?

Arduino F. schrieb:
>>uint8_t a =  PIND|(1<<PD0);
was soll das jetzt bewirken?

von Jobst M. (jobstens-de)


Lesenswert?

Arduinoquäler schrieb:
> Man versteht ja schon deine Ausdrucksweise nicht. Sorry.

Du gehst davon aus, dass er Deinen Satz verstanden hat. Hat er nicht!
Er geht davon aus, dass Du rätselst, ob es sich um C handelt.
Auch einige andere Sätze scheint er nicht verstanden zu haben.

@TO:
Verkauf den Krempel. Du kannst damit nichts anfangen, es überfordert 
Dich!
Und die Aufgaben werden bei weiteren Projekten wesentlich (!) komplexer.


Gruß

Jobst

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Ralf G. schrieb:
> Arduino F. schrieb:
>>>uint8_t a =  PIND | (1<<PD0);
> was soll das jetzt bewirken?

Naja...
Ich dachte mir so...

Huber M. schrieb:
>>int a = PIND;
>>int a = (1<<PD0);
Das wäre ein unbeholfener Versuch einen Taster einzulesen....
Vielleicht habe ich mich ja auch getäuscht.
Dann bin ich jetzt ent- täuscht.

von Arduinoquäler (Gast)


Lesenswert?

Jobst M. schrieb:
> Hat er nicht!

Ja.

Jobst M. schrieb:
> Auch einige andere Sätze scheint er nicht verstanden zu haben.

Ja.

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Anbei mal Entprellung mit Timerinterrupt (ungetestet).

von Dieter F. (Gast)


Lesenswert?

Peter D. schrieb:
> ungetestet

:-) witzig ...


Da sind wir aber einige Sphären außerhalb "Huber M."-s aktuellem 
Kenntnisstands.

Er (der TO) hat sich wohl ein C-Buch gekauft (welches auch immer) aber 
die Verwendung ist fraglich. Hinweise auf das GCC-Tutorial fallen 
scheinbar nicht auf fruchtbaren Boden.

Ich habe mir div. Threads des TO angeschaut und finde überall die 
gleiche Unsicherheit. Aus meiner Sicht fehlen die Grundlagen, die sich 
jeder halt beibringen muss oder via Volkshochschule oder wie auch immer 
erlangen muss.

Karl-Heinz ist ja wohl nicht mehr aktiv ( was mich wirklich sehr 
"bedrückt" - ich finde keinen anderen Ausdruck) und ich habe weder die 
Geduld noch die Leidensfähigkeit ähnlich aktiv einzugreifen. Auch fehlen 
mir die tiefgreifenden Kenntnisse.

@Hubert: Lese Dein Buch und vollziehe alles nach. Gehe das GCC-Tutorial 
Schritt für Schritt durch und probiere alles aus. Setze Dich mit dem 
Debugger des Atmel-Studios auseinander (das ist nicht allzu schwer - das 
weiß ich aus eigener Erfahrung).

von PfostenStecker (Gast)


Lesenswert?

Dieter F. schrieb:
> ...und ich habe weder die
> Geduld noch die Leidensfähigkeit ähnlich aktiv einzugreifen. Auch fehlen
> mir die tiefgreifenden Kenntnisse.

Aber was willst Du dann in diesem Thread? Nutzlose Nebenschauplätze 
eröffnen, oder was sonst?

PfostenStecker

von Dieter F. (Gast)


Lesenswert?

PfostenStecker schrieb:
> Aber was willst Du dann in diesem Thread? Nutzlose Nebenschauplätze
> eröffnen, oder was sonst?

Auf die Sinnlosigkeit (welche Dir wohl entgangen ist) hinweisen.

Wobei Dein Beitrag mehr als nutzlos ist. Typisch Gast, eigentlich wollte 
ich solche Beiträge ignorieren. Ich gelobe Besserung!

von Geduldiger (Gast)


Lesenswert?

Huber M. schrieb:
> ich wollte eigentlich einfach nur per Tasterdruck (ohne dass, das die
> Standard mässige vorgehensweise ist) eine Variable hochzählen ohne  das
> es einen grossen Sinn macht,


Du willst bei einem bestimmten Ereignis, bei einem Tastendruck 
hochzählen. Ein Ereignis passiert zu einem bestimmten Zeitpunkt.

Wenn Du aber mit dem Finger eine Taste drückst, drückst Du aber für eine 
bestimmte Zeitdauer auf die Taste.

Während Du mit dem Finger auf der Taste bist, führt der Mikrocontroller 
locker ein paar Millionen mal Deine Schleife aus. Der ist rasend 
schnell.

Mache Dir den Unterschied zwischen einem Zeitpunkt und einer 
Zeitdauer klar.

Eine kleine Grafik:



      Zeitdauer Taster                Zeitdauer Taster
      nicht gedrückt                      gedrückt
  <-------------------------> <----------------------->

  0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1

                              |
                              |

              Zeitpunkt, hier hat sich der Taster
              von "nicht gedrückt" auf "gedrückt"
              geändert!



Verstehst Du, was ich Dir erklären will?

von Arduinoquäler (Gast)


Lesenswert?

Geduldiger schrieb:
> Verstehst Du, was ich Dir erklären will?

Dieser Mensch gibt keine Rückmeldungen auf Fragen oder
Erklärungen.

Mit anderen Worten:

Vergebene Liebesmüh, du redest an eine Wand.

von Huber M. (michael_h784)


Lesenswert?

Mahlzeit,

Erstmal danke für die Mühe, und die vielen Erklärungen. ich glaube ich 
habe es jetzt..... da es beim taster eigentlich nur vier Zustände gibt

-wenn er gedrückt wird
-wenn er gedrückt ist
-wenn er losgelassen wird
-wenn er nicht gedrückt ist

diese Zustände kann ich dann mit rückgabe jeweils auswerten

grüsse huber

: Bearbeitet durch User
von Murmelchen (Gast)


Lesenswert?

Huber M. schrieb:
> ich glaube ich habe es jetzt.....

Das glaube ich wiederum nicht. ;-)

Vielleicht solltest Du Dir erst mal klar machen, wie diese Art von 
Programmierung überhaupt so abläuft.

Diese Programme bestehen in der Regel aus zwei Teilen. Im ersten Teil 
wird der Controller für seine Aufgabe konfiguriert und die für den 
weiteren Teil des Programms nötigen Variablen deklariert und 
initialisiert. Dieser Teil des Programms wird nach dem Start oder einem 
Reset nur einmal durchlaufen, sprich, die Anweisungen werden nur einmal 
ausgeführt. Hier wird z. Bsp. festgelegt, ob und welche Port(pin)s als 
Eingang oder als Ausgang fungieren und hier wird z. Bsp. deine 
Zählervariable initialisiert.

Der zweite Teil des Programms, bei den es ja darum geht, dass der 
Controller auf bestimmte Ereignisse reagiert, wird dann in der Regel in 
Form einer Endlosschleife ausgelegt. Da so ein Controller so eine 
Endlosschleife aber recht fix durchläuft, ein menschlicher Tastendruck 
aber immer eine gewisse Zeit dauert und Taster und Schalter zudem auch 
noch prellen, also bei Betätigung den Kontakt oft noch mehrmals ändern, 
bevor sich der vom Betätiger gewünschte Zustand stabil einstellt, muss 
im einfachsten Fall nach Erkennen des Tastendrucks eine gewisse Zeit 
gewartet werden, bevor die Taste erneut abgefragt und bei Betätigung 
erneut gezählt wird.

Dein Programm könnte also folgenden Aufbau haben:

1
// nötige Bibliotheken einbinden
2
3
int main(void)
4
{
5
  // Controller konfigurieren
6
  
7
  // Variablen deklarieren und initialisieren
8
9
  int zaehler = 0;
10
11
12
  while(1)  // Beginn der Endlosschleife, durch den Wert 1
13
  {         // immer gültig, wird also endlos ausgeführt
14
15
    if (taste_gedrueckt)    // Abfrage, ob Taste gedrückt
16
    {  // Ausdruck 'taste_gedrueckt' wahr
17
       // es folgen Anweisungen, die nur dann ausgeführt werden, 
18
       // wenn Taste bei Abfrage gedrückt war
19
20
       zaehler = zaehler + 1;
21
22
       // zaehler z. Bspl. zur Visualisierung über einen Port ausgeben
23
      
24
       delay(300ms);  // oder länger warten - Funktionsaufruf 
25
                      // einer Zählschleife
26
27
    }  // Ende der Anweisungen, die nur abgearbeitet werden, 
28
       // wenn bei Abfrage die Taste gedrückt war
29
30
  }  // Ende der Endlosschleife - es folgt der nächste while(1) Durchlauf
31
     // die Taste wird dabei erneut abgefragt 
32
33
}  // Programmende - wird durch die Endlosschleife nie erreicht


Die Sache mit dem Entprellen könnte man natürlich noch stark verfeinern, 
z. Bsp. kurze Störungen filtern, die Verzögerungszeit soweit verkürzen, 
dass der Einfluss des Prellen zwar eliminiert wird, dabei aber trotzdem 
keine unnötigen Verzögerungen entstehen. Sicherstellen, dass nach 
drücken der Taste diese auch erst wieder losgelassen werden muss, bevor 
erneutes drücken als gültig betrachtet wird usw. Auch wäre eine 
Auswertung über einen Interrupt möglich. Aber all das dürfte deine 
Fähigkeiten und deinen Kenntnisstand zur Zeit noch überfordern. Deshalb 
versuche erst mal anhand der obigen Beschreibung ein lauffähiges 
Programm zu erstellen.


Mit besten Grüßen

Murmelchen

von W.S. (Gast)


Lesenswert?

Huber M. schrieb:
> da es beim taster eigentlich nur vier Zustände gibt
>
> -wenn er gedrückt wird
> -wenn er gedrückt ist
> -wenn er losgelassen wird
> -wenn er nicht gedrückt ist

Du schreibst und denkst noch immer unlogisch und wirr.

Also: Es gibt bei einem Taster nur exakt 2 Zustände:
1. gedrückt
2. ungedrückt.

Das "gedrückt _werden_" ist kein Zustand, sondern ein Übergang, nämlich 
von einem Zustand in einen anderen. Ebenso das "ungedrückt werden" bzw. 
losgelassen werden.

An einem Übergang muß man ein Ereignis generieren, das zu einer Reaktion 
führen soll (beispielsweise zum Hochzählen eines Zählers): entweder beim 
Übergang von ungedrückt zu gedrückt oder bei dem anderen Übergang.

Ich hab dir weiter oben mit der Fabel vom fleißigen Beamten quasi eine 
Bauanleitung für deine Software geschrieben, aber du scheinst sie 
überhaupt nicht gelesen zu haben, weswegen du immer noch 
orientierungslos dahintaumelst.

W.S.

von Geduldiger (Gast)


Lesenswert?

Huber M. schrieb:
> -wenn er gedrückt wird
> -wenn er gedrückt ist
> -wenn er losgelassen wird
> -wenn er nicht gedrückt ist

Ja, das kommt in etwa hin. Der Taster hat entweder den Zustand 
"gedrückt" oder "nicht gedrückt".

Aber Dein Programm muss unterscheiden, zwischen:

- Taster jetzt nicht gedrückt, vorher war er auch nicht gedrückt
- Taster jetzt gedrückt, aber vorher eben war er noch nicht gedrückt
- Taster jetzt gedrückt, und vorher war er auch gedrückt
- Taster jetzt nicht gedrückt, aber vorher eben war er gedrückt

Genau das sind die Fälle, die dein Programm unterscheiden muss. Und in 
genau einem Fall der vier möglichen Fälle, soll dein Programm zählen 
oder etwas anderes machen. Der Hauptteil des Programms könnte so 
aussehen:

1
  int taster_vorher = 0;
2
  int taster_jetzt = 0;
3
4
  // Endlosschleife
5
  while(1)
6
  {
7
    // Nachschauen, wie der Taster jetzt steht
8
    if ( (PINA & (1<<PA0)) )
9
      taster_jetzt = 1;
10
    else
11
      taster_jetzt = 0;
12
13
    // Prüfen, ob der Taster sich gegenüber vorher verändert hat
14
    if ( taster_vorher == 0  &&  taster_jetzt == 1 )
15
    {
16
      // Bingo, Taster wurde gerade eben gedrückt, hier also Zählen etc.
17
      ...
18
    }
19
20
    // Endlosschleife springt gleich an den Anfang zurück: Was jetzt aktuell ist, ist nachher alt  
21
    taster_vorher = taster_jetzt;
22
  }


Versuch mal, das Programm zu vervollständigen.

Viel Erfolg! Du bekommst das bestimmt hin!

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.