1、DMX512協議簡介
DMX 是Digital MultipleX 的縮寫,意為多路數字傳輸(具有512條信息的數字多路復用”)。DMX512控制協議是美國舞臺燈光協會(usITT)于1990年發布的燈光控制器與燈具設備進行數據傳輸的工業標準,全稱是USITTDMX512(1990);
DMX512 在其物理層采用EIA-485差分信號,結合可變尺寸,基于分組的通信協議。它是單向的。DMX512不包含自動錯誤檢查和糾正功能,因此不適用于危險應用,如煙火或舞臺裝置的移動。電磁干擾,靜電放電,不正確的電纜端接,電纜過長或電纜質量都可能造成虛假觸發,但是在連接控制器(如照明控制臺)與調光器和特效設備等都有廣泛應用。
2、DMX512協議分析
2.1、DMX512指令幀介紹:
每一個DMX 控制字節叫做一個指令幀,稱作一個控制通道,可以控制燈光設備的一個或幾個功能。一個DMX 指令幀由1個開始位(S)、8個數據位(D0-D8)和2個結束位(E)共11位構成,采用單向異步串行傳輸,如圖1所示。
圖1 DMX512 定時程序的幀結構(上圖)和信息包結構(下圖)
圖1 中虛線內控制指令中的S 為開始位,寬度為一個比特,是受控燈具準備接收并解碼控制數據的開始標志;
E為結束位,寬度為兩個比特,表示一個指令幀的結束;
D0~ D7為8 位控制數據,其電平組合從00000000一11111111 共有256個狀態(對應十進制數的0~255),控制燈光的亮度時,可產生256個亮度等級,0000~ (0)對應燈光最暗,11111111(255)對應燈光最亮。
DMX512指令的位寬(每比特寬度)是4 us,每一個指令幀11位,故指令幀寬度為44 us,傳輸速率為1/44us = 250 kbps。
2.2、DMX512信息包
一個完整的DMX512信息包(Packet)由一個MTBP位、一個Break 位、一個MAB位、一個SC 和512個數據幀構成。
MTBP(Mark TimeBetween Packets)標志著一個完整的信息包發送完畢,是下一個信息包即將開始的“空閑位”,高電平有效。
Break為中斷位,對應一個信息包結束后的程序復位階段,寬度不少于兩個幀(22 比特)。程序復位結束后應發送控制數據,
MAB位,由于每一個數據幀的第一位(即開始位)為低電平,所以必須用一個高電平脈沖間隔前后兩個低電平脈沖,這個起間隔、分離作用的高電平脈沖即MAB(Mark After Break),此脈沖一到,意味著“新一輪”的控制又開始了。
SC(Start Code)意為開始代碼幀(圖1中的第0幀),和此后到來的數據幀一樣,也是由11 位構成,除最后的兩個高電平的結束位之外,其他9位全部是低電平,通常將其叫做第0 幀或第0通道(Ch~nel No 0),可理解為一個不存在的通道(Non一~istent Channe1)。
表1 DMX512 信息包定時表
表1 是DMX512 信息包的定時表,表中NS意為自己設定,寬度沒有嚴格限制,由程序設計者自行決定,比如MTBP的寬度可以介于0~1秒之間,其他建議采用典型值。
調光控制臺每發送一個信息包,可以對全部512個受控通道形成一次全面的控制。發送一個信息包的時間大約是23 ms,每秒鐘將對所有512個受控通道完成44 次控制,即受控光路的刷新頻率44 Hz,如果實際受控通道少于512個,那么刷新頻率將相應提高。
3、DMX512接口電路
以下是使用RJ45連接器的接線及驅動電路 :
(XLR-5和RJ45基本類似)
表2 DMX512 設備使用RJ45連接器的接線表
圖2 DMX512 設備接口驅動電路
4、C51開發的DMX512發送程序
[cpp] view plain copy
1. // 串口工作在方式3
2. void send_dmx (void)
3. {
4. unsigned int count;
5. EA = 0;
6. TXD = 1; //break
7. TXD = 0;
8. Delay88us();
9. TXD = 1;
10. Delay8us();
11. TB8 = 1; //MAB
12. SBUF = 0x00;
13. while (!TI);
14. TI = 0;
15. for (count=0 ; count
16. TB8 = 1;
17. SBUF = XBYTE[count];
18. while(!TI);
19. TI = 0;
20. }
21. TXD = 1;
22. EA = 1;
23. }
5、C51開發的DMX512接收程序
[cpp] view plain copy
1. // 串口工作在方式3
2. void uart(void) interrupt 4
3. {
4. static bit flag = 0;
5. if(RI) {
6. if(RB8 == 0) {
7. if(SBUF == 0)
8. flag = 1; //set flag when meet a break
9. Recv.count = 0; //reset uart data counter
10. }
11. else if (flag == 1) {
12. if(Recv.count == 0) //byte after reset
13. if(SBUF != 0) //not a start code
14. flag = 0; //error, reset flag
15. if(Recv.count >= Recv.addr && Recv.count < Recv.addr + CTL_LEN) {
16. Recv.dat.Byte[Recv.count - Recv.addr] = SBUF;
17. }
18. If (Recv.count < 512) Recv.count++;
19. else flag = 0;
20. }
21. RI = 0;
22. }
23. }