Conversione seriale/DMX con AVR

CONVERSIONE SERIALE/DMX CON AVR

Ecco  come  realizzare un  convertitore  da  seriale verso  il  protocollo   DMX  tipicamente  usato  nel campo  del  controllo  dei  sistemi  di  illuminazione. L’hardware è piuttosto semplice: un AVR (90S2313) il  cui  UART (PD0 e PD1) sono  connessi  ad  un MAX232, mentre il PB0 connesso ad un MAX485. Il sistema funziona con un cristallo da 4MHz e l’UART dovrà essere impostato su 19200bps, 8 bit dati, 1 stop bit e nessuna parità. Connettendo il sistema ad un PC via RS232 il protocollo di comunicazione consiste nei seguenti passi:

  1. Il  PC  invia  all’AVR  il  byte  0xFF  (comando START);
  2. Quindi viene inviato un byte compreso tra 0x01 e 0x6C (costituisce il canale DMX);
  3. Quindi inviato il valore vero e proprio (un byte compreso tra 0x00 e 0xFF).

In caso di successo l’AVR risponderà con 0x00, altrimenti verrà restituito 0xFF. Di seguito il codice sorgente.

.include “2313def.inc”
.DEVICE AT90S2313
.def Temp = r16
.def Count = r17
.def FrameCount = r18
.def DMXByte = r19
.def BitCount = r20
.def RXBufferA = r21
.def RXBufferB = r22
.def RXBufferC = r23
.org 0x0000
    rjmp RESET
RESET:
    ldi Temp, 0xFF
    out DDRB, Temp
    sbi PORTB, 0
    ldi Temp, RAMEND
    out SPL, Temp
    sbi UCR, RXEN
    sbi UCR, TXEN
    ldi Temp, 4000000/(19200*16)-1
    out UBRR, Temp
    ldi XH, 0x00
    ldi XL, 0x61
    ldi Temp, 0x00
    ldi Count, 0x6C
ZEROMEM:
    st X+, Temp
    dec Count
    brne ZEROMEM
    ldi RXBufferA, 0x00
    ldi RXBufferB, 0x00
    ldi RXBufferC, 0x00
MAINLOOP:
    rcall SENDPACKETSTART
    ldi DMXByte, 0x00
    rcall SENDFRAME
    ldi XH, 0x00
    ldi XL, 0x61
    ldi FrameCount, 0x6C
POLLNEXTFRAME:
    sbis USR, RXC
    rjmp LOADBYTE
    rjmp STOREBYTE
SENDNEXTFRAME:
    rcall SENDFRAME
    dec FrameCount
    brne POLLNEXTFRAME
    rjmp MAINLOOP
LOADBYTE:
   ld DMXByte, X+
   rjmp SENDNEXTFRAME
STOREBYTE:
   in Temp, UDR
   cpi RXBufferA, 0x00
   brne CHECKBUFFERB
   mov RXBufferA, Temp
   ld DMXByte, X+
   rjmp SENDNEXTFRAME
CHECKBUFFERB:
   cpi RXBufferB, 0x00
   brne SYNC
   mov RXBufferB, Temp
   ld DMXByte, X+
   rjmp SENDNEXTFRAME
SYNC:
   mov RXBufferC, Temp
   cpi RXBufferA, 0xFF
   brne RETRANSMIT
   cpi RXBufferB, 0xFF
   breq RETRANSMIT
   cpi RXBufferB, 0x6E
   brge RETRANSMIT
   push XL
   ldi XL, 0x60
   add XL, RXBufferB
   st X, RXBufferC
   pop XL
   ldi RXBufferA, 0x00
   ldi RXBufferB, 0x00
   ldi RXBufferC, 0x00
   ldi Temp, 0x00
   out UDR, Temp
CMDOKWAIT:
   sbis USR, UDRE
   rjmp CMDOKWAIT
   ld DMXByte, X+
   rjmp SENDNEXTFRAME
RETRANSMIT:
   ldi RXBufferA, 0x00
   ldi RXBufferB, 0x00
   ldi RXBufferC, 0x00
   ldi Temp, 0xFF
   out UDR, Temp
RTRQWAIT:
   sbis USR, UDRE
   rjmp RTRQWAIT
   ld DMXByte, X+
   rjmp SENDNEXTFRAME
SENDPACKETSTART:
   cbi PORTB, 0
   ldi Count, 0x90
BRKDELAY:
   dec Count
   brne BRKDELAY
   sbi PORTB, 0
   ldi Count, 0x0b
MABDELAY:
   dec Count
   brne MABDELAY
   ret
SENDFRAME:
   cbi PORTB, 0
   ldi BitCount, 0x08
   nop
   nop
NEXTBIT:
   ror DMXByte
   brcs SENDONE
   nop
   nop
SENDZERO:
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   cbi PORTB, 0
   dec BitCount
   brne NEXTBIT
   rjmp STOPBITS
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   sbi PORTB, 0
   dec BitCount
   brne NEXTBIT
   nop
   nop
STOPBITS:
   ror DMXByte
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   nop
   sbi PORTB, 0
   ldi Count, 0x0b
STOPDELAY:
   dec Count
   brne STOPDELAY
   ret
Listato 1

Una risposta

  1. Maurizio Di Paolo Emilio Maurizio 3 settembre 2016

Scrivi un commento

Send this to a friend