-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 18

Thema: Assembler in BASCOM verwenden

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    28.05.2007
    Ort
    Mannheim
    Alter
    30
    Beiträge
    270

    Assembler in BASCOM verwenden

    Anzeige

    Hallo Leute,

    ich arbeite zur Zeit an einem Programm, wo es eine sehr Zeitkritische Operation zu bewerkstelligen gibt.
    Mein Problem ist, das Bascom für folgenden Code:
    Code:
    Daten(1).bitcount = PORTD.2
    über 50 Cyclen braucht. So viel Zeit habe ich aber nicht zum Speichern des Pinzustandes. Desshalb wollte ich diesen Teil selbst in Assembler schreiben.
    Nun gut, das ganze funktioniert ja Dank $asm sehr gut.
    Die Variablenübergabe von bitcount ins ASM geht dank {bitcount} auch sehr gut.
    Aber beim Array bleib ich hängen.

    Wie kann man ein Array an einen ASM-Code übergeben?
    wenn ich {daten(1)} schreibe, kommt die Fehlermeldung "No more Space for BIT"
    Also wie kann ich das übergeben? vorallem: Die 1 muss dann später auch noch variabel sein.

    Hoffe mir kann jemand weiter helfen.

    Vielen Dank schonmal.

    Gruß Robodriver
    Wer aufhört besser zu werden, hat aufgehört gut zu sein

    Jeder I/O Port kennt drei Zustände: Input, Output, Kaputt

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.112
    Das Problem mit den 50 Cyclen tritt nur dann auf, wenn du über eine Variable (bitcount) ein einzelnes Bit ansprichst. Das gleiche hatte ich auch festgestellt und daher meinen Code so umgestellt, dass ich mit festen Werten arbeite. Bei dir würde das also heißen, dass du z.B. Daten(1).1 = PortD.2 setzen musst.
    Schau mal, ob du das ändern kannst, dann brauchst du nicht auf Asm zu gehen.

    Gruß

    Rolf

  3. #3
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    28.05.2007
    Ort
    Mannheim
    Alter
    30
    Beiträge
    270
    Naja, das bringt mir nicht viel.
    Denn diese ganze Routine liegt in einem Interrupt und schaut komplett so aus:
    Code:
    Daten(1).bitcount = Sda_line
    Bitcount = Bitcount + 1
    If Bitcount = 8 Then
      Ready = 1
      Cli                                                       'Globale Interrupts deaktivieren
    End If
    Return
    Sprich, bei jeden Interrupt wir der Pin zustand in ein anders Bit im Byte geschrieben.
    Ist quasi ein Byte was seriell eingelesen wird. Und der Interrupt wird immer ausgelöst wenn der Takt eine Positive Flank aufweist.
    Wer aufhört besser zu werden, hat aufgehört gut zu sein

    Jeder I/O Port kennt drei Zustände: Input, Output, Kaputt

  4. #4
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Du hast da mehrere Möglichkeiten, eine davon

    Du kannst beliebige (SRAM) Adressen in Pointer-Register laden, z.B.
    Loadadr Arr(4) , X
    Dann muß Bascom das mit dem Index erledigen, du brauchst dann nur
    LD register, X oder
    ST X, register
    zu machen

    Ich persönlich würde aber die ganze ISR-Routine in assembler machen, wenn schon die Zeit knapp ist.

    Noch'n Tip:
    du kannst dir "ready=1" sparen, weil BitCount ist ja nur ein Byte, das kannst du im Hauptprogramm auch auf BitCount = 8 abfragen, das ist dieselbe arbeit
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  5. #5
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    28.05.2007
    Ort
    Mannheim
    Alter
    30
    Beiträge
    270
    Hi,
    danke für deine Antwort.

    Naja, das ist jetzt momentan nur ein Test. Das ready könnt ich momentan schon so abfangen. Aber wenn das Byte voll ist, wird der Counter wieder auf 0 gesetzt und schon weiß ich nicht mehr dass das Byte fertig ist
    Kommt halt später noch mehr drum herum.

    Die komplette ISR in Assembler zu schreiben würd ich ja gern.
    Aber in der ISR muss dieses Array gefüllt werden.
    Und das Array wird später in der Hauptschleife weiter verarbeitet.

    Aber danke für deinen Tipp mit dem Loadadr
    Wer aufhört besser zu werden, hat aufgehört gut zu sein

    Jeder I/O Port kennt drei Zustände: Input, Output, Kaputt

  6. #6
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Ich vermute mal, dass die ein Bytearray bitseriell befüllen willst, mit dem Takt über einen Interrupt.
    Das hiesse aber, daß weder der Index noch bitcount irgendwelche beliebigen Werte einnehmen, sondern immer der Reihe nach, d.h. Bit 0-7, schalten auf nächstes Byte und wieder 0-7.

    Da ist es effizienter, die Bits nicht einzeln zu setzen, sondern mit shift reinzuschieben
    Und nicht mit Array-Index, sondern mit einen Pointer, der nach 8 Bit immer inkrementiert wird

    Dazu brauchst du
    eine Word-Variable für den pointer und
    einen Byte-Zähler für die Bits

    die setzt du zu Beginn auf die Anfangsadresse des Array und auf Null
    z.B.
    Code:
    DIM array (nn) AS BYTE
    DIM pointer AS WORD
    DIM Bits  AS Byte
    
          Bits = 0
          pointer = VARPTR(array(1))
    
    
    In der ISR:
          LOADADR  pointer, Z
          LDD  XL , Z + 0         (low pointer
          LDD  XH , Z + 1        (hig pointer
    
          LD    R24, X              aktuelles array-byte
          CLC                         clear carry
          SBIC    portx , inp-pin        ' Input -pin = 0/1 ? 
          SEC                          set carry
          ROL   r24                   bit reinschieben
          ST     X, R24             aktuelles byte speichern 
          LDD  R24,  Z + 3      (Bitcounter)
          INC   R24                 bitcounter+1
          ANDI  R24 , 7           es gilt nur 0-7
          BRNZ   _next_bit
     _next_byte:
          ADIW    X, 1             pointer+1      
          STD      Z + 0, XL          neuen low pointer speichern
          STD      Z + 1, XH         neuen hig pointer speichern
     _next_bit:
          STD  Z + 3, r24             (Bitcounter speichern
    -- ISR fertig
    Es zahlt sich auch aus, die ISR mit "nosave" zu definieren und nur die Register (und den Status) zu pushen, die du tatsächlich brauchst. Bascom pusht sonst alles von rechts bis links


    Was da fehlt, ist die Endebedingung, also ein Signal, wenn es genug ist.
    Ich weiss nicht, was du da brauchst

    Wenn irgendwas unklar ist, frag nur.

    (das ganze mit vorbehalt von Schreibfehlern und anderen Schweinereien)
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    28.03.2004
    Beiträge
    185
    Hallo PicNick,

    ich habe Deinen sehr interessanten Code mal in den Bascom Simulator eingepasst:
    Code:
    $regfile = "m8def.dat"
    $framesize = 32                                             'Stack
    $swstack = 32
    $hwstack = 64
    
    Dim Array(5) As Byte
    Dim Dummy(4) As Byte
    Dim Pointer As Word At Dummy(1) Overlay
    Dim Bits_ As Byte At Dummy(4) Overlay
    
    Dim I As Byte , J As Byte
    
    Bits_ = 0
    Pointer = Varptr(array(1))
    
    For I = 1 To 40
      Gosub Shifter                                             'hier mit Breakpoint PinB.0 auf 0/1 umschalten
      For J = 5 To 1 Step -1
        Print Bin(array(j));
      Next
      Print
    Next
    End
    
    Shifter:
          Loadadr Pointer , Z
          LDD  XL , Z + 0                                       'low pointer
          LDD  XH , Z + 1                                       'hig pointer
    
          LD    R24, X                                          ' aktuelles array-byte
          CLC                                                   '  clear carry
          SBIC PINB, 0                                          ' inp-pin   Input -pin = 0/1 ?
          SEC                                                   '   set carry
          ROL   r24                                             ' bit reinschieben
          ST     X, R24                                         'aktuelles byte speichern
          LDD  R24,  Z + 3                                      ' (Bitcounter)
          INC   R24                                             ' bitcounter+1
          ANDI  R24 , 7                                         ' es gilt nur 0-7
          Brne _next_bit
    '_next_byte:
          ADIW XL, 1                                            'pointer+1
          STD   Z + 0, XL                                       '  neuen low pointer speichern
          STD   Z + 1, XH                                       'neuen hig pointer speichern
     _next_bit:
          STD  Z + 3, r24                                       'Bitcounter in Bits_ speichern
    Return
    Der Code shiftet nicht über die Bytegrenzen hinweg. Einfach mal im Simulator durch Umschaltung des grünen Kreies für PinB.0 mit 10111.. durchspielen.
    Ich denke, beim Kopieren ist der Sprung zu _next_byte untergegangen.

    Gruß
    Tomas

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.07.2004
    Ort
    Südhessen
    Beiträge
    1.312
    Ober eben einfach das Carry-Flag mit dem Bitwert setzen und dann mit ROL reinshiften. In ASM wären das 3 Befehle mit 3 oder 4 Takten. Ungefähr so:

    sec ;Carry-Flag setzen
    sbis Sda_line ;Sda_line ersetzen
    clc ;Carry-Flag bei Bedarf löschen
    rol REG ;REG ersetzen

    So wird einfach das Bit von rechts reingeschoben.

  9. #9
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Zitat Zitat von tomas
    ..Der Code shiftet nicht über die Bytegrenzen hinweg.
    Bestreite ich glatt.

    Zitat Zitat von thewulf00
    Ober eben ..
    Wieso oder ? Was steht denn bei mir drin ?
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.07.2004
    Ort
    Südhessen
    Beiträge
    1.312
    Zitat Zitat von PicNick
    [...] sondern mit shift reinzuschieben [...]
    Hatte das so verstanden, dass Du das 1. Bit setzen willst und dann Schiften willst. Ich schifte nicht, ich rolle, und damit nutzt er das Carryflag. War ja auch nur ne Idee. Hab ich mal gemacht und hat echt super geklappt. Man muss nur aufpassen, dass durch das Rollen das Carryflag wieder verändert wird. (Es wird zu dem Wert des "rausgerollten" Bits)

    Edit: Ich muss dazu sagen, dass ich den Code nicht angeschaut hatte, weil ich mir dachte, ich verstehe den BASCOM-Code eh nicht.

    Alles klar, ich gebe zu, eine Idee wiederholt zu haben, die von Dir stammt.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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