- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 8 von 8

Thema: Reset nach Input-Abfrage bei PCF8574AP

  1. #1
    Erfahrener Benutzer Begeisterter Techniker Avatar von Jacob2
    Registriert seit
    26.05.2007
    Ort
    Berlin
    Beiträge
    345

    Reset nach Input-Abfrage bei PCF8574AP - Interruptproblem?

    Anzeige

    Powerstation Test
    Hallo!
    Ich habe vier Taster an einem PCF8574AP angeschlossen (Taster nach GND), welcher wiederum an einem ATmega48 hängt (I2C). Nun nutze ich diese Funktionen (s. unten) von Mikrocontroller.net. Um die Vorgänge zu überwachen lasse ich Kurznachrichten auf einem LCD anzeigen.
    Der Interruptausgang des Portexpanders löst einen Pin-Change-Interrupt aus, was auch wunderbar funktioniert:
    Code:
    ISR(PCINT2_vect)//PCINT20 -> Ein Taster wurde gedrückt
    {
        cli();
        //Welche Taste?
        lcd_clrscr();
        lcd_puts("Vorher...");
        _delay_ms(500);
        uint8_t Taste = pcf8574_get_inputs(0);//Adresse = 0 (alle auf GND)
        lcd_clrscr();
        lcd_puts("Nachher!");
        sei();
    };
    Das Problem ist, dass sich der Controller bei der Get-Inputs-Funktion resettet, d.h. auf dem LCD bleibt "Vorher..." stehen. Den Neustart kann ich auch mithilfe des LCD erkennen (Mitteilung am Anfang der main()-Funktion).
    Mit dem Oszilloskop habe ich schon so gut es geht überprüft, dass weder die Betriebsspannung einbricht noch der Reset-Pin auf low gezogen wird...

    Hier die Funktionen von Mikrocontroller.net, die ich verwende:
    Code:
    #include "pcf8574.h"
    
    
    void pcf8574_init (void)
    {
        /*set bus speed*/
        TWBR = 0x10;
    }
    
    
    unsigned char pcf8574_send_start (void)
    {
        /*writing a one to TWINT clears it, TWSTA=Start, TWEN=TWI-enable*/
        TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
        /*wait, until start condition has been sent --> ACK*/
        while (!(TWCR & (1<<TWINT)));
        return TWSR;
    }
    
    
    void pcf8574_send_stop (void)
    {
        /*writing a one to TWINT clears it, TWSTO=Stop, TWEN=TWI-enable*/
        TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);    
    }
    
    
    unsigned char pcf8574_send_add_rw (unsigned char address, unsigned char rw)
    {
        /*address can be 0 .. 8; rw=0 --> write, rw=1 --> read*/
        unsigned char addr_byte = 0;
        /*shift address one bit left*/
        addr_byte = address << 1;
        /*set RW-Bit, if necessary*/
        addr_byte |= rw;
        /*0b0111xxx0 --> address of Expander*/ //für PCF8574AP angepasst (0b0100xxx0 --> 0b0111xxx0)
        addr_byte |= 0b01110000;
        /*TWDR contains byte to send*/
        TWDR = addr_byte;
        /*send content of TWDR*/
        TWCR = (1<<TWINT) | (1<<TWEN);
        /*wait, until address has been sent --> ACK*/
        while (!(TWCR & (1<<TWINT)));
        return TWSR;
    }
    
    
    unsigned char pcf8574_send_byte (unsigned char byte)
    {
        /*TWDR contains byte to send*/
        TWDR = byte;
        /*send content of TWDR*/
        TWCR = (1<<TWINT) | (1<<TWEN);
        /*wait, until byte has been sent --> ACK*/
        while (!(TWCR & (1<<TWINT)));
        return TWSR;
    }
    
    
    unsigned char pcf8574_read_byte (void)
    {
        /*send content of TWDR; TWEA = enable ACK*/
        TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
        /*wait, until byte has been received --> ACK*/
        while (!(TWCR & (1<<TWINT)));
        return TWDR;
    }
    
    
    unsigned char pcf8574_get_inputs (unsigned char address)
    {
        pcf8574_init ();
        pcf8574_send_start ();
        pcf8574_send_add_rw (address, 1);
        unsigned char input = pcf8574_read_byte ();
        pcf8574_send_stop ();
        return input;
    }
    
    
    void pcf8574_set_outputs (unsigned char address, unsigned char byte)
    {
        pcf8574_init ();
        pcf8574_send_start ();
        pcf8574_send_add_rw (address, 0);
        pcf8574_send_byte (byte);
        pcf8574_send_stop ();
    }

    Was könnte den Reset verursachen?
    Vielen Dank im Voraus!

    PS: Hier ist noch der Schaltplan:
    Klicke auf die Grafik für eine größere Ansicht

