PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Einfaches, kurzes selbst geschriebenes Programm überprüfen



Da_Vinci13
20.01.2009, 19:50
Hi,
Ich hab jetzt mal kurz ein Programm für einen ATmega8 geschrieben...
Ich will, dass sobald Spannung auf PA1 liegt, PA2 aktiviert wird... auf dem Datenblatt steht neben PA1 (ADC), was auch immer ADC bedeuten wird...

include <avr/io.h>

int main (void)
{
DDRA = 0x00
}

if (PINA & ( 0x02))
{
DDRA = 0x04
PORTA = 0x04
}
return 0;



Würde das so aufgehen?

Grüsse!

askazo
20.01.2009, 21:30
Im Ansatz richtig, in der Ausführung nicht ganz.
1. In Deiner main-Funktion steht nur
DDRA = 0x00;
Die if Schleife steht völlig außerhalb jeder Funktion, da würde der Compiler meckern.
2. Die DDR-Register werden normalerweise nur einmal beim initialisieren des Controllers gesetzt. Einen Port zur Laufzeit von Eingang zu Ausgang zu wechseln oder umgekehrt macht man eigentlich nicht.
3. So wie Du's jetzt hast, würde PA1 nur ein einziges mal abgefragt, danach steht der Controller still. Da müsste noch eine Endlosschleife hin.
4. Du hast ein paar Semikola vergessen...

Hier mal das Programm, wie's korrekt aussehen würde:

include <avr/io.h>

int main (void)
{
DDRA = 0x04;

while(1)
{
if (PINA & 0x02)
{
PORTA = 0x04;
}
}
return 0;
Allerdings würde so PA2 angehen, wenn PA1 auf High geht - aber nie wieder aus. Da müsste dann noch was dazu, aber da lasse ich Dich erst mal basteln....

Ach ja: ADC = Analog-Digital-Wandler = Eingang, um analoge Spannungen zu messen.

Gruß,
askazo

markusj
20.01.2009, 22:43
Schön wäre jetzt noch die Verwendung von Konstanten anstelle von 0x04 ...
Bsp:

include <avr/io.h>

int main (void)
{
DDRA |= (1 << DDA2); //A2 auf Ausgang konfigurieren

for(;;) //effektivste endlosschleife *g*
{
if (PINA & (1 << PINA1))
{
PORTA |= (1 << PA2); //Ausgang auf 1 setzen, ohne die anderen Werte "kaputt" zu machen - wenn direkt überschrieben werden soll wird anstelle von |= einfach nur = geschrieben.
}
return 0;
}


mfG
Markus

Edit: Im Nachfolgepost erwähnte Fehler behoben, danke johns!
Edit: PB2 durch PA2 ersetzt - ich werd' auch immer wacher^^.

johns
21.01.2009, 00:26
hallo,

bin zwar ein alter copy'n'paster, aber das return sollte innerhalb der main funktion sein (letzte beiden zeilen vertauschen).
(anmerkung: je nach compiler kann man das return statement auch weglassen, denn es wird ohnehin nie erreicht.)

ausserdem passt in zeile 4 das kommentar nicht zur semantik des statements:
DDRA = (1 << DDA2); //A2 auf Ausgang konfigurieren
hier werden in wirklichkeit zusätzlich alle anderen pins von port A als eingang konfiguriert.

und da markus die bitweisen operatoren eingebracht hat, hier weiter information zu diesem wichtigen thema:

&, |, ^ und ~ operatoren:
http://de.wikipedia.org/wiki/Bitweiser_Operator#Bitweise_Operatoren
<< und >> operatoren (für vorzeichenlose ganze zahlen):
http://de.wikipedia.org/wiki/Bitweiser_Operator#Logische_Verschiebung
und hier nochmal für C speziell:
http://home.fhtw-berlin.de/~junghans/cref/CONCEPT/bitwise.html

und die (grösse der) in C verfügbaren elementaren datentypen:
https://www.roboternetz.de/wissen/index.php/C-Tutorial#Elementare_Datentypen

ausserdem wurde im gezeigten code die kuzschreibweise für arithmetische und logische operatoren verwendet (i.e. |=), eine erklärung ist hier in der tabelle "Kurzschreibweisen" zu finden:
https://www.roboternetz.de/wissen/index.php/C-Tutorial#Liste_der_Operatoren

lg


ps. zu erwähnen dass es sich bei 0x04 auch um eine konstante handelt würde wohl nur unnötig verwirrung stiften ;)

askazo
21.01.2009, 06:49
hallo,

bin zwar ein alter copy'n'paster, aber das return sollte innerhalb der main funktion sein (letzte beiden zeilen vertauschen).
Uups, natürlich....mein Fehler....

@Markus:
Wieso ist for( ; ; ) effektiver als while(1) ?

Was man doch über ein so simples kleines Programm philosophieren kann....:cheesy:

markusj
21.01.2009, 10:47
Danke johns, ich war so frei den Post oben entsprechend zu editieren ...

Randbemerkung zu dem 0x04: Natürlich ist das auch eine Konstante, aber der sieht man nicht auf den ersten Blick an, was sie tut - bei:
DDRA |= (1 << DDA2);
weiß man sofort, dass hier der Pin A2 auf Ausgang konfiguriert wird.

@askanzo: Sagt Atmel in der Application Note 35 (Efficient C-Code), dass for(;;) {} für Endlosschleifen am effektivsten ist ... komische Welt.

mfG
Markus

PS: Ich würde dem Threadersteller die beiden AVR-C-Einführungen aus dem RN-Wissen und von mikrocontroller.net empfehlen!

Da_Vinci13
21.01.2009, 16:33
Hi!
Danke für die vielen Antworten!
@askazo:
Du hast gefragt wie man es machen könnte, damit der Roboter irgendwann wieder etwas anders macht:
Könnte man vielleicht das "if" durch ein "while" ersetzen? In meinem Buch steht:
Solange Anweisung, Ausdruck:
while (PINA & (1 << PINA1))
PORTA |= (1 << PORTA2)
Danach könnte man einen neuen Block machen, welcher dann ausgeführt wird sobald (PINA & (1 << PINA1)) False ist...

@markusj:
Bei deinem Programm steht:
PORTA |= (1 << PB2)
Warum PB?
Müsste da nicht PORTA2 stehen?

Stimmt das ist die übersichtlichere Schreibweise... wenn ich z.B. PORTA |= (1 << PORTA3) schreibe, sind dann die restlichen PORTs von PORTA 0? bzw. Eingänge?

Grüsse!


Denn solange

markusj
21.01.2009, 20:38
@markusj:
Bei deinem Programm steht:
PORTA |= (1 << PA2)
Warum PB?
Müsste da nicht PORTA2 stehen?

Stimmt das ist die übersichtlichere Schreibweise... wenn ich z.B. PORTA |= (1 << PORTA3) schreibe, sind dann die restlichen PORTs von PORTA 0? bzw. Eingänge?Ich verweise jetzt einfach einmal auf mikrocontroller.net (http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Vordefinierte_Bitnummern_f.C3.BCr_I.2FO-Register). Die Konstanten korrespondieren mit dem jeweiligen Register (X = Pinnummer):
DDR? => DD?X
PIN? => PIN?X
PORT? => P?X

mfG
Markus

Edit: PB2 durch PA2 ersetzt - ich werd' auch immer wacher^^.

johns
21.01.2009, 21:12
PORTA |= (1 << PB2)
Warum PB?
Müsste da nicht PORTA2 stehen?

es sollte PA2 sein, würde aber so das selbe ergebnis liefern, da PA2 den selben wert darstellt wie PB2 (und PC2, ...), nämlich 2, den index des pins eben.



Stimmt das ist die übersichtlichere Schreibweise... wenn ich z.B. PORTA |= (1 << PORTA3) schreibe, sind dann die restlichen PORTs von PORTA 0? bzw. Eingänge?


du hast einen port A an dem gewisse pins für andere dinge konfiguriert sind, und der pin mit nummer 3 ist 0. das konnte in binärdarstellung so aussehen:

PORTA: 01100011

als nächstes wird die klammer ausgewertet, also werden die bits des wertes 1 um 3 (wert von PA3) stellen nach rechts verschoben:

00000001 << 3 ergibt 00001000

dieser wert wird nun mit PORTA oder-verknüpft und das ergebnis wird in PORTA gespeichert:

01100011 ODER
00001000
------------
01101011

wie du siehst bleiben die restlichen pins unverändert.


lg