Forum: Mikrocontroller und Digitale Elektronik Taster LED Evaluation Board v2.01


von Christof K. (christof_k)


Lesenswert?

Hallo

Ich arbeite mich gerade durch das Tutorial. Dazu habe ich ein 
selbstbestücktest Stechboard und ein Atmel Evaluation Board v2.01.

Zu Anfang habe ich versucht die LEDs zum leuchten und den Summer des 
Evaluation Boards zum summen zu bringen.

Die LEDs leuchten zu lassen, wenn der Taster gedrückt, ist kein Problem.

Der Summer benötigt zwischen den Zustandswechsel des Ausgangs PD07 
"längere" Pausen. Das wird aber erst im späteren Kapitel erläutert. Zur 
Zeit knackt nur einmal und das wars.

Nun wollte ich einfach mal schauen, ob ich mit dem bis jetzt erlerntem 
auch die Taster als Schalter nutzen kann um die LEDs an und aus zu 
schalten.

Nach vielen misglückten Versuchen frage ich mal nach, wo mein Fehler 
liegt.

Das aktuelle Programm sieht so aus. Liefert aber nicht das gewünschte, 
sondern nur ein chaotisches Verhalten. Mal funktionierts, mal schaltet 
die falsche LED an und aus, mal beide.
1
 .include "m8def.inc"
2
3
 .def temp = r16
4
5
  ldi temp, 0b11100000
6
  out DDRD, temp          ;Setzt die Pins PD5 - PD7 als Ausgang
7
8
  ldi temp, HIGH(RAMEND)      ; HIGH-Byte der obersten RAM-Adresse
9
  out SPH, temp
10
  ldi temp, LOW(RAMEND)      ; LOW-Byte der obersten RAM-Adresse
11
  out SPL, temp
12
13
  ldi temp, 0x00
14
  ldi r17, 0b00100000        ;Byte mit dem man Ausgang PD5 mit dem XOR-Befehl switched
15
  ldi r18, 0b01000000        ;Byte mit dem man Ausgang PD6 mit dem XOR-Befehl switched
16
17
  or temp, r17          ;LEDs werden angeschaltet
18
  or temp, r18
19
  out PORTD, temp
20
21
  rcall loop            ; loop aufrufen
22
 
23
loop:    
24
  sbic PIND, 2          ;Wenn Taster gedrückt wird, soll die LED1 entwerden an- oder ausgeschaltet werden
25
  rcall led1
26
27
  sbic PIND, 3          ;Wenn Taster gedrückt wird, soll die LED2 entwerden an- oder ausgeschaltet werden
28
  rcall led2
29
30
  rjmp loop
31
 
32
led1:
33
  eor temp, r17          ;Setzt den Ausgang für die LED1 mit dem XOR Befehl auf 1 oder 0
34
  out PORTD, temp
35
  rcall wait1
36
  ret
37
  
38
led2:
39
  eor temp, r18          ;Setzt den Ausgang für die LED1 mit dem XOR Befehl auf 1 oder 0
40
  out PORTD, temp
41
  rcall wait2
42
  ret
43
44
wait1:                ;Wartet bis Taster 1 wieder losgelassen wird
45
  sbis PIND, 2
46
  ret
47
48
wait2:                ;Wartet bis Taster zwei wieder losgelassen wird
49
  sbis PIND, 3
50
  ret

von Linüx (Gast)


Lesenswert?

Ja dir fehlt die sog. 
Entprellung.http://www.mikrocontroller.net/articles/Entprellung

von oldmax (Gast)


Lesenswert?

Hi
Wenn der "Summer" knackt, dann ist es kein Summer, sondern eher eine Art 
Lautsprecher. Wenn du das Signal schnell wechseln läßt, wirst du einen 
Ton hören.
Das deine LED's zufällig an oder aus sind, liegt am Prellen des 
Schalters. Ein Kontakt schaltet nicht einfach, sondern "flackert" erst 
ein paar mal. Da du aber bei jedem Signalzustand "gedrückt" die LED 
umschaltest, ist das Ergebnis davon abhängig, wie offt du das Flackern 
mitbekommen hast. Da du eine kurze Zykluszeit durch das kleine Programm 
zugrunde legen kannst, ist es nicht unwahrscheinlich, das 15 bis 20 
Flankenwechsel bis zur stabilen Signallage erfasst werden.
Einfache Rechnung:
Taster sind grundsätzlich erst einmal zu entprellen. Die Kondensatoren 
auf dem Board sind ein "Versuch", das entprellen Hardwaremäßig 
durchzuführen.
Einen weiteren Hinweis möchte ich auch noch geben. Nach deiner Denkweise 
erfasst der Controller den Taster, schaltet die LED und springt dann in 
eine Routine Wait. Dort soll er bleiben, bis die Taste wieder 
losgelassen wird. Damit ist der Controller aber für andere Aufgaben 
platt. Er ist ja damit beschäftigt, darauf zu warten, bis es dir genehm 
ist, die Taste wieder loszulassen. Was du brauchst, ist zur Entprellung 
eine Flankenerfassung. Such mal danach.
gruß oldmax

von ok (Gast)


Lesenswert?

Erst mal die Taster umbauen
http://www.mikrocontroller.net/articles/Diskussion:Pollin_ATMEL_Evaluations-Board

Dann noch an den anfang deiner wait Funktionen eine Warteschleife 
einbauen.

von Christof K. (christof_k)


Lesenswert?

Danke für die Hinweise. Ich werde es mit dem Softwareentprellen nach 
Peter Dannegger versuchen. Löten möchte ich erstmal vermeiden, da es bei 
mir viel Zeit in Anspruch nimmt.

@ oldmax
Hast recht, das ist ein Lautsprecher. Ich habe über den AVRDelyloop 
Warteroutinen erzeugt und diesen alle 0,5 - 5000ms ansteuern lassen. Und 
es funktioniert.
Das Problem war, dass das Signal zu schnell gewechselt hat. Ich weiss 
jetzt nicht genau ob der Ton dann so hochfrequent war, dass ich ihn 
nicht hören konnte oder es zu schnell für den Lautsprecher war. Ich 
würde erstmal auf das zweite Tippen.

Zu dem Delay hätte ich noch eine Frage. Im Assembler lässt man eine, dem 
Takt entsprechende, Anzahl Taktzyklen durchlaufen und kommt auf die 
Anzahl Millisekunden.
Wie funktioniert dies in C?

Dort habe ich dieses Codebeispiel ausprobiert.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
int main(void) {
5
  DDRB = 0xFF;
6
  for (;;) {
7
    PORTB = 0;
8
    _delay_ms(500);
9
    PORTB = 0xFF;
10
    _delay_ms(500);
11
  }
12
}

Dort stimmt die Zeit nicht. Es sind keine 500ms. Der ATmega8 wird auf 
dem Board mit 16MHz getaktet. Wie stelle ich das für ein C-Programm ein?

von oldmax (Gast)


Lesenswert?

Hi
Vergiss Delay auf die von dir beschriebene Weise. Du beschäftigst 
ddeinen Controller mir irgendwelchem Blödsinn, so das er für die 
wichtigen Dinge keine Lust hat. Versuch mal nach folgendem SChema zu 
denken:
Information aufnehmen
Bearbeiten
und ausgeben
Darfst das auch EVA nennen: Einlesen - Verarbeiten - Ausgeben
Und das ohne Verzögerung im Kreis
Nun wirst du natürlich zu recht sagen: "Damit ist doch noch nichts 
entprellt."
Nein, dasfür brauchst du auch eine Verzögerung, umm einen Signal eines 
Einganges für gültig zu erklären. Und diese Zeit generierst du mit den 
Timern. Die arbeiten nebenher und lösen, wenn es an der Zeit ist, einen 
Interrupt aus. Der unterbricht dein Programm nur ganz kurz. Schau dir 
mal das Tutorial zum Timer an. Da wird erklärt, wie er arbeitet. Nun 
parametrierst du ihn so, das du jede mSek einen Interrupt bekommst. Dann 
hast du einen Zeittakt, aus dem du dann alle benötigten Zeiten ableiten 
kannst.Alles was du dafür brauchst ist eine Variable. Im Timer-Interrupt 
setzt du dir ein Bit in dieser Variablen und gut. Dein Programm fragt 
bei jedem Durchlauf das Bit ab und ist es gesetzt, werden die 
entsprechenden Routinen angestoßen. Dann löscht du dieses Bit nach 
erledigter Arbeit.
Gruß oldmax

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.