Hi! Es gibt bestimmt Köpfe, die da einen Tip haben... Beim Attiny261 bekomme ich keine ISR (TIMER1_OVF_vect) aufgerufen. Bitte entschuldigt manch falsche Komentare im Code - er ist eben kopiert und abgeändert - ich will erst mal nur den verd... Iterrupt aufgerufen bekommen. den Rest schaffe ich hoffentlich wieder alleine. Hier mein Code: (Ich weiß, dass das kein vorzeigecode ist... ich bin halt nicht so fit darin... :-) ) #include <avr/io.h> #ifndef F_CPU #define F_CPU 1000000 //laut Datenblatt Quarz (8MHz/8) #endif #include <avr/interrupt.h> #include <util/delay.h> //DEFINE PORTZUWEISUNGEN--------------------------------------------------------- -------- #define LED PORTA #define LED_blau 0 #define LED_rot 1 #define AUSGANG_B PORTB #define PB_SDA 0 #define PB_SCL 2 #define Pullup_B PORTB #define EINGANG_B PINB #define PB_PTC 6 // Multiplexer ADC: Bit 7 Reserviert; Bit 6 1,1V Ref; Bit 5 Messergebniss links schieben für 8Bit ...Bit 1 und 0 Bereichswahl #define W_ADC_unten 0b01001001 //ADC9 PTC ausgewählt ref. 5V PTC 25Grad = 511dig. //Sollwerte Laut Tabelle #define W_30Grad 511 //Max Temperatur 30Grad 456 (500 26Grad) //Zeitbasis 0,1Sekunden 1,0MHz /512 = Teiler 195 #define W_Zeitbasis 195 //REGISTER NAMENSGEBUNG------------------------------------------------------------ -------- volatile struct { unsigned char ADC_STATUS :2; //0=ADC frei, 1=Messung läuft, 2=Messung abrufbar unsigned char WECKER :1; //Wenn Timer0 abgelaufen (0,1 Sek.) unsigned char ADC_Quelle :1; //ADC Quelle unten "0" und oben "1" }PAR; //ProgrammAblaufRegister //ADC Quelle #define unten 0 #define oben 1 //Wecker #define schlaf 0 #define wach 1 //ADC STatus #define frei 0 #define misst 1 #define fertig 3 /*//Taster #define nicht_gedrueckt 0 #define war_gedrueckt 1 */ unsigned char R_Pieper_AUS; //Hochzählregister für Pieper ist AUS max 255 unsigned char R_Pieper_AN; //Hochzählregister für Pieper ist AN max 255 unsigned char R_Pieper_WERT_AUS; //Hochzählregister für Pieper ist AUS max 255 unsigned char R_Pieper_WERT_AN; //Hochzählregister für Pieper ist AN max 255 unsigned int R_unten; //Register für Messung unten 16Bit unsigned int R_oben; //Register für Messung oben 16Bit //Einrichten: //---------------------------------------------------------------------- ------ int init(void) { //Ein- und Ausgänge DDRA |= (1 << LED_blau)|(1 << LED_rot); //Ausgänge setzen //Pullup_B |= (1<< PB_Taster); //PULL-Up setzen /*//PWM einrichten ----Kein PWM nötig TCCR0A |= (1<<COM0A1) | (1<<WGM01) | (1<<WGM00); //PWM A (PB0) und B (PB1), Fast PWM-Mode Ausgabe ca.38kHz 0=0= Kein Strom TCCR0A |= (1<<COM0B1); */ //ADC einrichten: zwischen 50 und 200kHz Taktrate: 1000kHz= Vorteiler zwischen 5 und 20 auswählen ADCSRA |= (1<<ADEN|1<<ADPS2); //ADEN=ADC einschalten; ADPS2:0 = Vorteiler 16 = 62,5kHz/13 = 4,8kHz = 0,2mS = Eine Messung DIDR1 |=(1<<ADC9D); //Eingänge für ADC freigeben ADMUX = W_ADC_unten; //Eingang unten wählen //Erste Messung wird verworfen... ADCSRA |= (1<<ADSC); //Messung starten while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten } (void) ADC; //ADC muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen. //ganz zum Schluss alles starten und freigeben: //Register auf Start laden R_Pieper_WERT_AN = 0; R_Pieper_WERT_AUS = 10; TC1H = 0x00; //00= 8BIT tiefe 03=10Bit tiefe OCR1C = 0xff; //GANZ WICHTIG Maximalwert eintragen!!! Sonst zählt der T1 nur bis 3!!! S.121 12.12.11 OCR1A = W_Zeitbasis; //Zeitbasis laden //TCCR1A | = (1<<PWM1A) //?????????????????????????????? S.114 TCCR1B |= (1<<CS13)|(1<<CS11); //Vorteiler auf 512 einstellen und loslegen!!!!!!!!!!! //Interrupts freigeben S.122 TIMSK |=(1<<OCIE1A) | (1<<TOIE1); //(Overflow TOIE0)/CompareA OCIE1A Interrupt freigeben ADCSRA |= (1<<ADIE); //ADC-Interrupt freigeben sei(); //Globalen Interrupt freigeben return 0; } //Unterprogramme-------------------------------------------------------- ---------------- //Interruptroutinen ISR (TIMER1_COMPA_vect) { cli(); LED |=(1<<LED_blau); //Pieper Steuern PAR.WECKER = wach; //Zeit abgelaufen Wecker aktivieren _delay_ms(5) LED &=~(1<<LED_blau); sei(); } ISR (TIMER1_OVF_vect) { LED |=(1<<LED_rot); _delay_ms(5); LED &=~(1<<LED_rot); } ISR (ADC_vect) { cli(); PAR.ADC_STATUS = fertig; //ADC Messung abrufbar sei(); }
Hallo, wo finde ich den int main(void) {} Block?
Hallo,
1 | ISR (ADC_vect) |
2 | {
|
3 | cli(); |
4 | PAR.ADC_STATUS = fertig; //ADC Messung abrufbar |
5 | sei(); |
6 | }
|
Was bezweckst Du mit dem Sperren und vorzeitigem Freigeben des globalen Interrupts? Im Datenblatt ist das Interruptverhalten erläutert.
> Bei Attiny261 wird Interrupt TIMER1_COMPA nicht aufgerufen > Beim Attiny261 bekomme ich keine ISR (TIMER1_OVF_vect) aufgerufen Kannst du dich für ein Problem entscheiden, oder funktionieren beide Interrupts nicht? cli() und sei() haben normalerweise in ISR nicht verloren. Hast du einen guten Grund, das zu machen? > wo finde ich den int main(void) {} Block? Gute Frage!
Stefan Us, das Programm, sollte wohl maximal klein, durch den gcc Compiler, optimiert werden. :-)
thomas schrieb: > Bitte entschuldigt manch falsche Komentare im Code - er ist eben kopiert > und abgeändert - ich will erst mal nur den verd... Iterrupt aufgerufen > bekommen. den Rest schaffe ich hoffentlich wieder alleine. Ja, dann mach das doch. Schmeiss alles, was mit diesem Interrupt nichts zu tun hat, raus. Und wenn es dann läuft, setzt du alles andere Schritt für Schritt wieder rein. Und beachte die Warnings des Compilers.
Hallo, Dabla: "Interrupt vectors of ATtiny261A/461A/861A are described in Table 9-1 below." http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html Du solltest genau diejenigen Namen eintragen, die Dein Compiler kennt. Dann noch in Timsk einzeln frei geben. Sei (); MfG
:
Bearbeitet durch User
> Du solltest genau diejenigen Namen eintragen, die Dein Compiler kennt. hat er doch! > Dann noch in Timsk einzeln frei geben hat er auch > Sei () ist auch im Code Sag mal, liest du eigentlich die Frage, bevor du sie beantwortest? oder arbeitest du mit Textbausteinen, wie der Support von Ebay?
Stefan U. schrieb: > Sag mal, liest du eigentlich die Frage, bevor du sie beantwortest? Weil die Frage schlichtweg unlesbar ist. Keine Forenregeln eingehalten, d.h. nicht als Anhang gepostet oder wenigstens Codetags verwendet. Und dann noch nen riesen Wust an Code drin, der mit T1 absolut nichts am Hut hat. Was mit schonmal bitter aufstößt, sind die Delays im Interrupt.
Wer hat noch mehr Wohlwollen zum Ausschütten im Überfluß übrig? Und warum geht sein Interrupt nicht? MfG
Karl M. schrieb: > wo finde ich den int main(void) {} Block? Den sollte man schon haben ... (den ADC-Kram habe ich mal rausgenommen)
1 | #include <avr/io.h> |
2 | |
3 | #ifndef F_CPU
|
4 | #define F_CPU 1000000 //laut Datenblatt Quarz (8MHz/8)
|
5 | #endif
|
6 | |
7 | #include <avr/interrupt.h> |
8 | #include <util/delay.h> |
9 | |
10 | |
11 | //DEFINE PORTZUWEISUNGEN-----------------------------------------------------------------
|
12 | |
13 | #define LED PORTA
|
14 | #define LED_blau 0
|
15 | #define LED_rot 1
|
16 | |
17 | #define AUSGANG_B PORTB
|
18 | #define PB_SDA 0
|
19 | #define PB_SCL 2
|
20 | |
21 | #define Pullup_B PORTB
|
22 | |
23 | #define EINGANG_B PINB
|
24 | #define PB_PTC 6
|
25 | |
26 | // Multiplexer ADC: Bit 7 Reserviert; Bit 6 1,1V Ref; Bit 5 Messergebniss links schieben für 8Bit ...Bit 1 und 0 Bereichswahl
|
27 | #define W_ADC_unten 0b01001001 //ADC9 PTC ausgewählt ref. 5V PTC 25Grad = 511dig.
|
28 | |
29 | //Sollwerte Laut Tabelle
|
30 | #define W_30Grad 511 //Max Temperatur 30Grad 456 (500 26Grad)
|
31 | |
32 | //Zeitbasis 0,1Sekunden 1,0MHz /512 = Teiler 195
|
33 | #define W_Zeitbasis 195
|
34 | |
35 | //ADC Quelle
|
36 | #define unten 0
|
37 | #define oben 1
|
38 | //Wecker
|
39 | #define schlaf 0
|
40 | #define wach 1
|
41 | //ADC STatus
|
42 | #define frei 0
|
43 | #define misst 1
|
44 | #define fertig 3
|
45 | /*//Taster
|
46 | #define nicht_gedrueckt 0
|
47 | #define war_gedrueckt 1
|
48 | */
|
49 | |
50 | unsigned char R_Pieper_AUS; //Hochzählregister für Pieper ist AUS max 255 |
51 | unsigned char R_Pieper_AN; //Hochzählregister für Pieper ist AN max 255 |
52 | |
53 | unsigned char R_Pieper_WERT_AUS; //Hochzählregister für Pieper ist AUS max 255 |
54 | unsigned char R_Pieper_WERT_AN; //Hochzählregister für Pieper ist AN max 255 |
55 | |
56 | unsigned int R_unten; //Register für Messung unten 16Bit |
57 | unsigned int R_oben; //Register für Messung oben 16Bit |
58 | |
59 | volatile struct |
60 | {
|
61 | unsigned char ADC_STATUS :2; //0=ADC frei, 1=Messung läuft, 2=Messung abrufbar |
62 | unsigned char WECKER :1; //Wenn Timer0 abgelaufen (0,1 Sek.) |
63 | unsigned char ADC_Quelle :1; //ADC Quelle unten "0" und oben "1" |
64 | }PAR; //ProgrammAblaufRegister |
65 | |
66 | ISR (TIMER1_COMPA_vect) |
67 | {
|
68 | LED |=(1<<LED_blau); |
69 | |
70 | //Pieper Steuern
|
71 | PAR.WECKER = wach; //Zeit abgelaufen Wecker aktivieren |
72 | _delay_ms(5); |
73 | LED &=~(1<<LED_blau); |
74 | }
|
75 | |
76 | ISR (TIMER1_OVF_vect) |
77 | {
|
78 | LED |=(1<<LED_rot); |
79 | _delay_ms(5); |
80 | LED &=~(1<<LED_rot); |
81 | }
|
82 | |
83 | ISR (ADC_vect) |
84 | {
|
85 | cli(); |
86 | PAR.ADC_STATUS = fertig; //ADC Messung abrufbar |
87 | sei(); |
88 | }
|
89 | |
90 | |
91 | |
92 | |
93 | int main(void) |
94 | {
|
95 | |
96 | TC1H = 0x00; //00= 8BIT tiefe 03=10Bit tiefe |
97 | OCR1C = 0xff; //GANZ WICHTIG Maximalwert eintragen!!! Sonst zählt der T1 nur bis 3!!! S.121 12.12.11 |
98 | OCR1A = W_Zeitbasis; //Zeitbasis laden |
99 | //TCCR1A | = (1<<PWM1A) //?????????????????????????????? S.114
|
100 | TCCR1B |= (1<<CS13)|(1<<CS11); //Vorteiler auf 512 einstellen und loslegen!!!!!!!!!!! |
101 | |
102 | //Interrupts freigeben S.122
|
103 | TIMSK |=(1<<OCIE1A) | (1<<TOIE1); //(Overflow TOIE0)/CompareA OCIE1A Interrupt freigeben |
104 | |
105 | sei(); //Globalen Interrupt freigeben |
106 | |
107 | while(1) { }; |
108 | |
109 | }
|
Bist du ganz sicher, dass die Interrupts nicht aufgerufen werden? Vielleicht hast du die LED's falsch herum angeschlossen oder bist einfach nicht imstande, das kurze 5ms Blitzen zu sehen.
Stefan U. schrieb: > Bist du ganz sicher, dass die Interrupts nicht aufgerufen werden? Wie soll das ohne "(Main-)Schleife" gehen? Es wird initialisiert und das Programm ist dann zu Ende. (Punkt)
Dieter F. schrieb: > Es wird initialisiert und das > Programm ist dann zu Ende. Welches Programm?
1 | error: undefined reference to main |
oder so ähnlich
> Wie soll das ohne "(Main-)Schleife" gehen?
Wegen der Timer Interrupts!
Ich bin davon ausgegangen, dass eine main() Funktion schon vorhanden
ist, aber dass der TO annahm, sie wäre für die Klärung des Problem nicht
relevant.
Stefan U. schrieb: > Ich bin davon ausgegangen, dass eine main() Funktion schon vorhanden > ist, aber dass der TO annahm, sie wäre für die Klärung des Problem nicht > relevant. Natürlich hat er die. Sonst lässt der Compiler das ja auch nicht durch. Und da ist auch irgendwo der Fehler. Der Fehler ist immer da, wo jemand meint, daß er da garantiert nicht sein könnte. Viel schlimmer finde ich allerdings, daß er seinen Rotz hier reinstellt und sich dann nicht wieder meldet. Womöglich beschwert er sich heute abend noch, daß keine fertige Lösung vorliegt.
Thomas E. schrieb: > Welches Programm? > error: undefined reference to main > > oder so ähnlich Stimmt ...
"Viel schlimmer finde ich allerdings, daß er seinen Rotz hier reinstellt und sich dann nicht wieder meldet. " Mindestens ein Dankeschön würde man doch erwarten können, oder? Erstmal ist Wochenend-Tralala... MfG
Hi! Hier ist der Autor der Frage. Ich bin über die vielen Einträge und Helfer überwältigt! Wollte mich schon mal bedanken - auch wenn der entscheidente Hinweis noch nicht dabei war. Verstehen kann ich manch Komentare nicht - gerade die, die um Mtternacht geschrieben wurden. Ich habe eben andere Arbeitszeiten - und kann wegen Familie nicht immer und sofort Antworten. Dass das Main komplett fehlt war mir nicht aufgefallen. Wie man einen Quelltext RICHTIG reinstellt, konnte ich in meiner ERSTEN Frage nicht aneignen. Der Interrupt (TIMER1_OVF_vect) wird doch nach einem Test, den ich nach der Beerdigung eines langjährigen Arbeitskolleken durchgeführt habe, aufgerufen - so viel zum Thema ein wenig mehr GEDULT, Bitte! Der Interrupt ISR (TIMER1_COMPA_vect) wird nach einem weiteren Test GAR nicht aufgerufen. Das mit dem Sperren und freigeben des i-Interrupts habe ich irgendwo aufgenommen und fand es jetzt nicht fehlerhaft. Sicher ist sicher eben. Aktuell habe ich es so: ______________________________________________________________________ __ ISR (TIMER1_COMPA_vect) { cli(); LED |= (1<<LED_blau); //Pieper Steuern PAR.WECKER = wach; //Zeit abgelaufen Wecker aktivieren sei(); } ISR (TIMER1_OVF_vect) { LED ^= (1<<LED_rot); } ISR (ADC_vect) { cli(); PAR.ADC_STATUS = fertig; //ADC Messung abrufbar sei(); } //---------------------------------------------------------------------- ------ int main(void) { init(); //Hauptprogramm while(1) { if (PAR.WECKER=wach) { OCR1A = OCR1A + W_Zeitbasis; //Neuen Aufwecktermin übergeben PAR.WECKER=schlaf; //wieder schlafen legen } /*//ADC: Wenn frei, dann Messung loslegen if (PAR.ADC_STATUS=frei) { ADCSRA |= (1<<ADSC); //Messung starten PAR.ADC_STATUS=misst; //Messung läuft } if (PAR.ADC_STATUS=fertig) { R_unten=ADC; //Messung in das richtige Register sichern } */ } } ______________________________________________________________________ _ UND hier ist die Main auch dabei - aber das ganze einrichten nicht. JETZT bin ich mal am Hobbyplatz und ansprechbar - falls weitere Kontruktive Fragen gestellt werden. Manch Sachen, die nicht unbedingt nötig sind sind eben noch im Programm drin, werden aber später benötigt. Diese stören jedoch nicht das aufrufen, denn das Interrupt ISR (TIMER1_OVF_vect) kann ja aufgerufen werden. Gruß Thomas
thomas schrieb: > JETZT bin ich mal am Hobbyplatz und ansprechbar - falls weitere > Kontruktive Fragen gestellt werden. Sourcecode in [c] Tags einklammern, siehe ---> Wichtige Regeln - erst lesen, dann posten! Peter D. schrieb: > Keine Forenregeln eingehalten, d.h. nicht als Anhang gepostet oder > wenigstens Codetags verwendet. Solche Hinweise ignorierst du einfach?
Aktuell habe ich die blaue LED im Main eingeschaltet - diese leuchtet. Danke des Hinweisen, wie man den Code einstellt. Hatte ich noch nicht gelesen - manch Komentare überlese ich eben. Soll ich nochmal den kompkletten Conde in diesen Klammern einstellen? Habe auch angefangen unwichtiges zu entfernen - wie z.B. das mit den I-Interrupt.
thomas schrieb: > Aktuell habe ich es so: Ne, das compiliert nicht. Gehe mal zurück auf Start: Hänge das Projekt als Anhang an. Entweder das *.c oder als *.zip, wenn es mehrere Dateien sind. Und schmeiß den ganzen ADC-Krempel raus, der interessiert hier niemanden. Dann weißt Du auch, ob der Fehler nicht im ADC-Krempel liegt. D.h. Du prüfst selbstverständlich vor dem Posten, ob der Fehler im gekürzten Code immer noch auftritt und ob der überhaupt compiliert.
Das Gespräch jetzt hatte sehr viel gebracht. Vor einigen Tagen: Ich war eben am verzweifeln. (Post) Hatte sonst ( Bei anderen Projekten) mich durchgekämpft. Das mit dem einstellen kann ich gerne jetzt noch machen, jedoch habe ich den Fehler gefunden. Eine einfache LEERSTELLE nach einem "=" hatte das ganze ausgemacht. Hatte auch den Code ausgespeckt und siehe da, der Kompiler hatte eine Anmerkung, mit der ich nichts anfangen konnte nicht mehr aufgerufen. Ich hatte gedacht, dass nur "rote" Fehler vom Compiler richtig wichtig sind. Danke des netten Gespräches - und das mit den ForenRegeln hatte ich wegen Zeitmangel nicht gelesen, da nicht gefunden. Hatte nicht gedacht, dass es so schlimm im Browser dargestellt wird, dass alles verzerrt ist. Man lernt nie aus - beim nächsten mal besser und überlegter.
thomas schrieb: > der Kompiler hatte eine > Anmerkung Damit qualifizierst Du Dich als fortgeschrittener Frager, wenn Du solche Meldungen gleich am Anfang per Copy&Paste mitteilst. Und wenn dann noch der Code als Anhang ist, kann man sogar die Zeilennummer der Meldung richtig zuordnen. Das erspart uns nen gewaltigen Haufen Sucherei und Hellsehen.
thomas schrieb: > if (PAR.WECKER=wach) thomas schrieb: > if (PAR.ADC_STATUS=frei) Das willst du aber nicht wirklich, oder? Du willst vergleichen, weist aber zu.
Ich kann es nun gut verstehen, weswegen direkt unmut zu lesen war. (Einsichtig!) Kannst du mir noch vielleicht einen Tip geben, was sich unter dem Register (Und Bit) versteckt? TCCR1A | = (1<<PWM1A) Datenblatt S.114 Ich kann das Englisch nicht so sehr... Würde ich damit den einfachen PWM beim Controller am PIN einschalten?
@ Hin Weisa: Schit! Dass letzte Programmieren ist mehr als ein Jahr zurück! Danke! Anfängerfehler... Wird gleich mit "==" berichtigt! Wow ihr nehmt euch richtig Zeit - so macht Programmieren gleich mehr Spaß!
"TCCR1A | = (1<<PWM1A) " Hallo, Dieses Bit schaltet den Fast-PWM-modus für den Pin OC1A ein und wirkt zusammen mit den Bits COM1AX. Was genau passiert, ist in den umfangreichen Tabellen aufgeführt. Man kann die Einstellungen auch alle durchprobieren und mittels Oszilloskop beobachten, was passiert. "The fast Pulse Width Modulation or fast PWM mode (PWM1A/PWM1B = 1 and WGM1[1:0] = 00) provides a high frequency PWM waveform generation option. The fast PWM differs from the other PWM option by its single-slope operation. The counter counts from BOTTOM to TOP (defined as OCR1C) then restarts from BOTTOM." Im Vergleich zum normalen PWM-modus dauert der Zyklus nur halb so lange, weil der Zähler nur von Null bis OCR1C-Wert hoch zählt. MfG
Danke der Antwort - dann sehe ich bald beim nächsten Bit CO1Ax nach.
Hallo, hier noch eine deutsche Kurzanleitung als Orientierung: https://www.google.de/url?sa=t&source=web&rct=j&url=http://www.hochschule-bochum.de/fileadmin/media/fb_e/labore/aidlab/coersmeier/AVR-PWM%2520(BAU).pdf&ved=0ahUKEwjD0IyTmJXYAhVoKMAKHQ1CD_4QFggkMAQ&usg=AOvVaw0Rz3aVtahVJFWC62RbyCC_ MfG
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.