Forum: Mikrocontroller und Digitale Elektronik C-Programmieren LED & Schalter


von Marc S. (geforce8100)


Lesenswert?

Hallo Leute,

ich habe eben hier angemeldet, da ich bitte unbedingt Hilfe von euch 
benötige.

Und zwar machen wir gerade in der Schule Projekte, dort geht es auch ums 
programmieren.

Mein Projekt soll ein Timer werden. - Bestückt wurde die Platine mit 
einem ATtiny2313, 9 LEDs und einem Taster.

Jede 10 Sekunden soll eine LED angehen, sobald 60 Sekungen vergangen 
sind, sollen diese wieder ausgehen und LED 7 angehen. Danach sollen die 
6 LED wieder hinauf zählen und LED 9 soll sich anschalten. Zum Schluss 
soll sich LED 8 einschalten.

Wenn der Taster gedrückt wird, soll der Timer resetet werden.

Pin belegung:

LED1    Port D 0x08
LED2    Port D 0x10
LED3    Port D 0x20
LED4    Port D 0x40
LED5    Port B 0x01
LED6    Port B 0x02
LED7    Port B 0x04
LED8    Port B 0x08
LED9    Port B 0x10
Taaster Port D 0x04


Leider bin ich ein totaler Neuling und verstehe nicht sehr viel von der 
C-Programmierung. - Vllt. hat ja jemand Lust & Zeit von euch den 
Programmiercode zu schreiben :-) !!

LG und Danke

von Düsendieb (Gast)


Lesenswert?


von Janeistklar (Gast)


Lesenswert?

Präsentiere uns doch mal deinen Ansatz, dann können wir punktuell 
helfen.
Copy&Paste ist eher üblich bei Promotionen.

von Marc S. (Gast)


Lesenswert?

Also, mein Testprogramm sieht zurzeit so aus:
1
#include <avr/io.h>
2
3
4
int main ()
5
{
6
// Init der Ports
7
DDRB = 0xFF;
8
DDRD = 0xFB;
9
10
PORTB = 0xFF;
11
PORTD = 0xFF;
12
13
// Start Hauptprogramm mit Tastendruck
14
while (!(PORTD &= 0b00000100));
15
16
while (1)
17
  {
18
    PORTB = 0x00;
19
    PORTD &=0x0F;  
20
  }
21
}

Wenn ich aber den Taster nun betätige, dann gehen die LEDs nicht aus, 
sondern werden nur dunkler. Hat jemand ne Ídee wo der Fehler liegt?

Danke

: Bearbeitet durch User
von Lutz H. (luhe)


Lesenswert?

Siehe  Beitrag
Idiotischer Anfängerfehler

von gestern.

In der while-Schleifewird die LED ganz schnell ein- und ausgeschaltet.
Nach dem Ein- oder Ausschalten   mus eine Pause rein. Zum Beispiel von 
0,5 Sekunden.

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Hier wird dir niemand ein Programm schreiben, im Gegenteil, die meisten 
sind hier, um es wieder auseinander zu nehmen :-)
Jetzt mal Ernst beiseite, zerlege die Aufgabenstellung in einzelne 
Schritte:

Marc S. schrieb:
> Jede 10 Sekunden soll eine LED angehen

Du brauchst also einen 10 Sekunden Timer. Lies dir im AVR Tutorial den 
Abschnitt über Timer durch und erschaffe einen Timer, der alle 10 
Sekunden eine LED an bzw. ausschaltet.

> Wenn der Taster gedrückt wird, soll der Timer resetet werden.
Lies dir den Artikel über Input/Output durch und erfinde eine 
Unterroutine, dir dir den Zustand des Taster zuverlässig zurückgibt, am 
einfachsten über True und False.

> LED1    Port D 0x08
> LED2    Port D 0x10
> LED3    Port D 0x20
> LED4    Port D 0x40
> LED5    Port B 0x01
> LED6    Port B 0x02
> LED7    Port B 0x04
> LED8    Port B 0x08
> LED9    Port B 0x10

Nun machst du dir Gedanken über die Anordnung der LED. Da ihr eine 
'Kraut- und Rüben' Pinanordung gewählt habt, ist es evtl. am 
einfachsten, ein Array (-> C-Strukturen) zu erschaffen, in dem alle 
möglichen Zustände der LED gespeichert sind.

Noch ein Tipp. Wenn du so deine Ports ansprichst

> while (!(PORTD &= 0b00000100));
weisst du nach einem Monat nicht mehr, was du da eigentlich machst. 
Abgesehen von dem Fehler, das du den PORT liest und nicht das PIN 
Register , sind klare Definitionen besser:
1
#define Buttonport PORTD
2
#define ButtonDir DDRD
3
#define ButtonPin PIND  
4
#define Button 2
Damit sieht das dann deutlicher aus:
1
// Tastenport init
2
ButtonDir = ~(1 << Button);
3
// lese Taste
4
result = !(ButtonPin &= (1 << Button));

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Die wichtigste Frage ist doch:
wie ist dein Kenntnisstand? Welche Dinge solltest du eigentlich schon 
können?

Denn eine handwerklich solide Lösung mit einem Timer nimmt dir dein 
Lehrer nicht ab. Halte die nicht für blöd. Der weiß auch ganz genau, 
dass da was nicht stimmt, wenn die größte Pfeife in der Klasse plötzlich 
mit dem handwerklich besten Programm daher kommt.

Wenn du noch nichts anderes gelernt hast, dann ist _delay_ms dein 
Freund, auch wenn es eine schlechte Lösung ist. Aber irgendwo muss man 
mal anfangen.

von Marc S. (Gast)


Lesenswert?

Okay, vielen Dank.

Das Testprogramm funktioniert jetzt :-)

von Matthias L. (Gast)


Lesenswert?

Wahrscheinlich mit Tippfehlern. Aber darüber darfst du dir jetzt 
Gedanken machen:
1
//------------------------------------------------------------------------
2
struct T_Data
3
{
4
    uint8_t   u08Port_b;
5
    uint8_t   u08Port_d;
6
    uint32_t  u32Delay;
7
} 
8
scLedData[] = { {0x01,0x00, 10000},
9
                {0x02,0x00, 10000},
10
                {0x04,0x00, 10000},
11
                {0x08,0x00, 10000},
12
                {0x10,0x01, 10000},
13
                {0x00,0x08, 10000},
14
                {0x00,0x10, 10000},
15
                {0x00,0x20, 10000},
16
                {0x00,0x40, 10000}  };
17
18
volatile  uint32_t  u32Tick;
19
volatile  uint8_t   u8State;
20
21
//------------------------------------------------------------------------
22
void main (void)
23
{
24
  //-- outputs --------------------
25
  DDRB |= 0x1F;
26
  DDRD |= 0xF8;
27
28
  //-- init timer to normal mode, clk/64 => 1ms 
29
  TIMSK  |= (1<<TOIE0);
30
  TCCR0B |= (3<<CS00);
31
  sei();
32
33
  //-- run program ----------------
34
  while ( 1 )
35
  {
36
    if ( PIND & 0x04 )
37
    {
38
      u8State = 0;
39
    }
40
41
  }
42
}
43
44
45
//------------------------------------------------------------------------
46
isr ( TIMER0_OVF_vect)
47
{
48
  uint32_t  u32TimeToWait = scLedData[u8State];
49
  if ( ++u32Tick < u32TimeToWait ) return;
50
51
  u32Tick = 0;
52
  u8Max   = (uint8_t) ( sizeof(scLedData)/sizeof(scLedData[0])  );
53
  if ( ++u8State >= u8Max ) 
54
  {
55
    u8State = 0;
56
  }
57
58
  PORTB = scLedData[u8State].u08Port_b;
59
  PORTD = scLedData[u8State].u08Port_d;
60
}

von Studentle (Gast)


Lesenswert?

Ooooh Lippy... so lernt er das doch nie!!!

Und da wundert man sich, dass sich so viele mit Plagiatsvorwürfen 
herumschalgen müssen, wenn es einem so einfach gemacht wird.

von Matthias L. (Gast)


Lesenswert?

Aber Erklärung gibt es keine dazu.

Wie Karl Heinz schon sagte:
>wenn die größte Pfeife in der Klasse plötzlich
>mit dem handwerklich besten Programm daher kommt.

Aber wenn er es kapiert hat und erklären kann....

Und wenns keine Klausur im geschlossenen Raum ist, ist Hilfe zulässig...

von Marc S. (Gast)


Lesenswert?

Vielen vielen Dank!

Selbstverständlich mache ich mir meine Gedanken dazu, Hilfe ist 
natürlich in diesem Projekt von allen Seiten zulässig!

Tests und Schularbeiten gibt es in diesem Fach auch nicht ;-)

Danke!!
LG

von Karl H. (kbuchegg)


Lesenswert?

Marc S. schrieb:

> Selbstverständlich mache ich mir meine Gedanken dazu,

Na da bin ich neugierig.

Wenn ich deine Fragen zu Grunde lege, dann dauert das 3 Monate, bis du 
den Code verstanden hast.

Ganz ehrlich Matthias. Ich denke nicht, dass du ihm damit einen Gefallen 
getan hast. Das geht weit darüber hinaus, was er mit seinem Wissen noch 
verstehen kann. Da kannst nicht einen Grundschüler mit 
Differentialgleichungen überfallen, wenn er Probleme mit dem kleinen 
Einmal Eins hat. Selbst wenn Diff-Gleichungen die richtige Lösung für 
eines seiner Probleme wäre.

