- LiFePO4 Speicher Test         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 17

Thema: Einfacher ADC-interrupt

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    27.02.2013
    Beiträge
    7

    Einfacher ADC-interrupt

    Anzeige

    E-Bike
    Hi zusammen,

    ich habe ein wahrscheinlich relativ einfaches Problem, aber komme leider nicht weiter.
    Ich verwende einen ATmega32L.
    Am PINA7 ist ein einfacher Knopf angebracht, der beim Drücken einen Interrupt auslösen soll. Ich habe dann ins Datenblatt des ATmega32L geguckt und da steht neben dem PINA7 (ADC7).
    Wie gesagt, ich weiß leider echt nicht viel von Interrupts, habe mir dann einige Tutorials angeguckt und da bisschen was abgeguckt:

    Code:
    int main()
    {
    
    DDRA &= ~((1<<PA7));	// Pin PA7 auf Eingang setzen, da hängt der Botton dran
    ADCSRA = 0x8F;                 // ADC und Interrupts aktivieren
    ADMUX |= ((1<<MUX0)|(1<<MUX1)|(1<<MUX2));  // Auf ADC7 setzen
    sei();
    ADCSRA |= 1<<ADSC;      //starten
    
    	
    	while(1){}
    }
    
    
    ISR(ADC_vect){
    	GREEN_LED_ON(); // Macro, schaltet LED für 1 sek an, dann wieder aus
    }
    Er springt beim Starten des Programms rein, aber danach nicht wieder ( also reagiert allgemein nicht auf den Button).
    Kann mir da wer helfen?


    Vielen Dank und sry, dass ich eine wahrscheinlich simple Frage habe.
    Geändert von RumpelHumpel (28.02.2013 um 08:41 Uhr)

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von HeXPloreR
    Registriert seit
    08.07.2008
    Ort
    Bad Bramstedt
    Alter
    45
    Beiträge
    1.369
    Hallo,

    und das ist der ganze Code?

    Ich bin der Meinung Du beschreibst gut was Du machen willst, aber das Programm sieht etwas merkwürdig aus. Ich gebe zu ich habe noch nicht viel in C programmiert...aber ich denke das man nicht über einen ADC-Eingang gleichzeitig auch einen Interrupt erhalten kann. Was man bekommen könnte bzw daraus machen könnte wäre eine Schaltschwelle...

    Einen Pin auf Ausgang zu setzen der als Eingang benutzt werden soll (- da hängt der Button dran), macht ziemlich wenig Sinn.
    Prüfe auch mal ob "ADCSRA |= 1<<ADSC; " so richtig wäre. Hier vermute ich zumindest einen dreher...
    Mit xxMUX stellt man soweit ich weiß die Widerstände intern ein...was 0, 1, 2 genau mit ADC7 zu tun hat würde ich gerne wissen?

    Ich fürchte für Dich ist es nicht getan ein paar Tutorials anzusehen und schon läuft die Sache. C ist etwas komplizierter in solchen Dingen asl z.B. Bascom.
    Geändert von HeXPloreR (27.02.2013 um 17:47 Uhr)

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    27.02.2013
    Beiträge
    7
    Sry, war falsch kommentiert. Sollte eigentlich "Pin auf Eingang setzen" heißen

  4. #4
    Erfahrener Benutzer Roboter Genie Avatar von HeXPloreR
    Registriert seit
    08.07.2008
    Ort
    Bad Bramstedt
    Alter
    45
    Beiträge
    1.369
    jo, das mit dem ADMUX scheint auf jedenfall schon mal irgendwie dazu zu gehören, und ist so auf "7" eingestellt - mein Fehler, irgendwie mit irgendwas verwechselt.

  5. #5
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.678
    ... springt beim Starten des Programms rein, aber danach nicht wieder ...
    Woher weißt Du, dass die ISR nicht wieder angesprungen wird? Ich nehme in solchen Fällen in der ISR meist ein zusätzliches Statement, mit dem ich nen Ausgang (üblicherweise ne LED) toggle. Damit kann man etwas sehen oder bei schnellen Zyklen evtl. auf dem Oskar verfolgen.

    Code: ... wait{} ... ISR { ... GREEN_LED_ON;} ...
    Setzen wir mal voraus, dass das GREEN_LED_ON ein Makro ist, das auch den Ausgang so setzt, dass die LED angeht. Und wo bitte geht die wieder aus?!?!? Ich seh nur die leere wait{}. Dein Codefenster enthält 1. nicht den ganzen Code - siehe das fehlende Makro, 2. eine ISR mit einer einzigen Funktion und 3. eine leere wait-Schleife die keine Änderung des einmal hergestellten Zustandes bewirkt.

    Heilung evtl. durch ein Statement in der while-Schleife: delay_ms ( 1000); LED_OFF; delay_ms ( 1000); ... Das delay evtl. als die übliche Compilerroutine oder eine eigene Konstruktion - oder irgendeine Bremsschleife . . .

    Viel Erfolg
    Ciao sagt der JoeamBerg

  6. #6
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Der ADC wird für eine Wandlung gestartet, entsprechend wird auch nur eine Wandlung fertig und löst einen Interrupts aus.
    Der ADC kann nicht dazu genutzt werden um direkt bei einer Änderung am Eingang einen Interrupt auszulösen. Das ginge mit dem analogen Komparator, und über den MUX vom ADC könnte man hier auch den PIN PA7 als Eingng wählen.

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    27.02.2013
    Beiträge
    7
    Das GREEN_LED_ON schaltet eine grüne LED für 1 Sek an, dann wieder aus, sry, habe ich nicht erklärt.
    Ok, danke für die Info. Ich dachte, wenn ich ADMUX vom ADC auf PIN PA7 stelle merkt der, wenn da eine Änderung passiert. Dann werde ich mir den Komparator mal angucken.

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.678
    Zitat Zitat von RumpelHumpel Beitrag anzeigen
    ... GREEN_LED_ON schaltet eine grüne LED für 1 Sek an, dann wieder aus ...
    Es macht herzlich wenig Sinn, wenn man nur den halben Code einstellt und dann Zeile für Zeile nachbessert. Es macht nur die Lösungssuche ziemlich diffuser. Vor Allem wenn der geheimgehaltene Codeteil ("... LED für 1 Sek ...") möglicherweise den Kern des Problems in sich trägt.

    Zitat Zitat von RumpelHumpel Beitrag anzeigen
    ... dann wieder aus, sry, habe ich nicht erklärt ...
    Wurde ja schon von HeXPloreR angemerkt, dass Du recht wenig Code bereitgestellt hast, vermutlich um unsere Ratemöglichkeiten zu vervielfachen.

    Ich habe nen free running ADC z.B. für die Spannungscontrolle meiner Energieversorgung. Hier mal eine 1:1-Kopie des Codes für den m1284 - vielleicht hilft Dir das als Leitlinie für Deine Lösung. Übrigens siehst Du in der ISR auch zwei Zeilen für LED-Tests (wobei die Zeitmessung NICHT der tatsächliche Zeitbedarf der ISR im Target ist ! ! ! weil dabei der Overhead nicht erfasst wird). Den switch-Abschnitt kannst Du Dir ersatzlos sparen. Und nur als Warnung: keine Garantie für die Funktion - auch wenns bei mir bestens läuft - und abschreiben und experimentell weiterentwickeln hilft meist auch nicht.

    Code:
    // ============================================================================== =
    // ===  Initialisierung fuer ADC    mega1284   MIT Interrupt free running
    // ===    ADC5/PA5 auf 10 Bit,  fertige Wandlung ###>>> löst Interrupt aus
     void ADC_init_10_irupt(void)  // Initialisiere ADC, Kanal5, 10 Bit, MIT Interrupt
     {                         //
      if (adcptnr > 7) adcptnr  = 5;  // Defaultwert adcpnr
    // - - - - - - - - - - - - - - -
      switch (adcptnr)               // Initialisiere je nach ADC Pin Nummer
      {                             //
        case 0: case 1: case 2: case 3: case 4: case 6:     //
          break;                    //
        case 5:                     //
          adc5_cnt = 0;             // ADC-Wert wird x-fach aufaddiert
          adc5tcnt = 1;             //
          adc5_tmp = 0;             // ADC-x-fach-Speicher
          ADC5bMIN  = 1023;         // bisheriges Minimum setzen
          ADMUX  |= (1<<MUX0)|(1<<MUX2);    // Wandlung mit ADC5 (mega1284)   doc S 259
          uputs0 ("\r\tInitialisierung ADC auf ADC5/PA5=Poti\r");   //
          break;                    //
        default:                    //
          uputs0 ("\r\tInitialisierung ADC fehlgeschlagen\r");     //
          break;                    //
      }                             //
    // - - - - - - - - - - - - - - -
      ADMUX  |= (1<<REFS0);         // Referenzspannung ist AVcc                  S 258
      ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);   // Prescaler = clock/128      S 261
                            // Prescaler NUR für system clck 
      ADCSRA |= (1<<ADATE);         // Auto Triggering Enable               S 245 + 260
                    // es wird bei clock 20 Mhz mit ca. 80 µs getriggert
      ADCSRA |= (1<<ADIE);          // ADC Interrupt Enable                   doc S 260
      ADCSRA |= (1<<ADEN);  // ADC Enable
      ADCSRA |= (1<<ADSC);         // starte gleich die erste Wandlung
     }                              //
    // ============================================================================== =
    
    // ============================================================================== =
    // ===  Nicht unterbrechbare ISR für ADC
    // Routine übernimmt ADC-Wert und sichert Minimum
     ISR(ADC_vect)                  // VECTOR 25, Adr $0030
     {                              //
    //ClrBit(PORTC, 7);             // LED C7 ein, Zeitmessung: LED/PIN PC7
      adc5_tmp      = ADC;          // Hole Wert
      adc_status    = 170 + adcptnr; // Setze Flag "ADC-Wert abgeholt
      if (adcptnr == 5)              //
      {if (ADC5bMIN > adc5_tmp) ADC5bMIN = adc5_tmp;}   // Sichere bisheriges Minimum
    //SetBit(PORTC, 7);             // LED C7 aus, Zeitmessung: LED/PIN PC7
     }                              //
    // ============================================================================== =
    Und damit Du mir nicht ne Geheimhaltung von Makros vorhalten kannst:
    Code:
      #define SetBit(ADDR,BIT)       ((ADDR)  |=  (1<<(BIT)))       // Setzt Bit
      #define ClrBit(ADDR,BIT)       ((ADDR)  &= ~(1<<(BIT)))       // Löscht Bit
      #define ToggleBit(ADDR,BIT)    ((ADDR)  ^=  (1<<(BIT)))       // Toogelt Bit
    Geändert von oberallgeier (28.02.2013 um 09:10 Uhr) Grund: Macro nachgetragen (Verzug durch Telefonanruf)
    Ciao sagt der JoeamBerg

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    27.02.2013
    Beiträge
    7
    Code:
    #define GREEN_LED_on		PORTA |= (1<<PA3)
    #define GREEN_LED_off		PORTA &= ~(1<<PA3)
    Code:
    int main()
    {
    
    DDRA &= ~((1<<PA7));	// Pin PA7 auf Eingang setzen, da hängt der Botton dran
    ADCSRA = 0x8F;                 // ADC und Interrupts aktivieren
    ADMUX |= ((1<<MUX0)|(1<<MUX1)|(1<<MUX2));  // Auf ADC7 setzen
    sei();
    ADCSRA |= 1<<ADSC;      //starten
    
    	
    	while(1){}
    }
    
    
    ISR(ADC_vect){
    	GREEN_LED_ON(); // Macro, schaltet LED für 1 sek an, dann wieder aus
    }
    Code:
    void GREEN_LED_ON(void)
    {
    GREEN_LED_on;
    _delay_ms(1000);
    GREEN_LED_off;
    }

    Dein Beispiel würde ja einen Interrupt auslösen, wenn der ADC fertig mit der Arbeit ist. Ich bräuchte aber irgendwie eine Möglichkeit, dass der ADC ständig guckt, ob sich was ändert und im Falle einer Änderung einen Interrupt wirft. Also so ne Art externer Interrupt bei Benutzereingabe. Ist sowas möglich? Also gibts es ne Möglichkeit, den ADC dauerhaft laufen zu lassen und nur bei einer Änderung einen Interrupt zu generieren?

    ich habe dann mal auf den Tip von weiter oben gehört und mir den Komparator angeguckt. Der sollte ja 2 Eingänge überprüfen können und mir dann sagen, ob sich was geändert hat. Führt man den auch nur einmal aus,sprich gibt es nur eine Überprüfung oder wird der dauerhaft betrieben?
    Geändert von RumpelHumpel (28.02.2013 um 15:12 Uhr)

  10. #10
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    Zitat Zitat von RumpelHumpel
    Ich bräuchte aber irgendwie eine Möglichkeit, dass der ADC ständig guckt, ob sich was ändert und im Falle einer Änderung einen Interrupt wirft. Also so ne Art externer Interrupt bei Benutzereingabe. Ist sowas möglich? Also gibts es ne Möglichkeit, den ADC dauerhaft laufen zu lassen und nur bei einer Änderung einen Interrupt zu generieren?
    Geht mit dem ADC nicht.

    Zitat Zitat von RumpelHumpel
    Der sollte ja 2 Eingänge überprüfen können und mir dann sagen, ob sich was geändert hat. Führt man den auch nur einmal aus,sprich gibt es nur eine Überprüfung oder wird der dauerhaft betrieben?
    Der Analog Comparator wird dauerhaft betrieben.

    Warum nimmst du nicht INT0,1 oder 2? Bist du da auf den PA7 festgenagelt?

    Welche Spannungsänderungen verursacht denn der Button?

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Interrupt nach Aktivierung auslösen...
    Von Flario im Forum AVR Hardwarethemen
    Antworten: 2
    Letzter Beitrag: 08.10.2009, 14:35
  2. Einfacher Befehl um nach Variablenderung einmalig ausführen
    Von mirco99 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 7
    Letzter Beitrag: 06.11.2008, 11:00
  3. Eingabe als Interrupt? Geht das
    Von hunni im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 19
    Letzter Beitrag: 20.08.2008, 10:58
  4. [gelöst] Variable löscht sich nach Interrupt?
    Von robodriver im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 6
    Letzter Beitrag: 14.11.2007, 12:26
  5. Rücksprungposition nach einem ext.Interrupt
    Von lejcko im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 9
    Letzter Beitrag: 27.01.2006, 17:21

Berechtigungen

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

12V Akku bauen