www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR Tiny2313 eeprom vergesslich?


Autor: Une E. (une_e)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

um unsere Mediacenter PC's per Fernbedienung einschalten zu können haben 
ein Kollege und ich einen Tiny und IRMP verwendet.

Dies funktioniert auch tadellos, nur vergisst der Tiny manchmal den 
angelernten und im eeprom abgelegten ir-Code.
Anbei der c-Code, worann kan es liegen, dass der IR-Code manchmal 
wiedergefunden und manchmal vergessen wird (bei ca. 1 von 5 Versuchen, 
also Spannungslos machen und wieder Spannung, wird der Ir-Code 
vergessen.

/*---------------------------------------------------------------------------------------------------------------------------------------------------
 * main.c - Ir-einschalter mit AtTiny2313 mit IRMP
 *
 * ATTINY2313 @ 8 MHz
 *
 * Fuses: lfuse: 0xE4 hfuse: 0xDF efuse: 0xFF
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *---------------------------------------------------------------------------------------------------------------------------------------------------
 */

#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "irmp.h"
#include "irmpconfig.h"
#include "avr/eeprom.h"

#ifndef F_CPU
#error F_CPU unkown
#endif

// Defines fuer den Taster-Input
#define Taster_PORT                               PORTB
#define Taster_DDR                                DDRB
#define Taster_PIN                                PINB
#define Taster_BIT                                2       // use PB2 as Taster on AVR
// Defines fuer die LED
#define Led_PORT                               PORTB
#define Led_DDR                                DDRB
#define Led_PIN                                PINB
#define Led_BIT                                0       // use PB0 as Taster on AVR
// Defines fuer den Schaltausgang
#define Schalt_PORT                               PORTB
#define Schalt_DDR                                DDRB
#define Schalt_PIN                                PINB
#define Schalt_BIT                                1       // use PB1 as Taster on AVR
// EEPROM Variablen anlegen
uint16_t Ziel_Command EEMEM = 12345;
uint8_t CodeErlernt EEMEM = 0;

void timer_init(void) {
  OCR1A = (F_CPU / F_INTERRUPTS) - 1; // compare value: 1/10000 of CPU frequency
  TCCR1B = (1 << WGM12) | (1 << CS10); // switch CTC Mode on, set prescaler to 1
  TIMSK = 1 << OCIE1A; // OCIE1A: Interrupt by timer compare
}

/*---------------------------------------------------------------------------------------------------------------------------------------------------
 * timer 1 compare handler, called every 1/10000 sec
 *---------------------------------------------------------------------------------------------------------------------------------------------------
 */
// Timer 1 output compare A interrupt service routine
ISR(TIMER1_COMPA_vect)
{
  (void) irmp_ISR(); // call irmp ISR
}

/*---------------------------------------------------------------------------------------------------------------------------------------------------
 * Hilfsroutinen
 *---------------------------------------------------------------------------------------------------------------------------------------------------
 */

uint8_t key_pressed(const volatile uint8_t *inputreg, uint8_t inputbit) {
  static uint8_t last_state = 0;

  if (last_state == !(*inputreg & (1 << inputbit))) {
    return 0; /* keine Änderung */
  }

  /* Wenn doch, warten bis etwaiges Prellen vorbei ist: */
  _delay_ms(20);

  /* Zustand für nächsten Aufruf merken: */
  last_state = !(*inputreg & (1 << inputbit));

  /* und den entprellten Tastendruck zurückgeben: */
  return !(*inputreg & (1 << inputbit));
}

/*---------------------------------------------------------------------------------------------------------------------------------------------------
 * MAIN: main routine
 *---------------------------------------------------------------------------------------------------------------------------------------------------
 */
int main(void) {
  IRMP_DATA irmp_data;
  char learning = 0;
  char learned = eeprom_read_byte(&CodeErlernt);
  uint16_t zielCommandSram = eeprom_read_word(&Ziel_Command);

  // Setzen der DatenRichtungsRegister
  Led_DDR |= (1 << Led_BIT);
  Schalt_DDR |= (1 << Schalt_BIT);

  irmp_init(); // initialize rc5
  timer_init(); // initialize timer
  sei ();  // enable interrupts

  for (;;) {
    if (key_pressed(&Taster_PIN, Taster_BIT)) {
      learning = 1; // setzen der learning Variable
      Led_PORT |= (1 << Led_BIT); // Einschalten der learning Led
    }

    if (learning && irmp_get_data(&irmp_data)) {
      // Speichern des IR-Codes im eeprom
      zielCommandSram = irmp_data.command;
      eeprom_write_word(&Ziel_Command, zielCommandSram);
      Led_PORT &= ~(1 << Led_BIT); // Ausschalten der learning Led
      learning = 0;
      learned = 1;
      eeprom_write_byte(&CodeErlernt, learned);
    }

    if (learned && irmp_get_data(&irmp_data)) {
      // Vergleichen des IR-Codes mit dem im eeprom
      if (irmp_data.command == zielCommandSram) {
        //Einschalten des Schaltports fuer 500ms
        Schalt_PORT |= (1 << Schalt_BIT); // Einschalten des Schaltausgangs
        Led_PORT |= (1 << Led_BIT); // Einschalten der Led
        _delay_ms(500);
        Schalt_PORT &= ~(1 << Schalt_BIT); // Ausschalten des Schaltausgangs
        Led_PORT &= ~(1 << Led_BIT); // Ausschalten der Led

      } //else {
        //Led_PORT |= (1 << Led_BIT); // Einschalten der Led
        //_delay_ms(100);
        //Led_PORT &= ~(1 << Led_BIT); // Ausschalten der Led

      //}
    }
  }
}

Ich hoffe irgendwer kann uns weiterhelfen.

Autor: Stefan P. (form)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Une E. schrieb:
> uint16_t Ziel_Command EEMEM = 12345;
> uint8_t CodeErlernt EEMEM = 0;


Die Adresse 0 im EEPROM wird manchmal bei unsauberer Versorgung 
überschrieben.
Definier davor noch ein DummyByte:

uint8_t DummyByte EEMEM = 0;
uint16_t Ziel_Command EEMEM = 12345;
uint8_t CodeErlernt EEMEM = 0;

Autor: Une E. (une_e)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, das werde ich heute ausprobieren.

Autor: Charly B. (charly)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan P. schrieb:
> Die Adresse 0 im EEPROM wird manchmal bei unsauberer Versorgung
> überschrieben.

Gab sogar mal ein erata von Atmel darueber

schreib mal obs dann weg ist wenn du die eepromzelle 0
nicht verwendest

vlG
Charly

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Une E. schrieb:
> hfuse: 0xDF

Das ist falsch.
Bei Nutzung des EEPROM muß das BOR aktiviert werden:
hfuse = 0xD9


Peter

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.