Forum: Mikrocontroller und Digitale Elektronik AVR Microcontroller in C


von Der M. (therfist)


Lesenswert?

In der Funktion beid en Kommentaren kann man lesen was das Programm 
können soll, allerdings blinkt die LED nach 3 Sekunden  nur 1 mal kurz.

//----------------------------------------------------------------------
// Titel       : Lichtschaltung mit Mikrocontroller MK2 von AVR

//----------------------------------------------------------------------
// Funktion    : Wenn der Controller für <3 Sekunden betätigt wird 
schaltet
//           sich eine LED für genau 30 Sekunden ein. Bei längerem (3>)
//          drücken schaltet sich die LED für 60 Sekunden an.
//              Wenn der Taster für <1 gedrückt wird, leuchtet die LED 
für 10 Sekunden.

// Schaltung   : Taster an PORTD.2, LED an PORTB.0
//----------------------------------------------------------------------
// Prozessor   : ATmega168P
// Takt        : 3.6864 MHz
// Sprache     : C
// Datum       : 02.12.2005
// Version     : 1.0
// Autor       : Der Morrian
// Programmer  : Der Morrian
// Port    : ...
// CompilerOption:  -Os
//----------------------------------------------------------------------
#define   F_CPU 3686400  // Taktfrequenz des myAVR-Boards
#include  <avr\io.h>    // AVR Register und Konstantendefinitionen
#include   <util\delay.h>  //Wartefunktion
//----------------------------------------------------------------------
void light(int);

main()
{

int f;
DDRB = 0xFF;                       // PORTB = Ausgang
DDRD = 0x00;                       // PORTD = Eingang
PORTD = 0x04;                      // PORTD = PULL-UP

do
{
     for(f=0;!(PIND&0x04);f++)
            _delay_ms(20);

     f*=20;

     if(f<1000)
            light(10000);

     else if(f<3000)
            light(30000);

     else
            light(60000);
}
while (true);                    // Mainloop
}


void light(int time_ms)
{
       PORTB = 0x00;
        _delay_ms(time_ms);
        PORTB = 0xFF;
}

von Sebastian (Gast)


Lesenswert?

fehlt in der for-schleife nicht eine { und eine } am Ende?

von Der M. (therfist)


Lesenswert?

habs gerade ausprobiert änder nichts.

von Sebastian (Gast)


Lesenswert?

was heißt "sie leuchtet kurz"? 10 Sekunden oder wirklich kurz, aslo nur 
ein gaches aufblitzen?

von Schorsch (Gast)


Lesenswert?

Der Moriaan schrieb:
> // Datum       : 02.12.2005

Wenn deine AVR-Libc genauso alt ist, kann das _delay_ms keine so großen 
werte verarbeiten. => Update.

Und

Der Moriaan schrieb:
> _delay_ms(time_ms);

ist eine ganz ganz schlechte Idee. Der Parameter zu _delay_ms muss immer 
eine Konstante sein. Warum? => siehe Doku.

von Der M. (therfist)


Lesenswert?

Konstante bedeutet?
Achso und Datum ist falsch.
Programm ist am neusten Stand.

würde das mit waitMS(time_ms) funktioniern?

@ Sebastian: ja nur kurz halbe sekunde oder so

von Muggel (Gast)


Lesenswert?

Schreib eine Funktion:

void delay_ms(uint16_t time)
{
     for(uint16_t i=0; i<time; time++)
     {
          _delay_ms(1);
     }
}


-->So umgehst du das Problem mit der eigentlichen _delay_ms, da du hier 
die konstante 1 halt so oft aufrust, wie du sie brauchst...ist zwar 
nicht das genauste, aber dürfte für dein problem erstmal reichen.

Gruß, Muggel

von Der M. (therfist)


Lesenswert?

ich verstehe die Funktion nicht.
Wäre nett wenn du mir die erklären würdest.

von Schorsch (Gast)


Lesenswert?

