- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 10 von 10

Thema: INT0 funktioniert nicht

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    08.07.2008
    Beiträge
    49

    INT0 funktioniert nicht

    Anzeige

    Praxistest und DIY Projekte
    Hallo,

    ich bin gerade dabei ein kleines Programm für eine Ladeschaltung zu Programmieren. Ich benutze einen Atmega8. Im Allgmeinen ist das Programm wie folgt aufgebaut:

    Ich benutze 2 Timer. Timer1 für die PWM generierung der LED. Einmal steuern der Helligkeit und einmal Ein und Aus schalten in abhängigkeit des ADUs. Außerdem ereuge ich durch zwei hochzählende Variablen Takte als abaufsteuerung des restlichen Programms

    Timer0 soll den µC aus dem Idle Mode wecken.

    Das alles funktioniert auch schön und gut. Allerdings möchte ich auch das der µC durch INT0 geweckt wird durch eine Positive Flanke. Leider funktioniert es nicht wirklich. Er springt glaub ich in die ISR rein allerdings hab ich da wohl nicht sauber Programmiert. Kann mir da einer helfen? Wäre super hab mir schon total den kopf zerbrochen....

    Ich bedanke mich schon einmal für die Hilfe.

    Gruß Jonas

    Hier der Code:

    Code:
    #define F_CPU 1000000UL            //CPU takt auf 1MHz#include <avr/io.h>
    #include <util/delay.h>
    #include <stdint.h>
    #include <avr/interrupt.h>
    #include "ADC.h"
    
    
    #define Uladeschluss 1014
    #define UladeschlussLED Uladeschluss-0
    #define UladeschlussR 914
    #define Uladeunter 814
    #define UladeunterLED Uladeunter+0
    #define UladeunterR 914
    #define adupwmmin Uladeunter
    #define adupwmmax Uladeschluss
    #define helligkeit 5 //10 ist maximum
    
    
    #define devidedeltaU (((UladeschlussLED)-(UladeunterLED))/100)
    
    
    #define ledddr DDRD
    #define ledPort PORTD
    #define ledG PD7
    #define ADC_ONddr DDRB
    #define ADC_ONPort PORTB
    #define ADC_ON PB0
    #define ladeddr DDRD
    #define ladeport PORTD
    #define ladeschlussS PD3
    #define ladeschlussR PD4
    #define ladeunterS PD5
    #define ladeunterR PD6
    #define ladeschlussRelais PD0
    #define ladeunterRelais PD1
    #define DynOn PD2
    #define Relaisddr DDRD
    #define RelaisPort PORTD
    #define RelaisPins PIND
    
    
    volatile unsigned char timerz=0;
    volatile unsigned char timerpwm = 0;
    volatile unsigned short adupwm;
    volatile unsigned short takt1 = 0;
    volatile unsigned short takt2 = 0;
    volatile unsigned char status1 = 0;
    volatile unsigned short adu, adu1, adu2;
    
    
    ISR(INT0_vect)
    {
        GICR &= ~(1<<INT0);        //INT0 aus
        MCUCR &= ~(1<<SE);
        timerz=0;
        timerpwm=0;
        takt1=0;
        takt2=0;
        TCCR0 |= (1<<CS01);  //Timer0 ein mit prescler 8
        TCCR1B = 0;            //Timer1 aus
    }
    
    
    ISR(TIMER0_OVF_vect)
    {
        takt1++;
        takt2++;
        timerz++;
        if(timerz <= helligkeit)
        {    
            if (adupwm < timerpwm)
            {
                ledPort &= ~(1<<ledG);
            }
            else
            {
                ledPort |= (1<<ledG);
            }
            if (timerpwm>=100)
            {
                timerpwm=0;
            }
        }
        else
        {
            ledPort &= ~(1<<ledG);
        }
        
        if(timerz==10)
        {
            timerz=0;
            timerpwm++;
        }    
    }
    
    
    ISR(TIMER1_OVF_vect)
    {
        MCUCR &= ~(1<<SE);
        GICR &= ~(1<<INT0);        //INT0 aus
        timerz=0;
        timerpwm=0;
        takt1=0;
        takt2=0;
        TCCR0 |= (1<<CS01);  //Timer0 ein mit prescler 8
        TCCR1B = 0;            //Timer1 aus
    }    
    
    
    void impuls(volatile uint8_t *port, uint8_t pin);
    
    
    int main(void)
    {
        //extern ref.. ADC0 als Eingang, rechts Ausrichtung
        ADMUX = 0;
        //ADU Einstellung:Einzelwandlung, 128 Teilung, keine Interrupts
        ADCSRA = 0;
        ADCSRA |= (1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0);
        
        //Timer0 Teiler
        TCCR0 = 0;
        TCCR0 |= (1<<CS01);  //prescaler auf 8 2ms pro Überlauf bei 1MHz
        //Timer0 Interrupt einschalten
        TIMSK = 0;
        TIMSK |= (1 << TOIE0);
        
        //Timer1 Teiler
        TCCR1B = 0;
        TCCR1B |= (1<<CS12)|(1<<CS10);    //prescaler auf 1024 alle 61sec ein Überlauf bei 1MHz
        //Timer1 Interrupt einschalten
        TIMSK |= (1<<TOIE1);
        
        //Extern Interrupt
        MCUCR |= (1<<ISC01)|(1<<ISC00);        //INT0 auf steigende Flanke (1<<ISC01)|(1<<ISC00)
        
        // Den Pin, an den die LED angeschlossen ist, als Ausgang setzen
        ledddr = 0;
        ladeddr = 0;
        ADC_ONddr = 0;
        Relaisddr = 0;
        
        ledddr |= (1 << ledG);
        ladeddr |= (1 << ladeunterR)|(1<<ladeunterS)|(1<<ladeschlussS)|(1<<ladeschlussR); //Als Ausgang
        ADC_ONddr |= (1<<ADC_ON);
        
        RelaisPort |= (1<<ladeschlussRelais)|(1<<ladeunterRelais);  //Eingänge setzen
            
        sei();
        
        
        /*
        do                        //Ersten ADU wert einlesen
        {
            timerz=0;
            ledPort &= ~(1<<ledG);
            
            if (takt1>489)                            //takt1 wird vom zähler gezählt, d.h. warten
            {
                if (!(status1 & (1<<0)))            //wenn noch nicht in schleife
                {
                    ADCSRA |= (1<<ADEN);            //Einschalten des ADU
                    ADC_ONPort |= (1<<ADC_ON);        //Einschalten ADC_ON um Spannungsteiler vom ADC auf Masse zu legen
                    status1 |= (1<<0);
                }
                
                if (takt1>=500 && !(status1 & (1<<1)))   //Erste AD Wandlung danach eine Zweite
                {                                        //beide werden verglichen ob sie auf bis zu
                    adu1 = getADC();                    //10 stellen ähnlich sind wenn ja
                    status1 |= (1<<1);                    //weiter mit arbeiten
                }
                
                if (takt1>=510)
                {
                    adu2 = getADC();
                    
                    if ((adu1<=(adu2+5)) && (adu1 >=(adu2-5)))
                    {
                        adu=adu2;
                    }
                    
                    
                    if (adu<=UladeunterLED)        //Kontrolle ob ladeunter- oder Ladeüberspannung
                    {                            //erreicht wurde und dadrauf die grenzen für das
                        adupwm=0;                //blinken der LED setzen
                    }
                    else
                    {
                        if (adu >= UladeschlussLED)
                        {
                            adupwm=100;
                        }
                        else
                        {
                            adupwm=((adu-UladeunterLED)/devidedeltaU);
                        }
                    }
                    
                    ADCSRA &= ~(1<<ADEN);            //Auschalten des ADU
                    ADC_ONPort &= ~(1<<ADC_ON);
                    status1 &= ~(1<<0);
                    status1 &= ~(1<<1);
                }                                        
            }        
        } while (takt1<=513);
        
        takt1=0;
        */
        while (1)                                    //Hauptschleife
        {
            if (takt1>489)                            //takt1 wird vom zähler gezählt, d.h. warten
            {
                if (!(status1 & (1<<0)))            //wenn noch nicht in schleife
                {        
                    ADCSRA |= (1<<ADEN);            //Einschalten des ADU                            
                    ADC_ONPort |= (1<<ADC_ON);        //Einschalten ADC_ON um Spannungsteiler vom ADC auf Masse zu legen
                    status1 |= (1<<0);
                }
                            
                if (takt1>=500 && !(status1 & (1<<1)))   //Erste AD Wandlung danach eine Zweite
                {                                        //beide werden verglichen ob sie auf bis zu
                    adu1 = getADC();                    //10 stellen ähnlich sind wenn ja
                    status1 |= (1<<1);                    //weiter mit arbeiten
                }
                
                if (takt1>=510)
                {
                    adu2 = getADC();
                    
                    if ((adu1<=(adu2+5)) && (adu1 >=(adu2-5)))
                    {
                        adu=adu2;
                    }
                                    
            
                    if (adu<=UladeunterLED)        //Kontrolle ob ladeunter- oder Ladeüberspannung
                    {                            //erreicht wurde und dadrauf die grenzen für das
                        adupwm=0;                //blinken der LED setzen
                    } 
                    else
                    {
                        if (adu >= UladeschlussLED)
                        {
                            adupwm=100;
                        }
                        else 
                        {
                            adupwm=((adu-UladeunterLED)/devidedeltaU);
                        }    
                    }
                    
                    ADCSRA &= ~(1<<ADEN);            //Auschalten des ADU
                    ADC_ONPort &= ~(1<<ADC_ON);    
                    takt1=0;
                    status1 &= ~(1<<0);    
                    status1 &= ~(1<<1);    
                    
                    //Kontrolle ob Ladeunter- oder Ladeüberspannung erreicht wurde dann Kontrolle ob Relais
                    //schon geschaltet haben sonst selber schalten
                    if ((adu > Uladeschluss) && !(RelaisPins & (1<<ladeschlussRelais)))
                    {
                        ladeport |= (1<<ladeschlussS);
                    }else ladeport &= ~(1<<ladeschlussS);
                    
                    if ((adu < UladeschlussR) && (RelaisPins & (1<<ladeschlussRelais)))
                    {
                        ladeport |= (1<<ladeschlussR);
                    }else ladeport &= ~(1<<ladeschlussR);
                    
                    if ((adu < Uladeunter) && !(RelaisPins & (1<<ladeunterRelais)))
                    {
                        ladeport |= (1<<ladeunterS);
                    }else ladeport &= ~(1<<ladeunterS);
                    
                    if ((adu > UladeunterR) && (RelaisPins & (1<<ladeunterRelais)))
                    {
                        ladeport |= (1<<ladeunterR);
                    }else ladeport &= ~(1<<ladeunterR);                        
                }
            }
            
            takt2=0;
            
            if (!(RelaisPins & (1<<DynOn)))
            {
                do                //Nichts tun nur Timer0 läuft daher LED blinkt
                {
                } while (takt2<=2100 && !(RelaisPins & (1<<DynOn)));
                
                TCCR0 = 0;                //Timer0 aus
                TCCR1B |= (1<<CS12)|(1<<CS10); //Timer1 ein
                ledPort &= ~(1<<ledG);    //LED aus
                GICR |= (1<<INT0);        //INT0 ein
                MCUCR |= (1<<SE);        //Sleep Modus ein
            }
                                        
        }
    }

  2. #2
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    Hallo!

    Ich bin ASMan und kenne "Cäh" gar nicht. Ich habe das Problem beim PIC per Verbinden des INT0 Pins mit anderem Pin gelöst: https://www.roboternetz.de/community...l=1#post559630 .
    MfG (Mit feinem Grübeln) Wir unterstützen dich bei deinen Projekten, aber wir entwickeln sie nicht für dich. (radbruch) "Irgendwas" geht "irgendwie" immer...(Rabenauge) Machs - und berichte.(oberallgeier) Man weißt wie, aber nie warum. Gut zu wissen, was man nicht weiß. Zuerst messen, danach fragen. Was heute geht, wurde gestern gebastelt. http://www.youtube.com/watch?v=qOAnVO3y2u8 Danke!

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Nur weil Du SE im MCUCR setzt, schläft da noch lange nix, das würde erst nach dem Opcode SLEEP passieren. Unter C gibt's für die Powermodes 'ne Lib, verwende am Besten die Lib.

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    08.07.2008
    Beiträge
    49
    Oh total überlesen im Datenblat...

    Aber das erklärt doch noch nicht warum er den Code in der INT0 ISR nicht ausführt. Er soll ja eigentlich genau das machen was auch beim Timer1 passiert und mit dem Timer1 geht es....

  5. #5
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    Sorry, aber ich mache nur das minimalste, was ich brauche.
    MfG (Mit feinem Grübeln) Wir unterstützen dich bei deinen Projekten, aber wir entwickeln sie nicht für dich. (radbruch) "Irgendwas" geht "irgendwie" immer...(Rabenauge) Machs - und berichte.(oberallgeier) Man weißt wie, aber nie warum. Gut zu wissen, was man nicht weiß. Zuerst messen, danach fragen. Was heute geht, wurde gestern gebastelt. http://www.youtube.com/watch?v=qOAnVO3y2u8 Danke!

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Da im Sleep der Hauptcode des uC nicht weiter ausgeführt wird, dürfte sich der tatsächliche Ablauf vom gedachten Ablauf doch deutlich unterscheiden. Damit ist natürlich möglich, dass der INT0 an anderer Stelle disabled wird. Bring doch erst mal Deinen Code so in Ordnung, dass er vom Powermode her so klappt, wie gedacht.
    Es macht keinen Sinn sich über das wie und warum eines anderen Fehlers Gedanken zu machen, wenn der offensichtlichste Fehler noch nicht behoben ist.
    Ob der INT0 dann später tatsächlich anspricht, lässt sich durch Wacklen eines Pins in der ISR testen.

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    08.07.2008
    Beiträge
    49
    OK sehr vielen dank werde ich morgen mal machen. Werde einfach überall da wo ich vorher das se Bit gesetzt habe die Funktionen:

    set_sleep_mode(SLEEP_MODE_IDLE);
    sleep_mode();

    nutzen. In den beiden ISR werde ich auch das löschen des SE Bits entfernen.

    Mich würde aber schon einmal interessieren wo ich im Datenblatt die so genannte SLEEP instruction finde.
    Weiß das jemand?

  8. #8
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    Normaleweise befindet sich der "sleep" Befehl in "Instruction Set Summary" vom Datenblatt (DB).
    MfG (Mit feinem Grübeln) Wir unterstützen dich bei deinen Projekten, aber wir entwickeln sie nicht für dich. (radbruch) "Irgendwas" geht "irgendwie" immer...(Rabenauge) Machs - und berichte.(oberallgeier) Man weißt wie, aber nie warum. Gut zu wissen, was man nicht weiß. Zuerst messen, danach fragen. Was heute geht, wurde gestern gebastelt. http://www.youtube.com/watch?v=qOAnVO3y2u8 Danke!

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    SLEEP ist wie schon geschrieben ein Opcode, Du könntest den per Inline Assembler einfügen, oder eben die entsprechenden Funktionen der Lib verwenden, die das alles für Dich machen.

  10. #10
    Benutzer Stammmitglied
    Registriert seit
    08.07.2008
    Beiträge
    49
    OK nun weiß ich was du da mit Opcode meintest. Fehler ist nun auch weg hat Wunderbar geklappt. Noch einmal vielen vielen Dank

Ähnliche Themen

  1. INT0 Interrupt funktioniert nicht
    Von Jason07 im Forum Assembler-Programmierung
    Antworten: 12
    Letzter Beitrag: 22.03.2013, 06:58
  2. Int0 wird bei direkt bei 'Enable Int0' ausgelöst - Warum?
    Von malthy im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 30.08.2010, 18:10
  3. RC5 Abfrage funktioniert per Polling, aber nicht per INT0
    Von luvat im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 17.03.2008, 04:10
  4. Int0 will einfach nicht - oder bin ich zu b....
    Von Raimond im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 9
    Letzter Beitrag: 27.11.2006, 20:28
  5. int0 bei Atmega162 will nicht
    Von MarkusH im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 07.01.2005, 19:49

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests