Forum: Compiler & IDEs Kleine Hilfestellung


von Jürgen D. (dell)


Lesenswert?

Erstmal meine Hardware

STK500 mit Atmega16
LEDs sind an PORTB angeschlossen und SWITCHES an PORTD

Irgendwie bekomme ich es nicht gebacken.
Im Grunde möchte ich verschiedenen Tastenkombinationen einen bestimmten 
Ascii Code hinterlegen. Wenn man z.B. Taste 1 + 2 + 5 drückt soll der 
Ascci Code für den Buchstaben "G" an den PC übersendet werden.
Bin totaler Anfänger in dem Gebiet von uC. Habe aber bereits kleine 
Übungen gemacht und einiges an Literatur über dieses Thema gelesen. 
Programmierkenntnisse sind in JAVA bei mir vorhanden.
Würde mir jemand dabei über einen Instant Messenger helfen, den 
schliesslich lernt man wenn man es selber macht und nicht fertiges 
überniehmt.

Das Tut hier auf der Seite habe ich zwar mir angeguckt, finde aber 
einiges schwer für einen Anfänger.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Willst du mit C programmieren? Hast du bereits einen C 
Entwicklungssystem für die AVRs installiert? Welches? WINAVR wenn du 
mit Windows PC arbeitest?

Du schreibtst was vom Tutorial - meinst du das AVR-GCC-Tutorial? 
Hast du schon die ersten kleinen Programme geschrieben?

LED blinken lassen? Taster abgefragt? LED auf Taste reagieren lassen? 
Text vom PC über UART empfangen und LED damit gesteuert? Taste abgefragt 
und Reaktion über UART zum PC gesendet?

Lass mal sehen, wie weit du schon bist.

von Jürgen D. (dell)


Lesenswert?

JA habe WinAVR und Halt AVR-Studio.

Ich komme mit dem Tut-GCC nicht ganz klar. Habe mir einige Beispiele aus 
nem Buch angeuckt und auch bsichen was hinbekommen. Also verstehen tue 
ich es schnell. Brauche nur eine Starthilfe und dann läuft das von 
alleine. Programmieren möchte ich in C.

""LED blinken lassen? Taster abgefragt? LED auf Taste reagieren lassen?
Text vom PC über UART empfangen und LED damit gesteuert? Taste abgefragt
und Reaktion über UART zum PC gesendet?
""

Genau dazu brauche ich paar Beispiele. So wurde mir Java bei gebracht. 
Warum ds Rad neu erfinden, wenn man vom fertigen abgucken kann.

Danke für deine Antwort.

von Simon K. (simon) Benutzerseite


Lesenswert?

Jürgen Dell wrote:
> Genau dazu brauche ich paar Beispiele. So wurde mir Java bei gebracht.
> Warum ds Rad neu erfinden, wenn man vom fertigen abgucken kann.

Weil man beim Rad-neu-erfinden die Problemstellung erfassen kann und 
sich selber einen Weg ausdenkt um somit was zu lernen?

Abgucken wäre also Copy&Paste, oder wie?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Jürgen du schreibst

> habe mir einige Beispiele aus 'nem Buch angeuckt und auch bischen was
> hinbekommen.

aber dann auch

> Genau dazu brauche ich paar Beispiele.

Das widerspricht sich ein wenig.

Die aufgeführten Beispiele

""LED blinken lassen? Taster abgefragt? LED auf Taste reagieren lassen?
Text vom PC über UART empfangen und LED damit gesteuert? Taste abgefragt
und Reaktion über UART zum PC gesendet?
""

beginnen mit dem einfachsten Beispiel und steigern sich im 
Schwierigkeitsgrad.

Bis wohin bist du schon gekommen?

Klappt das grundsätzliche Programmieren mit WinAVR/Brennen mit 
AVR-Studio/Ablaufenlassen auf dem STK500 nicht?

Oder hapert es an der zündenden Idee die Aufgabe als Rechenvorschrift 
abzubilden? In Java könntest du es lösen, bloss die Umsetzung nach C ist 
nicht dein Ding?

Oder ist letzteres kein Problem, aber du weisst nicht wie du konkret an 
die die Tasteneingabe bekommst und die Daten per UART verschickst? Dann 
schick ein Rumpfprogramm und markiere die Stellen, wo du Fragen hast.

ADD:

Für das einfachste Beispiel (Blinkende LED) gibt es eine Einführung bei 
http://www.geocities.com/thetonegod/micro/intro.html
Wenn es dann mit Tasten weiter geht, kommt 
http://www.geocities.com/thetonegod/micro/io_digital.html ins Spiel.

