Forum: Mikrocontroller und Digitale Elektronik Blinker in C @Atmega88


von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Kann mir jemand sagen warum das angehängte Programm nicht funktioniert?

Versuche einen Blinker in C mit dem Timer 0 beim Atmega88 zu erzeugen.
Ohne die Schleife funktioniert der Blinker, nur halt viel zu
schnell.....

von inoffizieller WM-Rahul (Gast)


Lesenswert?

setz mal ein "volatile" vor das unsigned char i.

von Karl heinz B. (kbucheg)


Lesenswert?

> Ohne die Schleife

Welche Schleife?

> nur halt viel zu schnell

Wie schnell soll er denn?

von Karl heinz B. (kbucheg)


Lesenswert?

OK. Sparen wir uns eine Runde hin und her.

Gib uns auch deine Berechnungsdaten: Welche
Taktfrequenz fährst du? Welche Blinkfrequenz
sollte das ergeben? Welche Blinkfrequenz schätzt
du hat der Mega?

von Michael Wilhelm (Gast)


Lesenswert?

Geht das denn mit einem xor?. Beim ersten Durchlauf ist der Port 0, wird
mit 1 exklusiv verodert. Dann passiert was. Im 2. Durchlauf sind aber
beide 1. Da dürfte doch nichts mehr passieren. Oder hab ich ein
Verständnisproblem? Bitte um Aufklärung.

MW

von Karl heinz B. (kbucheg)


Lesenswert?

A    B     A XOR B
 --------------------
  0    0        0
  1    0        1
  0    1        1
  1    1        0

von johnny.m (Gast)


Lesenswert?

Wahrheitstabelle von XOR:

  A    B    Y
  0    0    0
  0    1    1
  1    0    1
  1    1    0

Wenn A Dein Bit ist und Du es mit 1 verXORst, wird es gesetzt (1), wenn
es vorher 0 war und 0 wenn es vorher 1 war. XOR liefert immer dann eine
1, wenn die "Eingänge" nicht gleich sind. Wenn also schon ne 1 drin
steht und Du mit einer 1 verXORst, dann kommt ne 0 raus, weil beide
gleich waren.

von Michael Wilhelm (Gast)


Lesenswert?

Danke.

MW

von Stefan (Gast)


Lesenswert?

Hi,

meinte natürlich die if-Anweisung. ohne die Blinkts. Nur so schnell
dass man es gerade noch erkennen kann.

Der Controller wird mit einem 14,745600MHz Quarz getaktet. Hätte gerne
dass ca. alle 500ms der die LED an und 500ms später wieder aus geht.

> Welche Blinkfrequenz schätzt du hat der Mega?

Wie soll ich das schätzen...??

von johnny.m (Gast)


Lesenswert?

@Stefan:
Hast Du es denn wenigstens mit dem 'volatile' ausprobiert, wie der
inoffizielle vorgeschlagen hat? Dann müsste es jetzt nämlich eigentlich
funktionieren, wenn Du keinen Bug in der Hardware-Konfiguration hast
(wovon ich mal ausgehe, denn ohne das if dunktioniert es ja...).

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Ich bin der Meinung, i müsste nur bis 28(,125) für 500ms zählen, wenn es
sich um einen 8Bit-Zähler handelt.
150 müsste IMHO zu einer Pulsdauer von 2,667s führen; also einer
Periodendauer von 5,3s.
Kann aber auch sein, dass ich mal wieder Bockmist gerechnet habe...

von Karl heinz B. (kbucheg)


Lesenswert?

> Der Controller wird mit einem 14,745600MHz Quarz getaktet. Hätte
gerne
> dass ca. alle 500ms der die LED an und 500ms später wieder aus geht.

>
>> Welche Blinkfrequenz schätzt du hat der Mega?
>
>> Wie soll ich das schätzen...??
>
>> Ohne if - Nur so schnell dass man es gerade noch erkennen kann.

Na ja, das ist doch schon mal was.
Rechnen wir doch mal nach:

14 Mhz, bei einem Teiler von 1024 macht ca. 13,5 kHz am Timer.
Dividiert durch 256 macht 53 Hertz. Du toggelst den Pin mit dieser
Frequenz, also nochmal durch 2. Macht ~27 Hz. 27 Hz, das sind
3 Hunderstel Sekunden ein, 3,6 Hunderstel Sekunden aus.
Das kommt doch schon ganz gut hin zur Beschreibung:
"Nur so schnell dass man es gerade noch erkennen kann."
Das sagt mir, dass dein µC auch tatsächlich auf 14 Mhz zu
schwingen scheint.

So jetzt toggelst du nicht bei jedem Overflow, sondern nur
noch bei jedem 150. Overflow.
3,6 Hunderstel-Sekunden * 150 = ca. 5,6 Sekunden.

Wenn du ungedulgid bist, kann man das durchaus übersehen
und nicht lange genug warten :-)


@johnny.m
Wir müssen uns mal darüber unterhalten, was volatile wirklich
macht. Ich fresse einen Besen, wenn volatile hier irgendeine
Auswirkung zur Behebung des Problems hat.

von inoffizieller WM-Rahul (Gast)


Lesenswert?

>Wir müssen uns mal darüber unterhalten, was volatile wirklich
>macht. Ich fresse einen Besen, wenn volatile hier irgendeine
>Auswirkung zur Behebung des Problems hat.

Bis jetzt war volatile in Kombiantion mit einer ISR immer eine Art
"Allheilmittel".
In meinem K&R-Buch ist dieser Befehl leider (noch) nicht zu finden.

Microsoft (MSDN) meint zu dem Thema:

"Objects declared as volatile are not used in optimizations because
their value can change at any time. The system always reads the current
value of a volatile object at the point it is requested, even if the
previous instruction asked for a value from the same object. Also, the
value of the object is written immediately on assignment.

One use of the volatile qualifier is to provide access to memory
locations used by asynchronous processes such as interrupt handlers."

Würde also auf das Problem mit der ISR passen...
Ich würde einfach mal die 150 durch was kleineres ersetzen (und
volatile ausprobieren).
Vielleicht gibt es auch Schokoladenbesen. Davon würde ich einen
fressen, wenn volatile nichts bewegt.

von Patrick (Gast)


Lesenswert?

Hallo Stefan,

das du 28Hz mit dem Auge siehst kann ich mir nicht vorstellen. Ich habe
es zwar nicht im Selbstversuch überprüft, aber wenn man 28Hz sehen
würde, wäre Fernsehen eine Qual.

Mal was ganz anderes: wie hast du denn die Fuses gesetzt? (Nicht das du
gar nicht mit dem Quarz arbeitest, sondern mit dem internen Oszilator.)

von Karl heinz B. (kbucheg)


Lesenswert?

> Würde also auf das Problem mit der ISR passen...

Nicht wirklich.
volatile sagt dem Compiler, dass er sich mit Optimierungen
auf einer Variable raushalten soll, da es Wege gibt, die
für den Compiler ersichtlich sind, wie eine Variable ihren
Wert ändern kann und daher Optimierungen kontraproduktiv
sind.

Konkret:
Interessant ist das nur in 2 Fällen
* wenn es Hardware gibt, die memory mapped betrieben wird.
  zb. eine Uhr, die ihre Ergebnisse im Speicher hinterlässt.
* Multithreading

