mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LED einzeln an per Funktion


Autor: Dominique (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,
ich habe einen ATMega16 und an PORTA 8 LEDs angeklemmt,
die ich jetzt einzeln ein/aus schalten möchte. Dafür haeb ich mir eine 
Funktion geschrieben, welche ich wie folgt aufrufe:

unique(LEDNr, Status);

also z.B. so:
unique(3,1); //Schaltet LED3 (PORTA2) ein

aber irgendwie funktioniert das noch nicht richtig, habe die funktion 
erstmal soweit bis zum EINSCHALTEN programmiert, um das Ausschalten 
kümmere ich mich danach.
hier die Funktion:
unique(int LEDNr, int Status)
{
int  LED = LEDNr-1;
char  praefix[3];

praefix[0] = 'P';

if((LED >= 0) && (LED <= 7))
{
praefix[1] = 'A';
praefix[2] = LED;
}

if(Status == 1)
{
PORTA |= (1 << praefix);   // hier wird Fehler angezeigt (siehe unten)
}
}

Der Fehler: main.c:1265: error: invalid operands to binary <<

ich hoffe mir kann jemand weiterhelfen, ich denke ich weiß auch woran 
das liegt, nämlich an der char variable, oder ??

vielen dank

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähem, das geht so nicht...

wie wärs mit:
unique(int LEDNr, int Status)
{
  if (Status == 1)
    PORTA |= (1 << (LEDNr-1));
}


Autor: Dominique (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
:)
ja genauso hatte ich das vor, das funktioniert super und ist viel 
kompakter als meine Idee....
vielen dank simon !!

Jetzt muss ich bloß noch hingehen nund was programmieren, das ich auch 
PORTC und PORTD damit ansprechen kann...
Habe eine LED-Leiste mit 24 LEDs und Treiberbaustein, die ich gerne 
einzeln ansteuern würde....
Also dirty geht es, halt nur einzenl über Funktionsaufruf war noch ein 
Featue, was ich brauchte :)


VIELEN DANK !! echt super geil !!

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
// PORTNr: 0=PortA, 1=PortB, 2=PortC, 3=PortD
// LEDNr: 0..7
unique(uint8_t LEDNr, uint8_t PORTNr)
{
  switch ( PORTNr )
   {
     case 0:
       PORTA |= (1 << LEDNr);
       break;
     case 1:
       PORTB |= (1 << LEDNr);
       break;
     case 2:
       PORTC |= (1 << LEDNr);
       break;
     case 3:
       PORTD |= (1 << LEDNr);
       break;
   }
}

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominique wrote:
> :)
> ja genauso hatte ich das vor, das funktioniert super und ist viel
> kompakter als meine Idee....
> vielen dank simon !!
>
> Jetzt muss ich bloß noch hingehen nund was programmieren, das ich auch
> PORTC und PORTD damit ansprechen kann...
> Habe eine LED-Leiste mit 24 LEDs und Treiberbaustein, die ich gerne
> einzeln ansteuern würde....
> Also dirty geht es, halt nur einzenl über Funktionsaufruf war noch ein
> Featue, was ich brauchte :)
>
>
> VIELEN DANK !! echt super geil !!

Übrigens: Das Ausschalten funktioniert mit obiger Funktion nicht. Nur 
das einmalige Anschalten. Wenn du die LED auch ausschalten möchtest 
(über den Status Parameter) dann musst du die Funktion etwas erweitern:
unique(int LEDNr, int Status)
{
  if (Status == 1)
    PORTA |= (1 << (LEDNr-1));  //LED AN
  else
    PORTA &= ~(1 << (LEDNr-1)); //LED AUS
}

Autor: Dominique (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo das habe ich schon :) aber etwas anders, aber läuft auch sehr gut 
meine Lösung...

hier ist sie:
unique(int LEDNr, int Status)
{
int  LED = LEDNr-1;

if((LED >= 0) && (LED <= 7))
{
if(Status == 1)
{
  PORTA |= (1 << (LEDNr-1));
}
else if(Status == 0)
{
  PORTA &= (0 << (LEDNr-1));
}
}
}

ist doch auch gut, oder ??
das mit dem switch-case finde ich auch eine sehr gute Lösung

