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:
- Il PC invia all’AVR il byte 0xFF (comando START);
- Quindi viene inviato un byte compreso tra 0x01 e 0x6C (costituisce il canale DMX);
- 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 |

Il protocollo DMX è praticamente diffuso in varie situazioni di architettura circa l’illuminazione. Permette di gestire numerosi punti luce RGB grazie all’ottima velocità di trasmissione dati. Il codice proposto mi sembra una buona soluzione per interfacciare la seriale con dispositivi Digital Multiplex.