-
        

Ergebnis 1 bis 1 von 1

Thema: Ansteuerung Leds WS2811 mit ATXMega

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437

    Ansteuerung Leds WS2811 mit ATXMega

    Anzeige

    Nun, ich dachte mir: machst mal 'nen Crosspost

    Nachdem ein Mitglied im MCS-Forum die Ansteuerung eines WS2811 über einen NOP-Schlangen-Code versuchte, dieses nach Unterstützung durchaus erfolgreich, erschien mir der Code doch ein wenig ineffektiv und auch ein bisserl hässlich.
    Also hab' ich einen weiteren Code speziell für den ATXMega und dessen Fähigkeiten geschrieben.

    Die Funktionsweise ist dergestalt, dass zwei DMA-Kanäle aus einem Array, welches die Helligkeitseinstellungen der einzelnen Leds enthält, einen Doppelpuffer befüllen und diese zwei Puffer abwechselnd in ein als SPI verwendetes UART schreiben. Die Form der in das UART geschrieben Daten sorgt dann für die Erzeugung der Low/High-Bits am TXD-Pin des ATXMega. Sobald ein Puffer leer-geschrieben ist, übernimmt der zweite, während der erste Puffer wieder über eine ISR befüllt wird. Ein Puffer enthält immer einen Frame aus 24 Bit, dieser wieder besteht aus 3 x 8 Bit, welche die Helligkeit der einzelnen Leds steuern, ledarr(0) = grün, ledarr(1) = rot, ledarr(2) = blau, usw.

    Jedes Bit des Frames ist im Puffer als Nibble (4Bit) abgelegt, daraus ergeben sich die 12 Byte großen Puffer, welche per DMA in's UART befördert werden.

    Der Prozess wird im Hintergrund ausgeführt und verbraucht einen relativ kleinen Teil der vorhandenen Rechenleistung.
    Da bei mir kein WS2811-Strip vorhanden ist, jedoch das Mitglied im MCS-Forum das Funktionieren meines Codes bestätigt hat, würd' ich sagen dass es in Ordnung ist, den hier einzustellen.

    Denn brauchen kann den sicherlich irgendwer.

    Code:
    $regfile = "xm128a1def.dat"
    $crystal = 32000000
    $hwstack = 64
    $swstack = 40
    $framesize = 40
    '$noramclear
    '$sim
    
    Config Osc = Enabled , 32mhzosc = Enabled
    Config Sysclock = 32mhz
    Config Base = 0
    
    '### user configurable ###
    Const RGBunits = 3                                          ' total count of RGB units
    Const rstto = 2                                             ' reset timeout, 1 equals one empty frame, 24 bits * 1,25µs = 30µs
    '### user configurable ###
    
    Const bytesperRGBunit = 3                                   ' every RGB-unit has 3 leds, every led is controlled by 1 byte
    Const ledcnt = RGBunits * bytesperRGBunit                   ' total amount of leds
    Const dbfsize = 12                                          ' one nibble per sent bit, 24 bit per RGB unit, 24 nibbles = 12 bytes
    
    Const USART_TXEN = 3
    Const USART_CMOD0 = 6
    Const USART_CMOD1 = 7
    Const USART_UCPHA = 1
    Const USART_UDORD = 2
    Const DMA_CH0TRNIF = 0
    Const DMA_CH1TRNIF = 1
    
    Const SPItmpl = &b10001000
    Const SPIhnib = &b01000000                                  ' SPI_Out_0 = &b1000, 1.25µs/4*1 = H0.312µs, L0.938µs
    Const SPIlnib = &b00000100                                  ' SPI_Out_1 = &b1100, 1.25µs/4*2 = H0.625µs, L0.625µs
    
    Dim dblbuf_0(dbfsize) As Byte
    Dim dblbuf_1(dbfsize) As Byte
    Dim ledarr(ledcnt) As Byte                                  ' ledarr(0) is first led of strip
    Dim ledptr As Word                                          ' points to actual shifted out RGB data
    Dim toctr As Byte
    
    ledptr = 0
    ledarr(0) = 128
    ledarr(1) = 170
    ledarr(2) = 85
    ledarr(3) = 1
    ledarr(4) = 4
    ledarr(5) = 32
    
    
    On Dma_ch0 Dma_ch0_int NOSAVE
    On Dma_ch1 Dma_ch1_int NOSAVE
    
    'UART0 in SPI Mode, TXD --> PD3, XCK --> PD1 (unused)
    Config PORTD.3 = Output                                     ' set SPI TXD to output
    USARTD0_BAUDCTRLA = 4                                       ' BSEL = (32MHz/(2*3.2MBaud))-1, 1/(1.25µs/4bit) = 3.2MBaud
    USARTD0_BAUDCTRLB = 0                                       ' BSCALE = 0
    USARTD0_CTRLA = 0
    USARTD0_CTRLB = Bits(USART_TXEN)                            ' enable transmitter
    USARTD0_CTRLC = Bits(USART_CMOD1 , USART_CMOD0)             ' enable UART SPI-mode, MSB first, sample rising edge
    
    Config Dma = Enabled , Doublebuf = CH01 , Cpm = CH0123
    
    'Trigger Base Value = &H6B + Data register empty (DRE) &H01 --> &H6C
    Config Dmach0 = Enabled , Burstlen = 1 , Chanrpt = Enabled , Tci = Lo , Eil = OFF , Singleshot = Enabled , _
    Sar = BLOCK , Sam = INC , Dar = NONE , Dam = FIXED , Trigger = &H6C , Btc = dbfsize , Repeat = 0 , Sadr = Varptr(dblbuf_0(0)) , Dadr = Varptr(usartD0_data)
    
    Config Dmach1 = Enabled , Burstlen = 1 , Chanrpt = Enabled , Tci = Lo , Eil = OFF , Singleshot = Enabled , _
    Sar = BLOCK , Sam = INC , Dar = NONE , Dam = FIXED , Trigger = &H6C , Btc = dbfsize , Repeat = 0 , Sadr = Varptr(dblbuf_1(0)) , Dadr = Varptr(usartD0_data)
    
    Config Priority = Static , Vector = Application , Lo = Enabled , Med = Enabled
    Enable Interrupts
    
    Config PORTE.0 = Output                                     ' I'm alive led0 on Atmel XPlained ATMega128A1
    
    Config PORTD.2 = Output
    Dim A As Word
    Dim C As Word
    
    Const testspeed = 0
    
    #IF testspeed = 0
    Do
      Waitms 500
        Toggle PortE.0                                          
    Loop
    #ELSE
    Do
      Toggle PortD.2
        For A = 0 To 65535                                      ' 91ms for this loop with disabled interrupts (no DMA)
          C = A                                                 ' 108ms with interrupts (with DMA), CPU 84% App <-> 16% ISR/DMA
        Next A
    Loop
    #ENDIF
    
    End
    
    Dma_ch0_int:
      !PUSH       ZL
      !IN         ZL,        SREG
      !PUSH       ZL
      !PUSH       ZH
      Loadadr dblbuf_0(0) , Z
      !RCALL      dblbuff
      !LDI        ZL,        2^DMA_CH0TRNIF
      !STS        DMA_INTFLAGS, ZL
      !POP        ZH
      !POP        ZL
      !OUT        SREG,       ZL
      !POP        ZL
    Return
    
    Dma_ch1_int:
      !PUSH       ZL
      !IN         ZL,        SREG
      !PUSH       ZL
      !PUSH       ZH
      Loadadr dblbuf_1(0) , Z
      !RCALL      dblbuff
      !LDI        ZL,        2^DMA_CH1TRNIF
      !STS        DMA_INTFLAGS, ZL
      !POP        ZH
      !POP        ZL
      !OUT        SREG,       ZL
      !POP        ZL
    Return
    
    !dblbuff:
      !PUSH       r16
      !PUSH       r17
      !PUSH       r24
      !PUSH       r25
      !PUSH       XL
      !PUSH       XH
      !LDI        r16,        bytesperRGBunit
      !LDS        r24,        {toctr}
      !TST        r24
      !BREQ       filldb
      !LDI        r16,        dbfsize
      !CLR        r17
    !clrdblbuf:
      !ST         Z+,         r17
      !DEC        r16
      !BRNE       clrdblbuf
      !DEC        R24
      !STS        {toctr},    r24
      !RJMP       fillend
    !filldb:
      Loadadr ledarr(0) , X
      !LDS        r24,        {ledptr}
      !LDS        r25,        {ledptr+1}
      !ADD        XL,         r24
      !ADC        XH,         r25
      !ADIW       r24,        bytesperRGBunit
      !LDI        r17,        hbyte(ledcnt)
      !CPI        r24,        lbyte(ledcnt)
      !CPC        r25,        r17
      !BRCS       avail
      !CLR        r24
      !CLR        r25
      !LDI        r17,        rstto
      !STS        {toctr},    r17
    !avail:
      !STS        {ledptr},   r24
      !STS        {ledptr+1}, r25
    !byteloop:
      !LD         r24,        X+
      !LDI        r17,        SPItmpl
      !BST        r24,        7
      !BLD        r17,        6
      !BST        r24,        6
      !BLD        r17,        2
      !ST         Z+,         r17
      !LDI        r17,        SPItmpl
      !BST        r24,        5
      !BLD        r17,        6
      !BST        r24,        4
      !BLD        r17,        2
      !ST         Z+,         r17
      !LDI        r17,        SPItmpl
      !BST        r24,        3
      !BLD        r17,        6
      !BST        r24,        2
      !BLD        r17,        2
      !ST         Z+,         r17
      !LDI        r17,        SPItmpl
      !BST        r24,        1
      !BLD        r17,        6
      !BST        r24,        0
      !BLD        r17,        2
      !ST         Z+,         r17
      !DEC        r16
      !BRNE       byteloop
    !fillend:
      !POP        XH
      !POP        XL
      !POP        r25
      !POP        r24
      !POP        r17
      !POP        r16
    Return
    Geändert von MagicWSmoke (11.05.2013 um 08:40 Uhr)

Ähnliche Themen

  1. [ERLEDIGT] AtXMega und Quadraturdecoder
    Von the_Ghost666 im Forum C - Programmierung (GCC u.a.)
    Antworten: 0
    Letzter Beitrag: 08.11.2012, 21:47
  2. DIL-Mikrocontroller-Modul mit ATxmega und USB
    Von Roboternetz-News im Forum Neuigkeiten / Technik-News / Nachrichten / Aktuelles
    Antworten: 0
    Letzter Beitrag: 06.09.2012, 14:30
  3. Biete Job Ansteuerung von Servos und LEDs mit Display und USB-Input
    Von toby_nbg im Forum Jobs/Hilfen/Stellen - Gesuche und Angebote
    Antworten: 3
    Letzter Beitrag: 28.06.2012, 10:15
  4. Servo der Steuerung nachlaufen lassen mit Atxmega ?
    Von BlaueLed im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 25.06.2012, 22:15
  5. ATXMEGA UART Empfangsproblem
    Von aussternengemacht im Forum C - Programmierung (GCC u.a.)
    Antworten: 2
    Letzter Beitrag: 16.11.2010, 16:58

Berechtigungen

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