Hallo Leute!
Ich habe vor, mir eine Standheizung für mein Auto mittels ATmega8 und
einem Handy zu bauen.
Das Handy wird an den PinB-1 angeschlossen.
Sobald jemand zwei mal innerhalb 10 sec. (warte_sec()) auf diesem Handy
anruft, soll die Heizung (PinB-0) eingeschaltet werden und nach einer
gewünschten Zeit (warte_minuten()) wieder ausgeschaltet werden.
Ich habe bei dem C-Programm das Problem, dass nicht abgefragt wird, ob
bereits schon einmal innerhalb der 10 sec. angerufen hat.
Im Anhang findet ihr das gesamte Programm.
Könntet ihr mir helfen?
Vielen Dank!
Nachtrag:
Der Prescaler war hier in meinem Upload falsch eingestellt. er müsste
auf (CS00)|(CS02) stehen, damit er auf 1024 kommt. Das hat aber nicht
zur Lösung beigetragen.
Wie wäre es mit einer sauberen Lösung?
Eine Schrittkette:
Schritt1: Heizung aus
Transition1: Handyempfang => Schritt2
Schritt2: Heizung aus
Transition1: Handyempfang => Schritt3
Transition2: Timeout 10sek => Schritt1
Schritt3: Heizung ein
Transition1: Timeout x Minuten => Schritt1
So wird das sauber gelöst.
Unsetzung siehe mein Beitrag (Datum: 23.01.2008 11:36)
Beitrag "Programm bzw. Ablaeufe steuern"
Das Programm compiliert bei mir gar nicht.
Du misshandelst den Timer:
Einen Timeroverflow fragt man gewöhnlich per Interrupt ab und das
Overflowflag wird nicht per Hand gelöscht sondern automatisch wenn deine
Interruptroutine ausgeführt wird.
return 2; <--- return ist keine variable, die du später in
if ((AnrufAnzahl>1) && (return == 2)) abfragen kannst
Ich würde dir raten dich noch einmal in
- Timer und
- Funktionen und Rückgabewerte
einzulesen.
Kannst du den Code so überhaupt compilieren?
Der Vorschlag von Matthias ist langfristig gesehen auch sehr hilfreich,
wenn dein Projekt mal größer wird blickst du sonst garnicht mehr durch.
Gruß Marcus
Das Projekt wird nicht größer werden, mehr als die genannte Aufgabe soll
der AVR garnicht machen...
Ja ich kann den Code so kompilieren. Wie mache ich denn dann den
Rückgabewert für die Funktion, anstelle des "return 2"?
Wieso muss ich unbedingt mit Interrupts arbeiten? Das wird doch wohl
auch ohne gehen ?!
Danke
Dein Programm ist ziemlich mies, und ehrlich gesagt hab ich
da jetzt keine Lust, das gross auf Interrupt Betrieb umzustellen.
Das grundelgende Handwerkszeug dazu findest du im GCC_Tutorial
hier.
Aber: Zu deinem generellen Code Stil
Wenn du 'while' meinst, dann schreib auch 'while'.
So was:
for(;zuende==0;)
ist maximal ein Schuss ins eigene Knie. Und wenn du dich heute
nicht ins eigene Knie schiesst, dann eben morgen.
while( zuende == 0 )
{
}
PS: Die andere 'while'-Schleife in deinem Code sieht mehr als
suspekt aus.
Aber wie gesagt: Besser wäre es, wenn du auf Interrupt umstellst.
ja, wie karl-heinz schon sagt, "groß" auf Interrupt-Betrieb
umstellen....
Mir ist wiederum der Interrupt suspekt. Ich muss zugeben, dass ich sie
noch nie verwendet habe.
Die for-Schleife ist zwar nicht elegant, aber die Funktion deiner
genannten while-Schleife müsste sie auch machen oder?
Aber wie würde es denn OHNE Interrupts funktionieren?
Danke
Björn wrote:
> wie macht man denn eig. dann einen rückgabe-wert, wenn das von mir> programmierte "return" nicht klappen soll?!>>> danke
Du hast eine Funktion mit dem Funktionsprototypen in der Form:
Rueckgabedatentyp Funktionsname(Eingabedatentyp Variablenbezeichnung);
konkretes Beispiel:
1
intzaehleZweiDazu(int);
Der Funktionscode deiner Funktion:
1
intzaehleZweiDazu(inteingabewert)
2
{
3
returneingabewert+2;
4
}
Nun moechtest du angenommen die Funktion im Hauptprogramm verwenden:
1
voidmain(void)
2
{
3
intzahl=0;// Eine Variable anlegen und auf 0 setzen
4
5
zahl=zaehleZweiDazu(3);
6
/* An dieser stelle wird die Funktion mit dem "Parameter" 3 aufgerufen. Die Zahl 3 wird an dieFunktion übergeben. Die Funktion zählt dieser Zahl 2 hinzu und gibt das Ergebniss (5) mit return zurück.*/
ok jetzt von der Funktionsrückgabewert abgesehen, hier mal der
Code,soweit ich ihn nun habe , könntet ihr mal einen Blick draufwerfen
ob es so funktionieren würde?
Danke
Heinz der Heizer wrote:
> das Abfragen des Rückgabewerts klappt aber trotzdem nicht:
Fehlermeldungen sind dazu da, dass man sie auch liest.
OK. Manchmal sind Fehlermeldungen auch mal verwirrend, aber
nicht in diesem Fall.
Was sagt der Compiler:
> Compiler meldet : ../standheizung.c:53: error: too few arguments to> function `warte_sec'
Wenn man das mal Wort für Wort übersetzt.
Zu wenige Argumente an Funktion 'warte_sec'
Argumente sind die Dinger, die in eine Funktion hineingehen.
Also schaun wir mal. Hier ist der Aufruf
(warte_sec()==1
An warte_sec wird nichts übergeben.
Wie sieht die Funktion aus?
int warte_sec( int i )
Aha. warte_sec möchte ein Argument haben. Du übergibst aber keines.
Daher: Zuwenig Argumente
Warum schaust du dir nicht einfach mal an, wie das mit den
Interrupts funktioniert. Das hat doch so alles keinen
wirklichen Sinn.
Als Anfang:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
vvolatileuint8_tg_HaveOverflow;
5
6
ISR(TIMER2_OVF_vect)// wird aufgerufen, wenn der Timer
7
// den Overflow generiert
8
{
9
g_HaveOverflow=1;
10
}
11
12
intmain()
13
{
14
TCCR0|=(1<<CS00)|(1<<CS02);// Prescaler auf 1024
15
16
TIMSK=(1<<TOIE0);// Interrupt bei Overflow erlauben
17
18
sei();// Interrupts generell zulassen
19
20
while(1){
21
22
if(g_HaveOverflow==1){// der Timer hat einen Overflow ausgelöst
23
// als Folge davon wurde die ISR
24
// aufgerufen. In der ISR wurde die Variable
25
// g_HaveOverflow auf 1 gesetzt.
26
cli();
27
g_HaveOverflow=0;// Den Overflow wieder scharfstellen
28
sei();
29
30
....
31
}
32
}
33
}
Wenn ich jetzt hier keinen Tippfehler gemacht habe, wird in der
Hauptschleife der Code im Bereich .... jedesmal ausgeführt, wenn
der Timer einen Overflow hat. Von dort weg kannst du dann zb.
mitzählen wie oft das passiert und einen Sekundenpuls zu generieren.
Danke für den Interrupt-Anfang, aber ist ein Interrupt für den
Tastendruck nicht wichtiger, als ein Interrupt wenn ein Überlauf
stattfand?
Schade nur, dass im AVR-GCC-Tutorial nicht steht, dass IN der
ISR-Funktion die Anweisung steht, die ausgeführt wird, wenn der
Interrupt ausgelöst wird.
Danke
Heinz der Heizer wrote:
> Danke für den Interrupt-Anfang, aber ist ein Interrupt für den> Tastendruck nicht wichtiger, als ein Interrupt wenn ein Überlauf> stattfand?
Der Witz ist der, dass du in derselben ISR beides machen kannst.
Oder meinst du einen Interrupt der ausgelöst wird, wenn eine
Taste gedrückt wird?
1) ist das sowieso keine gute Idee. Tasten prellen und müssen
entprellt werden. Das kann man mit der PeDa Methode für
Tastenentprellen wunderbar in einem Timer Overflow Interrupt
machen.
2) Wer sagt, dass es nur eine ISR geben kann. Es gibt viele
verschiedene Interrupts. Für jeden einzelnen kann man eine
ISR angeben. Es ist nicht ungewöhnlich, wenn es in einem
Programm mehrere ISR gibt.
Genau aus dem Grund steht ja auch das TIMER0_OVF_vect bei
1
ISR(TIMER0_OVF_vect)
Dadurch wird diese ISR gekennzeichnet als: Wird aufgerufen
wenn beim Timer 0 ein Overflow auftritt.
>> Schade nur, dass im AVR-GCC-Tutorial nicht steht, dass IN der> ISR-Funktion die Anweisung steht, die ausgeführt wird, wenn der> Interrupt ausgelöst wird.
Na ja.
Das wäre dann in etwa so, als ob man extra betonen muss, dass
man in C innerhalb von Funktionen auch Anweisungen stehen haben
kann, die dann ausgeführt werden, wenn die Funktion aufgerufen
wird.
Eine ISR ist auch nichts anderes als eine Funktion, mit 3 Unter-
schieden:
* die Syntax der Funktionsdefinition ist ein wenig anders
* Der Aufruf der Funktion erfolgt nicht explizit durch einen
Funktionsaufruf im Programm, sondern durch die Hardware indem
irgendein Ereignis (in dem Fall: Timer ist übergelaufen)
eintritt
* Da es keinen expliziten Funktionsaufruf gibt, kann man auch
keine Argumente und keinen Returnwert haben. Jegliche Kommunikation
mit der ISR muss über globale Variablen erfolgen (die dann auch
volatile sein muessen)
Das wars. Mit diesen Punkten hast du den C-spezifischen Teil der
Interrupts erledigt. Der Rest ist Datenblattstudium: Welches
Bit in welchem Register muss wie gesetzt werden, damit welcher
Interrupt ausgelöst wird.
Habt ihr eine Lösung wie man den Interrupt so setzt, dass während der 10
sec. der Controller auf erneute Tastendrücke wartet und diese auswertet?
Danke
Heinz der Heizer wrote:
> Hallo nochmal!>>> Jetzt habe ich mal was mit Interrupt probiert, funktioniert aber auch> nicht...-Wie solls auch anders sein .
Hast du die Korrektur gesehen?
> [c]>>>> #include <avr/io.h>> #include <avr/interrupt.h>>> volatile uint8_t gTimeCounter=0;>> ISR( TIMER2_OVF_vect ) // wird aufgerufen, wenn der Timer> // den Overflow generiert
Du arbeitest mit Timer 0, nicht Timer 2.
Daher muss die ISR TIMER0_OVF_vect heissen und nicht TIMER2_OVF_vect
Mit welcher Taktfrequenz läuft dein µC eigentlich?
Ich kann dir leider jetzt dein Programm nicht komplett
fertig machen. Bin selber im Stress.
Aber ich kann dir ein Programm schreiben, welches bei einer 0 am
Pin D0 den Ausgang PB0 auf 1 setzt, eine gewisse Wartezeit abwartet
und danach den PB0 wieder auf 0 setzt.
Damit die Zeit aber einigermassen stimmt, brauch ich die Taktfrequenz
des µC.
Also meine Taktfrequenz ist bei 1 MHz, da ich damit am leichtesten auf
eine Sekunde komme.
Echt nett von dir, dass du dich für mich einsetzt, ich erläutere jedoch
nochmal kurz, was das Programm machen soll.
Wenn ein H-Pegel an PinD0 anliegt, soll das Programm prüfen, ob nach
einer gewünschten Zeit ein weiterer H-Pegel anliegt. Wenn dies der Fall
ist, soll PortB0 für eine bestimmte Zeit auf H gesetzt werden, danach
wieder auf 0 zurückkehren und von vorne beginnen...
Vielen Dank!
TIMSK=(1<<TOIE0);// Interrupt bei Overflow erlauben
23
24
sei();// Interrupts generell zulassen
25
26
while(1){
27
28
if((PIND&(1<<PD0)==0)// PinD0 auf 0 ?
29
PORTB=0x01;
30
31
g_TimeReached=0;
32
g_Delays=300;// ********
33
}
34
35
if(g_TimeReached==1){
36
PORTB=0x00;
37
}
38
}
39
}
Die mit // ******* markierte Zeile muesste angepasst werden.
Keine Anhnung wie lange 300 Overflows auf deinem µC bei einem
Vorteiler von 1024 dauern. Hängt von deiner Taktfrequenz ab.
Der Code war noch nicht im Simulator. Sollte aber ziemlich stimmen.
ich habe noch paar Sachen wie Klammern-Setzen verbessert:
er meldet nun "undefined reference to 'main' ". Was bedeutet das?
Hier nochmal der "verbesserte" Code:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
volatileuint16_tg_Delays;
5
volatileuint8_tg_TimeReached;
6
7
ISR(TIMER0_OVF_vect)
8
{
9
if(g_Delays>0){
10
g_Delays--;
11
12
if(g_Delays==0)
13
g_TimeReached=1;
14
}
15
16
intmain()
17
{
18
DDRD=0x00;// PortD auf Eingang
19
DDRB=0xFF;// PortB auf Ausgang
20
21
TCCR0|=(1<<CS00)|(1<<CS02);// Prescaler auf 1024
22
TIMSK=(1<<TOIE0);// Interrupt bei Overflow erlauben
Da ist nicht nur eine Klammer zu viel! Da stimmt alles Mögliche mit
der Klammerung nicht. In der ISR ist eine offene Klammer, zu der es in
der ISR keine geschlossene gibt. Dementsprechend ist main für den
Compiler in die ISR eingebettet, und das haut nicht hin!
Gewöhne Dir generell eine saubere Einrückung an. Dann passiert sowas
nicht. Also ungefähr so:
1
intmain()
2
{
3
while(1)
4
{
5
if(bedingung)
6
{
7
machwas();
8
undnochwas();
9
}
10
else
11
{
12
machwasanderes();
13
undvielleichtnochwasanderes();
14
}
15
}
16
}
Grundsätzlich sollten der Übersichtlichkeit halber Klammern, die
zusammengehören, immer direkt untereinander stehen.
So, ich hab Dein Programm mal neu formatiert. Jetzt müsste zumindest die
Klammerei passen.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
volatileuint16_tg_Delays;
5
volatileuint8_tg_TimeReached;
6
7
ISR(TIMER0_OVF_vect)
8
{
9
if(g_Delays>0)
10
g_Delays--;
11
12
if(g_Delays==0)
13
g_TimeReached=1;
14
}
15
16
intmain()
17
{
18
DDRD=0x00;// PortD auf Eingang
19
DDRB=0xFF;// PortB auf Ausgang
20
21
TCCR0|=(1<<CS00)|(1<<CS02);// Prescaler auf 1024
22
TIMSK=(1<<TOIE0);// Interrupt bei Overflow erlauben
23
24
sei();// Interrupts generell zulassen
25
26
while(1)
27
{
28
if((PIND&(1<<PD0)==0))// PinD0 auf 0 ?
29
{
30
PORTB=0x01;
31
g_TimeReached=0;
32
g_Delays=300;// ********
33
}
34
35
if(g_TimeReached==1)
36
PORTB=0x00;
37
}
38
}
Und auf die Weise sieht man immer sofort, wenn irgendwo eine Klammer
zu viel ist! Alle mir bekannten Editoren machen die Einrückungen
automatisch, so dass man sich da praktisch keine Gedanken machen muss.
Ähm ist das nun der Code von Karl-Heinz Buchegger, welcher - wie ich
geschrieben habe - die gewünschte Zeit wartet und dementsprechend den
Port-PinD auf H-Pegel setzt?
Oder ist das der:
Karl-Heinz Buchegger wrote: Aber ich kann dir ein Programm schreiben,
welches bei einer 0 am
Pin D0 den Ausgang PB0 auf 1 setzt, eine gewisse Wartezeit abwartet
und danach den PB0 wieder auf 0 setzt.
Vielen Dank!
Der Code ist doch wirklich schön übersichtlich.
Glaubst du nicht du könntest mal versuchen den selber zu analysieren?
Dabei lernt man unheimlich viel, vielleicht brauchst du dann auch nicht
bei jedem kleinsten Schritt eine Hilfestellung.
Falls du einen der Befehle nicht verstehst und nicht in den Tutorials
findest kannst du gerne nachfragen.
Heinz der Heizer wrote:
> vielmehr meinte ich eigentl. ob ich den Code von Karl-Heinz so umbauen> kann, dass er meinen Ansprüchen gerecht wird.
Klar kannst du das.
Der Code zeigt dir ein funktionierendes Beispiel wie man mit einem Timer
arbeitet. Du brauchst jetzt nur noch deine gewünschte Funktionen in den
Code einbauen.
Johannes M. wrote:
> Da ist nicht nur eine Klammer zu viel! Da stimmt alles Mögliche mit> der Klammerung nicht.
Das muss ich auf meine Kappe nehmen. Ich war unter Zeitdruck und
habe den Code direkt im Forumseditor runtergetippt. Da sind
dann wohl einige Klammern auf der Strecke geblieben.
Wenn er sich allerdings an der Einrückung orientiert hätte und
ein bischen analysiert hätte was wohl die Idee hinter so manchem
Codestück ist, dann sollte man das aber schon sehen können, wo
welche Klammer fehlt :-)
Und ja. Der Code ist nicht als Vorstufe zu deiner Lösung zu
sehen sondern als Anschungsbeispiel, wie man mit einem Timer
Zeitsteuerungen machen kann. Wenn du verstanden hast, wie das
funktioniert, ist dein eigentliches Problem nicht mehr so schwer.
Leider ist mir das mit den Interrupts noch nicht so klar. Die einzelnen
Befehle vielleicht schon, aber wie ich das jetzt speziell auf mein
Problem, bzw Programm, anwenden kann, verstehe ich noch nicht.
Wenn Du es (bis jetzt) noch nicht verstanden hast, dann schlage ich Dir
(gut gemeint) vor, dass Du Dich zuerst einmal mit den Sachen
beschäftigst, die Du verstehst und Dich dann selbstständig und
schrittweise an Deine Problemstellung annäherst.
Das würde ich ja gerne, aber ich stehe nunmal vor dieser
Problemstellung, und komme mit meinem bisherigen Wissensstand nicht
weiter. Zudem ist mir ja nahegelegt worden, dass hier Interrupts
unverzichtbar sind, ergo stecke ich momentan in einer Sackgasse :)
Heinz der Heizer wrote:
> Das würde ich ja gerne, aber ich stehe nunmal vor dieser> Problemstellung, und komme mit meinem bisherigen Wissensstand nicht> weiter. Zudem ist mir ja nahegelegt worden, dass hier Interrupts> unverzichtbar sind, ergo stecke ich momentan in einer Sackgasse :)
Wir sind hier keine Dienstleister, die dir eine funktionierende Software
schreiben. Sowas kostet in der Regel Geld.
Hier bekommst du nur Tipps und Hilfestellungen, wie du selber deine
Software schreiben kannst.
> Leider ist mir das mit den Interrupts noch nicht so klar.Was ist unklar?
Das die Interruptroutine jedesmal aufgerufen wird, wenn der Interrupt
ausgelöst wird is doch klar oder? Und in deinem Fall benutzt du den
Timer-Overflow Interrupt, der wird also jedes mal aufgerufen, wenn der
Timer überläuft.
> aber wie ich das jetzt speziell auf mein> Problem, bzw Programm, anwenden kann, verstehe ich noch nicht.
Tja, Programmieren muss man erlernen. Dazu braucht man Erfahrung. Das
Handwerkszeug haben wir dir erklärt. Du weißt jetzt wie du eine LED per
Knopfdruck eine bestimmte Zeit lang leuchten lassen kannst.
Wie man jetzt die LED erst beim zweiten Knopfdruck leuchten lassen kann
ist jetzt deine Aufgabe.
Vom Prinzip is der Ablauf so:
Signal kommt an (High), dann wartest du bis es wieder auf Low geht.
Im Anschluss startest du einen Timer und lässt ihn z.B. 10 Sekunden
laufen.
Damit schaltest du deine Schaltung quasi für 10 Sekunden scharf.
Wenn dann jemand anruft bevor der Timer überläuft wird die Heizung
angeschalten. (Ein Timer steuert dann im Anschluss wie lange die Heizung
anbleiben soll)
Läuft der Timer vorher über "entschärft" er die Schaltung wieder und die
Heizung geht nicht an.
Auch wenn du jetzt vor dieser Problemstellung stehst:
Wenn du es nicht hinbekommst muss deine Problemstellung eben warten und
du musst mit kleineren Sachen anfangen. Programmieren lernt man nicht
von heute auf morgen. Dein Problem ist wirklich Programmiertechnisch,
das hat nichts mit Elektronik oder Mikrocontrollern zu tun.
Die Alternative ist natürlich sich jemand zu suchen der dir für nen
Kasten Bier die Software schreibt, das is vielleicht ne Sache von 15
Minuten.
Das nächste Problem, um das du dich kümmern musst ist die Erkennung
des Anrufsignals. Es reicht nicht, wenn du nur die Information hast,
dass der Eingang eine 0 aufweist. Denn diese 0 wird ein paar
Millisekunden da stehen. Du musst die Flanke erkennen, wann
das Signal den Pegel wechselt!
Und von dort weg ist es dann eigentlich einfach.
Kommt eine Flanke herein gibt es 3 Möglichkeiten
* Läuft die 10 Sekunden Zeitmessung bereits und ist die noch
nicht abgelaufen, dann war das die zweite Flanke
-> der Ausgang wird geschaltet und eine zweite Zeitmessung
startet nach deren Ablauf der Ausgang wieder in seine
Ruheposition zurückkommt
Die 10 Sekunden Zeitmessung wird abgestellt
* Läuft die 10 Sekunden Zeitmessung noch nicht und läuft auch
die zweite Zeitmessung noch nicht, dann war das die erste Flanke
-> die 10 Sekunden Zeitmessung wird gestartet
* Läuft die 10 Sekunden Zeitmessung noch nicht, wohl aber die
zweite Zeitmessung, so liegt der Fall vor, dass während der
Heizperiode ein weiterer Anruf kam. Du musst entscheiden
was in diesem Fall passieren soll. Zb. Könnte man die Heizung
dann vorzeitig abschalten
-> Ausgang in den Ruheszustand zurückschalten
zweite Zeitmessung abschalten.
Zusätzlich gibt es noch die Fälle
* die 10 Sekunden laufen ab, ohne dass das Eintreffen einer
zweiten Flanke die Heizung eingeschaltet hat.
-> Es muss nichts weiter gemacht werden. Die 10 Sekunden
Zeitmessung schaltet sich ab
* die zweite Zeitmessung, die die Heizperiode steuert läuft ab
-> der Heizausgang wird wieder in seinen Ruhezustand zurückgesetzt.
die zweite Zeitmessung schaltet sich ab.
Du musst anfangen in Form von "Ereignis tritt ein" zu denken und
nicht in Form von "erst mach dies, dann mach das"
Also, jetzt habe ich den Code mal soweit es ging auf meine Bedürfnisse
angepasst:
Folgendes macht das Programm (im Simulator) bisher, so wie es sein soll:
Wenn ich PIND0 zweimal drücke, dann kriegt PortB H-Pegel. Ansonsten
nicht.
Außerdem schaltet er dann den PortB wieder nach einer gewissen Zeit aus.
-Soweit sogut!
Nun habe ich noch das Problem, dass ich nicht weiß, ob er mit meinem
Code die Zeit berücksichtigt, in der die Taste mind. 2x gedrückt werden
soll.
Außerdem weiß ich nicht, wie ich "AnrufAnzahl" auf NULL setzen kann,
damit nach dem Ausschalten des PortB der Mikrocontroller auf erneute
Tastendrücke wartet.
Bisher muss ich nach Ausschalten von PortB lediglich EINMAL PinD
betätigen, damit PortB wieder aktiv wird.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
volatileuint16_tg_Delays;
5
volatileuint8_tg_TimeReached;
6
7
8
ISR(TIMER0_OVF_vect)
9
{
10
if(g_Delays>0)
11
g_Delays--;
12
13
if(g_Delays==0)
14
{
15
g_TimeReached=1;
16
}
17
}
18
19
intmain()
20
{
21
DDRD=0x00;// PortD auf Eingang
22
DDRB=0xFF;// PortB auf Ausgang
23
24
intAnrufAnzahl=0;
25
26
27
TCCR0|=(1<<CS00);// Prescaler auf 1024
28
TIMSK=(1<<TOIE0);// Interrupt bei Overflow erlauben
29
30
sei();// Interrupts generell zulassen
31
32
while(1)
33
{
34
if((AnrufAnzahl==0)&&(PIND&(1<<PD0)==1))// PinD0 auf 0 ?
Ach was solls. Mein Service Techniker in Hongkong ist mit dem
Programmupdate glücklich und ich hab ein bischen Zeit.
Aber versprich mir, dass du den Code studierst und nicht einfach
nur in einen µC brennst und gut ists.
Der Code überwacht den Pin PD0.
Kommt dort ein 0 Signal an, dann beginnt eine Torzeit von 10
Sekunden (einstellbar mit TIME_1) zu laufen. Gleichzeitig wird
eine Kontrollled eingeschaltet um anzuzeigen, dass die Schaltung
scharf ist und auf den zweiten Puls wartet. Kommt innerhalb
dieser Zeit ein zweites 0 Signal, dann wird die Kontrolled wieder
abgeschaltet, die Heizung eingeschaltet und die Heizzeit
(einstellbar mit TIME_2) beginnt.
Nach Ablauf der Heizzeit wird die Heizung wieder abgeschaltet.
Kommt innerhalb der Heizzeit ein weiterer Impuls, so wird die
Heizung vorzeitig abgeschaltet.
PORTB: Heizung am Pin HEATER_PIN
Kontrolled am Pin LED_PIN
PORTD: Signaleingang am Pin INPUT_PIN
Programm ist auf einem Mega16 getestet. Die Makros LED_ON, LED_OFF,
HEATER_ON, HEATER_OFF musst du anpassen, je nachdem ob ein gesetztes
Bit die Led/Heizung ein oder aus schaltet. Ich habs aber einfach
gemacht den jeweiligen Zustand zu verstehen. Im Moment sind alle
Ausgänge so benutzt, dass eine 0 die jeweilige Funktionalität
(Heizung, Led) einschaltet.
Ob du den Pullup am PortD brauchst, musst du selbst eintscheiden.
Im Moment ist der auskommentiert.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
// Taktfrequenz des Controllers
5
#define F_CPU 1000000
6
7
// wo sind Heizelement und Kontrollampe am Port B angeschlossen
8
#define HEATER_PIN PB0
9
#define LED_PIN PB1
10
11
// an welchem Eingang am Port D kommt das Signal herein
ok. Vielen Dank!
Echt nett von dir, dass du dir so eine Arbeit machst. Es hätte auch eine
Verbesserung meines bereits geschriebenen Codes gereicht.
Ich versuche deinen Code zu verstehen.
Danke!