Forum: Mikrocontroller und Digitale Elektronik Verständnis Problem


von J. V. (avrmactech)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich bin Neu auf dieser Webseite und schwer begeistert von den vielen 
Informationen.
Seit nun ein paar Tagen habe ich angefangen, hier zu lesen und mich 
etwas in die Materie einzuarbeiten. Ziel soll es sein, dass ich kein 
Code - Kopierer werde, sondern das ich die Materie verstehe und selber 
entwerfen kann. (auch wenn es lange dauert:-) )

Es sind bei mir auch einfachste Grundkenntnisse in C vorhanden. Aber 
irgendwie bekomme ich das folgende Übungsprogramm trotzdem nicht zum 
laufen und hoffe auf Hilfe.

Ich möchte lediglich ein Programm schreiben, welches die Tastendrücke 
zählt, die in einer bestimmten Zeit anliegen und diese dann später 
wieder ausgibt.


Mein erster Ansatz, liegt in der angehängten Datei.


Ich hoffe, mir kann einer meinen Gedankenfehler aufzeigen und erklären.

MfG, Julian

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Codeausschnitt:
1
if (!(PIND & (1 << PD7)))     // Führe Aktion aus wenn, 
2
                              // PD 7 auf Masse gezogen wird 
3
  {
4
    anzahl++;                 // Inkrementiere anzahl um 1
5
    while(PIND & (1 << PD7)){ // Starte Schleife, 
6
                              // wenn an PD7 ein High anliegt

Um in dem if Fall in das while reinzukommen, musst du den Taster 
extrem schnell loslassen. Das schafft das kein Mensch (außer Chuck 
Norris natürlich).

von Michael U. (amiga)


Lesenswert?

Hallo,

Du hast zwar verraten, was Du erreichen willst, nicht aber, was 
stattdessen passiert...

Gruß aus Berlin
Michael

von Frank L. (franklink)


Lesenswert?

Hallo,
unabhängig davon, ob Dein Code wirklich das tut was er soll, hast Du 
Deine Aussgabe (LED blinken) innerhalb des Bereichs positioniert in dem 
der Schalter gedrückt ist.
1
#include <avr/io.h>                // Register Deklaration
2
#include <util/delay.h>              // Timer Funktion
3
4
int main(void){                  // Hauptfunktion
5
  
6
  DDRB = 0xff;                // Port B ist Ausgang
7
  DDRD = 0x00;                // Port D ist Eingang, Eing�nge sind �ber einen Wid. nach VCC gezogen
8
    
9
  unsigned char anzahl=0, i;          // Variablendefinition
10
  
11
  
12
  for(;;)
13
  {                  // Endlosschleife
14
    if (!(PIND & (1 << PD7)))          // F�hre Aktion aus wenn,PD 7 auf Masse gezogen wird 
15
    {
16
        anzahl++;                // Inkrementiere anzahl um 1
17
    }
18
19
    if (PIND & (1 << PD7))
20
    {        // Starte Schleife, wenn an PD7 ein High anliegt
21
          _delay_ms(500);            // ca. 5 Sekunden warten
22
          for(i = 0;i > anzahl;i++)
23
          {          // Schleife, so oft ausf�hren wie Tastegedr�ckt worden ist
24
        
25
            PORTB = 0xff;            // Port B einschalten
26
            _delay_ms(100);          // ca. 1 Sekunde Pause
27
            PORTB = 0x00;            // Port B ausschalten
28
            _delay_ms(100);          // ca. 1 Sekunde warten  
29
          }                          // Ende for
30
     }                // Ende if
31
  }                      // Ende for, Endlos
32
}

Gruß
Frank

von Stefan B. (stefan) Benutzerseite


Lesenswert?

So könnte es gehen:
1
#include <avr/io.h>           // Register Deklaration
2
#include <util/delay.h>       // Timer Funktion
3
4
int main(void)
5
{
6
  unsigned char anzahl = 0;
7
  unsigned char hunderstel = 0;
8
  unsigned char i;
9
  
10
  // Hardwareinitialisierung
11
  DDRB = 0xff;                // Port B ist Ausgang
12
  DDRD = 0x00;                // Port D ist Eingang, 
13
  // Eingänge sind über einen externen Widerstand nach VCC gezogen
14
15
  // Arbeitsschleife    
16
  for(;;)
17
  {
18
    // Grobe Uhr
19
    _delay_ms(100);
20
    hunderstel++;
21
22
    // Eingabe
23
    if (!(PIND & (1 << PD7)))
24
    {
25
      // Zählen, wenn PD7 auf Masse gezogen wird 
26
      anzahl++;
27
28
      // Warten auf losgelassen
29
      while(!(PIND & (1 << PD7))) 
30
      {
31
        _delay_ms(100);
32
        hunderstel++;
33
      } 
34
    }
35
36
    // Ausgabe
37
    if (hunderstel >= 50)      // ca. 5 Sekunden Eingabe abgelaufen?
38
    {
39
      // Anzahl-mal Blinken
40
      for(i = 0; i < anzahl; i++)
41
      {          
42
        PORTB = 0xff;          // Port B einschalten
43
        _delay_ms(1000);       // ca. 1 Sekunde Pause
44
        PORTB = 0x00;          // Port B ausschalten
45
        _delay_ms(1000);       // ca. 1 Sekunde warten  
46
      }
47
48
      // Ausgabe erledigt, jetzt Uhr und Eingabe zurücksetzen
49
      anzahl = 0;
50
      hunderstel = 0;
51
    }
52
  }
53
}

von J. V. (avrmactech)


Lesenswert?

Hallo,

danke für die ganzen schnellen Antworten!!!

Also die letzte Version von Stefan B. habe ich getestet, aber sie läuft 
nicht richtig.

Versuchsaufbau: ATmega 8 mit internem Takt von 8 MHz, Pin 13(PD7) mit 
Widerstand nach 5 VDC. Der Taster verbindet PD7 bei Betätigung mit 
Masse. An Port D sind LED Angeschlossen.

Die Zeiten für An/Aus habe ich etwas nach unten geändert.

Wenn ich den Taster betätige, wobei die Anzahl der Betätigungen keine 
Rolle zu spielen schein, dann blinken die LED's einmal auf und mehr 
passiert nicht.

Eigentlich müsste er doch in der while- Schleife hängen, oder? Da der 
Taster nach der Eingabe nicht mehr betätigt wird, müsste er doch die 
hunderstel ins Endlose zählen?!?!

MfG

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> ATmega 8 mit internem Takt von 8 MHz

Sicher?

Ab Werk sind es 1 MHz.
8 MHz geht nur nach Umprogrammieren der Fuses.

> An Port D sind LED Angeschlossen.

Die LED müssen an PORTB angeschlossen werden!

> Eigentlich müsste er doch in der while- Schleife hängen, oder? Da der
> Taster nach der Eingabe nicht mehr betätigt wird, müsste er doch die
> hunderstel ins Endlose zählen?!?!

In der while Schleife bleibt der Eingabeteil so lange, wie der Taster 
noch gedrückt ist. Ewig gedrückt zählt auch hunderstel hoch bis ein 
Überlauf stattfindet (255 => 0), d.h. max. in 255*0,1s = 25-26s stellt 
sich die Uhr selbst zurück.

Alle Zeiten sind nur gültig, wenn der Takt stimmt (1 MHz/8 MHz 
Geschichte). Bei falscher Einstellung hier wird es komisch.

von J. V. (avrmactech)


Angehängte Dateien:

Lesenswert?

Ja ich denke schon, habe den Takt im Makefile definiert (siehe Anhang).

Ja sind sie, hatte mich vertippt.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Julian Vogel schrieb:

> Ja ich denke schon, habe den Takt im Makefile definiert (siehe Anhang).

Reicht nicht. Die HARDWARE muss entsprechend zur Definition im Makefile 
eingestellt sein bzw. die Definition im Makefile richtet sich nach der 
aktuellen Taktrate in der Hardware.

von J. V. (avrmactech)


Lesenswert?

> In der while Schleife bleibt der Eingabeteil so lange, wie der Taster
> noch gedrückt ist. Ewig gedrückt zählt auch hunderstel hoch bis ein
> Überlauf stattfindet (255 => 0), d.h. max. in 255*0,1s = 25-26s stellt
> sich die Uhr selbst zurück.

Stimmt, die while Schleife ist ja hinter dem ersten if............ich 
sollte besser lesen ;-)

von J. V. (avrmactech)


Lesenswert?

im Makefile steht aber doch:

DEVICE     = atmega8
CLOCK      = 8000000
PROGRAMMER = -c USBasp

Verstehe nicht was wo fehlt, bzw wo ich es einstelle.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Wenn deine Hardware wie ab Werk mit 1 MHz läuft und deine Definition im 
Makefile 8 MHz ist, dann laufen deine Wartefunktionen (_delay_ms) 8x zu 
langsam.

Die grobe Uhr tickt statt im 0,1s Takt fast im 1s Takt. Eine Ausgabe ist 
erst statt in 5s in ca. 40s zu erwarten... Das kann die Geduld eines 
Testers auf die Probe stellen.

Die Definition im Makefile ist in dem Fall nur (!!!) dazu da, um die 
Anzahl der Maschinenbefehle in der _delay_ms Funktion zu berechnen, so 
dass (Anzahl der Befehle) multipliziert mit (Zeit für einen Befehl) die 
angegebene Zeit vertröderlt wird. Wenn von der Hardware her die Zeit für 
einen Befehl nicht stimmt (Oszillator auf 1 MHz statt auf 8 MHz), stimmt 
die Rechnung nicht.

Wie du die Taktrate (Clock) Hardware anders als in der Werkseinstellung 
einstellst, steht im Datenblatt. Ich rate dir als Anfänger aber, daran 
zunächst nichts zu ändern. Ändere lieber das Makefile von von 8000000 
auf 1000000.

von J. V. (avrmactech)


Lesenswert?

Stefan B. schrieb:
> Wenn deine Hardware wie ab Werk mit 1 MHz läuft und deine Definition im
> Makefile 8 MHz ist, dann laufen deine Wartefunktionen (_delay_ms) 8x zu
> langsam.
>
> Die grobe Uhr tickt statt im 0,1s Takt fast im 1s Takt. Eine Ausgabe ist
> erst statt in 5s in ca. 40s zu erwarten... Das kann die Geduld eines
> Testers auf die Probe stellen.

ggg alles klar, ich habe jetzt den Takt im Makefile auf 1 MHz gestellt 
und siehe da, deine Lösung funktioniert einwandfrei!!!
Vielen Dank!!

Gut daraus lerne ich, meine Fragen in Zukunft genauer zu stellen und 
mehr meine Birne anzustrengen. Motiviert durch den Erfolg, werde ich 
bestimmt zu einem Stammgast werden.

MfG, Julian

von Stefan B. (stefan) Benutzerseite


Lesenswert?

You are welcome ;-)

von Friedrich J. (franjuja)


Lesenswert?

Hallo Julian,

die AVR werden aus Anlaufgründen (siehe Datenblatt) nicht mit der 
externen Taktfrequenz angefahren sondern es wird ein Vorteiler 
eingeschaltet (typisch /8). Diesen kannst du SW-technisch ausschalten, 
danach läuft der Prozessor mit voller Geschwindigkeit.

Dein Makefile sollte daher auf die von Dir im Prozessor eingestellte 
Geschwindigkeit abgestimmt sein. Dies hast du in deinem Fall dadurch 
erreicht, daß du das Makefile geändert hast. SO geht es natürlich aus, 
aber die prozessorgeschwindigkeit hast Du damit noch nicht geändert.

rgds

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.