您好, 登录| 注册|
论坛导航
您好, 登录| 注册|
子站:
商城:
论坛首页    单片机MCU/嵌入式
  •  发帖
  • 收藏

【原创】高山云教你之四----利用51单片机实现DMX512协议控制LED灯
阅读: 13265 |  回复: 27 楼层直达

2014/06/25 10:23:39
1
yueyunno1[版主]
集齐5个最佳回复
电源币:26 | 积分:31 主题帖:19 | 回复帖:312
LV9
军长


QQ截图20160321155901 宝箱升级喽!开启探秘地宫之旅!

QQ截图20160321155901  【有奖DIY】工程师本色上演 设计征集活动



利用51单片机实现DMX512协议控制LED灯

DMX512协议
1.协议简介
DMX是Digital MultipleX的缩写 ,意为多路数字传输。DMX512 控制协议是美国舞台灯光协会(USITT)于1990年发布的灯光控制器与灯具设备进行数据传输的工业标准 ,全称是 USITT DMX512(1990) ,包括电气特性、 数据协议、 数据格式等方面的内容。
2.电气特性和物理层
2.1.电气特性
DMX512采用EIA-485标准。
发送端:逻辑“1”以两线间压差+(2~6)V表示;
逻辑“0”以两线间压差为-(2~6)V表示;
接收端:A比B高200mv以上即认为是逻辑“1”;
		  A比B低200mv以上即认为是逻辑“0”。

2.2.拓扑结构
如图1所示为EIA-485电路拓扑结构,一条EIA-485数据链路包括一个差分线驱动设备(D)和多个差分接收终端(R)。

图1基于485的 DMX512拓扑结构
2.3.DMX512 端口及数据链路 因为是采用485差分信号传输,因此DMX512端口一般采用3针或5针接口,相对应的导线则为1对或2对双绞线,导线同时应采用箔片或编织筛包裹。XLR针口分配如下表1所示,其中辅助数据链路可以不用。

基于EIA-485传输距离理论上可以达到1200m,建议控制在800m以内,若要加长传输距离,则需考虑中继器。DMX512数据链路的终接方式应消除信号环路和信号反射,否则可能导致正确设计的系统出现误操作。采用结终端电阻的方式可以消除信号反射,DMX512标准要求,终端电阻应放置在数据+和数据-信号针之间,阻抗范围120Ω+5%~120Ω-10%。 3.数据协议格式及传输 DMX512 协议规定数据以数据包的形式通过异步通讯的方式进行传输。每个数据包由若干数据帧组成, 每帧数据包括1 位低电平起始位、8 位数据位和2 位高电平停止位。DMX512协议要求数据传输的波特率为250kbps, 亦即每位的传输时间为4us, 每帧数据的传输时间为44us, 它支持多达512 帧数据传输, 每帧数据与相应的控制支路相对应。数据包的传送要符合一定的格式和时序要求,每个包需要发送2~513个字节数据(由总线设备来确定)。为了使接收器能够分辨出第一帧数据, 每一个数据包以一个不短于88us 的低电平信号为起始信号, 即所谓的BREAK信号, 接收器接收到BREAK信号就准备接受随后而来的数据帧; 紧接着BREAK信号之后是不短于8us 的高电平信号MAB (Mark after Break) ; 之后就是数据帧。在DMX512协议中, MAB之后的第一帧数据被称为SC(Start code), 即起始字节,在协议中规定其为零, 但在实际应用中可以由生产厂家自己确定其具体的值, 以传递特殊消息。SC标明其后面的数据是8位控制信号数据帧。一个数据包发送完成后,可以发送MT BP。MT BP (Mark Time Between Packets)标志着一个完整的信息包发送完毕 ,是下一个信息包即将开始的 “空闲位”,高电平有效数据帧之间可以有时间间隔, 也可以没有; 同样, 数据包之间可以有时间间隔, 也可以没有。DMX512协议规定BREAK信号、MAB信号的最短时间, 并规定BREAK信号、MAB信号、数据帧之间及数据包之间的时间间隔的最大值不得超过1s, 否则做出错处理, 但是DMX512 协议并未对出错处理做任何规定。DMX512协议所规定的数据格式如图2所示,各信号的定时时间如表2所示

图2中,虚线框内为一个数据帧的格式,S为1个比特起始位(低电平),E为2比特的停止位(高电平),D0~D7为8个比特的控制数据,其电平组合从 00000000~11111111 共有 256 个状态(对应十进制数的0~255) ,控制灯光的亮度时 ,可产生256个亮度等级 ,00000000 (0)对应灯光最暗 ,11111111(255)对应灯光最亮。信息包中,第1帧对应第1回路的灯具,第2帧对应第2回路灯具,依此类推,第512帧对应第512回路灯具,灯具回路的地址在灯具上可设置。 DMX512协议是一种基于主从式的协议,能够适应一对多的灯光控制系统。

标签 51单片机 MCU
8位微处理器兼容,双缓冲D/A转换器 面向自动PFC的电容组控制和HMI子系统 SIMPLE SWITCHER 60V,3A降压转换器,40uA Iq
30V N沟道MOSFET -55至150 智能电子式电表的3.3V低成本非隔离离线转换器 3.5 - 36V 2A、3A 低静态电流降压转换器
4.5V至17V输入,6A同步降压SWIFT™转换器 太阳能电池充电高效同步开关模式充电器控制器 具有 40μA 静态电流的 SIMPLE SWITCHER® 降压稳压器
2014/06/25 15:32:18
2
见仁见智
电源币:0 | 积分:0 主题帖:0 | 回复帖:2
LV2
班长
DMX512这个好像就是基于RS485通信协议的一种方式吧,这种方式只能一点对多点,不过用来控制灯光也完全够了,因为灯光是不用反馈数据的。
2014/06/25 15:46:21
3
电源网-娜娜姐
上一次首页头条
电源币:457 | 积分:217 主题帖:293 | 回复帖:1807
LV10
司令
乐工回来啦,新帖果断支持!~
2014/06/25 15:52:02
4
yueyunno1[版主]
集齐5个最佳回复
电源币:26 | 积分:31 主题帖:19 | 回复帖:312
LV9
军长
哈哈,回来了,也忙完了,感谢师长!
2014/06/25 15:52:50
5
yueyunno1[版主]
集齐5个最佳回复
电源币:26 | 积分:31 主题帖:19 | 回复帖:312
LV9
军长

原理图如下:

2014/09/10 11:37:16
22
S112
电源币:9 | 积分:0 主题帖:0 | 回复帖:7
LV2
班长
乐工,中断接入ISSI 402-3G这个芯片,不知道了解不?
2014/06/26 09:13:02
6
yueyunno1[版主]
集齐5个最佳回复
电源币:26 | 积分:31 主题帖:19 | 回复帖:312
LV9
军长
//============================================================================
//================         DMX512接收数据=====================================
//============================================================================   

#include<stc11f0x.h>
#define uchar unsigned char
#define uint  unsigned int

#define ON  1
#define OFF 0

sbit         R = P1^7 ;
sbit         G = P1^6 ;
sbit         Y = P1^5 ;

sbit   COM   =  P3^7 ;

sbit   EN_485   = P3^4;                        
sbit   Work_LED = P3^3;                         
sbit   TXD      = P3^1;                         

uint   Address;                     //  Set_R, Set_G, Set_B  ;  //3路 接收和设置地址
bit    start_ok, Head_ok;
bit    DMX512_ok;                 //DMX512信号标志
uchar  cnt;                                                      //

uchar  R_dat,  G_dat,  B_dat ;     //RGB三路数据
uint   DMX_channel;                //DMX三路的起始地址
uchar  PWM;

/******************************************************************
- 功能描述:延时函数
- 隶属模块:无
- 函数属性:无
- 参数说明:无         
- 返回说明:无
- 注:.....
******************************************************************/
void Delay(uint ms)
{ uint a,b;
        for(a=ms;a!=0;a--)
            for(b=1210;b!=0;b--)
                   ;
    WDT_CONTR= 0x3d; 
}

/******************************************************************
- 功能描述:PWM扫描
- 隶属模块:无
- 函数属性:无
- 参数说明:无         
- 返回说明:无
- 注:.....
******************************************************************/
void RGB(void)
{ 
	uchar x;
	for(x=255;x!=0;x--)
	for(PWM=0;PWM!=255;PWM++)  
	{
		if(R_dat>PWM) 
			{R=ON;}
		else                  
			{R=OFF;} 
			       
		if(G_dat>PWM) 
			{G=ON;}
		else                
			{G=OFF;}
		
		if(B_dat>PWM) 
			{Y=ON;}
		else                  
			{Y=OFF;}
	}                  
}

/******************************************************************
- 功能描述:七彩跳变函数
- 隶属模块:无
- 函数属性:无
- 参数说明:无         
- 返回说明:无
- 注:.....
******************************************************************/
void Tianbian(void)
{ uchar x=1,y;
   do
   {
                switch(x)
                {
                case 1:        
                   R=ON; G=Y=OFF; Delay(5);  break;
                case 2: 
                   G=ON; R=Y=OFF; Delay(5);  break;
                case 3:
                   Y=ON; G=R=OFF; Delay(5);  break;
                case 4:
                   R=OFF; G=Y=ON; Delay(5);  break;
                case 5: 
                   G=OFF; R=Y=ON; Delay(5);  break;
                case 6:  
                   Y=OFF; G=R=ON; Delay(5);  break;
                case 7:   
                   Y=ON; G=R=ON;  Delay(5);  break;        

                default:  x=1;                        break;

                }                                                         
                if(y++>100) 
                  {y=0;x++;}

   }while(!DMX512_ok);
}

/******************************************************************
- 功能描述:主函数
- 隶属模块:无
- 函数属性:无
- 参数说明:无         
- 返回说明:无
- 注:.....
******************************************************************/
void main(void)
{
     SCON=0xD0;             //UART工作于方式3  波特率为(1+SMOD)·(定时器1的溢出率)/32  REN=1接收允许
     PCON=0x0;              //不倍频,晶振24M 
     AUXR|=0X40;            //T1工作在1T模式*12         
     TMOD=0x20;             //T1工作于8位自动重装模式
     TH1 =0xFD;             //波特率20833*12=250K
     TL1 =0xFD;        

     TR1=1;                      //开定时器1
     PS=1;                  //设置串口中断为最高优先级
     ES=1;                  //开UART中断         
     EA=1;                                        //开总中断

     WDT_CONTR= 0x3d;             //开看门狗         64分频  16M   0.67s 

     cnt=3;                        //3通道
  
     EN_485=0;                        //MAX485收发选择 EN_485=1发, EN_485=0收
	/**************************************************************/	
     P1M1=0X00;                    //P1口设为推挽输出
     P1M0=0XFF;
     P3M1=0X00;                    //P3口设为推挽输出        P3.7为普通IO
     P3M0=0XFE;
	/**************************************************************/	    
	COM=0; 
	P1=0;
	Work_LED=0;	
	R=G=Y=OFF;
	Delay(10);

while(1)
  {        
	DMX512_ok=0;	   //DMX512信号标志
	DMX_channel=0;	   //DMX三路的起始地址
	WDT_CONTR= 0x3d;
	RGB();
	if(!DMX512_ok)
	{
		Tianbian();  //无信号
	}
  }
}

/******************************************************************
- 功能描述:串口中断函数,实现DMX512数据接收
- 隶属模块:无
- 函数属性:无
- 参数说明:无         
- 返回说明:无
- 注:.....
******************************************************************/
void Rec(void) interrupt 4             
{ 
	if(RI==1)  
	{ 
		RI=0; 
		if(Head_ok)                            //收到头码就可以收数据码
		{
			DMX512_ok=1;
			if( Address == DMX_channel )       //R 地址比较            
			{ 
				R_dat = SBUF;                   //取出数据 
				cnt--;
				if(!cnt) 
				{ 
					Address = 0; 
					start_ok = 0; 
					cnt=3; 
					Head_ok=0;   
				}
			} 
	      /**************************************************************/		 
			if(Address == DMX_channel+1 )      //G 地址比较                        
			{ 
				G_dat = SBUF;                  //取出数据 
				cnt--;
				if(!cnt) 
				{ 
					Address = 0; 
					start_ok = 0; 
					cnt=3; 
					Head_ok=0;   
				}
			}
		 /**************************************************************/	
			if( Address == DMX_channel+2 )      //G 地址比较                        
			{ 
				B_dat = SBUF;                    //取出数据 
				cnt--;
				if(!cnt) 
				{ 
					Address = 0; 
					start_ok = 0; 
					cnt=3; 
					Head_ok=0;  
				}
			}
		  /**************************************************************/	
			if(++Address>=512)                 //  地址溢出                
			{                 
				Address = 0; start_ok = 0; cnt=3; Head_ok=0;          //到此512个比较完
			}                             
		}  
		else
		{                      
			if(!RB8)//             //判断收到的第九位数据,只有在DMX送出>88us低电平的中断信号时(也叫同步码,起始码,),RB8才会为0
			{ 
				start_ok=1;   //收到起始位
				Address=0;    //0-255共256个通道                       
			}
			 
			else if(start_ok)
			{
				Head_ok=1;    // 收到设备信息数据
			}
		}
	} 
} 
 
2014/06/26 14:16:53
7
电源网-娜娜姐
上一次首页头条
电源币:457 | 积分:217 主题帖:293 | 回复帖:1807
LV10
司令
此贴已被推荐到论坛首页置顶头条~乐工继续!
2014/06/26 14:39:10
8
yueyunno1[版主]
集齐5个最佳回复
电源币:26 | 积分:31 主题帖:19 | 回复帖:312
LV9
军长
前段时间在帖子上看到有人在谈论用单片机来做DMX512协议去控制LED灯,这几天刚好有点时间就写了个,有部分资料也来自网上
2014/06/26 14:44:33
9
电子梦
电源币:0 | 积分:0 主题帖:0 | 回复帖:6
LV2
班长
正打算做DMX512的灯具,及时雨呀,网上也有很多资料,但是程序写得清晰明了的基本是没有的。
2014/06/26 15:00:56
10
单片机白菜
电源币:0 | 积分:0 主题帖:0 | 回复帖:6
LV2
班长
撸主你这个程序应该就是一个标准的DMX512程序吧,但是还有个问题,不带地址设置呀,如果有20条灯连接在一起的话估计全部都是一种变化效果,20条灯会同时动作。
2014/06/26 15:08:34
11
a2895812
电源币:24 | 积分:0 主题帖:0 | 回复帖:9
LV2
班长
标记个,下班回去了我也找段DMX512协议的调光灯程序贴上来,很久以前写的,非常乱,但是可以用。可以在普通ATMEL的2051上使用。方式和楼主不太一样,楼主的是中断接收,我的是查询接收;楼主的是主循环产生PWM,我的是定时器产生PWM。
2014/06/28 08:34:21
12
li9983456
电源币:0 | 积分:0 主题帖:0 | 回复帖:2
LV1
士兵
哇!这里还有有个高山云的新帖子,得顶~
2014/06/28 08:37:30
13
xiao245896
电源币:0 | 积分:0 主题帖:0 | 回复帖:5
LV1
士兵
恩,就是得支持,感谢楼主分享这么多。
2014/07/02 21:24:03
16
a2895812
电源币:24 | 积分:0 主题帖:0 | 回复帖:9
LV2
班长

//**********************************************************

//stc 2051 兼容ATMEL2051

//16M晶振 250k波特率

//最简实验DMX512调光序

//**********************************************************

//P3_5 - P1 0-511 通道选择 自动更新

//P3_2 P3_3 P3_4 R G B输出。

//**********************************************************  

 #include <AT892051.H>  

 #define        uchar unsigned char

//**********************************************************

//定义全局变量给中断程序使用。

//********************************************************** 

  uchar t0_mark=0x00,  data1=0x00, data2=0x00, data3=0x00,data4=0x00,

data5, data6, data7;  

 uchar da1=0x80, da2=0x80, da3=0x80,da4=0xff,mark=0x00,add=0x00; 

  unsigned  int   time;

//*******************************************************

//协议程序 

//*******************************************************  

 void start_bit(void) 

  { uchar a;     TR0=1;        while (P3_0==1);  

 // 等待传输暂停

 TR0=0;

TH0=0x00;

TL0=0x00;

TR0=1;

while  (P3_0==0); //等待端口变化

if(TL0>0x80||TH0>0x00)  //大于96微秒 

  { REN=1;time=0x00;while(RI==0);    

  data1=SBUF;  

if (mark==0x00)   

  { for( a=add; a!=0x00; a--){while(RI==0);   RI=0;  }  //启动串口  

while(RI==0);  

  data5=SBUF;    

  RI=0;   

 while(RI==0);     

 data6=SBUF;     

 RI=0;    

 while(RI==0); 

   data7=SBUF;

  RI=0; 

 REN=0;   

 if(data1==0x00)  { data2=(data5&0xfc)>>2;   

  data3=(data6&0xfc)>>2; 

  data4=(data7&0xfc)>>2; }              }

else { for( a=0xff; a!=0x00; a--)

{   while(RI==0);   RI=0;  }  //启动串口      

    for( a=add; a!=0x00; a--) 

  {while(RI==0);      RI=0;  }  //启动串口  

  while(RI==0);   

   data5=SBUF;   

   RI=0;   

 while(RI==0);   

   data6=SBUF;  

    RI=0;   

 while(RI==0); 

   data7=SBUF; 

 RI=0;

  REN=0;   

 if(data1==0x00)  { data2=(data5&0xfc)>>2; 

    data3=(data6&0xfc)>>2; 

  data4=(data7&0xfc)>>2; }                 }

P1=0xff;           

     if(P3_5==0)            

    { mark=0x00;            add=P1; }        

     else  { mark=0xff;             add=P1; }   }  } 

  void main(void)   

{       P3=0x00;

 P3_0=1;

 P3_1=1;

 P3_5=1;     

 P1=0xff;

 if(P3_5==0)  

  { mark=0x00;  add=P1; }

else  { mark=0xff;        add=P1; }    

     SCON=0x88;

 ACC=PCON;

   ACC=ACC+0x80;

 PCON=ACC; //串口方式2 

  TMOD=0x21; // 定时器0方式1 定时器1方式

TH1=0x80; //60个周期中断一次

 TL0=0x80;

 TR1=1;

 IE=0x8a;  //允许允许T0中断

 do { do { start_bit();                   }     

   while(REN==0);}

while(1) ;}   

 //****************************************

//定时器T0  16bit 

 //****************************************

        void  t0_irq(void) interrupt 1 

   { t0_mark++;   

  time++;

 if (time>0x500) 

     { time=0x00;    

 data2=0x00;

 data3=0x00;

 data4=0x00; }     }

//***************************************

//定时器T1  方式2  自动重装, PWM  200Hz

//***************************************

void  t1_irq(void) interrupt 3

{ if(da1==0x00)    

  {P3_2=0;  }   

  else  {da1--;         P3_2=1; 

}if(da2==0x00)    {P3_3=0;  } 

 else  {da2--;          P3_3=1;

}if(da3==0x00)    {P3_4=0;  }   

 else  {da3--;         P3_4=1;}

 if(da4==0x00)   

  { da1=data2;    da2=data3;da3=data4; da4=0x40;  }da4--;           }

//实验程序 谨慎使用!

2014/07/02 21:25:12
17
a2895812
电源币:24 | 积分:0 主题帖:0 | 回复帖:9
LV2
班长
DMX512.txt 排版惨不忍睹  文件上传吧,
2017/09/30 17:12:29
28
zhck
电源币:0 | 积分:0 主题帖:0 | 回复帖:23
LV2
班长

很好,不错学习了

2014/07/18 17:03:23
18
辷噺一意
电源币:0 | 积分:0 主题帖:1 | 回复帖:5
LV1
士兵
你好  你这个是不是和上面的电路图不匹配的呢?你那个R G B控制的引脚好像有点不对的呢?还问问你 想这种DMX一路的能传输多远的距离呢?是不是距离比较远的话就需要接连个DMX芯片一个作为输入 一个作为输出呢?
2014/07/19 16:02:20
19
a2895812
电源币:24 | 积分:0 主题帖:0 | 回复帖:9
LV2
班长

我不知道你是不是在问我,我这个程序是在控台上测试过的,是可以用的,DMX512协议规定在信号丢失多长时间后从设备应该自动关闭,这个程序里面也是有的,也就是说是按标准协议做的,但是测试不是完全,09年的时候刚出大学不久,水平有限,所以不建议使用这段程序。

管脚连接在程序的最前面我就标出来了,肯定和楼主的不兼容的,但只要按标名的管脚做外围就可以用了,具体我也多嘴说一下吧。

485总线按标准485总线电路连接即可,和楼主的应该一样,但也应该自己去看下485的标准接发。

P3_2 P3_3 P3_4是输出 注意极性,应接上拉电阻来驱动三极管,再驱动大功率三极管或者MOSFET,注意极性。

P3_5  和P1口  总共9个脚接DIP开关来设置地址,可以设置0-511地址,如果设置地址为32,则红色数据地址是32,绿色地址是33,蓝色地址是34;依此类推。

程序很乱,我自己都看不懂了。。。但是真的可以工作,还被我拿去卖了钱的。。。。。

2015/07/02 14:16:24
24
yhy630
电源币:4 | 积分:0 主题帖:7 | 回复帖:21
LV3
排长
谢谢楼主,要仔细研究一下.好好学习
2016/03/14 14:49:54
27
junfrom1989
电源币:0 | 积分:3 主题帖:0 | 回复帖:1
LV1
士兵
问一下 RB8是从哪里来的?

2014/07/01 22:17:02
14
phantasm
电源币:0 | 积分:0 主题帖:5 | 回复帖:119
LV5
营长
了解一下 虽然都用不用
2014/07/02 10:13:08
15
电源网-娜娜姐
上一次首页头条
电源币:457 | 积分:217 主题帖:293 | 回复帖:1807
LV10
司令
此贴已经被推荐社区经典!大家继续~楼主加油!~
2014/07/28 14:29:15
20
changlun
电源币:0 | 积分:0 主题帖:10 | 回复帖:466
LV7
旅长
哈哈~ 这个不错。
2014/08/09 09:23:28
21
mht820413
上一次首页头条
电源币:9 | 积分:29 主题帖:7 | 回复帖:160
LV6
团长
不懂但是也顶顶,会C的电源工程师,是未来的趋势。电源也得智能化
2015/01/02 10:29:56
23
jag6510
电源币:0 | 积分:0 主题帖:0 | 回复帖:34
LV3
排长
顶顶顶
2016/02/20 19:34:47
25
迪丽热巴
电源币:0 | 积分:3 主题帖:0 | 回复帖:1
LV1
士兵
还有好多不懂呢
2016/02/21 15:22:51
26
chen08046792
电源币:63 | 积分:0 主题帖:1 | 回复帖:51
LV3
排长
看看 
关注我们
新浪微博
官方Q群
客服热线
服务时间:周一至周五9:00-18:00
微信关注
免费技术研讨会
获取一手干货分享