Der Moriaan schrieb:
> ich verstehe die Funktion nicht.
> Wäre nett wenn du mir die erklären würdest.

Das ist eine ganz normale for-schleife. Die zählt von 0 bis "time" und 
wartet jedes mal eine millisekunde.

Schlag mal dein C-Buch auf, "for" sollte da in den ersten Kapiteln schon 
vorkommen.

von Muggel (Gast)


Lesenswert?

Naja, wie Schorsch schon geschrieben hat, sollte als Übergabeparameter 
für die Lib-Funktion _delay_ms eine Konstante stehen. Zudem bin ich mir 
nicht sicher, ob man auch nur 8-Bit Werte an diese Funktion übergeben 
kann(Was in etwa max 255ms entsprechen würde).

Mit dieser Funktion ohne _ for dem delay umgeht man diese Hürde. Ich 
sage einfach das der Übergabeparameter für _delay_ms() KONSTANT 1 ist, 
also immer 1ms verzögert. Mit dieser Funktion realisiere ich, dass ich 
bis 65536 ms, also etwa 65sec Verzögerung bereitstellen kann(das 
uint16_t sorgt dafür, dass ich 16-Bit-Werte übergeben kann).

Die for-Schleife ruft dann einfach time-mal die 1ms-Verzögerung auf. Das 
wars schon.

von Der M. (therfist)


Lesenswert?

also ich bin jez net der c experte..
das heißt ich habe keine ahnung
was ich jetzt in die for schleife noch reinschreiben soll :/

von Der M. (therfist)


Lesenswert?

achso und ja kla verstehe schon was die funktion macht.
aber nicht WIE sie was bringen soll :/

von Falk B. (falk)


Lesenswert?


von Muggel (Gast)


Lesenswert?

Funktioniert sie denn??

kopier die Funktion, so wie sie ist über deine main und

ändere dann die light-Funktion wie folgt:

void light(uint16_t time_ms)
{
       PORTB = 0x00;
        delay_ms(time_ms);
        PORTB = 0xFF;
}

und dann verrate mir, obs funktioniert, oder nicht!

von Hc Z. (mizch)


Lesenswert?

Und:

Der Moriaan schrieb:
1
> int f;
2
// f soll die Zeit in ms sein, die ein Taster gedrückt wird
3
>      if(f<1000)
4
>             light(10000);
5
> 
6
>      else if(f<3000)
7
>             light(30000);
8
> 
9
>      else
10
>             light(60000);
11
> }
Da musst Du schon ziemlich genau die 3 Sekunden einhalten, um ein 
light(6000) zu erreichen.  Schau Dir mal den Zahlenbereich einer 
16-Bit-int an und welchen Spielraum Du von 30000 aufwärts hast bis sie 
überläuft.

Angenommen, Dein Tastendruck würde genau gemessen (was aus den von 
anderen beschriebenen Gründen nur sehr ungefähr hinhaut), dürftest Du 
nur zwischen 3 und 3,28 Sekunden drücken.  Darüber bekommst Du 
light(1000), also Dein kürzeres Blinken.

von Der M. (therfist)


Lesenswert?

Lichtschaltung mit Funktion.o: In function `main':
Lichtschaltung mit Funktion.cc:(.text+0x132): Linkerfehler: undefinierte 
Sprungadresse: `light(int)'

von Der M. (therfist)


Lesenswert?

Hc Zimmerer schrieb:

> Da musst Du schon ziemlich genau die 3 Sekunden einhalten, um ein
> light(6000) zu erreichen.  Schau Dir mal den Zahlenbereich einer
> 16-Bit-int an und welchen Spielraum Du von 30000 aufwärts hast bis sie
> überläuft.
>
> Angenommen, Dein Tastendruck würde genau gemessen (was aus den von
> anderen beschriebenen Gründen nur sehr ungefähr hinhaut), dürftest Du
> nur zwischen 3 und 3,28 Sekunden drücken.  Darüber bekommst Du
> light(1000), also Dein kürzeres Blinken.


Würde es denn mit einem anderen Datentyp funktionieren?

von Hc Z. (mizch)


Lesenswert?

Hmm.. ich hab's mir gerade noch mal angeschaut.  Ich war zu schnell und 
meine Antwort kannst Du vergessen.  Irgendwie sah ich dort, wo 3000 
steht, 30000 stehen.  Dann hätte die Antwort hingehauen.  So aber nicht.

von Sebastian (Gast)


Lesenswert?

Hm. Das:
1
for(f=0;!(PIND&0x04);f++)
2
            _delay_ms(20);
3
4
     f*=20;

gehört auf jeden Fall so:
1
for(f=0;!(PIND&0x04);f++)
2
{
3
    _delay_ms(20);
4
     f*=20;
5
}
6
7
if (f<1000)
.... etc. Oder?!

weil wenn die Klammern fehlen geht er immer in den if(f<1000) rein oder?

von Hc Z. (mizch)


Lesenswert?

Argl ... jetzt kommt die Korrektur der Korrektur.  An einer anderen 
Stelle hast Du nämlich tatsächlich einen Überlauf.

Du kannst keinen light(60000) aufrufen, wenn der Parameter von light() 
eine 16-Bit-Integer (signed) ist.  Nimm kleinere Zahlen, übergebe z.B. 
die Blinkzeit in Sekunden oder Zehntelsekunden.

von Sebastian (Gast)


Lesenswert?

uint müsste doch von 0 bis 65535 gehen oder? Aber deine Methode 
(zehntel-sekunden übergeben) ist sicher trotzdem besser

von Der M. (therfist)


Lesenswert?

die dauer wie lange die led leuchten soll ist vorgeben -.-
und zur for-schleife -> hab ich schon behoben.

von Der M. (therfist)


Lesenswert?

wie soll man denn 10ntel sekunden uebergeben?

von Sebastian (Gast)


Lesenswert?

einfach
1
void delay_ms(uint16_t time)
2
{
3
     for(uint16_t i=0; i<time; time++)
4
     {
5
          _delay_ms(10);
6
     }
7
}

wobei jetzt time in 10tel sek. ist.

Poste doch nochmal deinen ganzen code, so wie er jetzt aussieht

von Karl H. (kbuchegg)


Lesenswert?

Sebastian schrieb:
> Hm. Das:
>
1
> for(f=0;!(PIND&0x04);f++)
2
>             _delay_ms(20);
3
> 
4
>      f*=20;
5
>
>
> gehört auf jeden Fall so:
>
>
1
> for(f=0;!(PIND&0x04);f++)
2
> {
3
>     _delay_ms(20);
4
>      f*=20;
5
> }
6
> 
7
> if (f<1000)
.... etc. Oder?!

kann ich mir nicht vorstellen.
Überleg doch mal wie schnell f bei dir wächst :-)

