Forum: Mikrocontroller und Digitale Elektronik anfänger frage zu mikrocontroller programmierung


von andi (Gast)


Lesenswert?

hallo, ich besitze schon seit längerer zeit einen lernroboter, welcher 
in c programmiert wird. zur erklärung: der roboter besitzt einen atmel 
atmega 32 mikrocontroller.

ich habe auch schon öfter mit ihm programmiert.

 nur ist es leider so, dass ich bisher hauptsächlich nur mit den makros 
programmiert habe und die eigentlichen grundlagen von c programmierung 
nicht wirklich gelernt habe.

kann mir vielleicht mal jemand ein ganz einfaches und kurzes programm 
mit hilfreichen kommentaren posten, mit dem ich per eingangssignal einen 
ausgang ansteuern kann?

also einen taster drücken, und damit eine LED leuchten lassen. die 
hardware ist bei mir komplett vorhanden.

danke schon mal im voraus

von Skua C. (skua)


Lesenswert?

Da must du schon ein wenig mehr erzählen damit hier einer was sagen 
kann.

von Timmo H. (masterfx)


Lesenswert?

Schau dir doch hier mal das GCC Tutorial an. 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
Wenn allgemein C lernen willst empfielt es sich ein Buch zu Kaufen z.B. 
"C Programmieren von Anfang an" von Helmut Erlenkötter.

von Christoph M. (fakulatus)


Lesenswert?

Grundsätzliche Frage: Kennst du Pin und Port schon?
Falls Ja:
1
//Unterprogramm für das Erzeugen eines Delays
2
//Übergabeparameter ist die Wartezeit in ms
3
4
void sleep(unsigned int ms)
5
{
6
  unsigned int i,j; //Deklariere die Zählvariable
7
8
  for(i=0;i<ms;i++)
9
    for(j=0;j<795;j++);  //Eine Schlaufe die nichts tut (busywait)
10
}
11
12
int main(void) //Hauptprogramm
13
{
14
  DDRD |= (1<<3);  //Setze Port D Pin 3 als Output (DDRD=Directionregister Port D)
15
  
16
  while(1) //Führe die Schlaufe für Ewig aus (solange 1 = 1 :)
17
  {
18
    PORTD |= (1<<3); //Setze Port D Pin 3 auf 1
19
    sleep(1000); //Warte eine Sekunde
20
    PORTD &= ~(1<<bit); //Setze Port D Pin 3 auf 0
21
    sleep(1000); //Warte eine Sekunde
22
  }
23
   
24
}

Also falls du jetzt an Port D Pin 3 eine LED angeschlossen hast, blinkt 
die schön im Takt von einer Sekunde

Falls du einen Pin als Input verwenden willst, dann musst du das 
DDRD-Register auf 0 setzen (input) und PIND als Port verwenden.

Ansonsten kann ich dir das Manual empfehlen: 
http://www.mikrocontroller.net/articles/AVR-Tutorial

Das Datenblatt für deinen Prozessor findest du unter:
http://www.atmel.com/dyn/resources/prod_documents/doc2503.pdf

Als Buch eignet sich auch "C als erste Programmiersprache" ISBN 
978-3-8351-0222-4
Hat auch sehr schöne Syntax drin

von Skua C. (skua)


Lesenswert?

"Schlaufe" find ich Klasse!

von hust (Gast)


Lesenswert?

Ich hab auch mit dem Buch "C als erste Programmiersprache" C gelernt, da 
die Autoren an meiner Hochschule Professoren sind. Ich finde aber dieses 
Buch zum erlernen der Programmiersprache nicht sooo toll. Zum 
nachschlagen wenn man die Grundlagen mal beherscht ist es allerdings 
super.

Kann jetzt aber leider keinen Vorschlag machen für ein anderes Buch, hab 
mich da hauptsächlich mithilfe des Internets durchgewurschtelt.


http://www.win-tux.de/index.htm ist zum Beispiel eine gute Seite...

von andi (Gast)


Lesenswert?

danke schon mal für eure antworten. jetzt werd ich heute abend mal eure 
vorschläge ausprobieren. hilfreich sind sie auf jeden fall.

p.s. das gcc- tutorial hab ich schon begonnen zu lesen, find es aber an 
einigen stellen nicht ganz so aufschlussreich.

gruß