Nun kann man Interrupt Programmierung als eine Form von
Multithreading auffassen. Der Compiler kann nicht vorhersagen
wann bzw. ob überhaupt, die ISR Funktion jemals aufgerufen wird.
Wenn du jetzt in main() folgendes hast:

  int main()
  {
    i = 0;
    while( i != 0 )
      ;

und i nicht volatile deklariert ist, dann wird der Optimierer
auf die Idee kommen, die Schleife vollständig rauszuschmeissen.
Denn innerhalb der Schleife hat i keine Chance jemals etwas anderes
als 0 zu werden. Dass i durch die ISR verändert wird, weiss der
Compiler nicht während er main() kompiliert. Selbst wenn du
hast:

    int main()
    {
      while( i != 5 )
        ;
    }

wird der Optimierer wahrscheinlich Mist erzeugen. Der Optimierer
wird i in einem CPU-Register halten und dieses Register wiederrum
hat keine Chance jemals einen anderen Wert zu kriegen als den
den es bekam als das erste mal der Wert von i in dieses Register
geladen wurde.

Erst volatile behebt dieses Problem: Es teilt dem Compiler mit,
dass i ausserhalb seiner Kontrolle seinen Wert verändern kann.
Wenn als ein Zugriff auf i erfolgt, so muss der erzeugte Code
tatsächlich den Wert aus dem Speicher holen und darf keinen
in einem Register zwischengespeicherten Wert benutzen.

All das ist hier nicht der Fall:
i wird nur in der ISR verwendet und der Optimierer darf Zugriffe
auf i nach Herzenslust optimieren ohne dass sich irgendetwas
verändern würde. Spätestens beim Verlassen der Funktion muss
der aktuelle Wert von i sowieso aus einem möglichen temporären
Register in die tatsächliche Variable zurückgeschrieben werden.
Das folgt schon aus der Tatsache, dass die ISR-Funktion ja die
CPU in demselben Zustand zurücklassen muss in dem sie sie
vorgefunden hat.

Zusammengefasst:
volatile ist nur dann interessant wenn mehrere Komponenten
asynchron (d.h. ohne dass ein expliziter Funktionsaufruf)
über globale Variablen zusammenarbeiten müssen. zb: in
einer ISR wird eine Variable verändert und ein anderer
Programmteil benutzt dieselbe Variable.

von Karl heinz B. (kbucheg)


Lesenswert?

> das du 28Hz mit dem Auge siehst kann ich mir nicht vorstellen. Ich >
habe
> es zwar nicht im Selbstversuch überprüft, aber wenn man 28Hz sehen
> würde, wäre Fernsehen eine Qual.

Du vergisst, dass am Fernseher die Leuchtschicht nachleuchtet.
Eine LED tut das nicht.

von Karl heinz B. (kbucheg)


Lesenswert?

> Nicht das du
> gar nicht mit dem Quarz arbeitest, sondern mit dem internen
> Oszilator.)

Das hatte ich zuerst auch gedacht. Wenn man das aber durchrechnet
ergibt sich eine Blinkfrequenz die so niedrig ist, dass sie nicht
mehr durch 'Blinken an der Wahrnehmungsgrenze' beschrieben wird.
So blind kann man gar nicht sein :-)

von johnny.m (Gast)


Lesenswert?

@Karl Heinz:
Hast natürlich recht (wie immer;-). Er fragt die Variable ja nur in der
ISR ab...

von Patrick (Gast)


Lesenswert?

Nö Karl Heinz,
hatte ich nicht vergessen.

Das Auge nimmt aber ziemlich genau 18 Bilder pro Sekunde auf. 28Hz
liegt also klar ausserhalb des Bereiche den das Auge wahrnimmt.

>Wenn man das aber durchrechnet ergibt sich eine Blinkfrequenz die
>so niedrig ist, dass sie nicht mehr durch 'Blinken an der
>Wahrnehmungsgrenze' beschrieben wird.
Echt? Wenn ich den internen Oszilators des ATmega88 mit 8MHz nehme,
komme ich auf eine Blinkfrequenz von ~15Hz (das Auge 'sieht' bis
18Hz). Für mich liegt das verteufelt dicht an der Wahrnehmungsgrenze'

von Karl heinz B. (kbucheg)


Lesenswert?

> Das Auge nimmt aber ziemlich genau 18 Bilder pro Sekunde auf. 28Hz
> liegt also klar ausserhalb des Bereiche den das Auge wahrnimmt.

Alles richtig.

Du wirst nicht jedes einzelne Blinken sehen können. Aber
das da was 'blinkt' kriegst du schon mit. Es gibt hier
Leute im Forum, die behaupten, dass sie eine PWM mit
100 Hz noch blinken sehen, wenn sie richtig hinsehen ...
aus den Augenwinkeln heraus. Blinken ist vielleicht zuviel
gesagt, aber dass die LED nicht ruhig vor sich hin leuchtet
kriegt man mit.

