- LiFePO4 Speicher Test         
Ergebnis 1 bis 3 von 3

Thema: Mischung von Assembler und C

  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076

    Mischung von Assembler und C

    Anzeige

    Praxistest und DIY Projekte
    Hallo zusammen,

    ich steuere grad mit dem PIC10F332 einen RGB-Stripe an.
    Das fuktioniert auch schon ganz hervorragend, bin ganz begeistert.
    Sein maximales Timing bekommt das grade so auf die Reihe.
    Die Ausschiebefunktion musste ich jedoch in Assembler implementieren wegen der Laufzeit
    und da taucht nun ein "kleines" Problemchen auf:

    In der Ausschiebefunktion benötige ich auch die Anzahl der LEDs die ich mit
    #define LED_COUNT 4
    in "C" declariert habe.

    Wie komme ich da aber ran innerhalb meiner Assembler Ausschiebefunktion ?

    Natürlich kann ich in Assembler hier den Wert multipliziert mit 3 direkt ins Register laden,
    aber dann muss ich bei Änderungen von LED_COUNT auch jedesmal den Assemblercode ändern,
    das halte ich für eine "schlechte/unschöne" Programmierung.
    ....vegesse ich auch garantiert irgendwann wenn ich später mal Änderungen vornehme...

    Code:
    // Declaration einer einzelnen RGB LED 
    // Jede LED hat 3 Bytes, insgesamt also 24 Bits 
    typedef struct // __pack ? bei 8 Bittern unnötig, ist immer packed
    {
      U8 green; /* 8 Bit fuer die Helligkeit gruen */
      U8 red;   /* 8 Bit fuer die Helligkeit rot   */
      U8 blue;  /* 8 Bit fuer die Helligkeit blau  */
    } TLed;     /* Type Bezeichner ist TLed */
    
    #define LED_COUNT 4         // Anzahl der anzusteuernden RGB Leds 
    
    TLed LedArray[LED_COUNT];   // gesamtes Datenarray der Ledkette 
                                // dieses Array wird dann per Assmblercode ausgeschoben
    
    //------------------------------------------------------------------------------
    // Der Assembler-Code zum Ausschieben von LedArray:
    // für 250ns Instruction Cycle Time 4 MHz
    // PMDATL enthält das auszuschiebene Datenbyte für die WS2812 RGB-Led Kette
    // wird also als Zwischenspeicher benutzt. (8 Bit Register)
    // PMADRL wird für den Bytezähler benutzt  (8 Bit Register)
    // PMDATH wird als Bitzähler benutzt !!! ist nur ein 6 Bit Register
    // das reicht aber, wir zählen ja nur von 8 bis 0
    
    void asm_LedShiftOut(void)
    {
      asm("movlw LOW _LedArray");  // address of LedArray
      asm("movwf FSR");            // to FSR index register
    
      asm("movlw 12");        // <==== eigentlich LED_COUNT * 3) das geht aber nicht <======
    
      asm("movwf PMADRL");         // use PMADRL as byteCount
      
    asm("Label_NextByte:");        // !! WICHTIG, der Doppelpunkt ab XC8 V2.20 !!
      asm("movlw 8");              // set bit count to 8
      asm("movwf PMDATH");         // use PMDATH as Bitcounter
      asm("movf  INDF,W");         // load byte from LedArray to W register
      asm("movwf PMDATL");         // save Databyte to PMDATL 
    
    asm("Label_ByteLoop:");
      asm("btfsc PMDATL,7");       // scip if databit is clear (MSB)
      asm("goto Label_High");      // else databit ist set
      asm("bsf LATA,0");           // set WS2812 DataLine to High 250ns
      asm("bcf LATA,0");           // set WS2812 DataLine to Low
      asm("goto Label_nextBit");
     
    asm("Label_High:");                    // High Bit
      asm("bsf LATA,0");                   // set WS2812 DataLine to High
      asm("NOP"); asm("NOP"); asm("NOP");  // hold Line High for 1000ns
      asm("bcf LATA,0");                   // set Line to Low
    
    asm("Label_nextBit:");
      asm("rlf PMDATL,F");          // databyte left
      asm("decfsz PMDATH,F");       // bitCount-1, scip if all bits done
      asm("goto Label_ByteLoop");   // next bit
      
      asm("incf FSR,F");            // address pointer to next Led Byte
      asm("decfsz PMADRL,F");       // byteCount-1 scip if all bytes done
      asm("goto Label_NextByte");   // else send next byte
    
      //   __delay_us(100); // Das Ende der Datenübertragung erreicht wenn die Leitung länger als 50us Low bleibt.
      //  !!! mindestens 80us bei SK68 Leds 
        
      // hier brauche ich eigentlich nicht warten, weil der restliche Programmcode benötigt ja schon Zeit ???
      asm("movlw 0x85");           // das sind 100us 
      asm("movwf PMDATL");
      asm("Label_delay100:");
      asm("decfsz PMDATL,F");
      asm("goto Label_delay100");
    }
    Vielleicht habt Ihr eine Idee wie man das evtl. auch anders lösen kann.

    Siro
    Geändert von Siro (17.09.2020 um 20:19 Uhr)

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von White_Fox
    Registriert seit
    04.10.2011
    Beiträge
    1.473
    Und wenn du LED_COUNT als Const deklarierst?

    Das #define ist ja, soweit ich weiß, eine reine Präprozessoranweisung von der der Compiler nix mehr mitbekommt und die sich dann auch nicht im Programmcode niederschlagen dürfte.

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Hallo White_Fox, ersteinmal Danke für die Rückmeldung, ich hab das grade mal probiert.

    const LED_COUNT = 4; // hier meckert der Compiler mit einem Warning, das wäre ja nicht so schlimm
    const int LED_COUNT = 4; // so ist der Warning weg. Aber es ist jetzt quasi eine initialisierte Variable.

    TLed LedArray[LED_COUNT]; // damit ist dieses Konstrukt nicht mehr gültig. "variable length array not supported"

    Eine Konstante muss ja irgendwie im Speicher abgelegt werden.
    Das kann der Compiler vermutlich selbst enscheiden ob er das im RAM oder im Codebereich macht ??
    Wenn ich const benutze habe ich anscheinend immer eine "Instanz" im RAM und benötige Speicherplatz,
    deshalb meckert der Compiler auch wenn ich die Typangabe weglasse, da er nicht weis wieviel Speicher er benötigt,
    somit reserviert er einen "int".

    Wie dem auch sei, ein Array benötigt einen "festen" Wert für die Größenangabe.
    Dieser feste Wert kann anscheinend nur eine Zahl bzw. ein #define sein ? (meine Vermutung)

    Ein #define kennt dann aber der Assembler nicht mehr, wie Du schon schriebst, ist das für den Preprozessor.

    Ich weis nicht ob man das irgendwie "übergreifend" declarieren kann.

    - - - Aktualisiert - - -
    --------------------------------------------

    Guten Morgen, es hat mir keine Ruhe gelassen

    Ich habe das Problem jetzt so gelöst:
    Es gibt eine Variable in der die Grösse des Led Arrays gespeichert wird.
    Diese wird vom Compiler selbst eingetragen

    Code:
    typedef struct 
    {
      U8 green;
      U8 red;  
      U8 blue; 
    } TLed;    
    
    #define LED_COUNT 4         // Anzahl der anzusteuernden RGB Leds 
    
    TLed LedArray[LED_COUNT];   // gesamtes Datenarray der Ledkette 
    
    // hier NEU: damit ich mit dem Assembler auf die Anazahl Bytes im LedArray zugreifen kann.
    unsigned char ArraySize = sizeof(LedArray);  // die Groesse des Arrays in Bytes
    Auf diese Weise kann ich nun mit

    asm("movf _ArraySize,W");

    auf die Anzahl der Bytes des LedArrays zugreifen.
    Nun brauche ich nur noch an einer Stelle, nämlich den Wert LED_COUNT ändern und die Assemblerfunktion macht es dann auch gleich richtig.
    Geändert von Siro (18.09.2020 um 09:17 Uhr) Grund: nun geht das

Ähnliche Themen

  1. RP6 und Assembler
    Von ThomasD im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 1
    Letzter Beitrag: 18.04.2010, 21:29
  2. assembler
    Von m1cha im Forum Allgemeines zum Thema Roboter / Modellbau
    Antworten: 1
    Letzter Beitrag: 29.01.2008, 13:27
  3. if in Assembler???
    Von XDavidX im Forum PIC Controller
    Antworten: 7
    Letzter Beitrag: 29.01.2006, 11:56
  4. Assembler und I2C ?
    Von ProgDom im Forum AVR Hardwarethemen
    Antworten: 5
    Letzter Beitrag: 20.07.2005, 14:46
  5. Assembler ADW ???
    Von ProgDom im Forum AVR Hardwarethemen
    Antworten: 3
    Letzter Beitrag: 11.07.2005, 20:59

Berechtigungen

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

LiFePO4 Speicher Test