von Stefan B. (stefan) Benutzerseite


Lesenswert?

andi wrote:

> p.s. das gcc- tutorial hab ich schon begonnen zu lesen, find es aber an
> einigen stellen nicht ganz so aufschlussreich.

Notiere dir die Stellen und deine Fragen/Unklarheiten.

Wenn du in absehbarer Zeit nicht weiter kommst (manches braucht etwas 
Reife ;-), frage hier konkret nach.

von andi (Gast)


Lesenswert?

so, das programm funktioniert jetzt. aber was bedeutet eigentlich das |= 
und das &=~ in diesem programm genau?

gruß

von andi (Gast)


Lesenswert?

So, jetzt hab ich mal ausprobiert mit einem taster eine led anzusteuern.
Der taster ist am Register B am Pin 0 angeschlossen. Die ist am Register 
B an Pin 7 angeschlossen. hier mein programm:
irgendwo liegt noch ein programmierfehler denn die led leuchtet nicht



#include "RP6RobotBaseLib.h"


void taster(void)

{if (PINB & (1<<0))  //wenn PINB high (taster gedrückt)

  {
  PORTB |= (1<<7);}  //PIN7 von PORTB auf high

else
  {PORTB &=~ (1<<7);}  //PIN7 von PORTB auf low

  }

int main(void) //Hauptprogramm
{initRobotBase();

 DDRB&=~ (1<<0);  //PIN0 von PORTB als Eingang
DDRB |= (1<<7);   //PIN7 von PORTB als Ausgang

 taster();
}

von hust (Gast)


Lesenswert?

a &= b;

heist soviel wie

a = a & b;

also ein bitweises und.


das gleiche mit dem oder (|=)

~ => bitweises invertieren

a &= ~b;

löscht bei a die bits die bei b 1 sind...

von andi (Gast)


Lesenswert?

So, jetzt hab ich mal ausprobiert mit einem taster eine led anzusteuern.
Der taster ist am Register B am Pin 0 angeschlossen. Die ist am Register
B an Pin 7 angeschlossen. hier mein programm:
irgendwo liegt noch ein programmierfehler denn die led leuchtet nicht



#include "RP6RobotBaseLib.h"


void taster(void)

{if (PINB & (1<<0))  //wenn PINB high (taster gedrückt)

  {
  PORTB |= (1<<7);}  //PIN7 von PORTB auf high

else
  {PORTB &=~ (1<<7);}  //PIN7 von PORTB auf low

  }

int main(void) //Hauptprogramm
{initRobotBase();

 DDRB&=~ (1<<0);  //PIN0 von PORTB als Eingang
DDRB |= (1<<7);   //PIN7 von PORTB als Ausgang

 taster();
}

von Jean P. (fubu1000)


Lesenswert?

Hi,
so sollte dein Code funzen. Allerdings sollten die Tasten noch entprellt 
werden.


#include "RP6RobotBaseLib.h"

void taster(void)
{
  if (PINB & 0x01)  //wenn PINB high (taster gedrückt)
  {
    PORTB |= (1<<PB7);}  //PIN7 von PORTB auf high
  }
  else
  {
    PORTB &=~ (1<<PB7);}  //PIN7 von PORTB auf low
  }
}


int main(void) //Hauptprogramm
{
   initRobotBase();

   DDRB = 0x80; //PIN0 von PORTB als Eingang
                //PIN7 von PORTB als Ausgang
  while(1)
  {
    taster();
  }
}

von andi (Gast)


Lesenswert?

danke für deine hilfe, dein programm funktioniert.
aber ich habe noch ein paar fragen?

und zwar kann ich das PINB & 0x01 nicht einfacher ausgedrückt schreiben 
bzw. was bedeutet es?

das gleiche gilt bei DDRB = 0x80; . was bedeutet das? bzw. kann man es 
vereinfachen?

vielen dank schon mal im voraus

von Jean P. (fubu1000)


Lesenswert?

Hi,
du solltest mal mit Google nach nem C-Tutorial suchen und das 
AVR-C-Tutorial auf dieser Seite durcharbeiten.

PINB & 0x01 bedeutet, daß das Port Eingangsregister mit 0x01 "verundet" 
wird. Also werden alle Bits, bis auf das erste (PB0,was ja dein Eingang 
ist) auf Null gesetzt.

