www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PortPins setzen und halten, Rotation


Autor: KernoKopp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Gemeinde.
Ich komme im Moment gar nicht weiter.

Device 8051
Sprache C

Ich möchte die 8 Pins eines Ports schalten.
Jedes gesetzte Pin soll gehalten bleiben.

Bspl.

Alle Pins sind auf Low.
Es wird ein Pin auf High gesetzt. z.B. Pin 5
Danach sollen automatisch die höherwertigen Pins (6 und 7) nacheinander 
gesetzt werden.
Ist Pin 7 erreicht soll es bei Pin 0 weitergehen, bis wieder Pin 5 
erreicht wird.
Dabei sollen die durchlaufenen Pins auf High bleiben.
Ist Pin 5 erreicht geht der ganze Port auf Low und es geht von vorn los.
Quasi wie eine Rotation, oder so. :o)

Hat jemand die zündende Idee?

Im Vorraus vielen Dank.

Kerno

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im einfachsten Fall über ne Tabelle:

#include <reg51.h>

char code pattern[] = { 0x01, 0x02, 0x04 };  // Hier die Bitmuster eintragen


void main( void )
{
  char code *p;
  unsigned int i;

  for(;;){
    for( p = pattern, i = sizeof(pattern); i; i-- ){
      P2 = *p++;
    }
  }
}


Peter

Autor: Drachenbändiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist vermutlich auch für den 8051 anwendbar:

Für AVR: Wenn es ganz schnell gehen muss, dann mit Inline-Assembler, 
weil Du damit Zugriff auf das Carry hast.

Ansonsten z.B. so:
   uint8_t pattern =0x40; // Anfangswert (nur als Beispiel)
   uint8_t oldpattern=0x40; // = Anfangswert
   
   do {     
        pattern |= (pattern<<1); 
        if (pattern==oldpattern) pattern|=1; // da wir kein Carry haben
        oldpattern=pattern;
        // hier die Ausgabe einfügen
    } while (pattern!=0xff);
    pattern=0;
    // wieder Ausgabe

Autor: KernoKopp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entschuldigt meine späte Antwort.
Danke für eure Denkanstöße.

Ich habe beide Varianten angesehen und mir angepasst.

@Peter:

In dieser Zeile habe ich noch das  "+" eingefügt, da bleiben die 
durchlaufenen Bits auf High. Sicher nur vergessen worden.
 P2 = *p++; 
 ->
 P2 += *p++; 

Diese Funktion kann ich mir jetzt nicht so anpassen, wie ichs brauche, 
damit´s bei 0 wieder los geht.
Werde mir aber bei Gelegenheit diese Variante nochmal vornehmen.


@Drachenjäger:

Dein
>> // hier die Ausgabe einfügen
habe ich an den Anfang der do-while Schleife gesetzt, sonst sind schon 
das Anfangsbit und das nächste Bit gesetzt im ersten Durchlauf gesetzt.

Wenn ab dem Anfangswert z.B Pin 5 alle Pins bis Pin7 gesetzt sind, 
dauert es ne weile bis bei Pin 0 weiter gemacht wird. Warum ist das so?
Ok habs: int -> u_char

Muss ich oldpattern mit einem Wert initialisieren?
Nein. Oder?

Ansonsten machte die Funktion auf Anhieb das, wie ich es mir vorgestellt 
habe.
#include<stdio.h>
#include<at89c51xd2.h>

sfr port = 0x90;

int main (void){

  int k;
  unsigned char pattern, oldpattern, startwert = 32; 
  pattern = startwert;
  
  while(1){ 
  
    if (port==0xff){  
      pattern = startwert;
    }
    port = pattern;   
    pattern |= (pattern<<1); 
    if (pattern==oldpattern) pattern|=1; // da wir kein Carry haben
    oldpattern=pattern;
    for(k=20000;k>=0; k--); 
  }
  return 0;
}


Vielen Dank für die Anregungen.
Ich hatte schon nen Knoten in den Fingern.

Oh! Da da sehe ich schon eine weitere Hürde.
Meine "Rotation" darf nur über 7 Pins und nicht über 8 Pins gehen.
Ist Drachenjäger´s Version nur für 8 Pins machbar?

Grüße Kerno.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
KernoKopp schrieb:
> In dieser Zeile habe ich noch das  "+" eingefügt, da bleiben die
> durchlaufenen Bits auf High. Sicher nur vergessen worden.

Nein.
Die Tabelle ist doch nur ein Beispiel.
Du mußt die Tabelle selber erstellen!


> Diese Funktion kann ich mir jetzt nicht so anpassen, wie ichs brauche,
> damit´s bei 0 wieder los geht.

Siehst Du.


Peter

Autor: KernoKopp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mhh...da bräuchte ich 49 Tabelleneinträge.
Ich habe eine Laufvariable, die nur die Zahl 1-7 annehmen kann.

-> Das ganze sieht aus wie ein Monatsplan. Einmal die Woche findet ein 
Event statt. Welcher Tag das ist, legt der Benutzer fest.

Pin0 = Montag
Pin7 = Sonntag

Es gibt ein Event, welches an einem beliebigen Wochentag passiert.
z.B. Mittwoch = Pin2.

Da leuchtet der Mittwoch.
Den nächsten Tag leuchtet Mittwoch und Donnerstag
dann Mittwoch und Donnerstag und Freitag......

Das läuft dann weiter über den Sonntag bis zum Dienstag.
Dann Mittwoch kommt wieder das Event.


Oder interpretiere ich deine Funkiotn falsch.

