Hallo, liebe Gemeinde,
ich erlaube mir, eine Frage zu ISR gesteuerten PORT änderungen zu
stellen.
Ich benutze das AVR STudio 4.13.528 mit c - Programmierung.
Prinzipiell scheinen die Port - Bits wie gewünscht (z.B. 1 s - hier
nicht unbedingt diese Zeit) getoggled zu werden - Prescaler und Timer
arbeiten.
Allerdings verstehe ich nicht, warum meine initialisierende Routine
immer wieder aufgerufen wird.
Ich würde erwarten, dass die main Routine in der Enlosschleife
weiterläuft,
aber ohne die init Routine aufzurufen.
Nach meinem Verständnis habe ich dem Prozessor über die Variable
go2initial
nach dem ersten Aufruf untersagt, sich wieder zu initialisieren (meine
initialisierungs- Routine).
Was mache ich falsch / wo liegt mein Denkfehler?
Ich muß hier doch nicht etwa mit "Bootloader " arbeiten?
Ich bedanke mich schon jetzt Recht herzlich.
Als allererstes:
Rücke deinen Code ein!
Ein optisch einigermassen ansprechender Code ist nicht einfach nur eine
Fleissaufgabe, sondern hilft auch Fehler zu finden!
1
//#include <avr/io.h>
aus welchem Grund benutzt du io.h nicht?
Das ist mehr als unklug! Das ist sogar ziemlich dämlich!
1
#define INT0_vect _VECTOR(1)
2
#define INT1_vect _VECTOR(2)
3
#define TIMER2_COMP_vect _VECTOR(3)
4
#define TIMER2_OVF_vect _VECTOR(4)
5
#define TIMER1_CAPT_vect _VECTOR(5)
6
#define TIMER1_COMPA_vect _VECTOR(6)
7
#define TIMER1_COMPB_vect _VECTOR(7)
8
#define TIMER1_OVF_vect _VECTOR(8)
9
#define TIMER0_OVF_vect _VECTOR(9)
10
#define SPI_STC_vect _VECTOR(10)
11
#define USART_RXC_vect _VECTOR(11)
12
#define USART_UDRE_vect _VECTOR(12)
13
#define USART_TXC_vect _VECTOR(13)
14
#define ADC_vect _VECTOR(14)
15
#define EE_RDY_vect _VECTOR(15)
16
#define ANA_COMP_vect _VECTOR(16)
17
#define TWI_vect _VECTOR(17)
18
#define INT2_vect _VECTOR(18)
19
#define TIMER0_COMP_vect _VECTOR(19)
20
#define SPM_RDY_vect _VECTOR(20)
Nein.
Definiere dir das nicht selber! Dazu gibt es die vorgefertigen Includes,
die dir diese Dinge definieren.
1
/* Timer/Counter0 Compare Match *///
2
ISR(TIMER0_COMP_vect)
3
{
4
PORTB=PORTB^0xff;
5
go2initial=0;
6
reti();
7
};
go2initial brauchst du in Wirklichkeit nicht (dazu später mehr), und
reti() rufst du nicht selber auf. Der Compiler weiß schon, dass er eine
ISR Funktion mit einem reti anstelle eines ret abschliessen muss.
Funktionen werden NICHT mit einem ; abgeschlossen
--->
1
/* Timer/Counter0 Compare Match *///
2
ISR(TIMER0_COMP_vect)
3
{
4
PORTB=PORTB^0xff;
5
}
1
voidinitial(void)//Timer setzen
2
{
3
TCCR0=TCCR0|0x03;//prescaler
4
TCNT0=0x00;
5
OCR0=0x08;
6
TIMSK=TIMSK|0x03;
7
//TOIE0=TRUE;
8
DDRB=0xff;
9
go2initial=0;
10
//asm volatile("cli"::);
11
//sei();
12
return;
13
};
Ein return am Ende einer Funktion ist nicht notwendig, schadet aber auch
nicht. Es ist aber unüblich eines zu schreiben.
Die main() kann man dann auch kürzer schreiben. Wozu der ganze Häckmäck
mit der Hilfsvariablen? Wenn initial() nur einmal bei Programmstart
ausgeführt werden soll, dann zieh doch den Aufruf einfach vor die
while-Schleife und du hast den gewünschten Effekt. Simpel, einfach und
doch geschmacklos.
Als allererstes:
Rücke deinen Code ein!
Ein optisch einigermassen ansprechender Code ist nicht einfach nur eine
Fleissaufgabe, sondern hilft auch Fehler zu finden!
//#include <avr/io.h>
aus welchem Grund benutzt du io.h nicht?
Das ist mehr als unklug! Das ist sogar ziemlich dämlich!
Soweit ich die Bibliothek angeschaut habe, wird io.h
bereits in interrupt.h eingebunden - warum sollte ich es nochmal tun?
Um weiter zu kommen, habe ich es aber getan.
#define INT0_vect _VECTOR(1)
#define INT1_vect _VECTOR(2)
#define TIMER2_COMP_vect _VECTOR(3)
#define TIMER2_OVF_vect _VECTOR(4)
#define TIMER1_CAPT_vect _VECTOR(5)
#define TIMER1_COMPA_vect _VECTOR(6)
#define TIMER1_COMPB_vect _VECTOR(7)
#define TIMER1_OVF_vect _VECTOR(8)
#define TIMER0_OVF_vect _VECTOR(9)
#define SPI_STC_vect _VECTOR(10)
#define USART_RXC_vect _VECTOR(11)
#define USART_UDRE_vect _VECTOR(12)
#define USART_TXC_vect _VECTOR(13)
#define ADC_vect _VECTOR(14)
#define EE_RDY_vect _VECTOR(15)
#define ANA_COMP_vect _VECTOR(16)
#define TWI_vect _VECTOR(17)
#define INT2_vect _VECTOR(18)
#define TIMER0_COMP_vect _VECTOR(19)
#define SPM_RDY_vect _VECTOR(20)
Nein.
Definiere dir das nicht selber! Dazu gibt es die vorgefertigen Includes,
die dir diese Dinge definieren.
Dann nenne mir diesen include doch bitte. und schaden kann es
doch eigentlich nicht - ich ersetzte doch nur Text in meinem Programm
über den Präprozessor - die eigendlichen Definitionen packe ich doch gar
nicht an - richtig?
/* Timer/Counter0 Compare Match *///
ISR(TIMER0_COMP_vect)
{
PORTB=PORTB ^ 0xff;
go2initial=0;
reti();
};
go2initial brauchst du in Wirklichkeit nicht (dazu später mehr), und
reti() rufst du nicht selber auf. Der Compiler weiß schon, dass er eine
ISR Funktion mit einem reti anstelle eines ret abschliessen muss.
Funktionen werden NICHT mit einem ; abgeschlossen
Nun gut - habe ich berücksichtigt.
--->
/* Timer/Counter0 Compare Match *///
ISR(TIMER0_COMP_vect)
{
PORTB=PORTB ^ 0xff;
}
habe ich auch gemacht
void initial(void) //Timer setzen
{
TCCR0=TCCR0|0x03; //prescaler
TCNT0 = 0x00;
OCR0 = 0x08;
TIMSK=TIMSK | 0x03;
//TOIE0=TRUE;
DDRB = 0xff;
go2initial=0;
//asm volatile("cli"::);
//sei();
return;
};
Ein return am Ende einer Funktion ist nicht notwendig, schadet aber auch
nicht. Es ist aber unüblich eines zu schreiben.
Die main() kann man dann auch kürzer schreiben. Wozu der ganze Häckmäck
mit der Hilfsvariablen? Wenn initial() nur einmal bei Programmstart
ausgeführt werden soll, dann zieh doch den Aufruf einfach vor die
while-Schleife und du hast den gewünschten Effekt. Simpel, einfach und
doch geschmacklos.
int main(void){
int b;
initial();
sei();
while(1){ // Endlosschleife
b=1;
}
}
Auch diese Idee hatte ich bereits (konntest du natürlich nicht
wissen). Aber sowohl mit deinem Vorschlag als auch mit meiner
ursprünglichen Version wird immer in main zurückgesprungen und nicht an
den Punkt nach initial();
Das ist ja gerade mein Problem.
die variablen hatte ich für die Probedurchläufe eingesetzt , um die
Register in der Simulation besser beobachten zu können, wenn ich auf
autostep stelle.
Die überarbeitete Version hänge ich an - übrigens handelt es sich um
einen ATMEGA16.
Kannst du oder jemand anders noch irgendwelche Tipps geben?
Hinweis: Nun zählt der Counter bis 255, was ich eigentlich gar nicht so
haben wollte.
meine überarbeitete Version habe ich angehängt. (version2)
Ist ja auch alles kein Wunder. Du schaltest Overflow und
Compareint. frei. Und dann kommentierst du die Routine
für Overflow weg. Was meinst du wo der dann hinspringt?
Hallo,
ein C-Programm für einen AVR sollte immer mit
#include <avr/io.h>
beginnen, das setzt alle defines in Bezug auf controllerspezifische
register,damit läuft der code auf jedem Atmel sofern die verwendeten
Features vorhanden sind.
Wenn du interrupts benutzt schreibe eine weitere Zeile
#include <avr/interrupt.h>
darunter.
Es ist völlig unrelevant ob in interupt.h das io.h nochmal includiert
wird, die includes regeln das ganz schön, dass sie nicht mehr als einmal
durchlaufen werden.
Das ganze funktioniert aber auch nur wenn das MCU-Define den richtigen
Wert für deinen verwendeten Controller hat. Das macht das AVR-Studio
eigentlich automatisch wenn du das richtige Target ausgewählt hast.
Hallo, ihr Lieben,
Ist ja auch alles kein Wunder. Du schaltest Overflow und
Compareint. frei. Und dann kommentierst du die Routine
für Overflow weg.
Stimmt, das war nicht clever - ist korrigiert.
Was meinst du wo der dann hinspringt?
Ich vermute ins Nirvana - aber warum bei mir immer wieder zu main?
Wird dann der "Nullvektor" der ISRs angesprungen?
Das ist aber auch nicht mehr so wichtig - ich nehme gerne noch einen
Ratschlag an, ansonsten bin ich für die Antworten dankbar.
Meine jetzige Version habe ich angehängt - vielleicht kann jemand etwas
damit anfangen.
Achso: Prinzipiell glaube ich, dass die (Haupt-)Lösung meines Problems
tatsächlich darin bestand, die ein / mehrere reti am Ende der ISR zu
löschen.
Hinzu kamen natürlich noch die auskommentierte ISR.
Danke nochmal für die Hilfe bei der Lösung der Aufgabe.
>Wird dann der "Nullvektor" der ISRs angesprungen?
Er springt auf den Resetvektor. Adresse 0.
>Achso: Prinzipiell glaube ich, dass die (Haupt-)Lösung meines Problems>tatsächlich darin bestand, die ein / mehrere reti am Ende der ISR zu>löschen.
Das sei() was du da jetzt eingebaut hast ist ziemlich
genau so schädlich wie reti(). Weg damit!
slorenz schrieb:
> #define INT0_vect _VECTOR(1)> #define INT1_vect _VECTOR(2)> #define TIMER2_COMP_vect _VECTOR(3)> #define TIMER2_OVF_vect _VECTOR(4)> #define TIMER1_CAPT_vect _VECTOR(5)> #define TIMER1_COMPA_vect _VECTOR(6)> #define TIMER1_COMPB_vect _VECTOR(7)> #define TIMER1_OVF_vect _VECTOR(8)> #define TIMER0_OVF_vect _VECTOR(9)> #define SPI_STC_vect _VECTOR(10)> #define USART_RXC_vect _VECTOR(11)> #define USART_UDRE_vect _VECTOR(12)> #define USART_TXC_vect _VECTOR(13)> #define ADC_vect _VECTOR(14)> #define EE_RDY_vect _VECTOR(15)> #define ANA_COMP_vect _VECTOR(16)> #define TWI_vect _VECTOR(17)> #define INT2_vect _VECTOR(18)> #define TIMER0_COMP_vect _VECTOR(19)> #define SPM_RDY_vect _VECTOR(20)>> Nein.> Definiere dir das nicht selber! Dazu gibt es die vorgefertigen Includes,> die dir diese Dinge definieren.>> Dann nenne mir diesen include doch bitte.
io.h
interrupt.h
In einem von beiden sind sie drinnen, oder zumindest wird von dort ein
File includiert, welche die richtigen #define für *deinen* Prozessor
hat.
Änderst du den Prozessor, passen sich die #define da drinnen an.
> und schaden kann es> doch eigentlich nicht
dann warte mal ab, bis du die falschen #define für einen anderen
Prozessor benutzt.
slorenz schrieb:
> Achso: Prinzipiell glaube ich, dass die (Haupt-)Lösung meines Problems> tatsächlich darin bestand, die ein / mehrere reti am Ende der ISR zu> löschen.
Man sollte eben nicht gedankenlos irgendwelchen Quatsch zusammencoden.
Hast Du denn nicht im "interrupt.h" gelesen, wofür das reti() gedacht
ist:
/** \def reti()
\ingroup avr_interrupts
\code #include <avr/interrupt.h> \endcode
Returns from an interrupt routine, enabling global interrupts. This
should
be the last command executed before leaving an ISR defined with the
ISR_NAKED
attribute.
Ohne ISR_NAKED ergibt sich nämlich folgender Code:
1
ISR(TIMER0_COMP_vect)
2
{
3
92:1f92pushr1
4
94:0f92pushr0
5
96:0fb6inr0,0x3f;63
6
98:0f92pushr0
7
9a:1124eorr1,r1
8
9c:8f93pushr24
9
PORTB=PORTB^0xff;
10
9e:88b3inr24,0x18;24
11
a0:8095comr24
12
a2:88bbout0x18,r24;24
13
reti();
14
a4:1895reti
15
};
16
a6:8f91popr24
17
a8:0f90popr0
18
aa:0fbeout0x3f,r0;63
19
ac:0f90popr0
20
ae:1f90popr1
21
b0:1895reti
D.h. Dein unsinniges reti() springt zum zufälligen Inhalt von r24,SREG.
Und das richtige RETI ist damit toter Code.
Peter