Hi Leute,
ich bin in Sachen µC soweit, als dass ich LEDs zum Blinken bringen kann.
Die Geschichte mit DDR, PORT und Bitmanipulation in dieser Hinsicht sind
mir also bekannt.
Nun möchte ich im nächsten Schritt gerne etwas mit Tastern herumspielen,
sprich auch PIN verwenden.
Im Anhang seht ihr die Beschaltung. Ich habe bewusst auf das "Drum
herum" verzichtet, da die LEDs funktionieren und ich den Fokus gerne auf
meine Beschaltung mit dem Taster und der LED setzen möchte.
Bevor ich den C Code poste, ein kleiner Kommentar vorab:
Ich habe bewusst auf das Thema Entprellen verzichtet, da ich es als
zweiten Schritt implementieren wollte. Mir geht es hier erstmal um PIN
und LED.
Hier also der Code:
1
#include<avr/io.h>
2
#include<inttypes.h>
3
#define F_CPU 1000000UL
4
#include<util/delay.h>
5
6
7
intmain(void)
8
{
9
DDRB&=~(1<<PB1);//PB1 auf Eingang (Taster)
10
PORTB&=~(1<<PB1);//Pullup-Widerstand deaktivieren
11
DDRD|=(1<<PD7);//PD7 als Ausgang (LED)
12
13
14
if(PINB&(1<<PB1))//Prüfe, ob PB1 logisch high ist
15
{
16
_delay_ms(500);
17
_delay_ms(500);
18
if(PINB&(1<<PB1))//Prüfe erneut, ob PB1 logisch high ist nach 1s
19
{
20
PORTD|=(1<<PD7);//Wenn PB1 immer noch logisch high ist, setze PD7 high
21
_delay_ms(500);//Warte 500ms, damit man die LED leuchten sieht
22
}
23
}
24
}
Beim Code habe ich mich teilweise an das AVR-GCC Tutorial gehalten.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
Kapitel: Eingänge Wie kommen Signale in den µC
Ich verwende einen Atmega8 mit AVR Studio4 und einem original AVR ISP
mkII programmer.
Kann mir jemand meinen Gedankenfehler zeigen?
Vielen Dank.
Gruß
>Ich habe bewusst auf das "Drum herum" verzichtet
Hast in dem Sinne darauf verzichtet, dass Du es hier nicht gezeichnet
hast oder in dem Sinne, dass Du es auch nicht eingebaut hast. Also
Abblockkondensatoren Takt etc.?
>Kann mir jemand meinen Gedankenfehler zeigen?
Was ist denn überhaupt das Problem?
Jedenfalls wird das Programm machen was dasteht. Allerdings wills Du
vermutlich, dass das nicht nur einmal funktioniert sondern immer wieder.
Dann fehlt eine Endlosschleife in main.
Und warum eigentlich mühsam einen Pull-Down-Widerstand einbauen und (ok,
weniger mühsam) den eingebauten Pull-Up deaktivieren?
Hallo Noname,
Noname schrieb:>>Ich habe bewusst auf das "Drum herum" verzichtet>> Hast in dem Sinne darauf verzichtet, dass Du es hier nicht gezeichnet> hast oder in dem Sinne, dass Du es auch nicht eingebaut hast. Also> Abblockkondensatoren Takt etc.?
Hmm, war wirklich ungeschickt ausgedrückt. Ich habe das Drum Herum
(Kondensatoren, Reset, Spannungsversorgung etc.) lediglich nicht
eingezeichnet. Auf meinem Steckbrett sind die aber alle vorhanden und
die LEDs (mein erstes Projekt mit µC) blinken, wie sie sollen.
>>Kann mir jemand meinen Gedankenfehler zeigen?>> Was ist denn überhaupt das Problem?
Wieder eine berechtigte Frage :D
Das Problem ist, dass die LED an PD7 nicht leuchtet, obwohl ich den
Taster an PB1 gedrückt halte. Dass an PB1 bei gedrücktem Taster ein
logisches High Signal ist, habe ich durch ein Multimeter geprüft. Sowohl
Durchgangs- als auch Spannungsprüfung. Beides OK.
> Jedenfalls wird das Programm machen was dasteht. Allerdings wills Du> vermutlich, dass das nicht nur einmal funktioniert sondern immer wieder.> Dann fehlt eine Endlosschleife in main.
Ohje, while(1){} habe ich total vergessen. Kann ja auch nix werden :D
Habe es eingefügt und nun leuchtet die LED, wenn ich den Taster drücke.
Danke für den Hinweis :)
> Und warum eigentlich mühsam einen Pull-Down-Widerstand einbauen und (ok,> weniger mühsam) den eingebauten Pull-Up deaktivieren?
Den Pull-Down Widerstand habe ich eingebaut, damit PB1 bei nicht
gedrücktem Taster ein fest definiertes Potential - nämlich GND - hat.
Um den internen Pull-Up Widerstand zu verwenden, müsste ich doch meine
Schaltung umbauen (okay, einmal den Taster umstecken). Nämlich Taster
gegen GND und dann den internen Pull-Up Widerstand aktivieren. Hmm,
ginge auch. Keine Ahnung, weshalb ich mich für diese Variante
entschieden habe.
Gruß
Meine Tipps:
#include <avr/io.h>
#include <inttypes.h>
#define F_CPU 1000000UL
#include <util/delay.h>
int main(void)
{
DDRB &= ~( 1 << PB1 ); //PB1 auf Eingang (Taster)
DDRD |= (1<<PD7); //PD7 als Ausgang (LED)
while(1) {
if (PINB & (1<<PB1)) //Prüfe, ob PB1 logisch high ist
{
_delay_ms(1000); //warte 1s
if(PINB & (1<<PB1)) //Prüfe erneut, ob PB1 logisch high ist
{
PORTD |= (1<<PD7); //Wenn PB1 immer noch logisch high ist,
setze PD7 high
_delay_ms(500); //Warte 500ms, damit man die LED leuchten
sieht
}
}
}
}
1: Wozu den internen Pullup Widerstand abschalten? Wenn du im Schaltplan
den Widerstand weglässt, ist das doch einfacher oder?
2: Programm in eine while-Schleife legen, damit das Programm sich immer
wiederholt und am ende des programms nicht einfach irgendwas passiert.
3: wozu 2x _delay_ms(500); schreiben, wenn man auch einmal
_delay_ms(1000); schreiben kann? spart schreibarbeit.
4: Am ende könnte das programm nochmal ca. 10s warten und die led wieder
ausschalten, damit man das programm wiederholen kann. sonst wäre es ja
etwas langweilig :)
Moin obi wan,
auch dir danke für deine Tipps.
Hier nun mein abgeänderter C Code
1
#include<avr/io.h>
2
#include<inttypes.h>
3
#define F_CPU 1000000UL
4
#include<util/delay.h>
5
6
7
intmain(void)
8
{
9
10
while(1)
11
{
12
DDRB&=~(1<<PB1);//PB1 auf Eingang (Taster)
13
PORTB&=~(1<<PB1);//Pullup-Widerstand deaktivieren
14
DDRD|=(1<<PD7);//PD7 als Ausgang (LED)
15
16
17
if(PINB&(1<<PB1))//Prüfe, ob PB1 logisch high ist
18
{
19
_delay_ms(50);
20
while(PINB&(1<<PB1))//Prüfe erneut, ob PB1 logisch high ist nach 1s
21
{
22
PORTD|=(1<<PD7);//Wenn PB1 immer noch logisch high ist, setze PD7 high
23
}
24
PORTD&=~(1<<PD7);//Setze PD7 low, damit die LED ausgeht.
25
}
26
}
27
return0;
28
}
Schließlich soll ja auch die LED ausgehen, wenn der Taster nicht mehr
gedrückt ist :D
Habs getestet, funktioniert sehr gut.
Zu deiner Frage mit dem internen Pull-Up Widerstand.
Ich stelle eine Gegenfrage:
Wozu sollte der aktiviert sein?
Wenn ich den Taster drücke, soll logisch 1 sein, sprich 5V an PB1. Ist
der interne Pull-Up Widerstand aktiviert, ist doch ständig eine logische
1 an PB1. Ferner brauche ich doch irgendwo einen Pull Down Widerstand,
der mir den PB1 fest auf GND zieht, wenn der Taster nicht gedrückt ist.
Ich kann eure Logik nicht ganz nachvollziehen :/
Gruß
>Wenn ich den Taster drücke, soll logisch 1 sein, sprich 5V an PB1
Gegenfrage: Warum muss ein gedrückter Taster eine 1 ergeben?
Wenn Du Dich von dieser Festlegung lösen kannst, dann sparst Du einen
Widerstand.
Noname schrieb:>>Wenn ich den Taster drücke, soll logisch 1 sein, sprich 5V an PB1>> Gegenfrage: Warum muss ein gedrückter Taster eine 1 ergeben?> Wenn Du Dich von dieser Festlegung lösen kannst, dann sparst Du einen> Widerstand.
True!
Zu Testzwecken wollte ich einfach sagen:
- LED ist aus
- Drücke ich den Taster, geht die LED an
Verwende ich den Pull-Up Widerstand und packe den Taster gegen GND,
müsste ich die if-Abfrage auch negieren. Soweit habe ich wohl gar nicht
gedacht, so dass ich in der von dir zitierten Festlegung verharrt bin.
Gruß