UDP-DMX512

Sorry, not translate to English.

//——————————————–

#ifndef Lan512DLL
#define Lan512DLL
#pragma pack(push, 1)
//必须是字节对齐方式,就是大小端的问题了

struct my_dmx {
unsigned char id[10]; //id必须为”AVLdiy.cn”
WORD Command; //命令有0xCA 0xCC 0x44 0x01 注意这是16进制数
WORD Channel; //通道 命令0xCC 用
BYTE Val; //通道里面的值 命令0xCA 和 0xCC 都用到
WORD BoxNum; //需要发那个盒子,就填盒子的数
BYTE xxx; // 保留
BYTE DmxDataStart; //512 个dmx开始的位置
};
/*
先来说下Command命令:
0xCA: 所有512个通道的dmx值变成结构中Val中的值
0xCC: 发送单通道的值,通道是结构的Channel,通道的值是结构中Val
0x4444: 恢复到出厂设置,出厂默认的IP是:192.168.1.15 MAC:00-1E-37-B2-33-B0
0x01:整个512通道在一个包里面批量发出,dmx[0]~dmx[511]填充在DmxDataStart位置
//注意了,UDP发包时,必须设置端口为0x1936(6454),不管是广播、单播还是组播都可以
//但端口一定必须是0x1936(6454)
先来举几个例子:

//——第1种发包方式————————————————–
全部512通道的值改变成8,命令为0xCA,笨的方式是不用我们的结构,自己填充:

unsigned char b[600]; //先定义一个600字节buff

b[0]=’A’; //填充我们协议规定的 id[0]
b[1]=’V’;
b[2]=’L’;
b[3]=’d’;
b[4]=’i’;
b[5]=’y’;
b[6]=’.’;
b[7]=’c’;
b[8]=’n’;
b[9]=0; //id[10] end

b[10]= 0xCA; //接着是command命令,注意command是2个字节,自己填充注意高低位
b[11]= 0x00; //command 的高位 目前都为0
b[12]= 0; //0xCA命令下 Channel 无用 / channel 低位
b[13]= 0; //0xCA命令下 Channel 无用 / channel 高位
b[14]= 8; //你想要改变全部512个通道的值,这里为8
b[15]=0; //发到哪个盒子 低位 第1个盒子填0,第2个盒子填1 ….
b[16]=0; //发到哪个盒子 高位 盒子少可以全部填0 除非你改变了SubNet
b[17]=0; //xxx 无用,保留字节
b[18]=0; //这个命令下,无用

UDPSend(b,18); //接着直接通过UDP发出去,发18个字节就可以,那么我们的盒子
//收到这个包后,会把全部的512个通道变成8,如果需要清零就把8
//改成0,如果需要512个通道全部开灯,就把8改成255
//注意了,UDP设置时,必须设置端口为0x1936(6454)
//UDPSend()这个函数为你自己写,就是发送UDP包,发送的端口必须为0x1936(6454)

//—第1种发包方式—–END—————————————

//———-第2种发包方式———————————————–
//命令为0xCC 给某个通道发送一个值,比如给第100通道发129的值,相当于第100个推子
//推到129那个位置

unsinged char b[600]; //先定义一个600字节buff

b[0]=’A’; //填充我们协议规定的 id[0]
b[1]=’V’;
b[2]=’L’;
b[3]=’d’;
b[4]=’i’;
b[5]=’y’;
b[6]=’.’;
b[7]=’c’;
b[8]=’n’;
b[9]=0; //id[10] end

b[10]= 0xCC; //接着是command命令,注意command是2个字节,自己填充注意高低位
b[11]= 0x00; //command 的高位 目前都为0
b[12]= 100; // channel 低位 这里为100
b[13]= 0; //channel 高位 如果通道大于255,这个值就转换下,需要填入
b[14]= 129; //通道的值,这里为129
b[15]=0; //发到哪个盒子 低位 第1个盒子填0,第2个盒子填1 ….
b[16]=0; //发到哪个盒子 高位 盒子少可以全部填0 除非你改变了SubNet
b[17]=0; //xxx 无用,保留字节
b[18]=0; //这个命令下,无用

UDPSend(b,18); //接着直接通过UDP发出去,发18个字节就可以,那么我们的盒子
//收到这个包后,会把第100这个通道变成129,如果需要改变第101通道
//为22,只需要把b[12]改为101,b[14]改为22,再UDPSend就可以
//——还是这个例子,聪敏的方式是用我们的结构,代码如下————

unsigned char b[600]; //先定义一个600字节buff
struct my_dmx *header;
header = (struct my_dmx *)&b[0];

header->id[0]=’A’;
header->id[1]=’V’;
header->id[2]=’L’;
header->id[3]=’d’;
header->id[4]=’i’;
header->id[5]=’y’;
header->id[6]=’.’;
header->id[7]=’c’;
header->id[8]=’n’;
header->id[9]=0;

header->Command =0xCC; //发单通道的命令
header->Channel=100; //第100通道,类似第100个推子
header->Val= 129; //通道的数值
header->BoxNum=SubNet<<4 | Universe; //盒子的分组,和分组中的位置 单个盒子填0
header->xxx =0; //保留字节

UDPSend(b,18); //把这个包通过UDP发出,发18个字节就可以了

//—第2种发包方式——END————————————–
//———-第3种发包方式———————————————–
//批量发送512个通道全部通道的值 命令为0x01
//还是举例子来说明 假设你有一个 DMXData[512] 保存的是你512个通道每个通道的值

unsigned char b[600]; //先定义一个600字节buff 里面需要512个字节保存512个通道的值
struct my_dmx *header;
header = (struct my_dmx *)&b[0];

header->id[0]=’A’;
header->id[1]=’V’;
header->id[2]=’L’;
header->id[3]=’d’;
header->id[4]=’i’;
header->id[5]=’y’;
header->id[6]=’.’;
header->id[7]=’c’;
header->id[8]=’n’;
header->id[9]=0;

header->Command =0x01; //批量发送命令
header->Channel=0; //这个命令下,此值无效
header->Val= 0; //这个命令下,此值无效
header->BoxNum=SubNet<<4 | Universe; //盒子的分组,单个盒子填0
header->xxx =0; //保留字节
//header->DmxDataStart = DMXData[0]; //笨方法
//header->DmxDataStart +1 = DMXData[1]; //笨方法
//…. = DMXData[2];

//把512字节的dmx值填充到 header->DmxDataStart后面
memcpy( &(header->DmxDataStart),DMXData,512); //聪敏的方法 512字节全部拷贝过去

UDPSend(b,600); //把这个包通过UDP发出,发600字节 盒子就会收到全部512通道的值了

//实际上你真正需要关心的是DMXData的值,每改变一次,就按上面的方式发出去
//那么你的灯,就会根据你的值来变化
//因为DMX512最大的刷新率为44Hz,也就是说不要超出22ms发一个包,如果超出的话
//发的包都是多余的包,类似精度的说法就是,每22ms发一个512通道的整包就是最大
//的精度了。顺便说下我们的盒子接的是10M的网卡,用到6M,因此即使你每隔0ms发
//数据包对盒子来说也是绰绰有余的。

//———-第3种发包方式—-End——————————————-
//恢复到出厂设置,命令为0x4444,万一设置乱了,可以通过这个命令恢复到出厂设置
unsigned char b[600]; //先定义一个600字节buff
struct my_dmx *header;
header = (struct my_dmx *)&b[0];

header->id[0]=’A’;
header->id[1]=’V’;
header->id[2]=’L’;
header->id[3]=’d’;
header->id[4]=’i’;
header->id[5]=’y’;
header->id[6]=’.’;
header->id[7]=’c’;
header->id[8]=’n’;
header->id[9]=0;

header->Command =0x44; //恢复出厂命令
header->Channel=0; //这个命令下,此值无效
header->Val= 0; //这个命令下,此值无效
header->BoxNum=0; //这个命令下,此值无效
header->xxx =0; //保留字节
UDPSend(b,18); //把这个包通过UDP发出,发18字节 盒子就会恢复到出厂设置了
//如果恢复到出厂设置,盒子的2个灯会闪10秒左右就恢复好了。
//出厂默认的IP是:192.168.1.15
//默认的MAC是:00-1E-37-B2-33-B0

//———-恢复出厂设置—-End——————————

*/
#endif