Forum: Mikrocontroller und Digitale Elektronik Problem mit dem überschreiben einer Variable


von Oliver K. (Firma: TGM) (oliver1990)


Angehängte Dateien:

Lesenswert?

Hi!

ich arbeite an meinem Maturaprojekt und bin jetzt vom ATMega8 auf den 
128er umgestiegen. Programmiert wird er mit einem von uns entwickeltem 
ISP-Programmer.
Jetzt habe ich seit letzter Woche folgendes Problem:
Ich hab eine Variable, in diesem Fall enablex die durch die if-Anweisung 
im Timer-Interrupt den PB5 HI oder LOW setzt. Jedoch sobald ich diese 
Variable mehr als einmal ändern will, funktioniert dies nicht. Bei dem 
Beispiel also setzt er es zuerst auf HI aber nie mehr auf LOW. In der 
Simulation funktioniert jedoch alles einwandfrei.
Anbei findet ihr das C-File, entschuldigt die vielen auskommentierten 
Zeilen, diese verwende ich momentan nach, will sie aber nicht löschen, 
da vl ja hier der Fehler liegt, was ich mir aber nicht vorstellen kann. 
Auch die Funktion zeilenscan sollte ja kein Problem darstellen, da sie 
ja nicht aufgerufen wird.
Aja beim Dateinamen hab ich mich vertippt, also nicht wundern ;-)

Im Voraus schon mal vielen Dank für eure Hilfe!

Lg Oliver

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> PORTC = PORTC | (0 << PC1);
Was wird da wohl rauskommen?
Dein Nachholbedarf liegt beim Thema Bitmanipulation in C.

Als Tipp:
Probiers mal so   PORTC = PORTC & ~(1 << PC1);

> In der Simulation funktioniert jedoch alles einwandfrei.
Das würde mir aber zu Denken geben... :-o

von Volker Z. (vza)


Lesenswert?

suche mal nach "volatile"

von Ga st (Gast)


Lesenswert?

> suche mal nach "volatile"
Wozu sollte er das tun?

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Lothar Miller schrieb:
>> PORTC = PORTC | (0 << PC1);
> Was wird da wohl rauskommen?
> Dein Nachholbedarf liegt beim Thema Bitmanipulation in C.
>
> Als Tipp:
> Probiers mal so   PORTC = PORTC & ~(1 << PC1);
>
>> In der Simulation funktioniert jedoch alles einwandfrei.
> Das würde mir aber zu Denken geben... :-o

Das kann gut sein, haben das leider nie so wirklich gelernt. Aber ein 
Oder scheint doch richtig, wenn ich nur den einen Pin ändern will?!

Also mit dem & ~ funktioniert es leider auch nicht.

Wie meinst du das mit der Simulation? Also, einen anderen 128er hab ich 
auch schon probiert, einen andern PC auch, weil evtl. ja das AVR-Studio 
was haben kann und einen anderen Programmer auch, jedoch leider einer 
der selben Bauweise. Aber letzte Woche hat alles komischer Weise noch 
funktioniert, in genau der selben Konfiguration.

lg

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Ga st schrieb:
>> suche mal nach "volatile"
> Wozu sollte er das tun?

Was soll das sein? Naja ich google mal.

von Volker Z. (vza)


Lesenswert?

Hast Recht, ist nicht nötig. Ich habe mich vertan.

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Also mit volatile funktioniert es leider auch nicht, nimmt trotzdem nur 
einmal einer Änderung der Variable vor. Sollte nicht eigentlich static 
reichen? Soll ich vl. alle Variablen anstatt mit static mit volatile 
deklarieren?

lg

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Das kann gut sein, haben das leider nie so wirklich gelernt. Aber ein
> Oder scheint doch richtig, wenn ich nur den einen Pin ändern will?!
Angenommen, dein Port hat den Zustand 0b11111111. Nun veroderst du dazu 
0b00000000. Danch hat dein Port immer noch 0b11111111. Also: Viel getan 
und nicht bewirkt.

Wenn du aber zu 0b11111111 den Wert 0b00000000 verundest, hat dein Port 
anschliessend 0b00000000.

> Das kann gut sein, haben das leider nie so wirklich gelernt.
Dann tus jetzt.
Der Ausdruck (1 << PC1) ist das selbe wie (1 << 1), es kommt also 
0b00000010 heraus.
Der Ausdruck (0 << PC1) ist das selbe wie (0 << 1), es kommt also 
0b00000000 heraus.
Und das Veroderst du zum PortC.