von Jürgen D. (dell)


Lesenswert?

In Java könnte ich das ohne weiteres hinbekommen. Es happert wie du 
schon sagtest die Transparation nach C. Programme auf den yC zu 
schreiben und in AVR Studio ablaufen zu lassen dass kann ich.

Copy & Paste meine ich damit nicht. Im Grunde brauche ich eine Person 
die mir bei den Grundlagen eniges erläutert.
Tastenabfrage
Datenübertragen

Das Programmieren muss ich selber fertig machen, schliesslich muss ich 
es später vorführen und auch erklären das ganze.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Bei den Links bitte beachten: die dortigen delay() Funktionen sind 
problematisch. Orientiere dich da besser am Abschnitt Warteschleifen im 
AVR-GCC-Tutorial

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Die Person hast du in Form von den Usern dieses Forums und in Form der 
Schreiber der Tutorials.

Es ist zu mühsam oder es fällt schwer, die Welt komplett umd von Anfang 
an zu erklären. Konkrete, bewältigbare Anfragen sind vielleicht 
schneller gelöst... Sage halt, um welche Grundlage es konkret geht.

Wenn du ausschliessen willst, stur aufs Tutorial verwiesen zu werden, 
lies das vorher durch und konkretisiere die Frage unter Berücksichtigung 
des "Lernstoffs". Vielleicht hilft deine Frage, das Tutorial noch 
verständlicher zu machen.

von Karl H. (kbuchegg)


Lesenswert?

Auch für C Neulinge emfehle ich einen Blick ins Assembler
Tutorial.
http://www.mikrocontroller.net/articles/AVR-Tutorial
Der Grund: Manchmal sind gerade die Hardwaredinge im
anderen Tutorial anders erklärt (nicht notwendigerweise
besser, einfach nur anders). Und aus einer zweiten Sichtweise
kann man oft den fehlen Zündfunken holen.
Zum zweiten ist gerade bei diesen Hardwaredingen der Schritt
von Assembler zu C nicht so der grosse Schritt. Ob man da
jetzt in Assembler in spezifisches Hardwareregister mit
einem bestimmten Wert laden muss, oder ob man das in C mit
einer Zuweisung macht, ist letzendlich ziemlich egal, zumal ja
 auch in beiden Sprachen die Registerbezeichnung identisch
ist. Der entscheidende Punktist ja nicht, wie das Register
heist, oder wie man es konkret lädt, sonder welches Bit in
diesem Register wöfür zuständig ist. Und das ist völlig
sprachunabhängig (BASCOM mal ausgenommen), da von der Hardware
vorgegeben.

von Jürgen D. (dell)


Lesenswert?

#include <avr/io.h>

int main (void) {

   DDRB  = 0xff;
   DDRD = 0x01;


#define WARTEPIN PIND
#define WARTEBIT PD0

// mit der avr-libc Funktion:
loop_until_bit_is_set(WARTEPIN, WARTEBIT);
while ( !(WARTEPIN & (1 << WARTEBIT)) ) ;
PORTB = 0x03;  //LEDs an ausser PB0 und PB1
}


In der Simulation wartet AVR Studio bis ich PD0 gesetzt habe. Aber auf 
dem STK500 sieht es so aus, als ob die Abfrage übersprungen wird. Jemand 
eine Erklärung für mich ?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ist klar, der Eingabepin ist falsch konfiguriert und die Abfrage benutzt 
die falsche Logik für die STK500-Beschaltung.

Achtung: fehlerhaft!
1
#include <avr/io.h>
2
3
// Defines üblicherweise am Programmanfang
4
#define WARTEPIN PIND
5
#define WARTEBIT PD0
6
7
int main (void) 
8
{
9
   // http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#I.2FO-Register
10
   DDRB = 0xff; // PORTB alle AUSGANG
11
   DDRD = 0x01; // PD0 AUSGANG, alle anderen EINGANG ====> #1
12
13
   // Bis zum nächsten RESET...
14
   while (1)
15
   {
16
#if 1
17
      // ENTWEDER
18
      // mit dem avr-libc Makro aus avr/sfr_defs.h 
19
      // (wird von avr/io.h included:
20
      loop_until_bit_is_set(WARTEPIN, WARTEBIT); // ====> #1
21
#else
22
      // ODER
23
      while ( !(WARTEPIN & (1 << WARTEBIT)) ) 
24
         ;
25
#endif
26
27
      PORTB = 0x03;  //LEDs an ausser PB0 und PB1
28
   }
29
30
   // Soll auf µCs nie erreicht werden!
31
   return 0;
32
}

