-         

Ergebnis 1 bis 6 von 6

Thema: Ports nach Bitmaske setzen?

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    11.01.2011
    Beiträge
    192

    Ports nach Bitmaske setzen?

    Anzeige

    Hallo,
    ich habe 20 Bits jedes Bit soll einen Pin zugewiesen werden.

    Bsp.
    100
    1=Bit 1 = PA7 auf high setzen
    0=Bit 2 = PA6 auf low setzen
    0=Bit 3 = PA5 auf low setzen

    Ich Suche also eine Funktion die genau das macht.

    Wie schreibe ich das möglichst effektiv? Ich hab bisher gedacht jedes Einzelne Bit zu maskieren und in einer if schleife zu prüfen... das muss doch auch einfacher gehen?

    Code:
    Bit1 = PA7
    Bit2 = PA6
    Bit3 = PA5
    Bit4 = PA4
    Bit5 = PA3
    Bit6 = PA2
    Bit7 = PA1
    Bit8 = PA0
    Bit9 = PC6
    Bit10 = PC5
    Bit11 = PD7
    Bit12 = PD6
    Bit13 = PD5
    Bit14 = PD4
    Bit15 = PD3
    Bit16 = PC4
    Bit17 = PC3
    Bit18 = PC2
    Bit19 = PC1
    Bit20 = PC0
    gruß Daniel

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Kandel
    Alter
    29
    Beiträge
    1.220
    Hi Daniel,

    mal vorweg: Streiche "if-Schleife" aus deinem Wortschatz.

    Zu deinem Problem: Wenn du die Belegung nicht ändern kannst, stellt sich nur die Frage, wie hässlich der Code wird. Eine schöne, schnelle und platzsparende Lösung gibt es dann nämlich nicht.

    Zerlegen wir das ganze Mal systematisch: Die Bits 1-8 (eigentlich zählt man in der Informatik ab 0 ...) müssen umgedreht werden. Das kann eine kleine Schleife erledigen und ist noch nicht so dramatisch. Das Ergebnis kann dann direkt zugewiesen werden.
    Die Bits 9 und 10 bilden zusammen mit den Bits 16-20 eine Sequenz von PC6-PC0, das kann man mit etwas Bitgeschubse auch wieder in ein Byte extrahieren, dann wieder Reihenfolge umdrehen und dem Port C zuweisen.
    Bleiben noch die Bits 11 bis 15, die müssen "nur" umgedreht und an die richtige Stelle im Byte geschoben werden.

    Bei Port C und Port D sind Bits unbelegt, die wirst du beim Zuweisen an den Port dann ausmaskieren wollen.

    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  3. #3
    Neuer Benutzer
    Registriert seit
    31.10.2008
    Ort
    Dresden
    Alter
    28
    Beiträge
    3
    Hi Daniel,

    sowas macht man am besten mit einer Lookup-Tabelle. Du übergibst der Tabelle die Nummer deines Bits (0..19) und sie liefert dir den PORT bzw. den PIN der angesteuert werden muss.
    Dann brauchst du noch eine Methode die PORT, PIN und einen Wahrheitswert übergeben bekommt und den Pin entsprechend ein oder ausschaltet.
    Für deinen konkreten Fall könnte es so aussehen:

    Code:
    //uint32_t_Auf_Ports_mappen.c
    #include <avr/io.h>
    
    
    #define ARRAY_LENGTH 20
    
    
    uint8_t Port_Mask[ARRAY_LENGTH] = {
        &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, 
        &PORTC, &PORTC, 
        &PORTD, &PORTD, &PORTD, &PORTD, &PORTD,
        &PORTC, &PORTC, &PORTC, &PORTC, &PORTC
    };
    
    
    uint8_t Pin_Mask[ARRAY_LENGTH] = {
        PA7, PA6, PA5, PA4, PA3, PA2, PA1, PA0,
        PC6, PC5,
        PD7, PD6, PD5, PD4, PD3,
        PC4, PC3, PC2, PC1, PC0
    };
    
    
    uint32_t Potenz_Zahlen[ARRAY_LENGTH] = {
        1,2,4,8,16,32,64,128,256,512,1024,
        2048,4096,8192,16384,32768,65536,131072,262144,524288
    };
    
    
    
    
    int main(void) {
        DDRA = 0xFF;
        DDRC = 0xFF;
        DDRD = 0xFF;
        
        uint32_t z = Potenz_Zahlen[2]| Potenz_Zahlen[7] | Potenz_Zahlen[11]; // schaltet bit 2,7 und 11 ein also PORTA.5 , PORTA.7 und PORTD.6
    
        SET_PORTS(z);
    }
    
    
    
    
    void SET_PORTS(uint32_t x){
        for(uint8_t i = 0; i< ARRAY_LENGTH; i++){
            BIT_BOOL_SET(Port_Mask[i], Pin_Mask[i], x & Potenz_Zahlen[i]); // von x bleibt nur das i-te Bit unmaskiert, 
                                                                                                    // danach ist das int entweder 0 und das Bit muss gelöscht werden 
                                                                                                    // oder > 0 und dann wird es gesetzt  
        }    
    }
    
    
    inline void BIT_BOOL_SET(volatile uint8_t *target, uint8_t bit, uint32_t b){
        if (b>0){
            BIT_SET(target, bit);        
        }else{
            BIT_CLEAR(target, bit);
        }
    }
    
    
    
    
    inline void BIT_SET(volatile uint8_t *target, uint8_t bit){
        *target |= (1<<bit);
    }
    
    
    
    
    inline void BIT_CLEAR(volatile uint8_t *target, uint8_t bit){
        *target &= ~(1<<bit);
    }
    Die wichtige Methode ist hier SET_PORTS der du einen 32-Bit int übergibst die setzt dann die Pins entsprechend in der Reihenfolge wie sie in Port_Mask und Pin_Mask aufgelistet sind.
    Das Array Potenz_Zahlen ist nur eine Hilfe um ein bestimmtes Bit in einem Int zu maskieren.

    Ich weiß zwar nicht welchen Chip du verwendest und welche Programmiersprache, aber vll hilft es dir trotzdem^^


    Gruß Martin

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Kandel
    Alter
    29
    Beiträge
    1.220
    Das hatte ich zuerst auch in Erwägung gezogen, ist aber deutlich ineffizienter als die direkte Lösung. Außerdem hast du einen kleinen aber fatalen Fehler in deinem Code:
    Port_Mask ist nicht vom Typ (uint8_t) sondern vom Typ (volatile uint8_t *).

    mfG
    Markus
    Tiny ASURO Library: Thread und sf.net Seite

  5. #5
    Neuer Benutzer
    Registriert seit
    31.10.2008
    Ort
    Dresden
    Alter
    28
    Beiträge
    3
    Ja stimmt, danke für den Hinweis, ich hatte es im Simulator getestet und da ist mit das nicht aufgefallen weil es schien trotzdem zu funktionieren.

    Der Vorteil von der Methode ist das man sie immer wiederverwenden kann und nur die beiden Arrays anpassen muss. Aber die Bits da an die richtige Stelle zu schubsen ist natürlich effizienter, da hast du recht.

    Gruß Martin

  6. #6
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Zitat Zitat von deko Beitrag anzeigen
    ... Bit zu maskieren und in einer if schleife zu prüfen ... das muss doch auch einfacher gehen? ...
    Ich nehme mal an, dass sich die Bitmuster immer wieder mal ändern. In einer Matrix von 10 x 12 LEDs (in einem LED-PingPong-Spiel) hatte ich verschiedene Muster mithilfe von Schleifen an- und ausgeknippst. Für Deine Aufgabe könnte das so aussehen:
    Code:
    // ........                     
     #define SetBit(ADDR,BIT)       ((ADDR) |= (1<<(BIT)))          // Setzt Bit
     #define ClrBit(ADDR,BIT)       ((ADDR) &= ~(1<<(BIT)))         // Löscht Bit
     #define IsBitSet(ADDR,BIT)     (((ADDR) & (1<<BIT))?1:0)       // Fragt Bit = 1?
    // ........                        
     volatile int8_t        Byte_A;         // 
     volatile int8_t        portpin;        // Pinadressierung (im Port A)
    // ........                        
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // ........                     
    //      Mal beispielsweise (m)ein Musterbyte für die ersten acht Bits
      Byte_A   = 0b00110000;        // Ist natürlich dasselbe wie Byte_A = 48,
                                    //   sieht für mich aber "deutlicher" aus
                                    //   ... dabei stehen hier        
    //        das Bit 1 als LSB (gaaanz rechts) und Bit 8 als MSB (gaaanz links)
                                    //
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // ........                     
    // Jetzt fragen wir mal acht bits ab und setzen die Portpins
      
      for (uint8_t loopus = 0; loopus <= 7; loopus++)
      {                             
        portpin = 7 - loopus;       // Brauchen wir zur Pinadressierung im Port A
        ClrBit (PORTA, nmbrbit)     // Pinn mal auf low setzen
        if (IsBitSet (Byte_A, loopus))      // Abfrage des tatsächlichen Bits und
          SetBit (PORTA, nmbrbit)           //  .. wenn das "1" ist - Pin auf high
      }                             // Ende for (uint8_t loopus ,,,
    // ........                     
    
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Die Bittabelle wie oben geschrieben:
    Bit1 = PA7
    Bit2 = PA6
    Bit3 = PA5
    Bit4 = PA4
    Bit5 = PA3
    Bit6 = PA2
    Bit7 = PA1
    Bit8 = PA0
    ....
    Für die einzelnen/anderen Ports ist der Start- und Endwert der Laufvariablen und die Rechenvorschrift für die Pinnummer den Gegebenheiten anzupassen.

    Natürlich ist das nix für Leute, die keine Schleifen mögen.
    Ciao sagt der JoeamBerg

Ähnliche Themen

  1. Hilfe bei Optimierung von Ports setzen
    Von graffiti im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 06.07.2008, 22:25
  2. Denkanstoß... Setzen rücksetzen von Ports
    Von EDatabaseError im Forum C - Programmierung (GCC u.a.)
    Antworten: 2
    Letzter Beitrag: 31.03.2008, 19:41
  3. Ports aus Variablen setzen/löschen
    Von humperdinger im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 28.02.2008, 15:12
  4. Nach Interrupt werden die Ports zurückgesetzt
    Von DanielV. im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 22.09.2007, 20:20
  5. Zustand der Ports nach verlassen von Schleife festlegen
    Von popi im Forum C - Programmierung (GCC u.a.)
    Antworten: 11
    Letzter Beitrag: 21.06.2006, 23:17

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •