mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR Microcontroller in C


Autor: Der Moriaan (therfist)
Datum:

Bewertung
0 lesenswert
nicht 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;
}

Autor: Sebastian (Gast)
Datum:

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

Autor: Der Moriaan (therfist)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
habs gerade ausprobiert änder nichts.

Autor: Sebastian (Gast)
Datum:

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

Autor: Schorsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Der Moriaan (therfist)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Muggel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Der Moriaan (therfist)
Datum:

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

Autor: Schorsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Muggel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Der Moriaan (therfist)
Datum:

Bewertung
0 lesenswert
nicht 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 :/

Autor: Der Moriaan (therfist)
Datum:

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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Muggel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und:

Der Moriaan schrieb:
> int f;
// f soll die Zeit in ms sein, die ein Taster gedrückt wird
>      if(f<1000)
>             light(10000);
> 
>      else if(f<3000)
>             light(30000);
> 
>      else
>             light(60000);
> }
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.

Autor: Der Moriaan (therfist)
Datum:

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

Autor: Der Moriaan (therfist)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm. Das:
for(f=0;!(PIND&0x04);f++)
            _delay_ms(20);

     f*=20;

gehört auf jeden Fall so:
for(f=0;!(PIND&0x04);f++)
{
    _delay_ms(20);
     f*=20;
}

if (f<1000) 
.... etc. Oder?!

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

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Sebastian (Gast)
Datum:

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

Autor: Der Moriaan (therfist)
Datum:

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

Autor: Der Moriaan (therfist)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie soll man denn 10ntel sekunden uebergeben?

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
einfach
void delay_ms(uint16_t time)
{
     for(uint16_t i=0; i<time; time++)
     {
          _delay_ms(10);
     }
}


wobei jetzt time in 10tel sek. ist.

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian schrieb:
> Hm. Das:
>
> for(f=0;!(PIND&0x04);f++)
>             _delay_ms(20);
> 
>      f*=20;
> 
>
> gehört auf jeden Fall so:
>
>
> for(f=0;!(PIND&0x04);f++)
> {
>     _delay_ms(20);
>      f*=20;
> }
> 
> 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?

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry, nicht _delay_ms(10); sondern _delay_ms(100);

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Der Moriaan (therfist)
Datum:

Bewertung
0 lesenswert
nicht 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)'
*/

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Der Moriaan (therfist)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein ein Projekt wo ich nicht weiterkomme!

Autor: Sebastian (Gast)
Datum:

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

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

musst du hier
void light(uint16_t time_ms)
{
       PORTB = 0x00;
        _delay_ms(time_ms);
        PORTB = 0xFF;
}
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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.