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
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.
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
voidsleep(unsignedintms)
5
{
6
unsignedinti,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
intmain(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
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...
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ß
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.
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();
}
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...
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();
}
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();
}
}
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
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ß
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
intmain(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
return0;// 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.
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).
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ß
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.
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
voidtaster(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
intmain(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.
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ß