DDRB = 0x80 setzt alle Bits des Data Direction Registers auf Null, bis 
auf das letzte, das setzt es auf eins, also Ausgang (PB7).

Meine ganzen Zahlen sind im Hexadezimalformat geschrieben, vielleicht 
schauste dir das zusammen mit den Tutorialen auch gleich an.

Gruß

von andi (Gast)


Lesenswert?

aber ne möglichkeit das einfacher das eben erklärte zu verwenden gibt es 
nicht, oder?

von andi (Gast)


Lesenswert?

p.s. ich mein auf die art, wie ich es oben vorher schon einmal versucht 
habe.

von Иван S. (ivan)


Lesenswert?

andi wrote:
> hallo, ich besitze schon seit längerer zeit einen lernroboter, welcher
> in c programmiert wird. zur erklärung: der roboter besitzt einen atmel
> atmega 32 mikrocontroller.
> ich habe auch schon öfter mit ihm programmiert.
>
>  nur ist es leider so, dass ich bisher hauptsächlich nur mit den makros
> programmiert habe und die eigentlichen grundlagen von c programmierung
> nicht wirklich gelernt habe.

Hallo Andi, leider kenne ich weder Deine Hardware noch die 
Implementierung der Ansteuerung in deinen Makros und C-Bibliotheken. 
Daher kann dein Anliegen auch kaum sinnvoll bearbeitet werden. Die 
Sprache C an sich stellt dir nur ein syntaktisch standardisiertes 
Regelwerk zur Programmierung zur Verfügung. Der Compiler prüft Syntax 
(und in gewissen Grenzen die Semantik), wie genau das Endergebnis 
implementiert ist kannst Du jedoch nur durch Studium der Quelltexte der 
von Dir verwendeten Bibliotheken  herausfinden - oder, falls du 
Assembler kannst, durch Disassemblierung.

Ich verstehe Dein Problem und glaube zu wissen worauf Du hinauswillst.
Im Grunde läuft es doch daruf hinaus, daß du die Funktionsweise deiner 
C-Funktionen und -Makros verstehen willst. Ohne zuerst jedoch die 
Sprache  zu verstehen wird es ein nichttriviales Problem. Also lerne 
erst C (dazu gibt es verschiedene Ansätze) und versuche dann die 
Arbeitsweise der von Dir genutzten Funktionen zu verstehen.

> kann mir vielleicht mal jemand ein ganz einfaches und kurzes programm
> mit hilfreichen kommentaren posten, mit dem ich per eingangssignal einen
> ausgang ansteuern kann? also einen taster drücken, und damit eine LED
> leuchten lassen. die  hardware ist bei mir komplett vorhanden.

1
#include <roboter/iosubsys.h> // Headerdatei für Roboter einbinden
2
3
int main(void)                // Hauptroutinen-Einsprungspunkt
4
{
5
 while (true)                 // Endlosschleife
6
 {
7
  if ( inputpoller(IOINPUTPIN01,HIGH) == true) // Taster an Pin 1 abfragen
8
       output(IOOUTPUTPIN03,HIGH);             // LED an Pin 3 rinschalten
9
 }
10
return 0;                     // Korrekte Semantik beim Aufruf von main()
11
}

> danke schon mal im voraus

Keine Ursache und viel Erfolg.

PS: Die Verwendung der üblichen Groß- und Kleinschreibung erhöht die 
Chance auf sinnvolle Antworten.

von Gast (Gast)


Lesenswert?

Wenn Pins angesteuert werden, wird hier oft das Hexadezimalsytem 
verwendet. Es ist dafür einfach praktischer.

Zum Umrechnen auf Binär und Dezimal kannst du den Normalen Rechner 
deines Betriebssystems verwenden. Dazu musst du ihn auf wissenschaftlich 
schalten.

Hier mal eine kurze Tabelle:

Pin0 = 00000001 = 0x01 = 1
Pin1 = 00000010 = 0x02 = 2
Pin2 = 00000100 = 0x04 = 4
Pin3 = 00001000 = 0x08 = 8
Pin4 = 00010000 = 0x10 = 16
Pin5 = 00100000 = 0x20 = 32
Pin6 = 01000000 = 0x40 = 64
Pin7 = 10000000 = 0x80 = 128