BTW:
Du hast den falschen Ansatz. Deine Interruptroutine ist viel zu 
umständlich und lang... :-o

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Lothar Miller schrieb:
>> Das kann gut sein, haben das leider nie so wirklich gelernt. Aber ein
>> Oder scheint doch richtig, wenn ich nur den einen Pin ändern will?!
> Angenommen, dein Port hat den Zustand 0b11111111. Nun veroderst du dazu
> 0b00000000. Danch hat dein Port immer noch 0b11111111. Also: Viel getan
> und nicht bewirkt.
>
> Wenn du aber zu 0b11111111 den Wert 0b00000000 verundest, hat dein Port
> anschliessend 0b00000000.
>
>> Das kann gut sein, haben das leider nie so wirklich gelernt.
> Dann tus jetzt.
> Der Ausdruck (1 << PC1) ist das selbe wie (1 << 1), es kommt also
> 0b00000010 heraus.
> Der Ausdruck (0 << PC1) ist das selbe wie (0 << 1), es kommt also
> 0b00000000 heraus.
> Und das Veroderst du zum PortC.

PortB, aber is ja eh gleich. Und dann wird auch nur der eine Pin 
geändert? Ich bild mir immer ein, dass dann der Rest auch verändert 
wird. Ich will jedoch ja nur das eine Bit ändern.

> BTW:
> Du hast den falschen Ansatz. Deine Interruptroutine ist viel zu
> umständlich und lang... :-o

Das ist, damit der Takt zuerst schneller und dann wieder langsamer wird. 
Was ist da so umständlich, bzw. was könnte ich noch optimieren?


Aja vielen Dank einmal für eure schnellen Bemühungen.

lg

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Oliver Kra schrieb:
> Und dann wird auch nur der eine Pin geändert?
Siehe Bitmanipulation

> Was ist da so umständlich, bzw. was könnte ich noch optimieren?
Die Hauptarbeit bei einem uC-Programm wird in der Main-Schleife 
erledigt.
Interruptroutinen sind kurz. Sie verwenden nur vorberechnete Werte oder 
stellen Rohwerte bereit.

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Lothar Miller schrieb:
>> Was ist da so umständlich, bzw. was könnte ich noch optimieren?
> Die Hauptarbeit bei einem uC-Programm wird in der Main-Schleife
> erledigt.
> Interruptroutinen sind kurz. Sie verwenden nur vorberechnete Werte oder
> stellen Rohwerte bereit.

Also soll ich die ganzen if-Anweisungen in die while(1) hauen? Das mit 
dem Verändern der Variable DURCHLAUFE muss ich ja so lassen, sonst 
überprüft er mir das ja nicht immer, oder? und er wird dann nicht immer 
schneller und langsamer?

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Lothar Miller schrieb:
> Oliver Kra schrieb:
>> Und dann wird auch nur der eine Pin geändert?
> Siehe Bitmanipulation

laut Bitmanipulation stimmt es doch wenn ich "PORTB = PORTB | (1 << 
PB5);" schreibe, denn genau dann wird nur PB5 verändert und 
gegebenenfalls auf 1 gesetzt und wenn anstatt des 1 eine 0 drinn steht, 
dann umgekehrt. Oder denk ich hier vollkommen falsch?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Oder denk ich hier vollkommen falsch?
Nein. Soweit passt das zum Setzen eines Bits.

Nur das Rücksetzen muß über eine VerUNDung gehen...

von Karl H. (kbuchegg)


Lesenswert?

Oliver Kra schrieb:

> laut Bitmanipulation stimmt es doch wenn ich "PORTB = PORTB | (1 <<
> PB5);" schreibe, denn genau dann wird nur PB5 verändert und
> gegebenenfalls auf 1 gesetzt und wenn anstatt des 1 eine 0 drinn steht,
> dann umgekehrt.

Nix umgekehrt

mit
  PORTB = PORTB | ( 1 << PB5 );

wird das Bit PB5 auf 1 gesetzt. Punkt

mit

  PORTB = PORTB & ~( 1 << PB5 );

wird das Bit PB5 auf 0 gesetzt. Punkt.

Da gibts nichts 'umgekehrt'. Die Operation um ein Bit gezielt auf 1 zu 
bekommen ist eine andere als die, mit der ein Bit gezielt auf 0 gesetzt 
wird.

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Aja, ok, hab schon wieder mal nicht weitergelesen.
Danke, werd gleich mal probieren ob es jetzt funkt.

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Juhu, vielen Dank, das war der Fehler. Da sieht man, dass mir leider 
vieles vom Grundwissen fehlt.
Muss es mal genauer Durchtesten ob jetzt alles funktioniert.

Aja, soll ich jetzt die if-Anweisungen in die main unter die while(1) 
hauen?

lg

von Karl H. (kbuchegg)


Lesenswert?

Oliver Kra schrieb:
> Juhu, vielen Dank, das war der Fehler. Da sieht man, dass mir leider
> vieles vom Grundwissen fehlt.

Kann mir die Frage nicht verkneifen:
Warum nimmst du dir dann sowas zum Maturaprojekt?

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Karl heinz Buchegger schrieb:
> Oliver Kra schrieb:
>> Juhu, vielen Dank, das war der Fehler. Da sieht man, dass mir leider
>> vieles vom Grundwissen fehlt.
>
> Kann mir die Frage nicht verkneifen:
> Warum nimmst du dir dann sowas zum Maturaprojekt?

