Hallo,
Prozessor Attiny13, Sprache C
Ich habe ein Programm, welches zu Beginn einmal im Grunde in einer
Warteschleife hängt, da es etwas ausgibt und dazwischen immer kurz
warten muss.
Dies geschieht direkt nach main(), aber vor der Hauptschleife.
Der Benutzer kann aber mit einem Taster in das Programm eingreifen bzw.
Sachen aktivieren, deaktivieren. Die Taster werden über eine
Entprellroutine aber erst in Hauptschleife erkannt.
Ich hätte aber gerne, dass der Benutzer schon vor Beginn der
Hauptschleife, also während der Warteschleife schon mit Tastenimpulsen
interagieren kann.
Ist dies irgendwie möglich außer die Taster in einem Interrupt
abzufragen?
Danke.
@ Daniel (Gast)
>Ist dies irgendwie möglich außer die Taster in einem Interrupt>abzufragen?
Sicher, siehe Multitasking. Aber warum nicht einfach die Interrupts
VORHER freischalten und nutzen?
du mußt doch nur während des Wartens, die Tasten abfragen. Eigentlich ne
gute Zeit dafür, der Tiny hat ja eh nichts anderes zu tun :D
Sollte es zeitkritisch sein, mußt du es eben entsprechend
programmieren.
Hallo Falk und die anderen,
vielen Dank für den Link mit dem Multitasking. Ich denke, das hilft :-)
Werde mir das mal genauer ansehen und auf meinen Fall versuchen
anzuwenden.
Danke.
// Baudrate, das L am Ende ist wichtig, NICHT UL verwenden!
15
#define BAUD 9600L
16
17
#include"avr/io.h"
18
#include"util/delay.h"
19
20
// Berechnungen
21
// clever runden
22
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
23
// Reale Baudrate
24
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
25
// Fehler in Promille
26
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)
27
28
#if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))
29
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
30
#endif
31
32
uint8_ttaste_lesen(void){
33
if(PINA&(1<<PA0))
34
return1;
35
else
36
return0;
37
}
38
39
voidled_blinken(uint8_ttaste){
40
staticuint16_tzaehler=0;
41
42
if(taste){
43
if(zaehler>=999){
44
PORTB^=(1<<PB0);
45
zaehler=0;
46
}
47
}
48
else{
49
if(zaehler>=99){
50
PORTB^=(1<<PB0);
51
zaehler=0;
52
}
53
}
54
55
zaehler++;
56
_delay_ms(1);// 1 ms warten
57
}
58
59
voiduart_lesen(void){
60
uint8_ttmp;
61
if((UCSRA&(1<<RXC))){// empfangenes Zeichen abholbereit im UART ?
62
tmp=UDR;
63
while(!(UCSRA&(1<<UDRE)));// Warte auf freien Sendepuffer vom UART
64
UDR=tmp;
65
}
66
}
67
68
intmain(void){
69
int8_ttaste;
70
71
// IOs initialisieren
72
73
PORTA=1;// Pull Up für PA0
74
DDRB=1;// PB0 ist Ausgang
75
76
// UART initialisieren
77
78
UBRRH=UBRR_VAL>>8;
79
UBRRL=UBRR_VAL&0xFF;
80
UCSRB=(1<<RXEN)|(1<<TXEN);
81
82
// Endlose Hauptschleife
83
84
while(1){
85
taste=taste_lesen();
86
led_blinken(taste);
87
uart_lesen();
88
}
89
}
Ich habe mir gerade obiges Beispiel aus dem Tutorial mal genauer
durchdacht.
Dabei ist mir aufgefallen, dass in der Funktion led_blinken() immer 1ms
gewartet wird, bis der Zähler bei >=999 bzw. >99 ist (also 1000ms oder
100ms).
Allerdings hat das Programm bzw. die anderen Programmteile ja selbst
auch eine Durchlaufzeit. So wird in Summe die Vielzahl der Durchläufe
des Programms+die Wartezeit für das Leuchten der LEDs genommen oder bin
ich falsch?
Das entspricht ja prinzipiell nicht dem Ursprungsprogramm mit 1000ms
delay...
Daniel schrieb:> Dabei ist mir aufgefallen, dass in der Funktion led_blinken() immer 1ms> gewartet wird, bis der Zähler bei >=999 bzw. >99 ist (also 1000ms oder> 100ms).> Allerdings hat das Programm bzw. die anderen Programmteile ja selbst> auch eine Durchlaufzeit. So wird in Summe die Vielzahl der Durchläufe> des Programms+die Wartezeit für das Leuchten der LEDs genommen oder bin> ich falsch?
Nein, bist du nicht.
Im Prinzip hast du recht.
Allerdings reden wir hier um ein paar µs pro Schleifendurchlauf. Bei
1000 Durchläufen summiert sich der Fehler zu ~1 Millisekunde auf.
Kannst du tatsächlich mnit freiem Auge feststellen, ob das Blinken einer
LED genau 1 Sekunde oder 1 Sekunde + 1 Tausendstel Sekunde lang ist?
Wenn du genaue Zeiten brauchst, taugen diese ganzen _delay_ms Ansätze
sowieso nichts. Wie schon gesagt: _delay_ms ist oft nicht die Lösung,
sondern das Problem.
Hallo,
nein, für diesen Anwendungsfall "LED" ist das für das Auge natürlich
nicht erfassbar/messbar.
Ich wollte nur bestätigt haben, dass ich das Programm, so wie es da
steht, richtig durchschaue.
Um es genaue zu machen, würde man wahrscheinlich die Zählvariable
"zaehler" einfach entsprechend in einem Timer inkrementieren und bei
entsprechendem Inkrement die Abbruchbedienung in der if-Anweisung
setzen.
Danke.
@ Daniel (Gast)
>Allerdings hat das Programm bzw. die anderen Programmteile ja selbst>auch eine Durchlaufzeit. So wird in Summe die Vielzahl der Durchläufe>des Programms+die Wartezeit für das Leuchten der LEDs genommen
Ja.
>Das entspricht ja prinzipiell nicht dem Ursprungsprogramm mit 1000ms>delay...
Muss es auch nicht, weil es nur ein einfaches Beipiel ist, bei dem es
nicht auf die letzte Mikrosekunde ankommt.
Daniel schrieb:> Um es genaue zu machen, würde man wahrscheinlich die Zählvariable> "zaehler" einfach entsprechend in einem Timer inkrementieren und bei> entsprechendem Inkrement die Abbruchbedienung in der if-Anweisung> setzen.>
Praktisch JEDES ernst zu nehmende Programm aus der realen Welt (also
abseits von Tutorien) hat in irgend einer Form einen Timer als
'Heartbeat'. In diesem Heartbeat wird zb die Tastenentprellung gemacht
und er dient als Zeitbasis für das komplette Programm.
Das ist einfacher realisiert als viele glauben. Nur muss man sich halt
mal mit Timern beschäftigt haben.
Der spingende Punkt bei diesem Multitasking Beispiel ist der: das man
Aktionen aufteilt und nicht auf die Fertigstellung wartet. Darum gehts.
Eine eigene Frage?
Dieser Thread ist über 14 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.