AVR Microcontroller in C

OP #1985161
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;
}
Gast #1985218
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
Gast #1985251
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.
Gast #1985252
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.
Gast #1985284
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!
#1985293
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.
OP #1985304
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?
Gast #1985310
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?
#1985312
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.
Gast #1985322
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
#1985323
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?
OP #1985334
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)'
*/
Gast #1985340
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
#1985374
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren