Forum: Mikrocontroller und Digitale Elektronik LED blinken lassen - Falscher Rhytmus


von blabla (Gast)


Lesenswert?

Freude herrscht, ich habe gerade mein erstes LED blinken lassen. Nur 
leider überhaupt nicht im Takt den ich wollte. Eigtnlich wollte ich 
immer eine Sekunde Licht und eine Sekunde dunkel.

Kann mir jemand sagen wieso das LED viel schneller wechselt?
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <stdint.h>
4
5
void sleep_ms(uint16_t ms);
6
7
#define LED_DDR    DDRB
8
#define LED_PORT  PORTB
9
#define LED_PORTPIN  PB0
10
11
int main(void){
12
  LED_DDR |= (1<<LED_PORTPIN);
13
  
14
  while(1){
15
    LED_PORT |= (1<<LED_PORTPIN);
16
    sleep_ms(1000);
17
    LED_PORT &= ~(1<<LED_PORTPIN);
18
    sleep_ms(1000);
19
  }
20
}
21
22
void sleep_ms(uint16_t ms){
23
  while(ms){
24
    ms--;
25
    _delay_ms(1);
26
  }
27
}

Ausgeführt wird das ganze auf dem STK500 mit einem Atmeag8515.

MFG

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Statt dieser seltsamen while-Schleife verwendest mal besser for ;)
Die Makros funktionieren natuerlich nur richtig, wenn erstens F_CPU 
korrekt gesetzt ist und Deine Taktquelle entsprechend genau ist.

Was heisst "viel schneller"? Und wie ist F_CPU definiert?

von blabla (Gast)


Lesenswert?

Hallo,


Ich würde mal sagen das ganze läuft etwa 4 mal so schnell....
Wie mein F_CPU ist kann ich dir nict sagen. Ich arbeite mit dem AVR 
Studio und musste das nie angeben. Wo finde ich das?

MFG

von Vlad T. (vlad_tepesch)


Lesenswert?

wozu eigendlich die funktion mit der schleife um den _delay_ms(1) und 
nicht direkt _delay_ms(ms) - hab ich schon öfter gesehen?

Abgesehen davon dass es bei eine sekunde besser wär, den µc in einen 
energiesparmodus zu schicken und ihn per watchdog wieder aufzuwecken.

von blabla (Gast)


Lesenswert?

Vielen Dank, aber das ist so etwa mein erstes Programm. Also bitte noch 
keine Tipps wie man das ganze effizienter machen könnte...:)

von Simon K. (simon) Benutzerseite


Lesenswert?

Hast du F_CPU, also die Systemfrequenz des Controllers richtig im 
Projekt angegeben?

von blabla (Gast)


Lesenswert?

Wo finde ich diese Einstellung in AVR-Studio?

von Vlad T. (vlad_tepesch)


Lesenswert?

in den projekteinstellungen, auf der seite, wo du die ziehlplattform 
auswählst. da gibts nen feld, wo man die Taktfrequenz eintragen muss.

von and (Gast)


Lesenswert?

Hi blabla,
da du F_CPU nicht definiert hast wird eine Frequenz von 1000000 Hz 
angenommen.


#ifndef F_CPU
/* prevent compiler error by supplying a default */
# warning "F_CPU not defined for <util/delay.h>"
# define F_CPU 1000000UL
#endif

Du musst F_CPU deinen Takt anpassen.

Servus Andreas

von blabla (Gast)


Lesenswert?

Gut habe ich gefunden.. Und was muss ich dort eintragen? 16mHz?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

"16mHz" - Bloss nicht. Du müsstest fast 16s auf einen Wechsel warten!

Wenn 1 MHz (1000000 Hz) viermal zu schnell ist, würde ich als 
Schnellschuss mal 4000000 Hz (4 MHz) einstellen...

von blabla (Gast)


Lesenswert?

Vielen Dank. Es stimmt nun mehr oder weniger. Gibt es auch ein System 
wie man diese Zahl genau heraus findet und nicht nur abschätzt? Das 
Programm habe ich von: 
http://www.rn-wissen.de/index.php/LED-Blinken_ohne_Timer

Dort verwenden sie 16MHz...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

blabla schrieb:

> Vielen Dank. Es stimmt nun mehr oder weniger. Gibt es auch ein System
> wie man diese Zahl genau heraus findet und nicht nur abschätzt?

Man schaut sich seine Schaltung an und identifiziert die Taktquelle. 
Wenn es ein Quarz oder ein Oszillator ist, ist die Frequenz in MHz 
aufgedruckt. Wenn nicht kommt man mit einfachen Mitteln nicht weiter; 
man bräuchte einen Frequenzmesser oder ein Oszilloskop um die 
Taktfrequenz zu messen.

Wenn zusätzlich die AVR Fuses richtig auf diese externe Taktquelle 
eingestellt ist, ist man fertig: Die abgelesene Angabe in Hz trägt man 
als F_CPU ein.

Wenn die AVR Fuses noch in Werkseinstellung sind, dann passt 1000000 
Hz.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

blabla schrieb:

> Vielen Dank. Es stimmt nun mehr oder weniger.

Das mehr oder weniger liegt daran, dass du 1000x einen Funktionsaufruf 
und weiteren Code um die Wartefunktion (_delay_ms()) gepackt hast.

Ändere 1000x1ms Delay zum Spass mal in 1x1000ms oder 20*50ms oder 
10x100ms...

von and (Gast)


Lesenswert?

Hi blabla,
welchen Takt verwendest du denn?
Extern oder intern?

Wenn du einen externen Takt verwendest wirf ein Blick auf den 
verwendeten Quarz, bzw. Resonator. Wenn du den internen Takt verwendet 
solltest du die FUSE Bits checken. Das können wir von hier nicht 
machen:)

Wenn sie in diesen Beispiel 16MHz verwenden liegt es daran das dort ein 
16MHz Quarz verwendet wird.

Servus
Andreas

von blabla (Gast)


Lesenswert?

Also wie gesagt ich bin zeimlicher Neuling. Also das einzige das mich an 
einen Quarz erinnert ist der Clock-Generator im Register HW Settings.

Dieser Wert ist auf 3.686 MHz....

von and (Gast)


Lesenswert?

Das wird's sein. Stell mal diese Frequenz ein.
#define F_CPU 3686000

von Simon K. (simon) Benutzerseite


Lesenswert?

Hast du ein STK500?

von blabla (Gast)


Lesenswert?

Ja hab ich nun gemacht. Nun scheint es ziemlich genau zu stimmen. Vielen 
Dank euch allen...

Benutze ich nun einen externen Quarz oder einen internen? :)

von blabla (Gast)


Lesenswert?

@Simon K.:

Ja.

von and (Gast)


Lesenswert?

Du benutzt einen externe Taktquelle.

von Volker (Gast)


Lesenswert?

Welchen Takt der Controller benutzt siehst Du bei den Fuses.

Connecte zum Board, dann waehl den Reiter 'Fuses' und check SUT_CKSEL. 
Steht dort 'Ext. Clock', dann benutzt Du den Taktgeber des STK500 
(dessen Frequenz Du unter HW Settings einstellen kannst).

von Volker (Gast)


Lesenswert?

Unter SUT_CKSEL kannst Du natuerlich auch den internen Oscillator 
einstellen... Mit Frequenzwahl.

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Stefan B. schrieb:
> blabla schrieb:
>
>> Vielen Dank. Es stimmt nun mehr oder weniger.
>
> Das mehr oder weniger liegt daran, dass du 1000x einen Funktionsaufruf
> und weiteren Code um die Wartefunktion (_delay_ms()) gepackt hast.

Naja ne daran liegt es sicher nicht, sondern dass hier nicht klar ist, 
mit welchem Takt die MCU nun ueberhaupt laeuft.

von Volker (Gast)


Lesenswert?

Noch als Ergaenzung: Die Controller sind im Auslieferungszustand auf 
einen internen Takt gestellt, der 8515, der mit dem Board mitgeliefert 
wird, steht schon auf extern (und wird somit vom Board getaktet). Wenn 
Du nichts verstellt hast, mit oben genannter Frequenz.

Das Board liefert den Takt uebrigens ueber einen Controller, nicht ueber 
ein Quarz oder Oszillator.. deswegen kann man den auch so prima 
verstellen. ;)

Ansonsten kann ich Dir nur das AVR Tutorial an's Herz legen. Da sind 
viele Fragen schon beantwortet.

von Simon K. (simon) Benutzerseite


Lesenswert?

Michael G. schrieb:
> Stefan B. schrieb:
>> blabla schrieb:
>>
>>> Vielen Dank. Es stimmt nun mehr oder weniger.
>>
>> Das mehr oder weniger liegt daran, dass du 1000x einen Funktionsaufruf
>> und weiteren Code um die Wartefunktion (_delay_ms()) gepackt hast.
>
> Naja ne daran liegt es sicher nicht, sondern dass hier nicht klar ist,
> mit welchem Takt die MCU nun ueberhaupt laeuft.

Wieso nicht? Er meint sicher den Schleifenoverhead. Aber den merkt man 
wahrscheinlich nicht.

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.