: Bearbeitet durch User
von Matthias L. (Gast)


Lesenswert?

>Ich denke nicht, dass du ihm damit einen Gefallen
>getan hast.

Vielleicht hast du recht. Aber vielleicht kann er das als Richtung 
ansehen...

von Ingo (Gast)


Lesenswert?

Zumal es auch für geübte Menschen nicht leicht ist zu sehen was du da 
treibst!

von Marc S. (Gast)


Lesenswert?

Haha sehr lustig, ist wohl einer der Experten hier^^

Also ich versuche das irgendwie nachzuvollziehen.

Ob das Programm funktioniert oder nicht kann ich nicht sagen, da ich den 
Fehler bekomme:

Build FAILED.
========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped 
==========

von Dave C. (dave_chappelle)


Lesenswert?

@lippy

Du hättest noch irgendwo ein Zeichen weglassen sollen o.ä., dann hätte 
er sich wenigstens überlegen müssen, was da so abgeht ;)

Gruss

von Karl H. (kbuchegg)


Lesenswert?

OK.
Nachdem jetzt einige Zeit vergangen ist, mein Rat:
Leg das Programm beiseite. Man könnte zwar die paar Tippfehler 
korrigieren aber für jemanden, der in seiner Entwicklungsumgebung noch 
nicht einmal die Fehlermeldungen findet ist das wohl aussichtslos.
Nur um das klar zu stellen: Die Vorlage ist absolut in Ordnung. Da gibt 
es nichts daran auszusetzen. Genau so würde man das machen, wenn man 
sein Handwerk versteht.

Schreib das so, wie es deinem Können angemessen ist. Du bist nun mal 
noch kein Meister, sondern fängst gerade erst mit der Ausbildung an. 
Schreib es so, wie es dem entspricht, was du kannst und was du schon 
gelernt hast. Und wenn ich nach der Jahreszeit gehe und daran denke, 
dass die Semester gerade erst angefangen haben, dann kann das noch nicht 
viel sein.
D.h. Portpin setzen, delay, nächsten Portpin setzen, delay, etc. etc.

von Marc S. (Gast)


Lesenswert?

Da hast du wohl recht, ich versuche es gerade.
Zurzeit habe ich einen Timer, der jede 10 Sekunden eine LED hinaufzählt 
und sich danach resetet.

von Marc S. (Gast)


Lesenswert?

Generell wäre das programm nun fertig.

Jedoch funktioniert bei mir die Sleep Funktion noch nicht ganz.

Der Timer soll nach der Slee Funktion erwachen. - Weiß wer an was es 
liegt?
1
/*
2
 * AVRGCC1.c
3
 *
4
 * Created: 16.10.2013 13:01:56
5
 *  Author: Marc Svata
6
 */ 
7
8
#include <avr/io.h>
9
#include <avr/sleep.h>
10
#include <avr/interrupt.h>
11
12
13
14
//#define ten_secs 271000
15
#define ten_secs 27100
16
17
long i;
18
19
/*
20
void sleep()              // Timer befindet sich im Sleep Modus
21
{
22
  
23
  PORTD = 0x07;
24
  PORTB = 0;
25
  for (i=0;i = ten_secs;i++);  ____________
26
}
27
*/
28
29
void clear_leds()
30
{
31
  PORTD &= 0x07;
32
  PORTB &= 0xFC;
33
}
34
35
36
void cast_my_dice()                  // continue after keypress
37
38
{
39
  PORTD = 0x04;
40
}
41
42
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
43
44
void eine_minute()                  // Counter fuer eine Minute
45
{
46
47
      //for(i=0; i < ten_secs; i++);  
48
      PORTD |= 0x08;
49
      PORTB &= 0xFC;
50
      for(i=0; i < ten_secs; i++);  
51
      PORTD |= 0x18;
52
      for(i=0; i < ten_secs; i++);  
53
      PORTD |= 0x38;
54
      for(i=0; i < ten_secs; i++);  
55
      PORTD |= 0x78;
56
      for(i=0; i < ten_secs; i++);  
57
      PORTB |= 0x01;
58
      for(i=0; i < ten_secs; i++);  
59
      PORTB |= 0x03;
60
      for(i=0; i < ten_secs; i++);  
61
}
62
63
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
64
65
66
67
int main(void)
68
{  
69
  
70
  DDRB = 0x1F;                  // Pins PB0, PB1, PB2, PB3, PB4  "high"  Leds als Ausgang definieren
71
  DDRD = 0x78;                  // Pins PD3, PD4, PD5 und PD6 "high"   Leds als Ausgang definieren  
72
  PORTD = 0x07;                  // Pull Up Widerstand fuer den Taster setzen
73
  PORTB = 0x00;
74
75
sei();  
76
    while(1)
77
    {
78
    
79
    eine_minute();          
80
    clear_leds();                // 60 Sekunden LEDs schalten sich aus
81
    PORTB |= 0x10;                //  1. Minuten LED schaltet sich ein
82
    
83
    
84
    
85
    eine_minute();
86
    clear_leds();                // 60 Sekunden LEDs schalten sich aus
87
    PORTB |= 0x04;                //  2. Minuten LED schaltet sich ein
88
      
89
    
90
    
91
    eine_minute();            
92
    clear_leds();                // 60 Sekunden LEDs schalten sich aus
93
    PORTB |= 0x08;                //  3. Minuten LED schaltet sich ein
94
  
95
  clear_leds();
96
  
97
  
98
  for(i=0; i = ten_secs; i++)            // Setze fuer 10 Sekunden die 3 Minuten LED's auf "high" 
99
  
100
  {
101
    
102
    PORTB |= 0x10;
103
    PORTB |= 0x04;
104
    PORTB |= 0x08;  
105
  
106
  }
107
  
108
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);      // Setze Timer in Schlafmodus 
109
  sleep_mode();
110
  cast_my_dice();                  // continue after keypress
111
  
112
  
113
  
114
  }
