Hallo zusammen,
ich bin auf der Suche nach einem C-Code für den Atmega8.
An PD2 liegt ein Rechtecksignal an mit ca. 10 Hz. Wird dieses Signal
erkannt, soll an PD4 ein Dauersignal ausgegeben werden, solange das
Rechtecksignal an PD2 anliegt.
Habe zwar schon einen Code gebastelt aber der ist mir zu ungenau und
reagiert natürlich etwas "träge". Ausgang PD4 reagiert manchmal zu lange
nicht, und zwar genau dann, wenn an PD2 gerade eine steigende Flanke
kommt, wenn die Schleife beim "delay" Befehl ist, so ist das Signal an
PD2 dann wieder futsch, wenn die Schleife von vorne beginnt und PD4 ist
ungewollt nicht aktiv.
Jetzt möchte ich gerne das ganze über Interrupt Programmierung lösen.
Macht das Sinn? Oder kann man den bestehenden Code so hinbiegen, dass es
passt?
Danke
Christian
1
// Hauptschleife
2
while(1)
3
{
4
5
// WK-IN vorhanden?
6
if((PIND&(1<<PIND2)))
7
{
8
// Signal ausgeben
9
PORTD&=~(1<<PD4);
10
}
11
12
// WK-IN nicht aktiv?
13
if(!(PIND&(1<<PIND2)))
14
{
15
// Auf 100% Tastverhältnis "erweitern" und dann WK-OUT deaktivieren
Christian W. schrieb:> Habe zwar schon einen Code gebastelt aber der ist mir zu ungenau und> reagiert natürlich etwas "träge".
Schneller als 100ms wird nicht mal der beste Code reagieren können...
Ich würde das etwa so machen:
1
voilatileuint8_ttimeout;
2
3
TIMER_ISR()// 1ms
4
{
5
if(timeout)timeout--;
6
}
7
8
main()
9
{
10
11
// Hauptschleife
12
while(1)
13
{
14
15
// WK-IN
16
if(PIND&(1<<PIND2))timeout=100;// Signal da --> timeout auf 100ms setzen
17
18
// Ausgang
19
if(timeout)PORTD|=(1<<PD4);// setzen, solange timeout noch > 0
20
elsePORTD&=~(1<<PD4);
21
22
}
23
}
Abhaängig vom möglichen Tastverhältnis der PWM kann das timeout auch auf
kleinere Werte gesetzt werden. Wenn z.B. die High-Zeit nicht kleiner als
30ms werden kann, dann reicht ein Timeout von ca. 70ms aus, weil ja
solange das Eingangssignal 1 ist, der timeout immer wieder auf den
Startwert (hier 100) gesetzt wird...
Versuch mal ein ein Delay von 50ms (oder besser 51ms wenn eine
Verzögerung von 1ms drin is;)). (10Hz --> Periode 100ms = 50ms high;
50ms low)
Zur Flankenerkennung brauchst Du bei 10Hz wohl nicht unbedingt einen
Interrupteingang. Eine saubere Lösung wäre allerding mit einem
Timerinterrupt nach den 50ms, da kein busy-wait...
TT. schrieb:> Versuch mal ein ein Delay von 50ms (oder besser 51ms wenn eine> Verzögerung von 1ms drin is;)
Blöd nur, wenn die PWM zufällig mal 30/70 oder gar 99/1 beträgt... :-o
TT. schrieb:> Zur Flankenerkennung brauchst Du bei 10Hz wohl nicht unbedingt einen> Interrupteingang.
Ich würds trotzdem machen. PWM Pulse können sehr kurz sein.
Den Rest so wie Lothar das gezeigt hat.
Lothar Miller schrieb:> voilatile
Da musste ich doch gerade mal über mich selber lachen... :D
Karl Heinz Buchegger schrieb:> Den Rest so wie Lothar das gezeigt hat.
Mit dem Interrupt-Pin wird das Ganze noch hübscher:
1
volatileuint8_ttimeout;
2
3
TIMER_ISR()// 1ms
4
{
5
if(timeout)timeout--;
6
}
7
8
EXTERNERPIN_ISR()// Pinchange oder allg. Flanken-Interrupt für PIND2
9
{
10
timeout=100;// Signal da --> timeout auf 100ms setzen
11
}
12
13
main()
14
{
15
ISR_INIT();// deine Arbeit
16
// Hauptschleife
17
while(1)
18
{
19
// Ausgang
20
if(timeout)PORTD|=(1<<PD4);// setzen, solange timeout noch > 0
Hallo,
danke für die Antworten.
Habe ich hier noch ein Verständnisproblem?
Die Atmega8-Doku sagt folgendes zu den Externen Interrupts:
"Note that recognition of falling or rising edge interrupts on INT0 and
INT1 requires the presence of an I/O clock, described in “Clock Systems
and their Distribution” on page 23"
Heißt jetzt "requires the presence of an I/O clock", dass ich da noch
sowas wie einen Taktgeber programmieren/verwenden muss?
Einen internen Takt von 1 MHz habe ich ja sowieso...
Ich versteh die Aussage momentan nicht so richtig ;-) ;-)
Christian
Hi
>Heißt jetzt "requires the presence of an I/O clock", dass ich da noch>sowas wie einen Taktgeber programmieren/verwenden muss?
Nein. Mit dem IO-Clock (im allg. die Taktfrequenz des AVR) werden alle
getakteten IO-Module (z.B Timer und auch der Interrupteingang)
automatisch versorgt.
Siehe Datenblatt: 'Clock Systems and their Distribution'.
MfG Spess
>Heißt jetzt "requires the presence of an I/O clock", dass ich da noch>sowas wie einen Taktgeber programmieren/verwenden muss?
Nein. "I/O clock" ist ein Terminus aus dem Datenblatt der einen
bestimmten Takt meint der intern aus dem Haupttakt abgeleitet wird.
Sinngemäß bezeichnet er eine bestimmte Taktdomäne.
Der Satz ist im Zusammenhang mit den Power-Down-, resp. Sleep-Modi
wichtig, weil dann bestimmte Taktsignale, je nach Modus, nicht mehr
erzeugt werden. Es geht hier also darum, das Flankeninterrupts nur bei
vorhandenem I/O-Takt, also bei bestimmten Sleep Modi funktionieren.
Die Ursache hat mit dem Mechanismus für die Erkennung von Flanken zu
tun. Dieser benötigt nämlich einen Takt.
Näheres im Datenblatt.
Hallo zusammen,
danke für die Antworten.
Habe jetzt anhand der Vorschläge einen C-Code erstellt, der soweit gut
klappt, aber:
PD4 ist etwas mehr als 1 Sekunde aktiv, sollte aber nur ca. 100 ms aktiv
sein.
Was ist da noch falsch? Ich komm nicht drauf...
Danke!
Christian
1
#include<avr/io.h> // Grundfunktionen
2
#define F_CPU 1000000UL // CPU Frequenz
3
#include<util/delay.h> // Warteschleifen
4
#include<avr/interrupt.h> // Interrupts
5
6
7
8
// Variable für Timer
9
volatileuint8_ttimeout;
10
11
12
13
ISR(TIMER0_OVF_vect)// Interruptauslösung bei Timerüberlauf 1 ms
14
{
15
if(timeout)
16
{
17
// Zähler um 1 verringern
18
timeout--;
19
}
20
}
21
22
23
24
ISR(INT0_vect)// Auf wechselnde Flanke an INT0 (PD2) reagieren
25
{
26
// Falls Signalflanke erkannt, dann Timeout wieder auf 100 hochsetzen