#1:

Das passt nicht zu
DDRD = 0x01; // PORTD0 AUSGANG, alle anderen EINGANG
in Verbindung mit
#define WARTEPIN PIND
#define WARTEBIT PD0

Du musst PD0 als Eingang konfigurieren, d.h. dieses Bit darf gerade 
nicht gesetzt sein.

#2:

Die Switches  sind im STK User Guide im Abschnitt 3-2 beschrieben. Es 
handelt sich um eine Active-LOW Schaltung, d.h. bei offenem Switch liegt 
eine 1 an und es ist zu warten bis das Bit von 1 auf 0 wechselt 
(Tastendruck).
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Tasten_und_Schalter
1
DDRD = 0xFE; // PD0 EINGANG, alle anderen AUSGANG 
2
...
3
      loop_until_bit_is_clear(WARTEPIN, WARTEBIT);
4
...
5
      while ( (WARTEPIN & (1 << WARTEBIT)) )

Nächster Lernstoff:

1/ Programmlogik: Zurücksetzen der LEDs beim Löslassen des Tasters

2/ Entprellung: 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#.28Tasten-.29Entprellung

von Jürgen D. (dell)


Lesenswert?

Mit deiner Hilfe habe ich endlich einen kleines Programm geschafft.


#include <avr/io.h>
#define WARTEPIN PIND
#define WARTEBIT PD0

int main (void)
{
   DDRB = 0xff; // PORTB alle AUSGANG
   PORTB = 0xFF; //Alle LEDS aus auf LOW gesetzt
   DDRD = 0xFE; // PD0 EINGANG, alle anderen AUSGANG

   // Bis zum nächsten RESET...

   loop_until_bit_is_clear(WARTEPIN, WARTEBIT);
   PORTB = 0xFE;  //PB0 auf high
}



Die LED geht erst an wenn ich die Taste von high auf low setze (also die 
Taste drücke).
Nun mache ich mit dem nächsten Lernstoff weiter und vertiefe das grad 
erlernte

von Jürgen D. (dell)


Lesenswert?

Wie stelle ich es jetzt an, dass wenn ich beliebigen Taster drücke auch 
die dazugehörige LED angeht. Nach meinem Verständnis muss ja gelauscht 
werden welcher Taster gedrückt wurde, sprich also wo ein 
Potentialunterschied ensteht.
Könnte ich da weitere Hilfestellung bekommen?

von Rahul D. (rahul)


Lesenswert?

