Hallo,
ich bin kurz vor dem Verzweifeln. Atmega 8 funktioniert auf meiner
Schaltung und Timer2 wird verwendet um eine PWM-Modulation zu
simulieren, die durch einen RC-Tiefpass geglättet wird (benötige
einstellbare Gleichspannung). Die Variable SignalOVFL wird in der ISR
einfach auf 1 gesetzt.
Mein Problem besteht darin, dass ich in der while(1) Schleife nicht in
die 2. If-Abfrage hinein komme. Ändere ich die Variable "status" auf 1
(so wie im Code unten), komme ich in die obere If-Abfrage nicht hinein.
Kann mir einer sagen warum? Selbst im Debugger funktioniert es, nur
nicht auf meiner Schaltung...
Danke schonmal für eure Tipps.
1
/* Globale Variablen */
2
//Timer2
3
volatileuint8_tSignalOVFL=0;
4
volatileuint8_tstatus=1;
5
6
/* MAIN */
7
voidmain(void)
8
{
9
timer_kontrast();// Timer 2 initalisieren und starten
10
11
while(1)
12
{
13
if(SignalOVFL==1&&status==0)
14
{
15
//PORTB ^= (1<<PB2); // Pin einschalten
16
SignalOVFL=0;// Interrupt Rücksetzen
17
status=1;// Für nächsten Durchgang status = setzen
18
}
19
if(SignalOVFL==1&&status!=0)
20
{
21
PORTB^=(1<<PB2);// Pin ausschalten
22
SignalOVFL=0;// Interrupt Rücksetzen
23
status=0;// Für nächsten Durchgang status = löschen
Der Code fehlt wo SignalOVFL und status manipuliert werden. Deshalb kann
Dir so keiner sagen wo das Problem ist.
Mit dem Codesausschnitt dürfte er in gar keinen if-Block reinkommen.
Toni schrieb:> if(SignalOVFL == 1 && status == 0)
Bin mir nicht sicher wie die Reichenfolge der Operatoren ausgewertet
wird. Versuch mal:
if((SignalOVFL == 1) && (status == 0))
Toni pampig ?
wenn man den Code im ersten Post durchdenkt, sieht man, dass beide
If-Zweige immer Falsch (FALSE) sind. Deshalb sein Nachfragen.
Wenn Du Hilfe suchst musst Du IMMER ALLES hier veröffentlichen,
sonst erhälst Du eine "42" als Fehlergrund.
Raten ist nun mal schwierig.
STK500-Besitzer schrieb:> sieht besser aus.>> {> if(SignalOVFL == 1)> {> if (status == 0)> {> //PORTB ^= (1<<PB2); // Pin einschalten> SignalOVFL = 0; // Interrupt Rücksetzen> status = 1; // Für nächsten Durchgang status = setzen> }> else> {> PORTB ^= (1<<PB2); // Pin ausschalten> SignalOVFL = 0; // Interrupt Rücksetzen> status = 0; // Für nächsten Durchgang status = löschen> //TCNT2 = 0; // Timerregister vorladen> }> }>>> dürfte schneller sein (und funktionieren)...
naja, wenn man schon optimiert dann aber richitg. Es gibt noch gleihen
code in if und else.
Aber die alte version war auch nicht falsch.
Nein, nicht Toni pampig. Hab extra geschrieben, dass die Variable in der
ISR auf 1 gesetzt wird. Wollte euch eben etwas Denk-arbeit abnehmen.
Sorry.
Tipps von Klammeraffe und STK-500 Besitzer getestet, ohne Erfolg. In
eine If-Schleife kommt er nicht rein, egal wie ich es biege und
beklammere. PWM-Signal liegt auf dem Pin-Ausgang an, allerdings nur,
wenn man die richtige Schleife ausklammert... Ich verstehe es nicht.
Toni schrieb:> Mein Problem besteht darin, dass ich in der while(1) Schleife nicht in> die 2. If-Abfrage hinein komme. Ändere ich die Variable "status" auf 1> (so wie im Code unten), komme ich in die obere If-Abfrage nicht hinein.> Kann mir einer sagen warum?
Da ist irgendwas faul, was du nicht gezeigt hast.
Aber:
So wie ich das sehe, ist die Absicht hinter dem Code, den Pin bei jedem
Timer-Overflow umzuschalten. Oder bei jedem 2.ten Timer-Overflow? Doch,
ich denke du willst jeden 2.ten Timer Overfow.
Da frag ich mich, warum du das so komplizert mit 3 Millionen
zusätzlichen Variablen machst.
1
ISR(....)
2
{
3
staticintisrCount=0;
4
5
isrCount++;
6
if(isrCount==2){
7
PORTB^=(1<<PB2);
8
isrCount=0;
9
}
10
}
und gut ists. Die ganze komplizierte Steuerung über OverflowFlags und
signal Flag braucht doch (zumindest in dem Teil den du gezeigt hast) in
Wirklichkeit keiner (auch wenn ich im gezeigten Abschnitt nichts sehen
kann, was deine Beobachtung erklären würde - vergreifst du dich an
anderer Stelle im Code ebenfalls am PORTB? Da könnte zb auch ein Fehler
stecken)
Danke Karl Heinz,
du liegst nicht ganz Falsch. Ich benötige im Grunde eine PWM-Modulation
und möchte dementsprechend in einer der beiden Schleifen das
Zählregister mit einem Wert vorladen, sodass Einschalt - und
Ausschaltdauer unterschiedlich sind. Die entsprechenden Pins für die
PWM-modi stehen nicht zur Verfügung, deswegen möchte ich das ganze ein
Stück weit per Software abarbeiten.
Toni schrieb:> In> eine If-Schleife
es gibt keine if-Schleife.
Eine Schleife ist dem Wesen nach ein Code-Element, in dem anderer Code
wiederholt ausgeführt wird. Drum heißt es Schleife.
Macht ein if dieses?
Nein.
Also ist ein if keine Schleife.
> kommt er nicht rein, egal wie ich es biege und> beklammere. PWM-Signal liegt auf dem Pin-Ausgang an, allerdings nur,> wenn man die richtige Schleife ausklammert...
D.h. du machst das daran fest, dass du nichts am Ausgang siehst?
Ok. HJast du den Pin auch auf Ausgang gestellt?
Vergreifst du dich sonst irgendwo am PORTB?
> Ich verstehe es nicht.
Wenn du endlich deinen kompletten verdammten Code zeigen würdest, dann
hätte man das Problem in 3 Minuten gelöst. Aber du weigerst dich ja.
Toni schrieb:> du liegst nicht ganz Falsch. Ich benötige im Grunde eine PWM-Modulation> und möchte dementsprechend in einer der beiden Schleifen das> Zählregister mit einem Wert vorladen, sodass Einschalt - und> Ausschaltdauer unterschiedlich sind.
Und?
Das kann man nicht in der ISR erledigen, oder wie?
So, nachmal etwas ausprobiert, dass gleiche in Grün...
Nochmal; Das ist der komplette Code, mehr gibt es nicht.
Kann es sein, dass die Variable Status durch die Optimierung
wegoptimiert wird?! Das sollte doch eigentlich volatile verhindern,
oder?
Die auskommentierten Code-Schnipsel sind Verzweiflungsmaßnahmen, also
bitte nicht beachten.
1
// Definitionen
2
#define F_CPU 2000000
3
4
// INCLUDE
5
#include<avr/io.h>
6
#include<avr/interrupt.h>
7
#include<util/delay.h>
8
#include<stdint.h>
9
10
/* Globale Variablen */
11
//Timer2
12
volatileuint8_tstatus=0;
13
14
/* MAIN */
15
voidmain(void)
16
{
17
timer_kontrast();
18
19
while(1);
20
}
21
22
voidtimer_kontrast()//Ausgabe der Frequenz auf PB2 // Timer 2 wird verwendet
Toni schrieb:> Das ist der komplette Code, mehr gibt es nicht.
Na das ist doch mal ein Wort.
> TIMSK |= (1<<OCIE2) | (1<<TOIE2);
Du gibst einen Interrupt frei, für den du keinen ISR-Handler hast
-> µC wird resettet
Sonst noch was, womit du nicht weiter kommst?
Vielleicht verstehst du jetzt, warum wir lieber den kompletten Code
sehen anstelle von immer nur ein paar Ausschnitten.
1 Stunde Diskussion, damit du endlich den kompletten Code zeigst und
dann kann das Problem in ein paar Minuten in dem Codeteil gefunden
werden, den du eben nicht gezeigt hast.
Karl Heinz Buchegger schrieb:> Wenn du endlich deinen kompletten verdammten Code zeigen würdest, dann> hätte man das Problem in 3 Minuten gelöst. Aber du weigerst dich ja.Karl Heinz Buchegger schrieb:> Du gibst einen Interrupt frei, für den du keinen ISR-Handler hast> -> µC wird resettet
Das hat mal Stil. Gesagt und getan. Und in der Tat in exakt 3 Minuten.
:-)
Ich bin beeindruckt.
Grüsse,
René
> Darf man fragen woran du erkennst das die Bedingung nicht erfüllt wird?
Anhand eines an dem Pin angeschlossenem Oszis, dass mir ein PWM-Signal
anzeigt, sobald sich der µC in der entsprechenden Verzweigung befindet.
Ansonsten liegen konstante 0V an dem Ausgang an. Zusätlich liefert mir
ein Multimeter 2,5V bzw. 0V. Deshalb klammere ich den toggelnden Pin
entsprechend der Verzweigung aus. Aus diesem Grund nehme ich an, dass
Timer, ISR und co funktioniert, allerdings ein Problem mit der
Verzweigung besteht.
Toni schrieb:> if(status == 0)> {> PORTB ^= (1<<PB2);> status = 1;> }> if(status == 1)> {> //PORTB ^= (1<<PB2);> status = 0;> }
Das geht so nicht. Dein Status hat so immer 0.
Wenn, dann musst Du:
Peter II schrieb:> naja, wenn man schon optimiert dann aber richitg. Es gibt noch gleihen> code in if und else.
Weniger Abfragen. Die Zuweisungen habe ich mir nicht näher angesehen.
Rene schrieb:> if(status == 0)> {> PORTB ^= (1<<PB2);> status = 1;> }> if(status == 1)> {> //PORTB ^= (1<<PB2);> status = 0;> }
Wo ist da der Unterschied zum vorherigen Code?
Schon mal was von "else" gehört (nein, ich meine nicht "Else" aus
DOS-Zeiten ;)
Ja, das wollte ich in meinem Post korrigieren, was in einem Desaster
geendet hat (copy & paste will beherrscht werden). Karl Heinz ist schon
informiert. Sorry deswegen.
Also:
1
if(status==0)
2
{
3
PORTB^=(1<<PB2);
4
status=1;
5
}
6
elseif(status==1)
7
{
8
//PORTB ^= (1<<PB2);
9
status=0;
10
}
Grüsse,
R.
Beim ersten if Block setzt Du status = 1. Danach wird aber sofort Dein
zweiter if Block ausgeführt und der Status auf 0 zurück gesetzt. Du
musst also ein else dazwischen hängen.
Rene H. schrieb:> a, das wollte ich in meinem Post korrigieren, was in einem Desaster> geendet hat (copy & paste will beherrscht werden). Karl Heinz ist schon> informiert. Sorry deswegen.>> Also:> if(status == 0)> {> PORTB ^= (1<<PB2);> status = 1;> }> else if(status == 1)> {> //PORTB ^= (1<<PB2);> status = 0;> }>> Grüsse,> R.
na das ist nun auch nicht das gelbe vom ei.
Super Leute, vielen Dank. Endlich funktioniert der Code.
Im Bild ist das Ergebnis zu sehen.
Warum es im ersten Fall nicht funktioniert hat, ist mir immernoch
schleierhaft. Ich werde morgen nochmal ein bisschen herumprobieren.
Und hier noch die Änderungen:
Hi,
vollständigkeitshalber und für die Nachwelt hier noch der entsprechende
Code mit schlanker ISR.
Hier schon etwas weiter mit zweitem Timer0.
Kann man die ISR ohne das sichern des SREG-Registers so stehen lassen?
Toni schrieb:> Kann man die ISR ohne das sichern des SREG-Registers so stehen lassen?
Ja, weil wir hie rnicht bei Assembler sind. DArum kümmert sich der
Compiler.
Was soll das eigentlich werden?