renebiemans.nl

Elektronica · 28 december 2009

DMX met AVR Atmega 88

Dit is een werkende ASM Code om DMX te ontvangen. Hij werkt op een Atmega88 met een 20mHz clock. De hardware is eenvoudig. Een driver chip de SN75176 word aangesloten op de RXD pin van de Atmega. Als uitgang worden drie PWM kanalen gebruikt: OCR0A, OCR0B en OCR2B. Een schema zal later gepost worden.

De vier kanalen worden naar CH1, CH2, CH3 en CH4 geschreven. Deze worden dan in de main loop weggeschreven naar de uitgang zodat er ook gemakkelijk iets anders gedaan kan worden met de kanalen.

Het kanaal waar de ontvanger op reageerd is te veranderen in de code maar het is ook mogelijk om deze uit te lezen via een poort. Dit zal ik later uit gaan werken.

Een werkende code voor een PIC 16f628a is hier te vinden.

.include "m88def.inc"

;berekenen baudrate
.equ    CLOCK = 20000000
.equ    BAUD = 250000
.equ    UBRRVAL = CLOCK/(BAUD*16)-1

;instellen registernamen
.def    TEMP = r16
.def    TEM2 = r17
.def    DATA = r18
.def    CH1  = r19
.def    CH2  = r20
.def    CH3  = r21
.def    CH4  = r22
.def    DMX  = r23
.def    CNT  = r24
.def    ADR  = r25
    rjmp init

;interupt
.org 0x012      ;uart RX complete
    rjmp inte

init: 
; Stackpointer initialisieren
    ldi temp, LOW(RAMEND)
    out SPL, temp
    ldi temp, HIGH(RAMEND)
    out SPH, temp

; Instellen poorten
    ldi temp,255
    out DDRB,temp ;poort b uitgang
    ldi temp,0
    out DDRC,temp ;poort c ingang
    ldi temp,255
    out DDRD,temp ;poort d uitgang

; Baudrate instellen
    ldi temp, LOW(UBRRVAL)
    sts UBRR0L, temp
    ldi temp, HIGH(UBRRVAL)
    sts UBRR0H, temp

; Frame-Format: 8 Bit en 2 stop bits
    ldi temp, (1<<USBS0)|(3<<UCSZ00)
    sts UCSR0C, temp

; Enable transmitter en receiver
    ldi temp, (1 << TXEN0)|(1 << RXEN0|1 << RXCIE0)
    sts UCSR0B, temp

; Enable PWM
    ldi temp, (1 << WGM01)|(1 << WGM00|1 << COM0A1|0 << COM0A0|1 << COM0B1|0 << COM0B0)
    out TCCR0A, temp

    ldi temp, (0 << WGM02)|(1 << CS02|0 << CS01|0 << CS00)
    out TCCR0B, temp

    ldi temp, (1 << WGM21)|(1 << WGM20|1 << COM2A1|0 << COM2A0|1 << COM2B1|0 << COM2B0)
    sts TCCR2A, temp

    ldi temp, (0 << WGM22)|(1 << CS22|0 << CS21|0 << CS20)
    sts TCCR2B, temp
; Clear registers
    CLR DMX
    CLR CH1

; Stel adres in 
    ldi ADR,10
    mov CNT, ADR

; Set interupts
    sei

; Ga naar main programma
    rjmp main

; Framing error
FRe:
    sbr DMX,1       ;Set bit FRe
    reti            ;Return interrupt

;Startbyte dectie
StartByte:
    cpi data,0      ;compare if data = 0
    brne return     ;zo niet naar return
    sbr DMX,2       ;zowel set startbyte bit
    dec CNT         ;verlaag CNT
    reti            ;return interrupt

;Channel 3
c3: mov CH3, data   ;data naar CH2
    sbr dmx, 16     ;set CH2 data bit
    reti            ;return interrupt

;Channel 2
c2: mov CH2, data   ;data naar CH2
    sbr dmx, 8      ;set CH2 data bit
    reti            ;return interrupt

; Interupt programma
inte:
    lds temp,UCSR0A ;zet ontvang flags in register
    lds data, UDR0  ;zet ontvangen data in register
    sbrc temp,FE0   ;kijk of er een frame error is
    rjmp FRe        ;wel: ga naar FRe 

    sbrs DMX,0      ;niet: kijk of er een FRe is geweest
    reti            ;niet: return interrupt

    sbrs DMX,1      ;wel: kijk of er een startbyte is geweest
    rjmp StartByte  ;niet: ga naar startbyte detectie

    dec  CNT        ;wel: verlaag CNT 
    brge return     ;als CNT niet 0 is naar return

    sbrc DMX,4      ;wel nul: test als CH2 al geset is
    rjmp c4         ;wel: dan naar channel 3

    sbrc DMX,3      ;wel nul: test als CH2 al geset is
    rjmp c3         ;wel: dan naar channel 3

    sbrc DMX,2      ;wel nul: test als CH1 al geset is
    rjmp c2         ;wel: dan naar channel 2

    mov CH1, data   ;niet: move data naar CH1
    sbr DMX,4       ;set ch1 bit
    reti            ;return interrupt

c4: mov CH4, data   ;move data naar CH2
    mov CNT, ADR    ;stel counter weer in
    CLR DMX         ;haal register leeg 
                    ;hierdoor begint hij weer van voor af aan
return:
    reti            ;return interrupt

; Start programma
main:
    mul ch1,ch4     ;ch1 x master(ch4)
    out OCR0A, r1   ;bovenste product(R1) naar uitgang
    mul ch2,ch4     ;ch2 x master(ch4)
    out OCR0B, r1   ;bovenste product(R1) naar uitgang
    mul ch3,ch4     ;ch3 x master(ch4)
    sts OCR2B, r1   ;bovenste product(R1) naar uitgang
    rjmp main