Guten Tag, ich habe mir das Buch AVR Mikrocontroller Programmieren in C gekauft. Ich habe das Beispiel Programm zum erkennen einer Tastatur mit einem Interrupt sb getippt. Leider bekomme ich diesen Fehler nicht weg. EICRA was not declared in this scope. EIMSK was not declared in this scope. Hier mein Code. #include "ADConverter.h" volatile uint16_t ADC_Wert; #define Taster_1 ((ADC_Wert >= 168) && (ADC_Wert <= 174)) #define Taster_2 ((ADC_Wert >= 89) && (ADC_Wert <= 95)) #define Taster_3 ((ADC_Wert >= 0) && (ADC_Wert <= 3)) #define Taster_4 ((ADC_Wert >= 185) && (ADC_Wert <= 191)) #define Taster_5 ((ADC_Wert >= 113) && (ADC_Wert <= 119)) #define Taster_6 ((ADC_Wert >= 22) && (ADC_Wert <= 28)) #define Taster_7 ((ADC_Wert >= 202) && (ADC_Wert <= 208)) #define Taster_8 ((ADC_Wert >= 131) && (ADC_Wert <= 137)) #define Taster_9 ((ADC_Wert >= 46) && (ADC_Wert <= 52)) #define Taster_10 ((ADC_Wert >= 218) && (ADC_Wert <= 224)) #define Taster_11 ((ADC_Wert >= 150) && (ADC_Wert <= 156)) #define Taster_12 ((ADC_Wert >= 70) && (ADC_Wert <= 76)) void Init_ADC() { uint8_t x; DDRC &= ~(1<<PC0); ADCSRA |= (1<< ADEN); ADCSRA |= (1<<ADPS0) | (1<<ADPS1); ADMUX |= (1<<REFS0) | (1<<REFS1); ADMUX |= (1<<MUX2) | (1<<MUX0); // Hier könnte ein Fehler liegen. Laut AVR Buch "ADC5 (PIN PC5) = ADC Channel" ADMUX |= (1<<ADLAR); // DIDR0 |= (1<<ADC5D); ADCSRA |= (1<< ADSC); while (ADCSRA & (1<<ADSC)); x = ADC; } void Init_INT0 () { DDRC &= ~(1<<PD2); EICRA |= (1<<ISC01); EIMSK |= (1<<INT0); sei(); } void ADC_Main () { DDRB |= 0xFF; Init_ADC(); Init_INT0(); while (1) { if (Taster_1) { DOGM204_Clear_Display(); DOGM204_Set_Cursor(1,2); sprintf(text,"Taster 1"); DOGM204_Write_Text(text, true); } ADC_Wert = 0; } } ISR (INT0_vect) { ADCSRA |= (1<< ADSC); while (ADCSRA & (1<<ADSC)); ADC_Wert += ADCH; ADCSRA |= (1<< ADSC); while (ADCSRA & (1<<ADSC)); ADC_Wert += ADCH; ADCSRA |= (1<< ADSC); while (ADCSRA & (1<<ADSC)); ADC_Wert += ADCH; ADC_Wert = ADC_Wert / 3; } Hier die Header-Datei. #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include "DOGM204.h" #include <stdio.h> // wegen printf // Funktionen void Init_ADC (); void Init_INT0 (); void ADC_Main (); ISR (INT0_vect); //extern DOGM204_Clear_Display(); extern char text[20]; Kann mir jemand Helfen ? Gruß Nutnic
Schon man nachgeschaut ob der verwendete Kontroller? diese Register überhaupt hat. Welchen du verwendest hast du ja verschwiegen.
Hallo, die Header Datei habe ich eigebuden. Ich nutze den AtMega32. Gruß Nutnic
Da wirst du im Datenblatt nachsehen müssen wie die Register heißen in denen du den INT0 usw. aktivierst.
Das Beispielprogramm ist für einen anderen Controller, vielleicht den ATmega328. Also muss z.B. EICRA durch MCUCR sowie EIMSK durch GICR ersetzt werden. Um sicher zu sein, müsste man aber alle verwendeten SFRs kontrollieren bzw. abgleichen.
> ADMUX |= (1<<MUX2) | (1<<MUX0); > // Hier könnte ein Fehler liegen. > Laut AVR Buch "ADC5 (PIN PC5) = ADC Channel" Eben. Beim ATmega32 ist das PA5. > ADMUX |= (1<<REFS0) | (1<<REFS1); "Internal 2.56V Voltage Reference" beim ATmega32, aber z.B. bei einem ATmega328 1.1 V, welche der 32er aber gar nicht hat, d.h. man müsste alle ADC-Intervalle in diesen define Taster... neu berechnen.
Na, Letzteres nicht unbedingt, es hängt davon ab, wie die Taster verschaltet sind; ich kenne dieses Buch nicht.
Hallo Landolt, die Register habe ich gefunden. Jrtzt bekomme ich schon mal werte von den Tastern. Die Tastrer sind über eine Matrix angeschlossen. Anbei der Schaltplan. Kannst du mir sagen wie ich die Taster neu berechne ? Ich hatte nicht die Richtigen Widerstände da. Gruß Nutnic
Das hängt davon ab, von welcher Referenzspannung das Beispielprogramm ausgeht, also für welchen Controller es ursprünglich gedacht war. Ist es z.B. der ATmega328, dann müssten die Werte mit 1.1/2.56, d.h. Vref(ATmega328) / Vref(ATmega32), multipliziert werden. Alternativ könnte man auch eine Vref von 1.1 V extern anlegen.
Hsllo Landolt, das Beispiel ist für dem ATmega88 @ 1 Mhz ausgelegt. ich habe momentan 3,3 Volt anliegen. Kann ich das Problem auch mit nur 3,3 Volt lösen ? Sonst muss ich extra einen Festspannungsregler verbauen für die 5 Volt. Das will ich echt nicht machen. Gruß Nutnic
wenn ich deinen Schaltplan richtig gedeutet habe, ergeben sich diese Formeln bei gedrückten Tastern: U(S2C)= 0,0 / 39,9 * Vcc U(S1B)= 3,7 / 39,9 * Vcc U(S1A)= 7,4 / 39,9 * Vcc U(S3D)= 4,7 / 39,9 * Vcc U(S4E)= 1,0 / 39,9 * Vcc Die ADC-Vergleichswerte darfst du selber ausrechnen.
Martin B. schrieb: > Kannst du mir sagen wie ich die Taster neu berechne ? Man kann Konstanten den Compiler ausrechnen lassen, der macht das gerne und fehlerfrei. Man muß nur die Formel (Spannungsteiler) hinschreiben: Beitrag "Tastenmatrix auslesen über nur 2 Leitungen"
(Entschuldigung, da war eben ein 'Familieninterrupt') Ich hab's noch nicht verstanden, sind das fünf Einzeltasten, also keine Matrix?
Hallo, es sind 5 Einzeltaster. Bekomme ich das mit der 3,3 Volt Spannung so hin ? Gruß Nutnic
S. Landolt schrieb: > Ich hab's noch nicht verstanden, sind das fünf Einzeltasten, also keine > Matrix? Es ist keine Matrix. Drücke in Gedanken einfach jede Taste und berechne aus R1...R4 die heruntergeteilte Spannung - das hat ja STK500-Besitzer schon fast gemacht. Das geht auch mit 3.3V. Je nach Referenzspannung kannst dann den passenden Schwellwert dazu ausrechnen.
Ja eben, die Formeln von STK500-Besitzer kommen mir falsch vor, ich hätte gedacht: U(S2C)= 0.0 U(S1B)= 3.7 / (39.9+3.7) * Ucc U(S1A)= 7.4 / (39.9+7.4) * Ucc U(S3D)= 1.0 / (39.9+1.0) * Ucc U(S4E)= 4.7 / (39.9+4.7) * Ucc S2C und S3D liegen dann etwas dicht beieinander, aber es sollte eigentlich reichen.
HildeK schrieb: > Drücke in Gedanken einfach jede Taste und berechne aus R1...R4 die > heruntergeteilte Spannung - das hat ja STK500-Besitzer schon fast > gemacht. Für die Spannungsteilerberechnung würde ich aber für diese Formel plädieren: http://www.elektronik-kompendium.de/sites/slt/0201111.htm
S. Landolt schrieb: > Ja eben, die Formeln von STK500-Besitzer kommen mir falsch vor, ich > hätte gedacht: Wenigstens hast du den Fehler gefunden. Ich würde einfach ein Programm schreiben, das mir die gemessenen ADC-Werte ans Terminal schickt.
Also, mit Ucc= 3.3 V, Uref= 2.56 V (Datenblatt: 2.3 .. 2.7 V) sowie ADLAR=1 komme ich auf die ADC-Werte: U(S2C)= 0 U(S1B)= 28 U(S1A)= 52 U(S3D)= 8 U(S4E)= 35 Jetzt noch passende Intervallgrenzen auswählen, dann sollte das klappen. Ohne den anderen Vorschlägen vorgreifen zu wollen...
Hallo, ksnn man mir noch mal Helfen ? Ich glAub ich habe dar einen Fetten Fehler drin: #include "ADConverter.h" volatile uint16_t ADC_Wert; #define Taster_1 ((ADC_Wert >= 49) && (ADC_Wert <= 55)) #define Taster_2 ((ADC_Wert >= 25) && (ADC_Wert <= 31)) #define Taster_3 ((ADC_Wert >= 0) && (ADC_Wert <= 3)) #define Taster_4 ((ADC_Wert >= 32) && (ADC_Wert <= 38)) #define Taster_5 ((ADC_Wert >= 5) && (ADC_Wert <= 11)) void Init_ADC() { uint8_t x; DDRC &= ~(1<<PC0); ADCSRA |= (1<< ADEN); ADCSRA |= (1<<ADPS0) | (1<<ADPS1); ADMUX |= (1<<REFS0) | (1<<REFS1); ADMUX |= 1<<MUX0; ADMUX |= (1<<ADLAR); // DIDR0 |= (1<<ADC5D); ADCSRA |= (1<< ADSC); while (ADCSRA & (1<<ADSC)); x = ADC; } void Init_INT0 () { DDRC &= ~(1<<PD2); MCUCR |= (1<<ISC01); GICR |= (1<<INT0); sei(); } void ADC_Main () { DDRB |= 0xFF; Init_ADC(); Init_INT0(); while (1) { if (Taster_1) { DOGM204_Clear_Display(); DOGM204_Set_Cursor(1,2); sprintf(text,"Taster 1"); DOGM204_Write_Text(text, true); } else if (Taster_2) { DOGM204_Clear_Display(); DOGM204_Set_Cursor(1,2); sprintf(text,"Taster 2"); DOGM204_Write_Text(text, true); } else if (Taster_3) { DOGM204_Clear_Display(); DOGM204_Set_Cursor(1,2); sprintf(text,"Taster 3"); DOGM204_Write_Text(text, true); _delay_ms(1000); } else if (Taster_4) { DOGM204_Clear_Display(); DOGM204_Set_Cursor(1,2); sprintf(text,"Taster 4"); DOGM204_Write_Text(text, true); } else if (Taster_5) { DOGM204_Clear_Display(); DOGM204_Set_Cursor(1,2); sprintf(text,"Taster 5"); DOGM204_Write_Text(text, true); } ADC_Wert = 0; } } ISR (INT0_vect) { ADCSRA |= (1<< ADSC); while (ADCSRA & (1<<ADSC)); ADC_Wert += ADCH; ADCSRA |= (1<< ADSC); while (ADCSRA & (1<<ADSC)); ADC_Wert += ADCH; ADCSRA |= (1<< ADSC); while (ADCSRA & (1<<ADSC)); ADC_Wert += ADCH; ADC_Wert = ADC_Wert / 3; }
Es ruft das Vergnügen, ich möchte mich verabschieden - wünsche allerseits einen guten Rutsch und ein gutes Neues Jahr.
Hallo, Nein Nein, PA0 ist nur noch frei. Wenn alle Tasten angeschlossen sin. Erkennt er Taste 3 ohne das ich etwas drücke. Wenn ich Taster3 raus nehme, dann erkennt er zwar einzelne Tasten, aber sehr mühsam. Ich muss mehr mals drauf drücken damit er reagiert und dann erkennt er immer mal eine andere Taste ob wohl ich die selbe drücke. Gruß Sollen wir mal telefonieren ? Ich würde ich gerne an rufen das ist das vielleicht nicht so mühsam. Schreib mir einfach.
Martin B. schrieb: > Ich glAub ich habe dar einen Fetten Fehler drin: Zum ersten prellen die Tasten, das heißt, der Interrupt wird mehrmals aufgerufen. Dafür gibt es Entprellroutinen. Dann kannst du mal die Spannung am ADC Eingang messen und mit deinen theoretischen Werten vergleichen. Wie sieht deine Hardware aus. Kondensator am AREF und Kondensator an VCC nach GND? AVCC mit L/C von VCC entkoppelt? WAs ist mit den anderen Pin von PortA. Geben die Ruhe wenn auf PA0 gemessen wird?
Martin B. schrieb: > ((ADC_Wert >= 49) && (ADC_Wert <= 55)) Wenn dein Interrupt dazwischen reinkommt, sind deine Vergleiche falsch. Auch ist ADC_Wert 16 Bit breit und somit nicht atomisch. Somit kann ein Interrupt auch während des Lesens eines ADC_Wert dazwischenkommen. -> IRQs müssen in der Hauptschleife gesperrt werden.
Martin B. schrieb: > volatile uint16_t ADC_Wert; uint8_t genügt für ADC_Wert, da ohnehin nur ADCH abgefragt wird. Damit entfällt auch das Problem mit der ISR.
Hubert G. schrieb: > Damit > entfällt auch das Problem mit der ISR. Nein tut es nicht, weil ADC_Wert mehrfach für eine Bedingung abgefragt wird.
> Nein Nein, PA0 ist nur noch frei. Dass der ADC-Eingang auf PA1 programmiert ist, wurde ja bereits gesagt, auch dass das Ganze wegen des Tasterprellens eigentlich gar nicht stabil zu bekommen ist. Und mit dem > ADC_Wert = 0; in der Hauptschleife ist die Bedingung > #define Taster_3 ((ADC_Wert >= 0) && (ADC_Wert <= 3)) doch immer erfüllt. Insgesamt eine recht eigenwillige Konstruktion. Wie kommt es zu den ungebräuchlichen Widerstandswerten?
Martin B. schrieb: > ksnn man mir noch mal Helfen ? Warum folgst Du nicht einfach meinem Link? Da steht alles drin, mit Entprellung.
Man muß auch bedenken, daß die Wandlung asynchron zum Drücken erfolgt und sich die Spannung nicht unendlich schnell ändert, d.h. es werden Zwischenwerte anderer Tasten durchlaufen. Diese kurzzeitigen Fehlerkennungen filtert die Entprellung.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.