-
        

Ergebnis 1 bis 4 von 4

Thema: Atmega128 - Wieder mal Probleme mit UART Interrupt (Gelöst)

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    07.04.2009
    Beiträge
    19

    Atmega128 - Wieder mal Probleme mit UART Interrupt (Gelöst)

    Anzeige

    Hallo,

    jetzt probier ich schon seit einigen Stunden Daten mittels dem
    USART0_RX_vect Interrupt zu empfangen, aber aus irgendeinen Grund wird
    die ISR anscheinend nie aufgerufen.
    Daten Senden mittels USART0_UDRE_vect funktioniert ohne Probleme. Daten
    empfangen mittel Polling ebenfalls.

    Hier mal der vereinfachte Code der nur überprüft ob die ISR aufgerufen
    wird.
    Wenn ja, dann sollten sich 4 LEDs die am PortC hängen einschalten. Nach
    spätestens 4 sek sollen sich die LEDs aber auf jedenfall einschalten.
    Und da passiert jetzt was seltsames: Wenn ich im Hyperterminal nichts
    eingebe werden die LEDs nach 4 sekunden eingeschalten, aber wenn ich
    Daten sende, dann scheint das Programm abzustürzen, weil dann garnichts
    mehr passiert.

    Code:
    ...
    
    void uart_init()
    {
      uint8_t sreg = SREG;
    
        UBRR0H = UBRR_VAL >> 8;
        UBRR0L = UBRR_VAL & 0xFF;
    
        // Interrupts kurz deaktivieren
        cli();
    
        // UART Receiver und Transmitter anschalten, Receive Interrupt setzen
        // Data mode 8N1, asynchron
        UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
        UCSR0C = (1<<UCSZ1) | (1<<UCSZ0);
    
    
        // Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte)
        do
        {
            // UDR auslesen (Wert wird nicht verwendet)
            UDR0;
        }
        while (UCSR0A & (1 << RXC0));
    
        // Rücksetzen von Receive und Transmit Complete-Flags
        UCSR0A = (1 << RXC0) | (1 << TXC0);
    
        // Global Interrupt-Flag wieder herstellen
        SREG = sreg;
    }
    
    ISR(USART0_RX_vect)
    {
        uint8_t sreg = SREG;
        cli();
    
        // LEDS einschalten
        DDRC = 0xFF;
        PORTC = 0b11110000;
    
        UDR0;
    
        SREG = sreg;
    }
    
    int main (void)
    {
        sei();
    
        uart_init();
    
        // Nach 4 Sekunden sollen die LEDs auf jedenfall eingeschalten werden
        for(int i = 0; i< 4000; i++)
            _delay_ms(1);
    
        DDRC = 0xFF;
        PORTC = 0b11110000;
        while(1);
    
        return 0;
    }
    Sieht hier jemand einen Fehler? Kann das irgendwie mit dem AT103
    Kompatibilitätsmodus zusammenhängen? Oder liegts vielleicht sogar am
    Bootloader (es handelt sich dabei um den Conrad Bootloader der auf der C-Control Pro arbeitet)?.

    Danke schon mal im vorraus,

    Thomas

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    07.04.2009
    Beiträge
    19
    Endlich nach langen verzweifelten Herumprobieren und reichlich Unterstützung vom Nachbarforum ist das Problem gelöst.

    Der Conrad Bootloader aktiviert das IVSEL Bit im MCUCR und leitet somit alle Interrupts erstmal zur Bootloadersektion um. Manche Interrupts wie z.B USART0_UDRE_vect werden dann wieder an die ursprüngliche Adresse zurückgeleitet.

    Wenn man das IVSEL bit wieder zurücksetzt funktioniert aber alles so wie es soll. Also braucht man nur folgende 2 Zeilen vor dem eigentlichen Program einfügen:

    MCUCR = (1<<IVCE);
    MCUCR = 0;

    mfg Thomas

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.09.2006
    Beiträge
    734
    Hallo THomas,
    die erste Zeit hat keinen Effekt.

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    07.04.2009
    Beiträge
    19
    Hallo,

    sieht zwar komisch aus, aber steht so im Datenblatt. Das IVCE Bit muss zuerst gesetzt werden, dann kann innerhalb von 4 Taktzyklen das Register angepasst werden.

Berechtigungen

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