(wenn er das f ganz einfach vernünftig warteZeit genannt hätte, dann 
wärs wahrscheinlich zu einfach gewesen. Und im übrigen muss man die Zeit 
eigentlich ja auch nicht explizit ausrechnen. Man kann ja die Vergleiche 
auch auf die Anzahl der Schleifenwiederholungen aufbauen.

Ausserdem: Was passiert wohl, wenn der Benutzer auf der Taste 
einschläft?

von Sebastian (Gast)


Lesenswert?

sorry, nicht _delay_ms(10); sondern _delay_ms(100);

von Sebastian (Gast)


Lesenswert?

lol ja stimmt. bin schon zu müde und schreib nur stuss. ich klink mich 
aus. wollte helfen aber verursache nur chaos. schönen abend alle 
zusammen und guten erfolg.

von Der M. (therfist)


Lesenswert?

//----------------------------------------------------------------------
// Titel       : Lichtschaltung mit Mikrocontroller MK2 von AVR

//----------------------------------------------------------------------
// Funktion    : Wenn der Controller für <3 Sekunden betätigt wird
//schaltet
//           sich eine LED für genau 30 Sekunden ein. Bei längerem (3>)
//          drücken schaltet sich die LED für 60 Sekunden an.
//              Wenn der Taster für <1 gedrückt wird, leuchtet die LED
//für 10 Sekunden.

// Schaltung   : Taster an PORTD.2, LED an PORTB.0
//----------------------------------------------------------------------
// Prozessor   : ATmega168P
// Takt        : 3.6864 MHz
// Sprache     : C
// Datum       : 02.12.2005
// Version     : 1.0
// Autor       : Der Morrian
// Programmer  : Der Morrian
// Port    : ...
// CompilerOption:  -Os
//----------------------------------------------------------------------
#define   F_CPU 3686400  // Taktfrequenz des myAVR-Boards
#include  <avr\io.h>    // AVR Register und Konstantendefinitionen
#include   <util\delay.h>  //Wartefunktion
//----------------------------------------------------------------------
void light(int);



void delay_ms(uint16_t time)
{
     for(uint16_t i=0; i<time; time++)
     {
          _delay_ms(1);
     }
}


main()
{

int f;
DDRB = 0xFF;                       // PORTB = Ausgang
DDRD = 0x00;                       // PORTD = Eingang
PORTD = 0x04;                      // PORTD = PULL-UP

do
{
     for(f=0;!(PIND&0x04);f++)

    _delay_ms(20);

     f*=20;

     if(f<1000)
            light(10000);

     else if(f<3000)
            light(30000);

     else
            light(60000);
}
while (true);                    // Mainloop
}


void light(uint16_t time_ms)
{
       PORTB = 0x00;
        _delay_ms(time_ms);
        PORTB = 0xFF;
}

Aktueller Code mit folgedem Fehler..
und bei dem ganzen Fachchinesisch hier versteh ich eh nix :/
/* Lichtschaltung mit Funktion.o: In function `main':
Lichtschaltung mit Funktion.cc:(.text+0x132): Linkerfehler: undefinierte 
Sprungadresse: `light(int)'
*/

von Karl H. (kbuchegg)


Lesenswert?

Sebastian schrieb:
> lol ja stimmt. bin schon zu müde und schreib nur stuss.

Würd ich so nicht sagen.

Das Bespiel an sich ist nicht schwer, aber die ganze Vorlage ist schon 
nahezu für die Tonne.

Allerdings sieht mir das alles zu sehr nach Hausaufgabe aus, sodass ich 
mich ebenfalls ausklinke.

von Der M. (therfist)


Lesenswert?

Nein ein Projekt wo ich nicht weiterkomme!

von Sebastian (Gast)


Lesenswert?

ohne jemandem nahetreten zu wollen, vorlage ist zu vergessen und 
threaderöffner kann die tips nicht umsetzen.

diese Funktion hier:
1
void delay_ms(uint16_t time)
2
{
3
     for(uint16_t i=0; i<time; time++)
4
     {
5
          _delay_ms(1);
6
     }
7
}

musst du hier
1
void light(uint16_t time_ms)
2
{
3
       PORTB = 0x00;
4
        _delay_ms(time_ms);
5
        PORTB = 0xFF;
6
}
aufrufen. Am besten auch gleich mit _delay_ms(100) auf 10tel sekunden 
umbaun. aber ich glaub in deiner ganzen programmlogik ist der hund drin. 
das mit f hochzählen funktioniert imho so nicht.

jetzt aber wirklich schluss. baba

von Karl H. (kbuchegg)


Lesenswert?

Sebastian schrieb:
> ohne jemandem nahetreten zu wollen, vorlage ist zu vergessen und
> threaderöffner kann die tips nicht umsetzen.

Das Problem ist wieder mal das Übliche.
Die Grundlagen nicht lernen wollen, aber programmieren.

Und das hat alles nichts damit zu tun, kein C-Experte zu sein. Das ist 
bis jetzt Stoff der 2ten oder 3ten der Unterrichtseinheit von 40.

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.