mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Verständnis Problem


Autor: J. V. (avrmactech)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Codeausschnitt:
if (!(PIND & (1 << PD7)))     // Führe Aktion aus wenn, 
                              // PD 7 auf Masse gezogen wird 
  {
    anzahl++;                 // Inkrementiere anzahl um 1
    while(PIND & (1 << PD7)){ // Starte Schleife, 
                              // 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).

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

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

Gruß aus Berlin
Michael

Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht 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.
#include <avr/io.h>                // Register Deklaration
#include <util/delay.h>              // Timer Funktion

int main(void){                  // Hauptfunktion
  
  DDRB = 0xff;                // Port B ist Ausgang
  DDRD = 0x00;                // Port D ist Eingang, Eing�nge sind �ber einen Wid. nach VCC gezogen
    
  unsigned char anzahl=0, i;          // Variablendefinition
  
  
  for(;;)
  {                  // Endlosschleife
    if (!(PIND & (1 << PD7)))          // F�hre Aktion aus wenn,PD 7 auf Masse gezogen wird 
    {
        anzahl++;                // Inkrementiere anzahl um 1
    }

    if (PIND & (1 << PD7))
    {        // Starte Schleife, wenn an PD7 ein High anliegt
          _delay_ms(500);            // ca. 5 Sekunden warten
          for(i = 0;i > anzahl;i++)
          {          // Schleife, so oft ausf�hren wie Tastegedr�ckt worden ist
        
            PORTB = 0xff;            // Port B einschalten
            _delay_ms(100);          // ca. 1 Sekunde Pause
            PORTB = 0x00;            // Port B ausschalten
            _delay_ms(100);          // ca. 1 Sekunde warten  
          }                          // Ende for
     }                // Ende if
  }                      // Ende for, Endlos
}       

Gruß
Frank

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So könnte es gehen:
#include <avr/io.h>           // Register Deklaration
#include <util/delay.h>       // Timer Funktion

int main(void)
{
  unsigned char anzahl = 0;
  unsigned char hunderstel = 0;
  unsigned char i;
  
  // Hardwareinitialisierung
  DDRB = 0xff;                // Port B ist Ausgang
  DDRD = 0x00;                // Port D ist Eingang, 
  // Eingänge sind über einen externen Widerstand nach VCC gezogen

  // Arbeitsschleife    
  for(;;)
  {
    // Grobe Uhr
    _delay_ms(100);
    hunderstel++;

    // Eingabe
    if (!(PIND & (1 << PD7)))
    {
      // Zählen, wenn PD7 auf Masse gezogen wird 
      anzahl++;

      // Warten auf losgelassen
      while(!(PIND & (1 << PD7))) 
      {
        _delay_ms(100);
        hunderstel++;
      } 
    }

    // Ausgabe
    if (hunderstel >= 50)      // ca. 5 Sekunden Eingabe abgelaufen?
    {
      // Anzahl-mal Blinken
      for(i = 0; i < anzahl; i++)
      {          
        PORTB = 0xff;          // Port B einschalten
        _delay_ms(1000);       // ca. 1 Sekunde Pause
        PORTB = 0x00;          // Port B ausschalten
        _delay_ms(1000);       // ca. 1 Sekunde warten  
      }

      // Ausgabe erledigt, jetzt Uhr und Eingabe zurücksetzen
      anzahl = 0;
      hunderstel = 0;
    }
  }
}


Autor: J. V. (avrmactech)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: J. V. (avrmactech)
Datum:
Angehängte Dateien:

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

Ja sind sie, hatte mich vertippt.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: J. V. (avrmactech)
Datum:

Bewertung
0 lesenswert
nicht 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 ;-)

Autor: J. V. (avrmactech)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
im Makefile steht aber doch:

DEVICE     = atmega8
CLOCK      = 8000000
PROGRAMMER = -c USBasp

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: J. V. (avrmactech)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
You are welcome ;-)

Autor: Friedrich Janus (franjuja)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.