Insgesamt 8 Pins gibt 1 Port. Bei manchen µC sind nicht alle Pins 
vorhanden.

Um mehrere Pins gleichzeitig zu schalten, musst du am besten per 
Taschenrechner die einzelnen Pinzahlen zusammenrechnen.
Z.B. 0x55 = 01010101 = Pin6, Pin4, Pin 2, Pin 0 auf eine High oder 
Ausgang.
Beim Binär ist links der höchste Pin(7) und rechts der kleinste (0).

von andi (Gast)


Lesenswert?

danke. genau das wollte ich wissen. weil mir halt auffällt das die 
ausgänge auf sehr viel verschiedene arten angesteuert werden können, wie 
man auch in diesem thread sieht.

gruß

von andi (Gast)


Lesenswert?

wie kommt es dann, dass in fubu1000 geposteten programm er mit

DDRB = 0x80; //PIN0 von PORTB als Eingang
                //PIN7 von PORTB als Ausgang

dann diese funktion ausführen kann?
nach oberer erklärung dürfte er damit ja nur pin 7 ansprechen.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

andi wrote:

> wie kommt es dann, dass in fubu1000 geposteten programm er mit
>
> DDRB = 0x80; //PIN0 von PORTB als Eingang
>                 //PIN7 von PORTB als Ausgang
>
> dann diese funktion ausführen kann?
> nach oberer erklärung dürfte er damit ja nur pin 7 ansprechen.

Meinst du dieses Programm?
1
#include "RP6RobotBaseLib.h"
2
3
void taster(void)
4
{
5
  if (PINB & 0x01)       //wenn PINB high (taster gedrückt)
6
    PORTB |= (1<<PB7);   //PIN7 von PORTB auf high
7
  else
8
    PORTB &= ~(1<<PB7);  //PIN7 von PORTB auf low
9
}
10
11
int main(void) //Hauptprogramm
12
{
13
  initRobotBase();
14
  DDRB = 0x80; //PIN0 von PORTB als Eingang
15
               //PIN7 von PORTB als Ausgang
16
  while(1)
17
    taster();
18
}

Bei deiner Frage wird das Datenrichtungsregister DDRB gesetzt und anders 
geschrieben sieht das so aus (PB7 ist als 7 definiert):

  DDRB = 0 + (1<<PB7); // == 0x80 == 0b10000000

Alle 0 Bits im Register stellen den betreffenden Portpin auf Ausgang, 
alle 1 Bits auf Eingang.

Aufpassen muss man, wenn man statt = ein |= oder ein &= oder ein ^= im 
Code sieht. Denn

  DDRB |= (1<<PB7); // == 0x80 == 0b10000000

entspricht dann

  DDRB = DDRB | (1<<PB7); // == 0x80 == 0b10000000

Dder Eingang wird dann tatsächlich erst in dieser Zeile abgefragt:

  if (PINB & 0x01)       //wenn PINB high (taster gedrückt)

Anders geschrieben so (PB0 ist als 0 definiert)

  if (PINB & (1<<PB0))   //wenn PINB high (taster gedrückt)

Je nach Ergebnis der Abfrage des Eingangs wird der Ausgang in diesen 
Zeilen verändert:

    PORTB |= (1<<PB7);   //PIN7 von PORTB auf high
    PORTB &= ~(1<<PB7);  //PIN7 von PORTB auf low

Anders geschrieben so (PB7 ist als 7 definiert):

    PORTB |= 0x80;  //PIN7 von PORTB auf high
    PORTB &= 0x7F;  //PIN7 von PORTB auf low

Anders geschrieben so

    PORTB = PORTB | 0x80;  //PIN7 von PORTB auf high
    PORTB = PORTB & 0x7F;  //PIN7 von PORTB auf low

IMHO ist die Schreibweise mit (1<<irgendwas) am lesbarsten und am 
sichersten, wenn sich die symbolischen Namen irgendwas ändern.

von andi (Gast)


Lesenswert?

danke stefan, deine erklärung ist wirklich mehr als hilfreich.
jetzt hab ich mal einen guten überblick über die verschiedenen 
möglichkeiten.

kann ich das auch so machen?

PORTB |= 0x80;  //PIN7 von PORTB auf high
PORTB &=~ 0x80;  //PIN7 von PORTB auf low

gruß

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Kannst du.

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.