Name:	<a href=Staubsaugerroboter2.jpg Hits: 16 Größe: 85,0 KB ID: 19205" class="thumbnail" style="float:CONFIG" />
    Geändert von Jacob2 (29.06.2011 um 11:33 Uhr)
    Roboter, CNC Fräse, Elektronik und Basteleien stelle ich auf meiner Website vor...

  2. #2
    Erfahrener Benutzer Begeisterter Techniker Avatar von Jacob2
    Registriert seit
    26.05.2007
    Ort
    Berlin
    Beiträge
    345
    Okay, ich habe das Problem jetzt soweit eingrenzen können, dass der µC anscheinend nach der Interrupt-Funktion ISR(PCINT2_vect) ein Reset macht... Die I2C-Kommunikation scheint zu funktionieren, ich kann mir sogar den empfangenen Port-Status vom PCF8574 auf dem LCD anzeigen lassen, nur, danach ist immer ein Reset !

    Aber warum macht "er" dann ein Reset? In main() befindet sich der Controller in einer while(1); Schleife, in der er ja auch nach dem Interrupt noch sein müsste, richtig?

    Ich habe auch schon versuchsweise cli() und sei() auskommentiert, an denen liegt's wohl aber auch nicht...
    Roboter, CNC Fräse, Elektronik und Basteleien stelle ich auf meiner Website vor...

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.01.2006
    Beiträge
    4.555
    Ist es möglich das es zu einem Stack Überlauf kommt und Dein Programm im "Nirwana" endet?

    Gruß Richard

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.688
    Zitat Zitat von Jacob2
    ... danach ist immer ein Reset ! Aber warum macht "er" dann ein Reset? ...
    Bei Problemen mit undefiniertem Reset hatte ich mir mal eine extrem kurze LED-Signalroutine geschrieben, die von einer ISR angestossen wurde - z.B. drei mal kurz Blinken. Die Signalroutine wird von der ISR angestossen - sie wird nicht in der ISR ausgeführt. Dann hatte ich diese ISR Vektor für Vektor den verschiedenen Interruptvektoren zugewiesen. Irgendwann bekam ich den Auslöser identifiziert . . . .
    Ciao sagt der JoeamBerg

  5. #5
    Erfahrener Benutzer Begeisterter Techniker Avatar von Jacob2
    Registriert seit
    26.05.2007
    Ort
    Berlin
    Beiträge
    345
    @Richard Ich weiß nicht, wodurch könnte es denn zu einem Stack Überlauf kommen?
    Sind z.B. cli() und sei() überhaupt sinnvoll im ISR? Kann das Tastenprellen vielleicht einen Überlauf verursachen?
    Der µC hängt sich nicht auf, er startet definitiv neu, denn am Anfang von main() lasse ich eine Meldung ausgeben: lcd_puts("Starten..."); und die wird nach dem Interrupt angezeigt.
    @oberallgeier Ich verstehe nicht ganz, was Du meinst - ich habe ja nur eine ISR... D.h. ich weiß, dass diese ISR bzw., das was danach geschieht, den Reset auslöst. Das Problem ist, dass ich nicht genau weiß, was nach der ISR passiert - bisher war ich davon ausgegangen, dass in die while(1)-Schleife zurückgesprungen wird...
    Geändert von Jacob2 (29.06.2011 um 13:35 Uhr)
    Roboter, CNC Fräse, Elektronik und Basteleien stelle ich auf meiner Website vor...

  6. #6
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.688
    Zitat Zitat von Jacob2
    ... verstehe nicht ganz, was Du meinst - ich habe ja nur eine ISR ...
    Ok, bevor wir die Geheimnisse der Interrupt-Vektortabelle diskutieren: Wie wärs, wenn Du SICHERSTELLST, dass nach dem lcd_puts("Vorher...") ein Reset im m48 erfolgt? Versuch doch mal zwischen lcd_clrscr(); und dem lcd_puts("Vorher...") ein Delay-1000 einzufügen - dann wäre nach einem Reset immer wieder für eine Sekunde ein gelöschtes LCD zu sehen. DANN sind wir sicher, dass ein Reset stattfindet und nicht "nur" ein Hängenbleiben des Controllers . . . . Dann könnte man weitersehen.
    Ciao sagt der JoeamBerg

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.01.2006
    Beiträge
    4.555
    Zitat Zitat von Jacob2 Beitrag anzeigen
    @Richard Ich weiß nicht, wodurch könnte es denn zu einem Stack Überlauf kommen?
    Mit C habe ich leider Probleme und kann Deinen Code nicht wirklich nachvollziehen. Aber solche "Neustarts" sind typisch wenn z.B. eine Rücksprung Adresse fehlt oder überschrieben wurde. Zum Testen mal den Sack Bereich vergrößern könnte helfen. Auch wenn das Programm selber "ins leere" Endet oder eine Variable zu "klein" ist( buffer overlow), (kann) das zum Neustart führen.

    Gruß Richard

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.703
    Blog-Einträge
    133
    Hallo,
    ich verstehe C auch kaum, aber ein anderer Gedanke:

    Der PCF8574 zieht INT nach LOW, wenn ein Taster gedrückt wird.
    Das verursacht ein PCINT am ATMega und der springt in die ISR und der PCF wird ausgelesen.
    Nach Datenblatt des PCF8574 wird dessen INT Leitung resettet, wenn Daten von seinem Datenport gelesen werden.
    Das bedeutet, das am PCINT Pin der Pegel wechselt und ein neuer PCINT ansteht.
    Sobald aus der ISR zurückgekehrt wird muß µC da sofort wieder rein.

    Das Ganze ist davon abhängig, ob der µC das PCI Flag zu Beginn der ISR oder bei Rücksprung löscht. Das weis ich leider nicht.

    SEI und CLI in der ISR macht für mich keinen Sinn, da die sowieso während der ISR geblockt sind. Statt dessen eher Verhindern von PCINTs (im Maskenregister) und vor Rücksprung sicherheitshalber Löschen des PCI Flags und Wiederzulassen von PCINTs.

    Entprellung von Tasten?

    Gruß
    Searcher
    Geändert von Searcher (29.06.2011 um 17:03 Uhr)
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

Ähnliche Themen

  1. Nach Reset falsche Berechnung!?
    Von drivepro82 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 11.11.2008, 00:46
  2. Zustand von SRAM nach Reset
    Von bombatz im Forum AVR Hardwarethemen
    Antworten: 8
    Letzter Beitrag: 07.06.2007, 11:40
  3. Problem nach RESET
    Von bombatz im Forum Assembler-Programmierung
    Antworten: 7
    Letzter Beitrag: 12.08.2006, 12:10
  4. Timer1 reset nach Compare1A
    Von Theo16505 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 11.02.2006, 23:33
  5. Display nach Reset verwirrt
    Von highbeta im Forum AVR Hardwarethemen
    Antworten: 1
    Letzter Beitrag: 02.12.2005, 11:00

Stichworte

Berechtigungen

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

12V Akku bauen