Forum: Mikrocontroller und Digitale Elektronik Ausgang bei Pegeländerung am Eingang ändern


von Lokus P. (derschatten)


Lesenswert?

Ich möchte am Ausgang einen fix definierten Zustand ausgeben (LO), der 
allerdings geändert werden soll, wenn an einem bestimmten Eingang eine 
Pegeländerung stattgefunden hat.

Also wenn beim Einschalten der Eingang HI oder LO ist soll am Ausgang 
ein LOW ausgegeben werden.
Ändert sich jedoch der Eingang entweder auf LO oder auf HI, je nachdem 
was vorher war, soll am Ausgang ein HI ausgegeben werden, sollange sich 
der Pegel am Eingang nicht ändert.

Das ganze in C für einen ATMEGA.

von citb (Gast)


Lesenswert?

Ja und?
Eingangszustand merken, wenn veraendert, dann Ausgang auf High setzen.

citb

von Lokus P. (derschatten)


Lesenswert?

Ja, soweit war ich auch schon. Nur wo merken?
Wenn ich das ganze in den Timer Interrupt schmeiße wird der gemerkte 
Zustand ja ständig überschrieben. Gleichzeitig muß ich ja permanent den 
Zustand abfragen. Wie mach ich das?

von citb (Gast)


Lesenswert?

C-Tutorial lesen und durcharbeiten.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

citb

von Michel (Gast)


Lesenswert?

Das geht sogar in Assembler ;-)

von Lokus P. (derschatten)


Lesenswert?

Ja, warum sollte es in Assembler nicht gehen? Wenn, dann dort sowieso.

von Lokus P. (derschatten)


Lesenswert?

Also, niemand einen Tip für mich?
Es geht ja nicht nur um den Einschaltzustand, sondern immer dann wenn 
sich das Bit ändert.

von Lokus P. (derschatten)


Lesenswert?

Also ich habs jetzt mal so versucht:
1
    if(LICHT_EIN != lichtval)
2
    {
3
      lichtCount = 25;                  // LICHTAUSGANG für 150ms auf HI
4
      lichtval = LICHT_EIN;
5
    }

Läuft aber nicht so ganz.
Ausgang bleibt ständig auf HI, obwohl die Variable lichtval gleich 
LICHT_EIN gesetzt wird.

von citb (Gast)


Lesenswert?

Ich sehe keinen Ausgang.

citb

von Lokus P. (derschatten)


Lesenswert?

1
#define SCHALTER_PORT  PORTD
2
#define WRITE  0x10
3
#define LICHT_EIN    (PINC & 1 << PC3)
4
5
static int16_t lichtCount = 0;
6
static int8_t lichtval;
7
8
ISR(TIMER0_OVF_vect)
9
{
10
    if(lichtCount > 0)
11
    {
12
        SCHALTER_PORT |= (WRITE);
13
        lichtCount--;
14
        if(lichtCount == 0)
15
            lichtval = LICHT_EIN;
16
    }
17
18
    if(LICHT_EIN != lichtval)
19
    {
20
        lichtCount = 25;                  // LICHTAUSGANG für 150ms auf HI
21
    }
22
    if(LICHT_EIN == lichtval)
23
    {
24
        SCHALTER_PORT &= ~(WRITE);              // LICHTAUSGANG = LOW
25
    }
26
}

Also im Normalzustand soll der Ausgang immer auf LO sein. Nur bei einem 
Flankenwechsel soll er für 150ms auf HI gehen.

von M. J. (manfred-64)


Lesenswert?

Hi,

is zwar Assembler für'n Pic aber vielleicht hilft's Dir ja auf die 
Sprünge :)

Steht so bei mir in der Interruptroutine.
1
Sekunde  BCF    INTCON,T0IF    ; alle 1/125 Sec.
2
    bcf    Sec_Flag
3
    btfsc  DCF_Port
4
    goto  DCFPortHI
5
    goto  DCFPortLO
6
DCFPortHI          
7
    btfsc  DCF_Port_Flag  
8
    goto  DCFPortEND    ; DCF_PORT war Hi
9
    bsf    DCF_Rise_Flag  ; DCF_PORT ist Hi geworden
10
    bsf    DCF_Port_Flag  
11
    goto  DCFPortEND
12
DCFPortLO
13
    btfss  DCF_Port_Flag
14
    goto  DCFPortEND    ; DCF_PORT war bereits Lo
15
    bsf    DCF_Sink_Flag  ; DCF_PORT ist Lo geworden
16
    bcf    DCF_Port_Flag
17
DCFPortEND
18
    incf  DCF_Timer
19
    DECFSZ  Clock125
20
    goto  INT_END
21
    MOVLW  D'125'  
22
    MOVWF   Clock125
23
    bsf    Sec_Flag

von Lokus P. (derschatten)


Lesenswert?

Leider, damit fang ich gar nichts an.

Aber ich hab noch einen Fehler entdeckt.
Das         SCHALTER_PORT |= (WRITE); gehört natürlich noch weg.

Funkt aber immer noch nicht. Bleibt immer auf LO der Ausgang.

von M. J. (manfred-64)


Lesenswert?

Manfred W. schrieb:
> Leider, damit fang ich gar nichts an.

Du benötigst eine Hilfs-Var. wo Du Dir merkst was für ein zustand beim 
letzten Test am Port war, um entscheiden zu können ob ein Pegel Wechsel 
stattgefunden hat!

von Lokus P. (derschatten)


Lesenswert?

Ja, in meinem Fall die "lichtval"
Diese wird mit dem aktuellen Zustand gefüttert.

von Idee (Gast)


Lesenswert?

Hmm, könnte es vielleicht an der zweiten If-Abfrage liegen.

Angenommen Du erkennst "LICHT_EIN != lichtval" und
setzt den counter auf 25. Im nächsten durchlauf wird
counter zwar um eins runtergezählt, es gilt jedoch
weiterhin "LICHT_EIN != lichtval", weshalb die If-Abfrage
den counter wieder auf 25 setzt (und so weiter und sofort...).


Wie gesagt möglicherweise, eventuell, vielleicht
(ich bin nicht wirklich in der Materie verhaftet) :-)

Nur so als idee...

von Lokus P. (derschatten)


Lesenswert?

Du hast recht. Abgesehen davon gehört das:
1
SCHALTER_PORT |= (WRITE);
doch rein. Sonst geht der Ausgang ja nie auf HI.

So läufts nun:
1
#define SCHALTER_PORT  PORTD
2
#define WRITE  0x10
3
#define LICHT_EIN    (PINC & 1 << PC3)
4
5
static int16_t lichtCount = 0;
6
static int8_t lichtval;
7
8
ISR(TIMER0_OVF_vect)
9
{
10
    if(lichtCount > 0)
11
    {
12
        SCHALTER_PORT |= (WRITE);
13
        lichtCount--;
14
        if(lichtCount == 0)
15
            lichtval = LICHT_EIN;
16
    }
17
18
    if((LICHT_EIN != lichtval) && (lichtCount == 0))
19
        lichtCount = 25;                  // LICHTAUSGANG für 150ms auf HI
20
    if(LICHT_EIN == lichtval)
21
        SCHALTER_PORT &= ~(WRITE);              // LICHTAUSGANG = LOW
22
}

Danke dir für den Hinweis!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.