Hallo, ich bekomme leider in meiner ISR das Problem, dass der Compiler
meldet, dass er die Variablen nicht kennt. Es sind jedoch alle mit
volatile gekennzeichnet...
1
// Deklaration verschiedener Funktionen
2
3
4
intmain(void)
5
{
6
volatileunsignedcharactual_row=0;
7
volatileunsignedcharstatic_field[10][3];//static_field[x][y]: x=row from top; y=color. 0=red, 1=green, 2=blue
8
volatileunsignedcharvariable_field[8][3];//variable_field[x][y]: x=row from top; y=color. 0=red, 1=green, 2=blue
Die Fehler:
static_field, actual_row, border undeclared
Wo liegt mein Fehler?
Des Weiteren würde es mich noch interssieren, wo der Unterschieden
zwischen OCR1AH/L und OCR1BH/L liegt. Sind ja beides 16 Bit Register mit
denen dann der Timer verglichen wird. Aber warum 2 dieser
Vergleichsregister?
Michael N. schrieb:> Die Fehler:> static_field, actual_row, border undeclared>> Wo liegt mein Fehler?
Da du die Variablen innerhalb der main() deklariert hast, sind sie auch
nur innerhalb dieser gültig / bekannt.
Michael N. schrieb:> Wo liegt mein Fehler?
Das du nie gelernt hast, was Gültigkeitsbereiche sind (C-Grundlagen).
Die Sichtbarkeit bzw. Gültigkeit einer Variablen ist begrenzt! Nicht
jede Variable ist überall sichtbar.
Im wesentlichen kann man sagen, dass ein umschliessender {-} Block die
Sichtbarkeit und Gültigkeit einer Variablen begrenzt. In
if( i == 5 )
{
int j;
j = 8;
}
kommt die Variable j mit Beginn des { - Blockes zum Leben, existiert
dann in diesem Block und verschwindet beim } wieder. Genauso ist die
Sichtbarkeit geregelt: Diese Variable ist nur innerhalb dieses { }
Blocks sichtbar. Von ausserhalb dieses Blocks existiert diese Variable
nicht und sie ist auch von ausserhalb nicht sichtbar.
Und das gilt auf allen Ebenen!
In
1
voidfoo()
2
{
3
inta,b;
4
5
...
6
}
existieren die Variablen a und b nur innerhalb der Funktion und sie sind
auch nur innerhalb dieser Funktion sichtbar. Denn selbstverständlich ist
auch dieses { } ein Block von Anweisungen mit genau den gleichen
Eigenschaften wie jeder andere { } Block.
Hast du also
1
intmain(void)
2
{
3
volatileunsignedcharactual_row=0;
4
5
...
6
}
7
8
ISR(TIMER1_COMPA_vect)
9
{
10
...
11
12
...actual_row...
13
14
}
dann existiert actual_row aus Sicht der ISR-Funktion schlicht und
ergreifend nicht. Die Sichtbarkeit dieser Variablen ist durch den Block
in main() begrenzt. Ausserhalb dieser Funktion ist die Variable nicht
sichtbar.
Du musst also die Variable aus diesem Funktionsblock 'herausheben',
damit sie sowohl in main() als auch innerhalb der ISR Funktion sichtbar
ist
1
volatileunsignedcharactual_row=0;
2
3
intmain(void)
4
{
5
6
...
7
}
8
9
ISR(TIMER1_COMPA_vect)
10
{
11
...
12
13
...actual_row...
14
15
}
und nein: volatile hat damit erst mal nichts zu tun. volatile löst ein
ganz anderes Problem.
Michael N. schrieb:> Des Weiteren würde es mich noch interssieren, wo der Unterschieden> zwischen OCR1AH/L und OCR1BH/L liegt. Sind ja beides 16 Bit Register mit> denen dann der Timer verglichen wird. Aber warum 2 dieser> Vergleichsregister?
Damit man sich gegebenenfalls eben mit 2 Vergleichen an den laufenden
Timer koppeln kann.
Die Frage ist ungefähr so sinnvoll, wie die Frage:
Ich habe da eine Uhr die über eine Schalteinrichtung verfügt. Ich kann
am Rand meiner Uhr einen kleinen roten Pfeil einstellen und wenn der
kleine Zeiger der Uhr auf genau diesen Pfeil zeigt, dann schaltet diese
Uhr etwas.
Soweit so gut, aber warum gibt es diese ganze Einrichtung doppelt?
Und die Antwort darauf ist: weil es eben manchmal sinnvoll sein kann, 2
mal am Tag bei Übereinstimmung des kleinen Zeigers mit einer Markierung
etwas zu schalten.
Kein Mensch sagt, dass du das tun musst. Aber wenn du es brauchst, bist
du froh wenn du es hast.
Hm, logisch...Ich habe die Deklarationen aus der main rausgenommen.
Zum doppelten Vergleichsregister: Aber habe ich es richtig verstanden,
dass sich der Timer nach erreichung dieses wertes normal zurücksetzt?
Oder ist das nur optional.
Denn wenn ich einen Zähler bis zB 250 habe. Und bei 100 und 200 eine ISR
auslösen möchte, macht es keinen Sinn, wenn die erste ISR den Zähler
zurücksetzt. Deshalb meine Nachfrage.
Der Zähler 1 hat ein Zählregister und zwei Vergleichsregister.
Dies sind OCR1A und OCR1B (jeweils 16 Bit breit).
Ich kenne leider Deinen Prozessor nicht mit Vornamen aber oft haben die
Teile einen eigenen Interrupt und einen eigenen Ausgang, wenn es denn
gewünscht wird.
Normalerweise ist dies, mit allem Drum und Dran, im Manual beschrieben
und bebildert.
Michael N. schrieb:> Hm, logisch...Ich habe die Deklarationen aus der main rausgenommen.>> Zum doppelten Vergleichsregister: Aber habe ich es richtig verstanden,> dass sich der Timer nach erreichung dieses wertes normal zurücksetzt?
Nicht 'dieses Wertes'.
Sondern 'Stimmt der Inhalt des Zählregisters mit dem Inhalt des OCR1A
Registers überein (ein konkretes Register, nicht einfach irgendeines),
dann wird der Timer im nächsten Schritt auf 0 gesetzt'.
Ja, genau so ist der CTC Modus definiert.
Damit hast du dann noch ein OCR1B Register übrig, mit dem du bei
bestimmten Zählerständen eine weitere Aktion auslösen lassen kannst.
> Denn wenn ich einen Zähler bis zB 250 habe. Und bei 100 und 200 eine ISR> auslösen möchte, macht es keinen Sinn, wenn die erste ISR den Zähler> zurücksetzt.
Das Zurücksetzen ist zwanghaft an OCR1A gebunden. OCR1B kann das nicht.
Michael N. schrieb:> Oder ist das nur optional.
Alles ist optional. Man verwendet die zur Verfügung gestellten
Funktionen alle zusammen oder einzeln oder in Kombination oder überhaupt
nicht.
Die zur Verfügung stehenden Funktionen entnimmt man dem Datenblatt des
zugehörigen µC. Bei Nichtverstehen desselben würd ich konkrete Fragen
mit Bezug auf desselben (Datenblattes) stellen.
Karl Heinz Buchegger schrieb:> Damit hast du dann noch ein OCR1B Register übrig, mit dem du bei> bestimmten Zählerständen eine weitere Aktion auslösen lassen kannst.
Danke, jetzt habe ich den Sinn verstanden.