mikrocontroller.net

Forum: Compiler & IDEs Port als Variable


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte gern Atmel-Controller (myAVR) in der Schule einsetzen und 
hatte dazu einen Lehrgang besucht, in dem mit E-Lab AVRco (Pascal) 
programmiert wurde.

Nun gefällt mir Pascal nicht sonderlich und ich würde gern in C/C++ 
programmieren, auch weil es da mehr Hilfe und mehr Beispiele gibt.

Soweit so gut, einige Testprogramme aus Pascal konnte ich bereits in C 
nachvollziehen, aber an einer Sache beiße ich mir gerade die Zähne aus. 
In AVRco kann man einfach einem Port eine Variable zuweisen und diese 
Variable 1 oder 0 setzen:

var ledrt[@PortB,0]:bit;  //Variable für rote LED an Port B0, Typ bit
var ledge[@PortB,1]:bit;
...
ledrt:=1;
ledge:=0;
mdelay(300);
ledrt:=0;
ledge:=1;
mdelay(300);

In Entwicklungsumgebungen, die auf avr-gcc beruhen, habe ich keine 
solche Möglichkeit gefunden. Ich kann zwar der Portnummer eine Variable 
zuordnen, die Zuweisung des Status an/aus ist aber dann wesentlich 
kryptischer:

#define ledrt PORTB0
#define ledge PORTB1
...
PORTB |= (1<<ledrt);
PORTB &= ~(1<<ledge);
_delay_ms(300);
PORTB |= (1<<ledge);
PORTB &= ~(1<<ledrt);
_delay_ms(300);

Der Pascal-Code ist deutlich anschaulicher, auch wenn man an dem 
C-Beispiel gleich die Boolesche Algebra erklären kann.

Gibt es eine Pascal-ähnliche Syntax in C/C++?

Vielen Dank schon mal!
Jürgen

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen schrieb:

> solche Möglichkeit gefunden. Ich kann zwar der Portnummer eine Variable
> zuordnen, die Zuweisung des Status an/aus ist aber dann wesentlich
> kryptischer:
>
> #define ledrt PORTB0
> #define ledge PORTB1
> ...
> PORTB |= (1<<ledrt);
> PORTB &= ~(1<<ledge);
> _delay_ms(300);
> PORTB |= (1<<ledge);
> PORTB &= ~(1<<ledrt);
> _delay_ms(300);

Gewöhn dich daran.


> Gibt es eine Pascal-ähnliche Syntax in C/C++?

Wie gut sind deine C-Kentnisse?
Klar kann man. Nur eben nicht 'out of the box'. Aber für einen C-Kenner 
ist das kein Problem.

Nur um mal die einfchste Variante zu zeigen

#define SET_BIT(p,b)  (p) |= (1<<(b))
#define CLR_BIT(p,b)  (p) &= ~(1<<(b))

#define ERROR_LED_PORT   PORTB
#define RED_LED          PB0
#define YELLOW_LED       PB1
...


int main()
{
  ...


  SET_BIT( ERROR_LED_PORT, RED_LED );
  CLR_BIT( ERROR_LED_PORT, YELLOW_LED );

  ...
}

Oder, das ganze noch eine Klkeinigkeit weiter getrieben

#define SET_BIT(p,b)  (p) |= (1<<(b))
#define CLR_BIT(p,b)  (p) &= ~(1<<(b))

#define ERROR_LED_PORT   PORTB
#define RED_LED          PB0
#define YELLOW_LED       PB1
...

#define RED_ERROR_LED_ON    SET_BIT( ERROR_LED_PORT, RED_LED )
#define RED_ERROR_LED_OFF   CLR_BIT( ERROR_LED_PORT, RED_LED )
...

int main()
{
  ...

  RED_ERROR_LED_ON;

  ...


oder man kann sich dafür Funktionen schreiben. Oder ....
Und man kann natürlich, wenn man es kann, sich auch etwas zurecht legen, 
so dass man schreiben kann
int main()
{

    ErrorPort.RedLed = ON;

...

Hängt alles nur davon ab, wie gut dein C ist.
Aber: Da jeder eine andere Vorstellung davon hat, wie sowas aussehen 
sollte, gibt es da kaum Standard-Verfahren, bzw. man landet auf 
unterster Stufe immer wieder beim

   PORTB |= ( 1 << PB0 );

das ist nun mal das universellste und alles weitere leitet sich davon 
ab. PS: Was machst du, wenn du wirklich mehrere Portpins auf einmal auf 
1 setzen willst? In C schreibst du

   PORTB |= ( 1 << PB0 ) | ( 1 << PB1 );

bzw. mit entsprechendem Makro-Ersatz dann eben auch mit sprechenderen 
Namen. Aber: es geht. Du kannst in einem Aufwasch mehrere Portpins auf 
einmal schalten.

Autor: troll (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen schrieb:
> Gibt es eine Pascal-ähnliche Syntax in C/C++?
Über Bitfelder (eher was für Fortgeschrittene) 
Beitrag "Re: "Syntaxbefehl" erstellen" oder 
Präprozessormakros
#define AN(p,v) (p|=(1<<v))
#define AUS(p,v) (p&=~(1<<v))
und das Spiel kann man dann weiter treiben
#define PORTLED PORTB
#define LED1 3
#define LED1_AN AN(PORTLED,LED1)
usw.

Autor: troll (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
KHB war mal wieder schneller. :-)

Autor: Karl H. (kbuchegg) (Moderator)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Und Ach ja.

Die Schwierigkeit bei Programmen aus der realen Welt besteht ja darin 
die Logik hinzukriegen und nicht welche Syntax man jetzt benutzt um 
einen Portpin auf 0 oder auf 1 zu schalten. In der Praxis sehen die 
wenigsten Programme nun mal so aus
int main()
{
  DDRB |= ( 1 << PB0 ) | ( 1 << PB1 );

  while( 1 ) {

    PORTB |= ( 1 << PB0 );
    PORTB &= ~( 1 << PB1 );
    _delay_ms( 1000 );

    PORTB &= ~( 1 << PB0 );
    PORTB |= ( 1 << PB1 );
    _delay_ms( 1000 );
  }
}

Sowas ist ja die Ausnahme. Reale Programme haben einen wesentlich 
höheren Logikanteil, so dass die paar Portzuweisungen kaum ins Gewicht 
fallen. Und wenns einen stört, dann versteckt man die eben hinter 
Makros.

Autor: Julius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also Bitfelder finde ich gar nicht sooo schwierig besonders wenn die 
schon vordefiniert sind ;-) mit einem myAVR hast doch schon sowas schau 
mal hier: http://www.avr-cpp.de das sieht dann in etwa so  aus:
   ...
   ddrB.bit0=1;   // B.0 auf Ausgang
   portB.bit0=1;  // B.0 LED an
   ...

Gruß J.

Autor: Peter D. (peda)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Jürgen schrieb:
> die Zuweisung des Status an/aus ist aber dann wesentlich
> kryptischer:

Nö, muß man nicht.
Es geht auch ähnlich einfach, wie unter Pascal:
#include "sbit.h"
#define IN_A      PIN_D2
#define OUT_A     PORT_D5
#define OUT_A_oe  DDR_D5

int main(void)
{
    OUT_A_oe = 1;

    while(1)
    {
        if(IN_A)
          OUT_A = 1;
        else
          OUT_A = 0;
        // oder so:
        OUT_A = IN_A; // ist aber mehr Code
    }
}

http://www.mikrocontroller.net/attachment/157663/sbit.h

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Tip mit sbit.h - das ist genau was ich will und dazu (so 
hoffe ich) auch frei.
#include  <avr\io.h>
#include  <avr\sbit.h>
#define Taster  PIN_D2  
#define LED     PORT_D5

int main(void)
{
    PORT_D2 = 1;     // Pull-Up-Widerstand 
    DDR_D5 = 1;       // Ausgang setzen

    while(1)
    {
        if(Taster)
          LED = 1;
        else
          LED = 0;
    }
}

SiSy (http://sisy.de) gefällt mir zwar noch besser (objektorientiert), 
kostet aber als Schulversion 49 EUR je Arbeitsplatz und zeigte unter Win 
7 Probleme bei normalen Benutzerrechten.

Jürgen

Autor: iab (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> #include  <avr\io.h>

Besser:

#include  <avr/io.h>

da portabler.

Noch besser:

#include  <io.h>

und den Includepfad per Compileroption auf .../avr
setzen.

Autor: Oliver (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
iab schrieb:
> Noch besser:
> #include  <io.h>
>
> und den Includepfad per Compileroption auf .../avr
> setzen.

Warum sollte das noch besser sein? Das einzige, was du damit erreichst, 
ist, daß sich deinen Programme auf keiner anderen 
avr-gcc-Standardinstallation ohne Anpassungen compilieren lassen.
#include  <avr/io.h>
ist Standard, und dabei solte man auch bleiben.

Oliver

Autor: Julius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich halte die GCC-Standard-Installation nicht unbedingt für den Stein 
der Weisen und das oberste Ende der Entwicklung. Der GCC ist eher eine 
Basis von der aus man ausgehen kann und etwas auf seine Bedürfnisse 
zuschneiden  oder weiterentwickeln kann. Das Sieht man deutlich bei den 
kommerziellen oder herstellerspezifischen Umgebungen. Es taucht hier 
immer wieder das Bedürfnis ich nenne es mal "moderneren" 
Sprachkonstrukten als Shift-Opreationen zu benutzen. Solche Angebote 
wie:

http://www.luna.de
http://www.avr-cpp.de
http://sourceforge.net/projects/veavrcclasslibr/
http://www.mySTM32.de
usw. usw.

kann man nicht einfach wegbügeln mit "das ist kein GCC-Standard deswegen 
mach das nicht" besser ist es darüber konstruktiv zu diskutieren. So das 
musste mal raus ;-)

Also ich find es absolut OK wenn er sich seine IDE verbiegt :-D er 
erkundet wie es besser gehen kann und lernt und wir lernen mit ihm

Gruß J.

Autor: Julius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so sorry

http://avr.myluna.de/doku.php

das gemüse meinte ich nicht ;-)

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julius schrieb:
> Es taucht hier
> immer wieder das Bedürfnis ich nenne es mal "moderneren"
> Sprachkonstrukten als Shift-Opreationen zu benutzen.

Klar kann man sich für Port-IO elegantere Lösungen denken, als das 
Standard-C-Bitgeschubse, aber:

Ich sach mal so: In jeder ernsthaften Anwendung, die über das erste 
Testprogramm "LED-Blinken" hinausgeht, machen die Port-IO-Operationen 
weniger als 0,00x% des gesamten Codes aus. Wer da schon an den 
Bitoperationen scheitert, kriegt den Rest eh nicht hin.

Und die, die den Rest hinkriegen, die störten die paar Zeilen nicht.

Das es mit Arduino, Luna, Bascom, et. al. alternative toolchains mit 
Vor- und Nachteilen gegenüber einem avr-gcc mit avrlibc gibt, ist prima. 
So hat jeder die freie Wahl.

Vorhandene libs der Struturen auf Sourccde-Ebene zu erweitern, ist eine 
geute Sache. IDEs verbiegen ohne sinnvollen Grund zu verbiegen ist 
dagegen keine gute Idee. Spätestens mit dem nächste Update läuft man 
damit voll in die Schxxxe.

Oliver

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Julius schrieb:
> ich halte die GCC-Standard-Installation nicht unbedingt für den Stein
> der Weisen und das oberste Ende der Entwicklung.

Das bedeutet aber nicht, dass man es deshalb zwanghaft anders machen 
muss. Ich finde ein avr/io.h auch besser als nur io.h. Das ist ähnlich 
wie in C++ mit Namespaces. Man verteilt die Header auf verschiedene 
Verzeichnisse, abhängig davon, für welchen Bereich von Funktionalität 
sie verwendet werden. Und man läuft nicht Gefahr, dass sich jemand ein 
eigenes io.h definiert hat, das dann damit kollidiert.
Das ist etwas, das sehr viele Bibliotheken so machen. Was findest du 
daran schlecht?

> kann man nicht einfach wegbügeln mit "das ist kein GCC-Standard deswegen
> mach das nicht" besser ist es darüber konstruktiv zu diskutieren. So das
> musste mal raus ;-)

Es geht nicht um GCC selbst, sondern eher um die avr-libc. Und ich kann 
umgekehrt auch sagen, nur weil die von dir genannten Projekte es 
irgendwie anders machen, heißt das nicht, dass das der Stein der Weisen 
ist und man bei der Benutzung von avr-libc die avr-libc-Gepflogenheiten 
verwerfen sollte.

> Also ich find es absolut OK wenn er sich seine IDE verbiegt :-D er
> erkundet wie es besser gehen kann und lernt und wir lernen mit ihm

Wie schon gesagt wurde: Was du vorschlägst, ist nicht besser. Es hat 
keinerlei Vorteil, außer dass man 4 Zeichen weniger tippen muss.
Und wenn man etwas "verbiegen" muss, weil man es anders machen will als 
alle anderen, dann ist das zwar nicht immer, aber doch meistens ein 
Zeichen dafür, dass man was falsch macht.

: Bearbeitet durch User
Autor: Peter D. (peda)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Das bedeutet aber nicht ...

Ob Julius nach 6 Jahren noch mitliest?

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Huch? Warum wurde mir der Thread als einer mit neuen Beiträgen 
angezeigt? Ich bin verwirrt…

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.