Also die Hardware läuft jetzt fehlerfrei.

Jetzt gibt nur noch in der Software ein paar Probleme.
Hab mal den Basic-Code von http://home.arcor.de/output/elektronik/5ton-AVR.pdf versucht zu verwenden; klappt "eigentlich" auch. "Eigentlich" deswegen, weil die erkannte Frequenz nicht mit der wirklichen übereinstimmt.
Im angefügten Code muss ich von den #defines für FTONx noch etwas abziehen, damits stimmt.
Also werden z.B. 1060 Hz gesendet, werden diese als ca. 1040 erkannt; bzw. ich muss 1080 senden, damit 1060 erkannt werden.

Evtl ne Idee dazu? Ich denk mal, dass diese zusätzliche Zeit einfach dadurch zustande kommt, dass die ISR ja erst mal aufgerufen werden muss etc.


EDIT: Mal wieder den Code vergessen:

Code:
// µC:   ATMega8
// Takt: 8MHz intern
// Pwr:  5 VDC

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
#include "glob_type.h"    // Datentypen ui8_t, ui16_t, etc.

#define FTON1 1060 -20
#define FTON2 1160 -20
#define FTON3 1270 -20
#define FTON4 1400 -20
#define FTON5 1530 -23
#define FTON6 1670 -25
#define FTON7 1830 -25
#define FTON8 2000 -25
#define FTON9 2200 -25
#define FTON0 2400 -30
#define FTONR 2600 -30



#define VSF_IS_NEW         (statusflags & 0x01)
#define VSF_IS_VALID       (statusflags & 0x02)
#define VSF_IS_GOTOMAIN    (statusflags & 0x04)

#define VSF_SET_VALNEW()     (statusflags |=  0x01)
#define VSF_SET_VALOLD()     (statusflags &= ~0x01)

#define VSF_SET_GOTOMAIN()   (statusflags |=  0x04)
#define VSF_CLR_GOTOMAIN()   (statusflags &= ~0x04)

#define VSF_SET_VALID()      (statusflags |=  0x02)
#define VSF_SET_INVALID()    (statusflags &= ~0x02)

#define TIMEOUT_MAX_VALUE 40  // Max. Timeout-Zyklen
#define AVG_VALUES        15  // Anzahl Werte für Durchschnittsbildung  


         ui32_t lgFreq;        // "Rohfrequenz" nach 1. Berechnung
         ui32_t lgFreqSum;     // Summe für Durchschnittswert-Bildung

volatile ui16_t T1Value;       // Gemessener Zählwert von T1 bei Signal an INT0
         ui16_t freqs[AVG_VALUES];  // Array für Mittelwertbildung
         ui16_t freq_avg;      // Durchschnittsfrequenz
         ui16_t fBorderLo;
         ui16_t fBorderHi;

         ui8_t TimeOut;       // Timeout-Variable
volatile ui8_t statusflags;   // Enthält Status-Bits (Value status flags, VSF):
                              // Bit 0:  Neuer Messwert per INT0 eingegangen
                              // Bit 1:  Messwert ungültig (max. Zähldauer überschritten)
                              // Bit 2:  "Goto Main"-Ersatz
         ui8_t Sequence[5];   // enthält empfangene Sequenz
         ui8_t SeqCnt;        // Anzahl Töne in Sequenz
         ui8_t Tone;          // Aktuell korrekt erkannter Ton
         ui8_t Tone_Old;      // Zuletzt korrekt erkannter Ton
         ui8_t icnt;          // allg. Zählvariable


int main(void)
{
  // einige Pins von PortC als Ausgang für Status-LEDs:
  DDRC |= (1 << PC0) | (1 << PC1) | (1 << PC2) | (1 << PC3) | (1 << PC4) | (1 << PC5);
  DDRB |= (1 << PB1) | (1 << PB2) | (1 << PB3) | (1 << PB4) | (1 << PB5);

  // Timer 1 setzen
  TCCR1A = 0;             // Standard Timer
  TCCR1B = (1 << CS10);   // Prescaler 1
  TCNT1 = 0;              // Startwert 0
  TIMSK |= TOIE1;         // Interrupt für Überlauf aktiv

  // INT0 auf steigender Flanke
  GICR  |= (1 << INT0); 
  MCUCR |= (1 << ISC01) | (1 << ISC00);
  
  // Interrupts global zulassen
  sei();

  // ************************************************************************************************
  // MAIN LOOP START
  // ************************************************************************************************

PORTC = (1 << PC5); _delay_ms(100); PORTC = 0;
PORTC = (1 << PC4); _delay_ms(100); PORTC = 0;
PORTC = (1 << PC3); _delay_ms(100); PORTC = 0;
PORTC = (1 << PC2); _delay_ms(100); PORTC = 0;
PORTC = (1 << PC1); _delay_ms(100); PORTC = 0;
PORTC = (1 << PC0); _delay_ms(100); PORTC = 0;

PORTB = (1 << PB5); _delay_ms(100); PORTB = 0;
PORTB = (1 << PB4); _delay_ms(100); PORTB = 0;
PORTB = (1 << PB3); _delay_ms(100); PORTB = 0;
PORTB = (1 << PB2); _delay_ms(100); PORTB = 0;
PORTB = (1 << PB1); _delay_ms(100); PORTB = 0;


  while(1)
  {
    VSF_CLR_GOTOMAIN();
    _delay_ms(1); // kleine Pause

    // Prüfen, ob T1Value in sinnvollem Bereich liegt:
    //  800 Hz => T1Value = 10000
    // 3000 Hz => T1Value =  2666
    if ((VSF_IS_VALID) && (VSF_IS_NEW))
    {
      if ((T1Value > 10000) || (T1Value < 2666))
      {
        // Wenn Wert ausserhalb: ungültig:
        VSF_SET_INVALID();
      }
    }

    // Folgendes nur, wenn: Wert gültig + in sinnvollem Bereich
    if ((VSF_IS_VALID) && (VSF_IS_NEW))
    {
      if (T1Value != 0) { lgFreq = F_CPU / T1Value;}  // "Rohfrequenz" berechnen
      T1Value = 1;                                    // Worst Case: Division durch 0 verhindern.

      TimeOut++;
      if (TimeOut >= TIMEOUT_MAX_VALUE)
      {
        memset(Sequence, 0x00, 5);
        Tone_Old = 0;
        TimeOut = 0;
        SeqCnt = 0;
        PORTB = 0;
        PORTC = 0;
      }

      // Wertearray weiterschieben; ältesten Wert verwerfen
      for (icnt = AVG_VALUES-1 ; icnt > 0 ; icnt--)
      {
        freqs[icnt] = freqs[icnt-1];
      }

      // Errechnete Frequenz in Array ablegen
      freqs[0] = (ui16_t) lgFreq;

      // Durchschnitt berechnen
      lgFreqSum = 0;
      for (icnt = 0 ; icnt < AVG_VALUES ; icnt++)
      {
        lgFreqSum += freqs[icnt];
      }
      freq_avg = lgFreqSum / AVG_VALUES;

      // Überprüfen, ob Durchschnitt "gehalten" wird
      fBorderLo = ((ui16_t) lgFreq) - 10;
      fBorderHi = ((ui16_t) lgFreq) + 10;

      if ((freq_avg > fBorderLo-1) && (freq_avg < fBorderHi+1))
      {
        Tone = 0;
             if ((freq_avg > FTON1 - 10 ) && (freq_avg < FTON1 + 10)) { Tone = '1'; }
        else if ((freq_avg > FTON2 - 10 ) && (freq_avg < FTON2 + 10)) { Tone = '2'; } 
        else if ((freq_avg > FTON3 - 10 ) && (freq_avg < FTON3 + 10)) { Tone = '3'; }
        else if ((freq_avg > FTON4 - 10 ) && (freq_avg < FTON4 + 10)) { Tone = '4'; }
        else if ((freq_avg > FTON5 - 10 ) && (freq_avg < FTON5 + 10)) { Tone = '5'; }
        else if ((freq_avg > FTON6 - 10 ) && (freq_avg < FTON6 + 10)) { Tone = '6'; }
        else if ((freq_avg > FTON7 - 10 ) && (freq_avg < FTON7 + 10)) { Tone = '7'; }
        else if ((freq_avg > FTON8 - 10 ) && (freq_avg < FTON8 + 10)) { Tone = '8'; }
        else if ((freq_avg > FTON9 - 10 ) && (freq_avg < FTON9 + 10)) { Tone = '9'; }
        else if ((freq_avg > FTON0 - 10 ) && (freq_avg < FTON0 + 10)) { Tone = '0'; }
        else if ((freq_avg > FTONR - 10 ) && (freq_avg < FTONR + 10)) { Tone = 'R'; }
        else
        { VSF_SET_GOTOMAIN(); }
      }
      else
      {
        VSF_SET_GOTOMAIN();
      }

      if (!VSF_IS_GOTOMAIN)
      {
        switch (Tone)
        {
          case '1':
            PORTB = 0;
            PORTC = (1 << PC5);
            break;
          case '2':
            PORTB = 0;
            PORTC = (1 << PC4);
            break;
          case '3':
            PORTB = 0;
            PORTC = (1 << PC3);
            break;
          case '4':
            PORTB = 0;
            PORTC = (1 << PC2);
            break;
          case '5':
            PORTB = 0;
            PORTC = (1 << PC1);
            break;
          case '6':
            PORTB = 0;
            PORTC = (1 << PC0;
            break;
          case '7':
            PORTB = (1 << PB5);
            PORTC = 0;
            break;
          case '8':
            PORTB = (1 << PB4);
            PORTC = 0;
            break;
          case '9':
            PORTB = (1 << PB3);
            PORTC = 0;
            break;
          case '0':
            PORTB = (1 << PB2);
            PORTC = 0;
            break;
          case 'R':
            PORTB = (1 << PB1);
            PORTC = 0;
            break;
          default:
            PORTB = 0;
            PORTC = 0;
        }
      }
      // Wert abgearbeitet und damit alt:
      VSF_SET_VALOLD();
    }



  }
  // ************************************************************************************************
  // MAIN LOOP ENDE
  // ************************************************************************************************
  return(0);
}


ISR (SIG_OVERFLOW1) // Interrupt Timer 1 Überlauf
{
  //Letzter Impuls liegt zu lange zurück => Wert verwerfen/ungültig
  VSF_SET_INVALID();
}

ISR (SIG_INTERRUPT0)
{
  T1Value = TCNT1;    // Wert sichern
  VSF_SET_VALID();    // Wert gültig
  VSF_SET_VALNEW();   // Neuer Wert
  TCNT1 = 0;          // Timer zurücksetzen
}