Forum: Compiler & IDEs Anfängerfrage


von kai m. (hiswif)


Lesenswert?

Hallo.

Ich bin relativ neu in der Programierung von Microcontrollern und 
arbeite mich deshalb gerade durch die Tutorials. Da ich Erfahrungen mit 
C habe arbeite ich mich gerade durch das AVR-GCC Tutorial. Jetzt bin ich 
an einen Punkt gestoßen wo sich mir einige Fragen stellen. Deshalb 
dachte ich mir, fragste mal die hilfsbereiten Mitmenschen, da mir Google 
und die SUFU leider nicht direkt weiterhelfen können. Sind eher 
Verständnissprobleme.

Im Grunde ist es ganz einfach und ich bin noch bei den Grundlagen. 
Sprich LED'S Blinken lassen, Taster auswerten.
Mein Grundaufbau ist relativ Simpel. Ein MEGA8, externer 4MHZ Quarz 
takt, 3 LEDS (PDB0-2) und ein Taster (PD4).

Ich habe eine Funktion geschrieben, welche alle drei LED'S im 
Sekundentankt nacheinander einschaltet und am Ende alle wieder aus. 
Diese Funktion wird aufgerufen wenn der Taster gedrückt wurde.

Dabei viel mir auf das er die Funktion 2 mal durchläuft sobald ich den 
uC einschalte. Der Taster ist aber nicht gedrückt!

1. Wieso durchläuft er die Funktion 2 Mal beim Einschalten der 
Schaltung?

Weiterhin viel mir auf das ich den Taster ziemlich lange gedrückt halten 
muss damit er ihn als gedrückt erkennt (etwa 1s) und die Funktion der 
LED'S aufruft. Liegt das am niedrigen Takt (4MHZ)? Oder geht das ohne 
interrupts nicht schneller?

2. Wie kann ich es erreichen das er schneller auf den Tastendruck 
reagiert?

Hier mal mein Programm:
1
#include <avr/io.h>
2
3
#define F_CPU 4000000UL
4
5
#include <util/delay.h>
6
7
// Ports der LED's festlegen.
8
#define ROT PB0
9
#define GELB PB1
10
#define GRUEN PB2
11
12
//Ports initialisieren
13
int IO_init(void){
14
  DDRB = (1 << DDB0) | (1 << DDB1) | (1 << DDB2); //Port B0 - B2 als Ausgänge
15
    DDRD &= ~(1 << DDD4);              //PORT D4 als Eingang
16
  PORTD |= (1 << DDD4);              //Port D4 interner Pullup
17
  return 0;
18
}
19
20
// LEDS schalten
21
int LED_ampel(void){
22
  PORTB |= (1 << ROT);              //Rote LED an
23
  _delay_ms(1000);
24
  PORTB |= (1 << GELB);              //Gelbe LED an  
25
  _delay_ms(1000);
26
  PORTB |= (1 << GRUEN);              //Grüne LED an
27
  _delay_ms(1000);
28
  PORTB &= ~((1 << ROT) | (1 << GELB) | (1 << GRUEN));    //Alle LED's aus
29
  return 0;
30
}
31
32
//Eingabe Taster an PD4
33
int BUTTON(void){                  
34
  if((PIND & 0x08)){                //Eingabe an PD4 prüfen
35
    LED_ampel();                //LED's schalten wenn Knopf gedrückt
36
  }
37
  return 0;
38
}
39
40
int main(void)
41
{
42
  IO_init();                    //Initialisieren
43
    while(1)
44
    {
45
    BUTTON();                  //Eingabe überprüfen
46
    }
47
}

Ich verwende übrigens AVR-Studio 6

Über hilfreiche Antworten freue ich mich immer.

MFG

his

von J.-u. G. (juwe)


Lesenswert?

kai m. schrieb:
> if((PIND & 0x08)){                //Eingabe an PD4 prüfen

Hier wird nicht PD4 abgefragt, sondern PD3.

von Route_66 (Gast)


Lesenswert?

Hallo!
Nach dem Reset macht der µC erst IO_init, danach LED_ampel, dann BUTTON 
um endlich im main zu landen. Deshalb die zwei automatischen Durchläufe!

von J.-u. G. (juwe)


Lesenswert?

Ausserdem schaltet doch Dein Taster gegen Masse, oder? Dann muss in der 
Abfrage geprüft werden, ob der zugehörige Eingangspin "LOW", also "0" 
ist.

von Karl H. (kbuchegg)


Lesenswert?

Route_66 schrieb:
> Hallo!
> Nach dem Reset macht der µC erst IO_init, danach LED_ampel, dann BUTTON
> um endlich im main zu landen. Deshalb die zwei automatischen Durchläufe!

Hä?
Wie kommst du da drauf?

von J.-u. G. (juwe)


Lesenswert?

Route_66 schrieb:
> Nach dem Reset macht der µC erst IO_init, danach LED_ampel, dann BUTTON
> um endlich im main zu landen. Deshalb die zwei automatischen Durchläufe!
Das ist Unfug. Die Abarbeitung beginnt immer bei der main-Funktion.

von geprellter (Gast)


Lesenswert?

kai m. schrieb:
> Weiterhin viel mir auf das ich den Taster ziemlich lange gedrückt halten
            ^f !!!
> muss

Thema Entprellung ducharbeiten:
http://www.ganssle.com/debouncing.htm
http://www.mikrocontroller.net/articles/Entprellung

von Karl H. (kbuchegg)


Lesenswert?

J.-u. G. schrieb:
> Ausserdem schaltet doch Dein Taster gegen Masse, oder? Dann muss in der
> Abfrage geprüft werden, ob der zugehörige Eingangspin "LOW", also "0"
> ist.

Theoretisch gäbs noch die Möglichkeit, dass sein Taster kein Schliesser 
sondern ein Öffner ist.
Wär zwar ungewöhnlich, aber möglich wärs.

Also. An den TO: Ohne genauere Hardware-Auskunft ist das so nicht zu 
klären.
Unbestritten ist hingegen, dass du gar nicht den Tasterport-Pin 
abgfrägst, wie J.-u. G. schon treffend feststellte.
Womit dann auch für dich die Frage beantwortet ist, warum die Profis 
eigentlich die
  if(PIND & (1<<PD3))
Schreibweise der
  if(PIND & 0x08)
Schreibweise vorziehen. Denn im ersten Fall wäre das leichter 
aufgefallen als im zweiten, in dem man Bits zählen muss.

PS. die richtigen Profis hätten das Analoge zu deinen LED gemacht

#define TASTER   PD4

und im restlichen Code dann mit 'TASTER' gearbeitet und nicht direkt mit 
DDD4, DB4, oder was auch immer.

von kai m. (hiswif)


Lesenswert?

Hallo.

Danke erstmal für die zahlreichen Antworten.

Also zum Taster. Ist ein simpler Standardtaster 0815 mit internem Pullup 
vom AVR, also Low aktiv. Was uns dazu führt, dass ich mich schon gefragt 
hatte warum die Funktion anspringt wenn ich den Taster mit
1
if((PIND & 0x08))

abfrage, statt mit

1
if(!(PIND & 0x08))

Ganz davon abgesehen hat J.-u. G. vollkommen recht. Ich hatte bei den 
Ports net bei 0 mit dem Zählen angefangen ;) Flüchtigkeitsfehler.

Allerdings wundert es mich dann schon warum die Funktion am Anfang 2 mal 
anläuft und dann auch wenn ich den Taster 1sek gedrückt halte.

Die Zuweisung mit
1
#define BUTTON PD4

hatte ich schon im ganzen Programm, hatte sie aber wieder rausgenommen, 
da ich dachte das darin irgendwo ein Fehler verborgen war.
Dazu aber mal ne Frage. Ist PD4 das gleiche wie DDD4? Im Tutorial kommt 
das nicht ganz raus, da dort mal die eine Schreibweise mal die andere 
verwendet wird.

Sonstige Hardwareauskunft.
Die Schaltung ist 1:1 aus dem Tutorial übernommen, mit der Erweiterung 
für die LED's und den Taster.

Zur Entprellung.

Das Thema ist in meiner Agenta grad ganz nach oben gerutscht ;) war 
vorher so "schau ich mir nachher an" ;) Dachte echt nicht das das solche 
enormen Auswirkungen haben kann. Also Abendlektüre für heute steht schon 
fest ;)

Also Danke euch nochmal für eure Hilfe. Fühle mich hier wirklich gut 
aufgehoben im Forum.

MFG

Kai


Nachtrag: Ich glaub ich hab mir die Antwort gerade selbst geben können 
;) Da ich den Pullup an PD4 aktiviert hatte. Jedoch PD3 abgefragt hatte 
kam es zu den Problemen, da der Status von PD3 nicht eindeutig war, da 
ich ihn ja weder angeschlossen noch mit nem Pullup versehen hatte. Liege 
ich da richtig? Denn ich habe jetzt erstmal die 0x08 in ne 0x16 geändert 
und alles läuft ohne Probleme.

von Karl H. (kbuchegg)


Lesenswert?

kai m. schrieb:

> Allerdings wundert es mich dann schon warum die Funktion am Anfang 2 mal
> anläuft und dann auch wenn ich den Taster 1sek gedrückt halte.

Weil ein offener Portpin ohne Pullup irgendwelche Werte liefert, die er 
sich gerade mal einfängt. Das Pin-Beinchen kann man sich wie eine kleine 
Antenne vorstellen, die sich auch schon mal was aus der Umgebung 
einfängt. Und da gibt es reichlich Zeugs: In deiner Wand sind 230V 
Leitungen, dein PC strahlt ein bischen was ab, der Fernseher auch, gehst 
du Staubsaugen läuft da ein Motor der elektomagn. Felder abstrahlt, du 
selbst wirkst als Antenne, wenn dein Handy sich bei der Station ummeldet 
strahlt es, etc....

> Dazu aber mal ne Frage. Ist PD4 das gleiche wie DDD4?

Ja.
PD4, DD4, PB4, PA4, PIND4, PINC4 ....  ist letzten Endes alles das 
gleiche.

irgendwo in den Tiefen des io.h steht

#define PD4    4
...
#define PIND4  4
...
#define DDD4   4
...
#define PA4    4
...
etc. etc.

das alles sind also einfach nur Verschiedene 'Schreibweisen' für 4.



> Das Thema ist in meiner Agenta grad ganz nach oben gerutscht ;) war
> vorher so "schau ich mir nachher an" ;) Dachte echt nicht das das solche
> enormen Auswirkungen haben kann.

Solange du derart lange _delay_ms Zeiten im Programm hast, kannst du es 
noch ignorieren. Dein Programm macht halt nicht

* einmal Niederdrücken -> eine (und nur eine!) Blinksequenz

sondern es macht

* solange gedrückt ist -> eine neue Sequenz starten

von kai m. (hiswif)


Lesenswert?

Ok,

wieder schlauer. Werd mich wohl am ehsten an PDx gewöhnen und mir eines 
durchgängig aneingnen. Macht das lesen auch einfacher ;)

Karl Heinz Buchegger schrieb:
> * einmal Niederdrücken -> eine (und nur eine!) Blinksequenz
>
> sondern es macht
>
> * solange gedrückt ist -> eine neue Sequenz starten

Stimmt. Gerade probiert. Wie gesagt, Programm für heute Abend steht 
fest. Meine Frau wird sich freuen, der Fernseher gehört ihr ;)

MFG

Kai

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.