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 }







Zitieren

Lesezeichen