115
}

von Karl H. (kbuchegg)


Lesenswert?

> - Weiß wer an was es liegt?

Das funtkioniert so nicht.
Um den µC wieder aus dem Sleep rauszuholen, benötigt es einen Interrupt. 
Von alleine wacht der µC nicht mehr auf.

Lass den sleep erst mal beiseite.

Dein Programm krankt noch an ganz anderen Stellen. Zb wird dir jeder 
vernünftige Compiler, wenn er das hier
1
     for(i=0; i < ten_secs; i++);
optimieren darf, die Schleife einfach rauswerfen.

Um derartige Zeitverzögerungen zu machen, gibt es die Funktion
1
   _delay_ms( .... )
die so gebaut wurde, dass sie gezielt Zeit verbrutzelt.
In Anbetracht dessen, dass du mit Timern noch nicht umgehen kannst, ist 
das das Mittel der (momentanen) Wahl.

Sleep ist etwas, das kommt irgendwann. Aber noch nicht jetzt. Dazu fehlt 
dir noch viel zu viel.

: Bearbeitet durch User
von Marc S. (Gast)


Lesenswert?

Der Sleep muss aber (leider) bei meinem Programm gemacht werden
-> Anforderung der Lehrperson.

Problem hierbei ist zurzeit das er nicht in den Slee Modus geht.
Interrupt muss dann noch gemacht werden...

Ansonsten funktioniert der Timer wunderbar...

von Karl H. (kbuchegg)


Lesenswert?

Marc S. schrieb:
> Der Sleep muss aber (leider) bei meinem Programm gemacht werden
> -> Anforderung der Lehrperson.

Jetzt muss ich lachen.

Dein Programm hat Probleme ohne Ende.
Da sind gefühlte 8-hundert-2-und-fünfzig Problemkreise die wichtiger und 
dringender in deinem Programm sind.
Und du kümmerst dich jetzt um Problem Nummer 853?

Sorry. Aber da muss ich lachen.

: Bearbeitet durch User
von Marc S. (Gast)


Lesenswert?

Verstehe ich nicht.

Das Programm funktioniert ja (Timer zählt 3 Minuten herunter mit LED 
Ansteuerung).

Vllt. ist es 'komisch' geschrieben, weil ich eben ein Anfänger bin ;-)

von Karl H. (kbuchegg)


Lesenswert?

> Ansonsten funktioniert der Timer wunderbar...

Das tut ein Klebeband an der durchgerosteten Autokarrosserie auch. 10 
Minuten lang.

PS: Ein 'Timer' ist in diesem Zusammenhang eine Hardwarekomponente im 
µC. Eine eingebaute Funktionalität. Das hat nichts damit zu tun, dass du 
das ganze Gerät einen 'Timer' nennst.
Wenn ich von "du kannst mit Timern noch nicht umgehen" rede, dann meine 
ich mit "Timer" ersteres und nicht letzteres.

von Marc S. (Gast)


Lesenswert?

Du bist ja heute wieder zum Scherzen aufgelegt ;-)

von Karl H. (kbuchegg)


Lesenswert?

Nicht wirklich.
Aber was soll ich dir hier erklären?
Mehr als "der sleep kann nicht funktionieren, weil es nichts gibt was 
den µC wieder aus dem Sleep herausholen könnte" kann ich dir jetzt nicht 
sagen.
Ich kann hier nicht mit dir 5 Stunden Unterricht im Schnelldurchlauf auf 
3 Bildschirmseiten kompremiert nachholen.

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.