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
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
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
intmain(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?
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