Für die Einarbeitung in der Programmierung des AVR uC mit C habe ich mir
die AVR GCC Tutorials angeschaut und auch einfache Programme
nachgebildet.
Nun wollte ich ein Programm schreiben der die elektrische
Wechselschaltung nachbildet und stoße da auf erhebliche Schwierigkeiten.
Im Grunde will ich folgendem Verhalten nachbilden:
Taste gedrückt ---> LED An (und bleibt an) bis die Taste wieder gedrückt
wird zum ausschalten.
Bisher stehe vor dem Problem dass der folgende Code nur dazu führt dass
die LED getoggelt wird (LED nur AN während Taste gedrückt wird):
if(PINB & (1 << PINB0)){
PORTA |= (1 << PINB0);
}
else
{
PORTA &= ~(1 << PINB0);
}
Das Rausnehmen des else Abschnittes bringt leider keine Abhilfe.
Beigefügt ist der Code dazu.
Ich freue mich, wenn ich Hinweise erhalten kann wie ich dies lösen.
Vielen Dank,
Jenny
N. G. schrieb:> false= !false;
Du meinst wohl:
t = !t;
> aber rein voon der Theoride...
Das reicht aber noch nicht. Man muss nach Toogeln von "t" noch warten,
bis der Taster wieder losgelassen wird, bevor "t" wieder getoggelt
werden darf.
Und entprellen fehlt natürlich auch noch ;-(
Gruß Dietrich
Danke für die Hilfe.
Das Programm habe ich nun wie folgt auf der Basis des Codes zur
Entrellung von Peter Dannegger geändert, weil ich gar keine Kenntnis von
Assembler habe und daher lieber auf C programmieren würde:
int main(void)
{
bool t=false;
DDRB = 0x00; //PortB als Eingang
PORTB = 0x01; //Pull-up Aktiv an PIN B0
DDRA = 0xff; //PortA als Ausgang
for(;;){
if(debounce(PINB, PB0))
{
t=true;
}
if(t){
PORTA |= (1<<PA0);
}
else
{
PORTA &= ~(1<<PA0);
}
_delay_ms(1000);
}
}
Leider führt dies dazu, dass die LED nur noch dauernd AN ist und keine
Reaktion auf Tastendrücke an PB0 zeigt. Was habe ich dabei falsch
gemacht.
Euere Unterstützung finde ich großartig und gerade für eine Neulinge
gibt das eine zusätztliche Motivation.
Kann mir bitte jemand einen Hinweis geben? Der Code habe ich nochmals
geändert aber leider ohne Erfolg. Die LED geht bei einem Tastendruck für
einige Sekunden AN, erlischt aber danach.
Ich wollte es aber so dass es bei einem Tastendruck AN bleibt solange
bis der Taster wieder betätigt wird.
----------
int main(void)
{
bool t=false;
DDRB = 0x00; //PortB als Eingang
PORTB = 0x01; //Pull-up Aktiv an PIN B0
DDRA = 0x01; //PortA als Ausgang
for(;;){
if(PINB & (1 << PINB0)){
t=true;
}
else
{
t=false;
}
if(t){
debounce(PINB, PB0);
PORTA |= (1<<PA0);
}
else
{
PORTA &= ~(1<<PA0);
}
_delay_ms(1000);
}
}
Danke,
Jenny
Du musst noch eine Variable einfügen, ob die LED zuletzt ein oder aus
geschaltet wurde, detektieren, ob die Taste losgelassen wurde und zwei
seperate Abfragen benutzen....
Deine Tastenabfrage ist zur Zeit doppelt - das bringt dich aber nicht
weiter.
Es müssten 2 separate if-Abfragen verwendet werden:
1. Ein: Taste UND !Letzte_Taste UND !Taste_betaetigt
2. Aus: Taste UND Letzte_Taste UND ! Taste_betaetigt
Der Code habe ich nun wie folgt geändert:
int main(void)
{
bool t=false;
DDRB = 0x00; //PortB als Eingang
PORTB = 0x01; //Pull-up Aktiv an PIN B0
DDRA = 0x01; //PortA als Ausgang
for(;;){
/* Ein */
if(PINB & (1 << PINB0)){
if(t==false & ~(1 << PINB0)){
debounce(PINB, PB0);
PORTA |= (1<<PA0);
}
t=true;
}
if(PINB & (1 << PINB0)){
if(t==true & ~(1 << PINB0)){
debounce(PINB, PB0);
PORTA &= ~(1<<PA0);
}
t=false;
}
}
}
Die 2 If-Abfragen sind verschachtelt. Leider ist die LED mit dem Code
auch nur dauernd AN.
1. Die Abfragen dürfen nicht verschachtelt sein.
2. Du fragst bei "ein" ab, dass die letzte Aktion "aus" war.
3. Du setzt eine Variable, dass eine Aktion erfolgte.
4. Du speicherst, die Aktion (1=ein, 0=aus).
4. Diese fragst du ebenfalls unter 2 auf FALSE ab.
5. Erst wenn die Entprellroutine "Taste nicht betätigt" liefert, setzt
du diese zurück.
Noch ein Update des Codes:
int main(void)
{
bool t=false;
bool f;
DDRB = 0x00; //PortB als Eingang
PORTB = 0x01; //Pull-up Aktiv an PIN B0
DDRA = 0x01; //PortA als Ausgang
for(;;){
/* 2. Ein t-->"aus" */
if(PINB & (1 << PINB0) & ~t & ~f){ // 2. Schritt
f=true; // 3.+4. Schritt
if(~debounce(PINB, PB0)){ // 5. Schritt
PORTA |= (1<<PA0);
}
else{
PORTA &= ~(1<<PA0);
}
}
else
{
f=false; // 3.+4. Schritt
}
}
}
Ich habe mich an dem Hinweis von Otto gerichtet aber offensichtlich noch
ein Fehler drin, weil es immer noch nicht klappt.
Danke für Hinweise,
Jenny
Jenny K schrieb:> keine> Reaktion auf Tastendrücke an PB0 zeigt.
Weil Du mit
> _delay_ms(1000);
die ganze Entprellung zunichte machst.
Riesige Delays sind Schweinereien, die in keinem Programm was verloren
haben. Es wird zwar oft kolportiert, daß sie Anfängern das Programmieren
erleichtern sollen, aber das genaue Gegenteil ist der Fall.
Die weiteren Versuche werden ja immer abstruser.
Debounce liefert genau einmal True bei jedem Drücken.
Einfach:
Habe nun versucht das Programm soweit zu erweitern, dass die LED an PA2
angeht, wenn sowohl PB0 als auch PB1 nacheinander betätigt wurden. Dazu
verwende ich zwei Variablen t und f in denen ich den logischen Zustand
zwischenspeichere. Leider funktioniert dies nicht.
Was mache ich dabei falsch oder worauf muss ich generell bei der
Zwischenspeicherung in einer temporären Variable achten?
int main(void)
{
bool t=false;
bool f=false;
DDRB = 0x00; //PortB als Eingang
PORTB = 0xff; //Pull-up Aktiv an PIN B0
DDRA = 0xff; //PortA als Ausgang
PINA &= 0x00;
for(;;){
if(debounce(PINB, PB0)){
t=true;
PORTA ^= (t <<PA0);//Toggle entsprechend PA0 läuft wie erwartet
}
else{
t=false;
}
if(debounce(PINB, PB1)){
f=true;
PORTA ^= (f <<PA1); //läuft wie erwartet
}
else{
f=false;
}
if(t&f){ //Bedingung wird nicht über die LED an PA2 nachgebildet
PORTA |= (1 <<PA2);
}
else
{
PORTA &= ~(1 <<PA2);
}
}
}
Danke für die Unterstützung.
Jenny
Jenny K schrieb:> Heißt es dann dass die debounce() Funktion nicht für Mehrtastenabfragen> verwendet werden kann?
Was ist eine 'Mehrtastenabfrage'?
Wenn du das meinst, was ich denke das du meinst, dann sieh dir halt mal
das letzte Beispiel von PeDa GENAU an.
Was denkst du, warum da einmal PB0 und das andere mal PB1 als Argument
zum debounce steht? Du musst schon die Dinge GENAU studieren, die du
fertig vorgesetzt bekommst!
der Hintergrund ist das ich für ein Praktikum eine Art Zustandautomaten
programmieren soll der abhängig von der gerade gedrückten Tasten
bestimmte Ausgänge (LED, Relais) an/aus machen soll. Da die Aufgabe für
mich komplex erscheint, habe ich überlegt erst mit
einfachen/grundsätzlichen Fragestellungen (Zustandszuweisung in
Hardware, boolsche Verknüpfung in HW,...) anzufangen.
Mit Mehrtastenabfrage meine ich:
Taster 1 wird betätigt --> debounce() wird aufgerufen und der ON
(betätigt) Zustand in einer boolschen Variable x (TRUE) gespeichert.
Falls der Taster 2 danach auch betätigt wird wird die debounce()
Funktion erneut aufgerufen und eine Variable y (TRUE) speichert
ebenfalls den Zustand.Erst abhängig von der Abfrage, ob x und y beide
TRUE sind wird der entsprechende Ausgang PIN aktiviert/deaktiviert.
In der C-Programmierung wie wir es in der Vorlesung machen geht das
ganze etwas einfacher. Die prinzipielle Funktion in C wobei die Taster
und LED als boolsche Variablen deklariert sind läuft auch.
Ich finde eure Unterstützung wirklich klasse und Danke dafür.
Jenny
Jenny K schrieb:> Mit Mehrtastenabfrage meine ich:>> Taster 1 wird betätigt --> debounce() wird aufgerufen und der ON> (betätigt) Zustand in einer boolschen Variable x (TRUE) gespeichert.> Falls der Taster 2 danach auch betätigt wird wird die debounce()> Funktion erneut aufgerufen und eine Variable y (TRUE) speichert
Du missverstehst das irgendwie.
Grundsätzlich muss dein Programm in einer Art Dauerschleife laufen.
Innerhalb dieser Dauerschleife wird debounce FÜR EINEN BESTIMMTEN PIN
aufgerufen. Dieser debounce Aufruf teilt dir mit, ob die Taste in der
Zeit seit dem letzten Aufruf für diese Taste niedergedrückt wurde oder
nicht. Allerdings überwacht debounce die Taste nicht ständig. Die
Grundannahme ist, dass bei zb 1000 Aufrufen von debounce in 1 Sekunde
keinen Menschen finden wird, der es schafft eine Taste kurz genug zu
drücken, dass dies bei diesen 1000 Aufrufen pro Sekunde unentdeckt
bleibt. debounce vergleicht einfach den jetzigen Tastenzustand mit dem
Tastenzustand vom letzten Aufruf und wenn der unterschiedlich ist, dann
meldet es einen Tastendruck. Unterscheiden sich die beiden nicht, dann
meldet es keinen Tastendruck. Aber debounce wartet nicht darauf, dass
der Benutzer eine Taste drückt.