mikrocontroller.net

Forum: Compiler & IDEs Kleine Hilfestellung


Autor: Jürgen Dell (dell)
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

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

Autor: Jürgen Dell (dell)
Datum:

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

Autor: Simon K. (simon) Benutzerseite
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

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

Autor: Jürgen Dell (dell)
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

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

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

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

Autor: Jürgen Dell (dell)
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

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

Achtung: fehlerhaft!
#include <avr/io.h>

// Defines üblicherweise am Programmanfang
#define WARTEPIN PIND
#define WARTEBIT PD0

int main (void) 
{
   // http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#I.2FO-Register
   DDRB = 0xff; // PORTB alle AUSGANG
   DDRD = 0x01; // PD0 AUSGANG, alle anderen EINGANG ====> #1

   // Bis zum nächsten RESET...
   while (1)
   {
#if 1
      // ENTWEDER
      // mit dem avr-libc Makro aus avr/sfr_defs.h 
      // (wird von avr/io.h included:
      loop_until_bit_is_set(WARTEPIN, WARTEBIT); // ====> #1
#else
      // ODER
      while ( !(WARTEPIN & (1 << WARTEBIT)) ) 
         ;
#endif

      PORTB = 0x03;  //LEDs an ausser PB0 und PB1
   }

   // Soll auf µCs nie erreicht werden!
   return 0;
}

#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-Tu...
DDRD = 0xFE; // PD0 EINGANG, alle anderen AUSGANG 
...
      loop_until_bit_is_clear(WARTEPIN, WARTEBIT);
...
      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-Tu...

Autor: Jürgen Dell (dell)
Datum:

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

Autor: Jürgen Dell (dell)
Datum:

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

Autor: Rahul Der trollige (rahul)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/io.h>
#define WARTEPIN PIND
#define WARTEBIT PD0

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;
   }
}


Ü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.

Autor: Jürgen Dell (dell)
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

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

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

#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.
#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...
   while(1)
   {
      loop_until_bit_is_clear(WARTEPIN, WARTEBIT);
      PORTB = 0xFE;  //PB0 auf high
   ]
}

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...
#include <avr/io.h>
#define WARTEPIN PIND
#define WARTEBIT PD0

int main (void)
{
   DDRB  = 0xff; // PORTB alle AUSGANG
   PORTB = 0xFF; // Alle LEDS aus (STK500 HIGH)
   DDRD  = 0xF0; // PD0, PD1, PD2, PD3 EINGANG, alle anderen AUSGANG

   // Bis zum nächsten RESET...
   while(1)
   {
      if ( (WARTEPIN & (1<<PD0)) )
      { 
         // Schalter PD0 offen => PORTB.0 HIGH (STK500) => LED0 aus 
         PORTB |= (1<<PD0);
      }
      else
      {
         // Schalter PD0 geschlossen => PORTB.0 LOW (STK500) => LED0 an 
         PORTB &= ~(1<<PD0);
      }
      
      if ( (WARTEPIN & (1<<PD1)) )
      { 
         // Schalter PD1 offen => PORTB.1 HIGH (STK500) => LED1 aus 
         PORTB |= (1<<PD1);
      }
      else
      {
         // Schalter PD1 geschlossen => PORTB.1 LOW (STK500) => LED1 an 
         PORTB &= ~(1<<PD1);
      }

      // ... 
   }
}

Autor: Jürgen Dell (dell)
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
#include <avr/io.h>
#define WARTEPIN PIND
#define WARTEBIT PD0

int main (void)
{
   unsigned char taste0_vorher = 0;

   DDRB  = 0xff; // PORTB alle AUSGANG
   PORTB = 0xFF; // Alle LEDS aus (STK500 HIGH)
   DDRD  = 0xF0; // PD0, PD1, PD2, PD3 EINGANG, alle anderen AUSGANG

   // Bis zum nächsten RESET...
   while(1)
   {
      if ( (WARTEPIN & (1<<PD0)) )
      { 
         // Schalter PD0 jetzt offen 
         if (taste0_vorher == 1)
         {
            // Schalter PD0 vorher geschlossen => LED umschalten (toggeln)
            PORTB ^= (1<<PB0);

            // neuen jetzt Zustand merken
            taste0_vorher = 0;
         }
      }
      else
      {
         // Schalter PD0 geschlossen 
         if (taste0_vorher == 0)
         {
            // Schalter PD0 vorher offen => LED umschalten (toggeln)
            PORTB ^= (1<<PB0);

            // neuen jetzt Zustand merken
            taste0_vorher = 1;
         }
      }

      // ... 
   }
}

Autor: Jürgen Dell (dell)
Datum:

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

Autor: Rahul Der trollige (rahul)
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

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

Autor: Rahul Der trollige (rahul)
Datum:

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

Autor: Jürgen Dell (dell)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

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

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.