Hallo habe auf dem Gebiet AVR noch recht wenig Erfahrung, deshalb bitte etwas Nachsicht ;-) ich versuche mit dem Timer0 (AT90S8515) einen interrupt zu erzeugen. Aber irgendwie funzt das im Simulator von AVR Studio nicht. Ich weiss beim besten Willen nicht mehr wo ich noch suchen soll. Hat jemand eine Idee und kann mir helfen? Im Voraus schonmal vielen Dank. Der Sourcecode sieht so aus und macht natürlich nicht wirklich Sinn. Wie gesagt sind die ersten Gehversuche. #include <avr/interrupt.h> int main(void) { InitTimer(); while(1) { ; } } void InitTimer() { TCCR0 =TCCR0 | (1<<CS00); TIMSK = TIMSK | (1<<TOIE0); sei(); } ISR(TIMER0_OVF_vect) { static int a = 0; a++; }
Bernd wrote: > habe auf dem Gebiet AVR noch recht wenig Erfahrung, deshalb bitte etwas > Nachsicht ;-) Naja, jeder hat mal angefangen (auch wenn manch einer das scheinbar schon vergessen hat...) > ich versuche mit dem Timer0 (AT90S8515) Oh, ein historischer AVR. Solltest vielleicht mal bei Gelegenheit auf was Aktuelles umsteigen... > einen interrupt zu erzeugen. > Aber irgendwie funzt das im Simulator von AVR Studio nicht. Zunächst mal hat der Simulator manchmal so seine Problemchen mit Timern. Allerdings stellt sich natürlich auch die Frage, wie Du simulierst... > Der Sourcecode sieht so aus und macht natürlich nicht wirklich Sinn. Macht nicht nur nicht viel Sinn, sondern müsste auch mindestens zwei fette Fehler produzieren: - Du hast die avr/io.h nicht eingebunden, weshalb überhaupt keine I/O-Register bekannt sind - Die Funktion InitTimer ist zum Zeitpunkt ihres Aufrufes unbekannt (kein Prototyp, Definition erst weiter unten) Das kann so schon mal gar nicht compilieren und deshalb auch nichts Simulierbares ergeben. Lies Dir bitte im AVR-GCC-Tutorial mal durch, wie es geht. Und ein C-Buch wäre auch nicht verkehrt. Außerdem solltest Du Code, den Du hier postest, auch vernünftig formatieren. Die Forensoftware hat dafür extra eine Möglichkeit, die unter den Forenregeln angegeben ist.
Der Code sieht OK aus. Wo hast du den Breakpoint im Simulator sitzen? Mein Vorschlag ist Position #1 (s.u.). Gibt es in der Doku von deinem AVR Studio (welche Version?) eine Liste mit bekannten Problemen bei der Simulation von Timern? Nebensachen: Das Forum besitzt eine schöne Möglichkeit zur Formatierung von Quelltexten ;-) Die Reihenfolge der Funktionen wurde etwas umsortiert. Die wichtige ISR am Anfang, dann die Hilfsfunktionen (damit der Compiler deren Prototypen kennt) und am Schluss die main(). Ist auch eine gängige Leseordnung von Programmierern. sei() wurde aus der InitTimer() nach main() verschoben: Wenn es später mal noch andere Interrupts gibt, sollte sei() nach allen Initialisierungen gemacht werden.
1 | #include <avr/io.h> // ADD: Anmerkung von Johannes M. |
2 | #include <avr/interrupt.h> |
3 | |
4 | ISR(TIMER0_OVF_vect) |
5 | {
|
6 | static int a = 0; |
7 | a++; // Breakpoint #1 im Simulator |
8 | }
|
9 | |
10 | void InitTimer(void) |
11 | {
|
12 | TCCR0 = TCCR0 | (1<<CS00); // Prescaler CK/8 |
13 | TCNT0 = 0; |
14 | TIMSK = TIMSK | (1<<TOIE0); |
15 | }
|
16 | |
17 | int main(void) |
18 | {
|
19 | InitTimer(); |
20 | sei(); |
21 | |
22 | while(1) |
23 | {
|
24 | }
|
25 | }
|
Vielen Dank für die Antworten. Hat sich aber auch schon erledigt. Man muss eben nur den richtigen µC im Simulator wählen und schon geht es. Das hätte ich auch schneller haben können.
Bernd wrote: > Vielen Dank für die Antworten. Hat sich aber auch schon erledigt. Man > muss eben nur den richtigen µC im Simulator wählen und schon geht es. > Das hätte ich auch schneller haben können. Mit dem Code? Nie im Leben! Jetzt veräppelst Du uns aber.
jo, mit dem code! hab lediglich die beiden Header die im posting fehlen nicht mit ins posting kopiert, aber trotzdem waren sie da. ok, wenn man die Funktionen so herum schreibt braucht man nur den io.h, aber auch der war vorhanden im orginal code.
Also doch nicht mit dem Code, sondern mit einem, den wir hier nicht sehen können!
Hallo! Ich hab mir aufgrund des ähnlichen Problems mal diesen Thread für meine Frage geschnappt. Leider konnt ich es trotz diverser ähnlicher Forenbeiträge und Artikel noch nicht lösen. Ich habe mir mal das Beispiel des Zählers des Funk-AVR-Evaluationsboardes ausgesucht http://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#2-Bit_Z.C3.A4hler Mittels eines längeren Tastendruckes wollte ich nun den Zähler (counter) wieder auf Null setzen. Mit der deklarierten Variable repeater hat das auch geklappt. Das habe ich jetzt auskommentiert und wollte es mit dem Timer0 und einer ISR lösen, verzweifle daran aber seit gestern. Es geht quasi um den Code ab dem Kommentar "button long pushed => set counter 0" sowie um die ISR(Timer0_OVF_vect). Zählen klappt also, aber bei der ISR und dem damit verbundenen Rücksetzen counter = 0 hab ich ein ziemliches Denkproblem. Wäre nett, wenn mir jemand weiterhelfen könnte. Danke schon mal!
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | //#include <avr/iotn2313>
|
4 | #include <stdint.h> |
5 | #include <util/delay.h> |
6 | |
7 | #define LED1 PD6
|
8 | #define LED2 PD5
|
9 | #define BUTTON1 PB1
|
10 | |
11 | #define LED_ON(LED) (PORTD |= (1<<LED)) //x or 1 = 1
|
12 | #define LED_OFF(LED) (PORTD &= ~(1<<LED)) //x and 0 = 0
|
13 | #define LED_TOGGLE(LED) (PORTD ^= (1<<LED)) //x xor 1 = !x
|
14 | #define BUTTON1_PUSHED (PINB & (1<<BUTTON1))
|
15 | #define ON 1 //for old_state (button pushed
|
16 | #define OFF 0 //for old_state (button not pushed)
|
17 | |
18 | volatile uint8_t counter; |
19 | |
20 | |
21 | ISR(TIMER0_OVF_vect) |
22 | {
|
23 | counter = 0; |
24 | }
|
25 | |
26 | |
27 | void output(uint8_t counter_out) |
28 | {
|
29 | if (counter_out & (1<<0)) //bit 0 |
30 | LED_ON(LED1); |
31 | else
|
32 | LED_OFF(LED1); |
33 | |
34 | if (counter_out & (1<<1)) //bit 1 |
35 | LED_ON(LED2); |
36 | else
|
37 | LED_OFF(LED2); |
38 | }
|
39 | |
40 | |
41 | int main(void) |
42 | {
|
43 | uint8_t old_state; |
44 | uint16_t repeater; |
45 | |
46 | DDRD |= (1<<LED1) | (1<<LED2); //set PD6, PD5 (LEDs) as output |
47 | DDRB &= ~(1<<BUTTON1); //set PB1 (push-button) as input |
48 | |
49 | counter = 0; |
50 | old_state = OFF; |
51 | // repeater = 0; //checking pushing duration
|
52 | |
53 | sei(); //global interrupt enable |
54 | |
55 | while(1) |
56 | {
|
57 | output(counter); //calling output function |
58 | |
59 | //button switched from open to closed => counting 1 up
|
60 | if(BUTTON1_PUSHED && old_state == OFF) |
61 | {
|
62 | counter++; |
63 | old_state = ON; |
64 | // repeater = 0;
|
65 | TCNT0 = 0; |
66 | }
|
67 | |
68 | //button open
|
69 | if(!BUTTON1_PUSHED) |
70 | {
|
71 | old_state = OFF; |
72 | // repeater = 0;
|
73 | TCNT0=0; |
74 | }
|
75 | |
76 | //button long pushed => set counter 0
|
77 | if(BUTTON1_PUSHED && old_state == ON) |
78 | {
|
79 | //configure timer interrupt
|
80 | TCCR0A |= (1<<CS02) | (0<<CS01) | (0<<CS00); //set prescaler = 1 |
81 | TCNT0 = 0; //counter register = 0 |
82 | TIFR |= (1<<TOV0); //delelte timer overflow flag |
83 | TIMSK |= (1<<TOIE0); //timer0 overflow enable |
84 | |
85 | /* repeater++;
|
86 | |
87 | if(repeater == 20000)
|
88 | {
|
89 | counter = 0;
|
90 | repeater = 0;
|
91 | }*/
|
92 | }
|
93 | }
|
94 | }
|
Hm, zu viel zu lesen oder zu undurchsichtig?! Ich bin leider auch allein noch nicht schlauer geworden.
Christoph P. wrote:
1 | > //#include <avr/iotn2313> |
Das hat auch in auskommentiertem Zustand da nichts zu suchen! Device-spezifische Header werden nie direkt eingebunden. Weg damit!
1 | > TCCR0A |= (1<<CS02) | (0<<CS01) | (0<<CS00); //set prescaler = 1 |
Ich frage mich, wann es sich wohl endlich herumspricht, dass eine VerODERung mit einer Null völlig witzlos ist... Und das Schieben einer Null genauso. Des weiteren erschließt sich mir die Funktionsweise des Programmes derzeit überhaupt nicht. Ich hab keinen Schimmer, was Du da wirklich machen willst. Der Timer wird gestartet und nirgends wieder angehalten. In irgendwelchen Programmteilen wird das Zählregister einfach mal zurückgesetzt, aber nirgends ist erkennbar, was das bringen soll. Eine Zählvariable namens counter wird ab und zu inkrementiert, aber nirgends ausgewertet. Im Timer Overflow Handler wird sie zurückgesetzt, aber was soll das bezwecken? Tipp: Bitte zeichne den von Dir gewünschten Ablauf in Form eines Programmablaufplanes oder Flussdiagramms hin. Und dann fängst Du an, zu programmieren. Durch das da oben steigt niemand durch (Du selber offensichtlich auch nicht)...
Danke erstmal für die Antwort. Die verODERung ist nur durch rumprobieren da so reingerutscht. Würd ich jetzt mal nicht überbewerten. Das Programm soll einfach mit jedem Tastendruck eins hochzählen und das Ergebnis an (in diesem Fall nur zwei) LEDs ausgeben. Das macht es auch. Soll der Zähler nun wieder auf Null gesetzt werden, soll das durch einen längeren Tastendruck geschehen. Statt einem kurzen tippen eben 3s Halten oder ähnlich. Das hat, wie gesagt, mit der deklarierten Variable repeater auch geklappt. Nun wollte ich das Zurücksetzen aber über den "eingebauten" Timer0 und der ISR realisieren. Und das funktioniert noch nicht. Das Zählregister wird immer dann zurückgesetzt, wenn der Taster nicht oder nur kurz gedrückt wird. In die ISR scheint das Programm aber gar nicht zu kommen, so dass der counter nie zurückgesetzt wird. Eine weiterführende Auswertung will ich an dieser Stelle gar nicht betrachten, einfach nur einen Zähler mit Rücksetzen bei langem Tastendruck und Hochzählen bei kurzem.
Christoph P. wrote: > Das Zählregister wird immer dann zurückgesetzt, wenn der Taster nicht > oder nur kurz gedrückt wird. Dir scheint nicht so recht klar zu sein, dass beim Drücken der Taste der dritte if-Block immer wieder und wieder ausgeführt wird, inklusive der Timer-Initialisierung mit dem "TCNT0=0" darin.
Bei der Initialisierung des Timer0 gibt es einen Fehler (TCCR0A verwendet statt TCCR0B), so dass der Timer nie lief. So wie im Anhang geht es auf meinem Pollin Board mit Attiny2312 und 8 MHz. Die 3s sind Pi*Daumen, siehe Anmerkung im Quellcode.
So nachträglich ist mir noch eine Unschönheit aufgefallen, die zwar die Funktion nicht beeinträchtigt, aber die einen wurmen kann ;-) Wenn die Taste vor dem 3 s Timeout losgelassen wird, läuft der Timer weiter. Man könnte das beheben, wenn man den button open Fall so anlegt:
1 | //button open
|
2 | if(!BUTTON1_PUSHED && (old_state == ON)) |
3 | {
|
4 | DISABLE_TIMER0(); |
5 | duration = 0; |
6 | old_state = OFF; |
7 | }
|
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.