Autor: Dominique (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alo gut, für PORTA und PORTC habe ich es am laufen, leider jedoch 
funktioniert die funktion nicht bei PORTD :(
hier mal die beiden Auszüge für A und D aus der Funktion unique();

=============================
if((LED >= 0) && (LED <= 7))
{
if(Status == 1)
{
  PORTA |= (1 << (LEDNr-1));
}
else if(Status == 0)
{
  PORTA &= (0 << (LEDNr-1));
}
}
=============================
if((LED >= 16) && (LED <= 23))
{
if(Status == 1)
{
  PORTD |= (1 << (LEDNr-1));
}
else if(Status == 0)
{
  PORTD &= (0 << (LEDNr-1));
}
}
=============================


Ich verstehe nicht ganz, wiedo das mit PORTD nicht geht :(
kann das an irgendwelchen Fuses liegen ??

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Ausschalten funktioniert in keiner der Varianten korrekt:

  PORTA &= (0 << (LEDNr-1));


Woran liegt das Problem?

0 << 1 ist 0, genauso wie 0 << 7 immernoch 0 ist.

PORTA &= 0 setzt den GESAMTEN PortA auf 0, schaltet also alle LEDs aus.


Simon hat bereits den richtigen Weg vorgeschlagen:

  PORTA &= ~(1 << (LEDNr-1));

Autor: Dominique (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Doch doch, Ausschalten geht auch mit meiner Variante, zumindest bei 
PortA und PORTC
bei PORTD geht garnichts mit dieser Variante, nichtmal einschalten :(

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominique wrote:
> Doch doch, Ausschalten geht auch mit meiner Variante, zumindest bei
> PortA und PORTC
Klar, wenn man das ganze Portregister Null schreibt, dann geht alles 
aus. Nur ist das, was Rufus schreibt, spätestens dann relevant, wenn an 
dem Port auch noch Sachen dranhängen, die nicht mit ausgehen sollen.

> bei PORTD geht garnichts mit dieser Variante, nichtmal einschalten :(
Das Problem mit Port D kann eigentlich nur in Deiner Initialisierung 
liegen, die Du geheimhältst... oder ein Hardware-Fehler.

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, aber wie Rufus bereits gesagt hatte: Du schaltet DEN GANZEN Port 
damit ab, und nicht einzelne LEDS.
Wenn natürlich nur eine an war, merkst du das nicht.

Wenn der PortD nicht geht, dann solltest du mal nach dem DDRD Register 
sehen, oder alternative Funktionen verwendet?

An Fuses liegt sowas nicht...

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

Bewertung
0 lesenswert
nicht lesenswert
Dominique wrote:
> if((LED >= 16) && (LED <= 23))
> {
> if(Status == 1)
> {
>   PORTD |= (1 << (LEDNr-1));
> }
> else if(Status == 0)
> {
>   PORTD &= (0 << (LEDNr-1));
> }
> }
> =============================
>
>
> Ich verstehe nicht ganz, wiedo das mit PORTD nicht geht :(
> kann das an irgendwelchen Fuses liegen ??

Überlag mal wie gross den LEDNr ist, wenn dieser if Zweig
betreten wird.
Und dann denk mal drüber nach, was mit einer 1 passiert, wenn
man sie derartig oft nach links schiebt.

Autor: Dominique (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja stimmt schon, das ich den ganzen port ausschalte, habe das jetzt 
alles geändert, aber es geht immer noch nicht:

Aber PORTD ist alles richtig initialisier, denn über meine anderen 
Funktionen kann ich den prima ansprechen, auch direkt aus der while 
schleife, alles kein problem, nur halt der aufruf aus dieser funktion 
heraus will nicht


=============================
if((LED >= 0) && (LED <= 7))
{
if(Status == 1)
{
  PORTA |= (1 << (LEDNr-1));
}
else if(Status == 0)
{
  PORTA &= ~(1 << (LEDNr-1));
}
}
=============================
if((LED >= 16) && (LED <= 23))
{
if(Status == 1)
{
  PORTD |= (1 << (LEDNr-1));
}
else if(Status == 0)
{
  PORTD &= ~(1 << (LEDNr-1));
}
}
=============================

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

Bewertung
0 lesenswert
nicht lesenswert
@Dominique

Du bist im Moment drauf und drann, dich regelmässig mit
übermässig kompliziertem Code selbst auszutricksen.

zb. Entweder du benutzt eine Variable LED, die grundsätzlich
um 1 kleiner ist als das übergebene Argument LedNr. Dann
benutzte aber bitte diese Variable quer durch deine Funktion.
Oder aber du schriebst überall in deiner Funktion LedNr-1.
Aber bitte dann auch konsequent
Oder aber du gehst den besten Weg von allen und akzeptierst
ganz einfach dass in C nun mal bei 0 angefangen wird zu
zählen. Gewöhn dich daran, das spart dir im Laufe der Zeit
viel Kopfzerbrechen: Das erste Element (egal wovon) ist
das mit der Ordnungszahl 0

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

Bewertung
0 lesenswert
nicht lesenswert
@Dominique

Ach ja, hab ich vergessen:

Ein konsistentes Einrückschema ist kein Luxus, sondern ein
Instrument um Fehler leichter sehen zu können. Also benutz
das auch.

Ich weiss: Neulinge sagen immer "Das mach ich später".
Nur: Ich hab schon erlebt, dass Neulinge stundenlang nach
Fehlern gesucht und nicht gefunden haben. Dann hab ich
als erstes mal den Code korrekt eingerückt und in 30 Sekunden
haben sie dann selbst das Problem gesehen.


PS: Hast du meine Anmerkung weiter oben gesehen?
Wenn nicht, hier ist sie nochmal:

> if((LED >= 16) && (LED <= 23))
> {
> if(Status == 1)
> {
>   PORTD |= (1 << (LEDNr-1));
> }
> else if(Status == 0)
> {
>   PORTD &= (0 << (LEDNr-1));
> }
> }
> =============================
>
>
> Ich verstehe nicht ganz, wiedo das mit PORTD nicht geht :(
> kann das an irgendwelchen Fuses liegen ??

Überlag mal wie gross den LEDNr ist, wenn dieser if Zweig
betreten wird.
Und dann denk mal drüber nach, was mit einer 1 passiert, wenn
man sie derartig oft nach links schiebt und nur 8 Bit zur Verfügung
hat.

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei Port D schiebst du in einem 8-bit Register die Leds 16 bis 23 mal. 
Also, bei Port D LEDNr - 16, dann sollte deine konstruktion 
funktionieren.

MW

Autor: Joe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau dir mal folgenden Thread an, hier wird eine Möglichkeit der 
direkten Zuweisung von PIN's innerhalb eines Ports erklärt.

Beitrag "sbit macro für avr-gcc"

Bei 8x51 Typen ist das kein Problem und für die AVR's gibts eben den 
genannten Workarround. Damit sollte es übersichtlicher und korrekt 
werden.

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.