Wir sind ja eh eine ganze Gruppe, jedoch muss einer den 
AVR-Programmieren und, traurig aber war, kann ich es am Besten. Da haben 
wir leider ein sehr Großes Defizit.

Aja die if anweisungen muss ich doch im Timer lassen, ansonsten, ruft er 
mir sie nie regelmäßig auf. Kennt ihr vl eine Lösung die effektiver ist?

lg

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

>  Kennt ihr vl eine Lösung die effektiver ist?
Setz im Timer ein Flag, und werte das in der Hauptschleife aus.

Ich würde die Daten für die Rampe in einer Tabelle vorbereiten, und in 
der ISR nur noch den Tabellenindex manipulieren.

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Lothar Miller schrieb:
>>  Kennt ihr vl eine Lösung die effektiver ist?
> Setz im Timer ein Flag, und werte das in der Hauptschleife aus.
>
> Ich würde die Daten für die Rampe in einer Tabelle vorbereiten, und in
> der ISR nur noch den Tabellenindex manipulieren.

ok, werd das mal am We probieren.
Das mit der Tabelle verstehe ich gerade nicht so wirklich. Kannst mir 
das näher erläutern?

von Karl H. (kbuchegg)


Lesenswert?

Lothar Miller schrieb:
>>  Kennt ihr vl eine Lösung die effektiver ist?
> Setz im Timer ein Flag, und werte das in der Hauptschleife aus.

Hab ich mir auch schon gedacht.
Aber dann wird die Sache mit dem Zeilenscan so nicht mehr gehen.
Aber egal wie man es dreht und wendet: Der ganze Ansatz ist verkorkst

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Karl heinz Buchegger schrieb:
> Aber egal wie man es dreht und wendet: Der ganze Ansatz ist verkorkst

Wie meinst verkorkst? Ein Schaß, oder wie?
Ich hoffe gar so schlimm ist es nicht, oder?
Für jeden produktiven Vorschlag bin ich dankbar und werde ihn Versuchen 
umzusetzen und zu probieren.

von Juergen (Gast)


Lesenswert?

> Aja, soll ich jetzt die if-Anweisungen in die main unter die while(1)
hauen?

"Hauen" ist ganz schlecht, man sollte immer wissen, was man tut.

Für den Anfang ist deine Interrupt-Routine garnichtmal so schlecht, 
immerhin hast du keine Schleifen oder Wartezeiten drin (hatten wir hier 
auch schon).

Noch besser wäre es, vorberechnete Werte für den Timer (und evtl. die 
Bits in PORTB und PORTC) zu speichern, die dann der Interrupt nur noch 
in die entsprechenden Register schreibt. Das muss natürlich mit dem 
Interrupt synchronisiert werden, dazu setzt der Interrupt ein Flag, wenn 
er fertig ist (hier z.B. eine Variable int flag auf 1). In der 
while-Schleife wartest du, bis das Flag gesetzt ist, setzt es zurück und 
dann berechnest die Werte für den nächsten Interrupt. Wenn jetzt noch 
das Timing stimmt, d.h. der Interrupt dem Hauptprogramm genügend 
Rechenzeit übriglässt, dann funktioniert das wunderbar.

Alle Variablen, die von Interrupt und Hauptprogramm benutzt werden, 
müssen volatile deklariert werden!

von Oliver K. (Firma: TGM) (oliver1990)


Lesenswert?

Juergen schrieb:
> evtl. die
> Bits in PORTB und PORTC

aber sobald ich die Bits in die jeweiligen PORTS schreibe übernimmt er 
diese ja auch. Das wäre ja dann zu früh, oder?
Wenn ich im TimerInterrupt mittels Flag auf die while-schleife verweise 
ist doch der zeilenscan schon vorbei, und die if-Anweisungen werden ja 
dafür benötig. Oder sucht sich der flag immer den Teil raus, wo er 
hinsoll und überspringt dabei alles andere?
Was würdet ihr davon halten, wenn ich für das ganzen einfach eine neue 
Funktion schreibe und diese im Timer aufrufe?

lg

von Karl H. (kbuchegg)


Lesenswert?

Oliver Kra schrieb:

> Was würdet ihr davon halten, wenn ich für das ganzen einfach eine neue
> Funktion schreibe und diese im Timer aufrufe?

Gar nichts.
Wenn du ein Loch gräbst, geht das auch nicht schneller wenn du einen 
Sichtschutz rundum stellst.
Bei 'kurze ISR' geht es nicht um die Anzahl der Codezeilen sondern um 
die Ausführungszeit. Und die hängt wiederrum von dem auszuführenden Code 
ab.

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
Noch kein Account? Hier anmelden.