Danke Kerno

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
KernoKopp schrieb:
> mhh...da bräuchte ich 49 Tabelleneinträge.
> Ich habe eine Laufvariable, die nur die Zahl 1-7 annehmen kann.

???

Den mußt Du mir mal erklären.

Wenn Du nur 7 Möglichkeiten hast, dann kannst Du auch nur 7 Einträge 
zugreifen.
Welche LED nun bei welchem Eintrag leuchtet, legst Du in der Tabelle 
fest.
Egal, ob Du alle 8 LEDs einschaltest (0xFF) oder keine (0x00).


Peter

Autor: Drachenbändiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Meine "Rotation" darf nur über 7 Pins und nicht über 8 Pins gehen.
> Ist Drachenjäger´s Version nur für 8 Pins machbar?

Verstehe ich nicht ... oben hast Du doch von den Bits 0 bis 7 
geschrieben!

Also, wenn Du z.B. die Bits 1-7 rotieren lassen willst (Bit 0 also 
ignorierst), kannst Du
 if (pattern==oldpattern) pattern|=3;
 statt  if (pattern==oldpattern) pattern|=1; schreiben.

Autor: Drachenbändiger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
KernoKopp schrieb:
> Muss ich oldpattern mit einem Wert initialisieren?

Ja, am Anfang muss irgendwo "oldpattern=pattern" stehen!

Autor: KernoKopp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter, Hallo Drachenbändiger,

vielen Dank für eure Mühen.
Jetzt ist der Groschen gefallen.:o)
Ich habe mal wieder viel zu kompliziert gedacht.
Eine solche "Rotation" ist völlig überflüßig.

Eine einfache Bitmaske (like Peter) ist da schon die Lösung.
Meine Laufvariable mit den Werten 1-7 wird ja extern erzeugt.
Da brauche ich mich nicht drum kümmern.

Somit kann ich mit ihr auf die Positionen im Feld zugreifen und mit dem 
nächsten Wert ODER verknüpfen.

Machmal hat man eben Brett vorm Kopp ;o)
#include<reg51.h>

sfr port = 0x90;

unsigned char code pattern[]  = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40};  //Bitmuster
unsigned char wt[]        = { 4, 5, 6, 0, 1, 2, 3};  //simuliert externe Laufvariable (Wochentage)


void main( void ){

  unsigned char w;
  int i,k;
  
  port=0x00;
  
  for(;;){
  
    while(i<= sizeof(wt)){
      if (port == 0x7f){    // ist eine Woche um gehts mit dem Startwochentag wieder los    
        i=0;
        w=0;
      }
      port = pattern[wt[i++]] | w;
      w=port;
      for(k=30000;k>=0; k--); 
    }
  }
}


So sollte es gehen.

Danke und Gruß Kerno

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
KernoKopp schrieb:
> Somit kann ich mit ihr auf die Positionen im Feld zugreifen und mit dem
> nächsten Wert ODER verknüpfen.

Oh Gott, nein doch.

Du trägst genau alle die LEDs ein, die leuchten sollen !!!

Nix rotieren und nix oder.

Es wird immer der komplette Port gesetzt.
Und wenn nach i == 6 von vorne, dann einfach:
if( i == 6 )
  i = 0;


Peter

Autor: KernoKopp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter, vielleicht ist mein TestCodeSchnippsel etwas ungünstig 
gewählt.

Der Code macht vom Prinzip her das, wie ich mir das vorgestellt habe.
Die Werte im Feld wt sind auch nur nachempfunden, wie sie decodiert vom 
DCF77 Signal, für die Wochentage als Dezimalzahl in dieser Reihenfolge, 
kommen könnten.
Diese Dezimalzahlen sind er Index für das "pattern" Feld.

Hier im Code fängt meine Woche z.B. mit Freitag (4), da ein Feld ja bei 
Index 0 anfängt, an. Vom DCF kommt da ja eine 5.
D.h es leuchtet als erstes der Pin für Freitag P1.4 (0x10)
Am Sonnabend soll nicht nur Sonnabend P1.5 (0x20), sondern auch 
weiterhinder Freitag P1.4 leuchten. -> 0x10 | 0x20
Ist der Sonntag P1.6 (0x40)erreicht gehts bei Montag P1.0 (0x01) weiter.
Bis zum Donnerstag P1.3 (0x08)
Die 7 Tage einer Woche können einem belibeigen Tag anfangen zu zählen.
Aber P1.0 ist Montag......und P1.6 ist Sonntag.


Die Schleife und die Incrementierung ist nur um mal alles druchlaufen zu 
lassen.
port = pattern[wt[i++]] | w;
w=port;

Ich mach mal wieder viel Lärm um Nichts.


Danke und Gruß Kerno

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
KernoKopp schrieb:
> D.h es leuchtet als erstes der Pin für Freitag P1.4 (0x10)

unsigned char code pattern[]  = { 0x10, ...

> Am Sonnabend soll nicht nur Sonnabend P1.5 (0x20), sondern auch
> weiterhinder Freitag P1.4 leuchten. -> 0x10 | 0x20

unsigned char code pattern[]  = { 0x10, 0x30, ...

Nun endlich klar?

Deine Rum-Oderei ist völlig unsinnig.


Die Tabelle sollte aber nicht mit Freitag anfangen, da DCF77 von Montag 
.. Sonntag (1 .. 7) zählt.

Also zuerst den Wert für  Montag in die Tabelle und zuletzt für Sonntag 
und dann:

  port = pattern[DCF77_wochentag - 1];

Und fertig ist die ganze Routine.


Peter

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.