1
#include <avr/io.h>
2
#define WARTEPIN PIND
3
#define WARTEBIT PD0
4
5
int main (void)
6
{
7
   DDRB = 0xff; // PORTB alle AUSGANG
8
   PORTB = 0xFF; //Alle LEDS ausschalten
9
   DDRD = 0x00; // PORTD alle AUSGANG
10
   PORTD = 0xFF; // Pullups einschalten
11
12
13
   while (!(PIND & PD0); // auf Tastendruck an PD0 warten
14
15
   PORTB = 0xFE;  //PB0 auf high
16
17
   // Bis zum nächsten RESET...
18
   while(1) // Endlosschleife
19
   {
20
    PORTB = PIND;
21
   }
22
}

Übrigens ist das Ende deines Programms ungewiss. Man setzt grundsätzlich 
eine Endlosschleife ein, damit der Controller in einem stabilen Zustand 
bleibt.
Selbst, wenn man nur eine Anweisung machen will und der Controller 
danach zum Nichtstun verdammt wird.

von Jürgen D. (dell)


Lesenswert?

Okay wieder was neues gelernt.
Ich als Anfänger erlaube es mir mal deinen Source-Code zu verbessern


""""
#include <avr/io.h>
int main (void)
{
   DDRB = 0xff; // PORTB alle AUSGANG
   PORTB = 0xFF; //Alle LEDS ausschalten
   DDRD = 0x00; // PORTD alle AUSGANG
   PORTD = 0xFF; // Pullups einschalten


   while ((PIND & PD0)); // auf Tastendruck an PD0 warten

   PORTB = 0xFE;  //PB0 auf high

   // Bis zum nächsten RESET...
   while(1) // Endlosschleife
   {
    PORTB = PIND;
   }
}
""""""
Nur wenn die Taste gedrückt ist, ist auch die dazu gehörige LED an.
Wie sehe es aus, wenn die LED so lange anbleiben soll, bis ich 
irgendwann wieder auf die Taste gedrückt habe?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

1
#include <avr/io.h>
2
#define WARTEPIN PIND
3
#define WARTEBIT PD0
4
5
int main (void)
6
{
7
   DDRB = 0xff; // PORTB alle AUSGANG
8
   PORTB = 0xFF; //Alle LEDS aus auf LOW gesetzt  
9
   DDRD = 0xFE; // PD0 EINGANG, alle anderen AUSGANG
10
11
   // Bis zum nächsten RESET...               =====> #1
12
13
   loop_until_bit_is_clear(WARTEPIN, WARTEBIT);
14
   PORTB = 0xFE;  //PB0 auf high
15
}

#1

Der Kommentar alleine bewirkt garnix. So wie in meiner Antwort oben und 
im Kommentar von Rahul zu sehen, brauchst du Schleifenanweisungen, damit 
das auch so ist. Z.B.
1
#include <avr/io.h>
2
#define WARTEPIN PIND
3
#define WARTEBIT PD0
4
5
int main (void)
6
{
7
   DDRB = 0xff; // PORTB alle AUSGANG
8
   PORTB = 0xFF; //Alle LEDS aus auf LOW gesetzt
9
   DDRD = 0xFE; // PD0 EINGANG, alle anderen AUSGANG
10
11
   // Bis zum nächsten RESET...
12
   while(1)
13
   {
14
      loop_until_bit_is_clear(WARTEPIN, WARTEBIT);
15
      PORTB = 0xFE;  //PB0 auf high
16
   ]
17
}

So sieht die Schleife formal aus. Eine Reaktion auf die Taste hast du 
aber noch nicht.

Wenn du auf mehrere Tasten testen willst, kannst du die loop_until... 
Schleife natürlich nicht mehr benutzen. Die blockiert dir den 
Programmablauf.

Du musst PIND direkt abfragen, die betreffenden Bits rausholen und dann 
mit bedingten Anweisungen (if, switch, ?:) darauf reagieren, d.h. 
Bitmanipulation an PORTB bzw. wie Rahul es macht PIND 1:1 auf PORTB 
durchgeben. Aber du willst ja später mehr im Programm machen als nur die 
Eingänge auf die Ausgänge zu spiegeln...
1
#include <avr/io.h>
2
#define WARTEPIN PIND
3
#define WARTEBIT PD0
4
5
int main (void)
6
{
7
   DDRB  = 0xff; // PORTB alle AUSGANG
8
   PORTB = 0xFF; // Alle LEDS aus (STK500 HIGH)
9
   DDRD  = 0xF0; // PD0, PD1, PD2, PD3 EINGANG, alle anderen AUSGANG
10
11
   // Bis zum nächsten RESET...
12
   while(1)
13
   {
14
      if ( (WARTEPIN & (1<<PD0)) )
15
      { 
16
         // Schalter PD0 offen => PORTB.0 HIGH (STK500) => LED0 aus 
17
         PORTB |= (1<<PD0);
18
      }
19
      else
20
      {
21
         // Schalter PD0 geschlossen => PORTB.0 LOW (STK500) => LED0 an 
22
         PORTB &= ~(1<<PD0);
23
      }
24
      
25
      if ( (WARTEPIN & (1<<PD1)) )
26
      { 
27
         // Schalter PD1 offen => PORTB.1 HIGH (STK500) => LED1 aus 
28
         PORTB |= (1<<PD1);
29
      }
30
      else
31
      {
32
         // Schalter PD1 geschlossen => PORTB.1 LOW (STK500) => LED1 an 
33
         PORTB &= ~(1<<PD1);
34
      }
35
36
      // ... 
37
   }
38
}

von Jürgen D. (dell)


Lesenswert?

Danke Stefan für deine Hilfe. Ich nehme deine Kommentare und Co gerne an 
und befasse mich weiter damit. Spätestens heute Abend habe ich wieder 
Fragen.""
Je mehr man sich damit beschäftigt desto logischer kommt es mir auch 
rüber.
Eine 1:1 Spiegelung bringt mir im späteren Verlauf sicherlich recht 
wenig. Frage mich grad selber warum ich nicht aus meinen 
Java-Kenntnissen nach verschachtelte-Anweisungen gesucht habe.

Vielen Dank bis später

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> Nur wenn die Taste gedrückt ist, ist auch die dazu gehörige LED an.
> Wie sehe es aus, wenn die LED so lange anbleiben soll, bis ich
> irgendwann wieder auf die Taste gedrückt habe?

D.h. Zustand merken und in der Abfrage berücksichtigen
1
#include <avr/io.h>
2
#define WARTEPIN PIND
3
#define WARTEBIT PD0
4
5
int main (void)
6
{
7
   unsigned char taste0_vorher = 0;
8
9
   DDRB  = 0xff; // PORTB alle AUSGANG
10
   PORTB = 0xFF; // Alle LEDS aus (STK500 HIGH)
11
   DDRD  = 0xF0; // PD0, PD1, PD2, PD3 EINGANG, alle anderen AUSGANG
12
13
   // Bis zum nächsten RESET...
14
   while(1)
15
   {
16
      if ( (WARTEPIN & (1<<PD0)) )
17
      { 
18
         // Schalter PD0 jetzt offen 
19
         if (taste0_vorher == 1)
20
         {
21
            // Schalter PD0 vorher geschlossen => LED umschalten (toggeln)
22
            PORTB ^= (1<<PB0);
23
24
            // neuen jetzt Zustand merken
25
            taste0_vorher = 0;
26
         }
27
      }
28
      else
29
      {
30
         // Schalter PD0 geschlossen 
31
         if (taste0_vorher == 0)
32
         {
33
            // Schalter PD0 vorher offen => LED umschalten (toggeln)
34
            PORTB ^= (1<<PB0);
35
36
            // neuen jetzt Zustand merken
37
            taste0_vorher = 1;
38
         }
39
      }
40
41
      // ... 
42
   }
43
}

von Jürgen D. (dell)


Lesenswert?

Kleine Korrektur

Entweder in der If oder in der Else Anweisung muss

aus PORTB ^= (1<<PB0); ---> PORTB ^= (0<<PB0);

gemacht werden.

Danke für die Hilfe. Ich vervollständige das auch für die restlichen 
Tasten. Könnten man das nicht wie in Java in einer Schleife machen ?

von Rahul D. (rahul)


Lesenswert?

>Entweder in der If oder in der Else Anweisung muss

>aus PORTB ^= (1<<PB0); ---> PORTB ^= (0<<PB0);

>gemacht werden.

Nö. Guck dir mal die Verknüpfung und den Sinn der Aussage (0<<PB0).
Es handelt sich dabei um ein XOR...

>Ich als Anfänger erlaube es mir mal deinen Source-Code zu verbessern

Vielleicht habe ich den Fehler absichtlich reingemacht?!

von Stefan B. (stefan) Benutzerseite


Lesenswert?

> Vielleicht habe ich den Fehler absichtlich reingemacht?!

Das bringt keinen Lerneffekt, sondern verunsichert nur den Gegenüber. 
Ich baue bestimmt keine Fehler absichtlich ein. Aber Fehler kommen vor, 
that's life.

von Rahul D. (rahul)


Lesenswert?

Stefan B. wrote:
>> Vielleicht habe ich den Fehler absichtlich reingemacht?!
>
> Das bringt keinen Lerneffekt, sondern verunsichert nur den Gegenüber.
> Ich baue bestimmt keine Fehler absichtlich ein. Aber Fehler kommen vor,
> that's life.

Nein, ich habe ihn nicht extra eingebaut. Das war nur eine Trotzreaktion 
auf
>Ich als Anfänger erlaube es mir mal deinen Source-Code zu verbessern

von Jürgen D. (dell)


Lesenswert?

Jeder macht mal Fehler. Ich setze mich wenigstens hin und gucke mir eure 
Hilfestellung an und teste es auch, viele würden ainfach Copy&Paste 
benutzen und nicht mal Danke sagen.
Ist doch gut, wenn ich selbständig Fehler berichtigen kann. Wollte dich 
(rahul) in keiner Weise angreifen.

von Peter D. (peda)


Lesenswert?

Jürgen Dell wrote:
> Ist doch gut, wenn ich selbständig Fehler berichtigen kann.

Hast Du aber nicht.

Du hast nur ein sehr verqueres NOP geschrieben.

Ob Stefans Code überhaupt falsch ist, hängt von der Betrachtungsweise 
ab.
Er macht an beiden Flanken eine Aktion und das muß ja nicht falsch sein.

Will man sie nur an einer Flanke, dann muß man eine davon wegnehmen, 
aber nicht durch einen unsinnigen Code ersetzen.

Und dann wird man auch das Problem des Prellens sehen.


Peter

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.