> Echt?
Na ja. Ich hab mit 1 Mhz gerechnet. Da kommt in etwa 1,5 Hz raus.
Und das wäre kaum zu übersehen.

von johnny.m (Gast)


Lesenswert?

@Patrick:
Dann mach doch bitte mal den Selbstversuch! Ich weiß z.B. aus
Erfahrung, dass selbst 50 Hz noch als Flimmern sichtbar ist (OK, da
kann man jetzt wieder streiten, wo blinken aufhört und wo flimmern
anfängt, aber ein gesunder Mensch nimmt das noch ziemlich gut wahr...)!

von Patrick (Gast)


Lesenswert?

Hi johnny.m,

Was du eigentlich wahnimmst ist, dass ein Leuchtkörper mit bekannten
Eigenschaften sich anders verhält als in Ruhe, oder wie du es
ausdrückst 'flimmert'. Aber hast schon selbst angedeutet, dass die
Diskussion wo Blinken aufhört ziemlich eher brotlos ist. Aus dem Grund
möchte ich sie auch nicht weiter vertiefen.
Vielleicht ist ja die Richtung die ich eingeschlagen hab völliger
Unsinn. Verwerfen möchte ich sie allerdings erst, wenn Stefan seinen
Beitrag dazu gegeben hat.

von Karl heinz B. (kbucheg)


Lesenswert?

> Vielleicht ist ja die Richtung die ich eingeschlagen hab völliger
> Unsinn.

Du meinst: die Fuses checken.

Das ist überhaupt kein Unsinn. Wenn ich eines im Forum gelernt
habe, dann: möglich ist alles. Und solange nicht alle simplen
Möglichkeiten abgeklärt sind hat es meist wenig Sinn sich auf
die komplizierten Dinge zu stürzen. Zu oft sind es die einfachen
Dinge - besonders wenn es um Timing geht: Interner Oszi statt
Quarz (ist besonders bei BASCOM Leuten beliebt).

von Stefan (Gast)


Lesenswert?

Hallo,

also die Fuses hab ich noch mal überprüft! Diese sind auf externen
Quarz eingestellt.

Die Deklaration von i mit volatile hat auch nichts gebracht.

Komisch ist jetzt nur, dass ich das Programm zum Spaß mal auf nem
Atmega8515 laufen ließ. Funktionierte bestens!

Irgendwie Merkwürdig, oder...???

von inoffizieller WM-Rahul (Gast)


Lesenswert?

Entweder heissen dann irgendwelche Register (-Bits) anders, was aber zu
einem Compiler-Fehler führen müsste, oder im Makefile ist der falsche
Controller angegeben.

von Stefan (Gast)


Lesenswert?

Das Makefile wars, dort war noch der Atmega88 eingetragen.....!!!

Vielen Dank!

von inoffizieller WM-Rahul (Gast)


Lesenswert?

>Das Makefile wars, dort war noch der Atmega88 eingetragen.....!!!
Und dann lief das Programm auf dem 8515?

von Stefan (Gast)


Lesenswert?

>Das Makefile wars, dort war noch der Atmega88 eingetragen.....!!!

Nicht ganz, der Atmega48 wars......

von Stefan (Gast)


Lesenswert?

Für den 8515 hatte ich ein komplett neues Projekt angelegt und dort dann
sofort den richtigen Controller gesetzt....

von Profi (Gast)


Lesenswert?

Schnelles Blinken von LEDs kann man leicht prüfen, indem man sie durch
die Flügel eines Lüfters betrachtet und dessen Drehzahl ändert (mit dem
Finger oder mit der Spannung) -> Interferenz.

Oder indem man die LED vor dem Auge bewegt.

Oder mit einem dieser LED-Spannungsprüfer, die einen Frequenzteiler mit
LED an jeder Teilerstufen eingebaut haben.

Oder indem man sich ein (billiges) Oszi zulegt.

Hest Du noch einen anderen µC, mit dem Du es probieren könntest?

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.