资讯详情

进制转换BCD码

//using System; //using System.Collections.Generic; //using System.Drawing; //using System.Text; //using System.Threading; //using System.Threading.Tasks;

//namespace ShellLibrary /{ // public class SwitchDemo //{ // /* // sh过程控制不能为空,如(以下为)php流程控制写法) // if(isset$_GET[“q”]) //{ // searcj(q); // }else //{ / /////什么都不做 // } // Linux远程登录 // Linux一般作为服务器使用,而服务器一般放在机房,你不可能在机房操作你的Linux服务器 这时,我们需要远程登录Linux服务器管理和维护系统 // Linux通过系统ssh远程登录功能的服务实现,默认ssh服务端口为22 / 4位二进制数表示1位十进制数0~这是一个数字,简称BCD码,即BCD码,BCD代码Binary-Coded Decimal? // 简称BCD,称BCD代码或二十进制代码已成二进码十进数。它是一种二进制数字编码形式,用二进制编码 / // 如果int a = 1677720,06进制x01 00 00 04则04属于低字节,01属于高字节 / 如果a存储顺序如下图所示(即低字节存储高地址),大端模式 01 00 00 04 00x0001 低地址 0x0004高地址 / // 如果a内存中的存储顺序如下图所示(即低字节存储在低地址) / / 3)如何交换(通过移位操作或) // 大端和小端如何转换? / 字数据(16位) // #define BigtoLittle16(A) (((uint16)(A)&0xff00)>>8)(((uint16)(A)&0x00ff)<<8) // 4存放顺序 // 1原则 / 1 / 低地址存储低,高地址存储高。int a = 1,存储条件为0000(高地址)0000 00001(低地址) / 2)几个局部变量(储存在栈中) / 先定义高地址,后定义低地址 // 3)类、结构体或数组元素 / 先定义低地址,后定义高地址 // 24C地址为两个8位,共有4095个存储单元 // 4095=0xFFF,因此,您存储的地址应由您自己确定。例如,我想将秒值(注意值,而不是地址)存储到0x00ff在这个单元中,地址是 / 高位0x00,低位0xff / 当然,您也可以将秒地址存储在那个单元中,这似乎毫无意义 / 字节序(大小端)从高低地址和高低位详细解释 / // 字节序,顾名思义,字节顺序,再说两句,就是内存中存储的存储顺序大于一个字节类型的数据(当然,一个字节的瞬间狙击手不需要谈顺序) / 事实上,大多数人在实际开发中很少直接处理字节目。只有在跨平台和网络程序中,字节序才是应该考虑的问题 / 在所有介绍字节序的文章中都会提到字节序分为两类:Bit-Endian和Little-Endian.引用标准的Big-Endian和Little-Endian的定义如下 // a)Little-Endian内存低地址端排放低字节,内存高地址端排放高字节。 // b)Big-Endian内存低地址端排放高字节,内存高地址端排放低字节 // c)网络字节序:4个字节32bit 以下顺序传输:首先是07bit,其次815bit,然后1623bit,最后是2431bit.这种传输顺序 / 称为大端字节序。TCP/IP第一部电影中所有的二进制整数在网络传输中都需要这个顺序,所以也叫网络字节序。比如以太网投失败 / 2字节"以太网帧类型",表示后面数据的类型。ARP对于以太网帧类型的请求或响应,在网络传输中,发送顺序为0x08,0x06. / 内存如下图所示 / 栈底(高地址) // x006 – 低位 // 0x08 – 高位 / 栈底 / 栈顶 // 在各种计算机系统结构中,字节计算机通信领域的一个非常重要的问题,字节和单词的存储机制不同 / 即通信双方交流的信息单元(比特、字节、单词、双字等)应按什么顺序传输。).如果没有一致的规则, / 通信双方将无法正确编码/翻译,导致通信失败。目前,字节存储机制主要用于各种系统的计算机 / 有两种:Big-Endian和Little-Endian,从字节序开始 / 一,什么是字节序? / 字节序,顾明思义字节的顺序,再说两句就是大于一个字节类型的数据Byte8位 // a)Little-Endian内存低地址端排放低字节,内存高地址端排放高字节 // b)Big-Endian是高字节排放再内存的低地址段,低字节排放在内存的高地址端 // 1.1 什么是高/低地址端? // 1.1 什么是高/低地址端? 首先,我们应该知道我们C程序图像中的空间布局:《C或在专家编程中《Unix环境高级编程》中有关内存空间布局的情况的 // 说明如下图所示 / -最高内存地址xffffffff / 栈底 // 栈 / 栈顶 // -------------- // Null(空洞) // __________ // 堆 // __________ // 未初始化数据 // ----------- / 正文段(代码端) / -0最低内存地址x00000000 以上图为例,如果我们在栈上分配一个unsign char buf[4]这个数组变量是怎么堆叠的? / 布局怎么样? / 栈底(高地址) // -------- // buf[3] // buf[2] // buf[1] // buf[0] // ------- / 栈顶(低地址) // 1.2 什么是高/低字节? / 现在我们找出了高/低地址,然后考虑了高、低字节。有些文章称低字节为最低有效位,高字节位为最高有效位 / 如果我们有32个无符号整形手术x12345678。那么什么是高位,什么是低位?其实很简单 // 在十进制中我们都说靠左边的是高位,靠右边的是低位,其他进制也是如此。就拿0x12345678,从高到低 // 字节依次为0x12,0x34,0x56,0x78 / 高/低地址端和高、低字节都清楚了。让我们回顾以下内容Big-Endian和Little-Endian用图表解释两个字节序的定义 // 以unsigned int value = 0x以12345678为例,我们可以分别看两个字节序下的存储。unsigned char buf[4]来表示value // Big-Endian如下图所示: / 栈底(高地址) // buf3–低位 // buf2 // buf1 // buf0–高位 / 栈顶(低地址) // Little-Endian:如下图所示: / 栈底(高地址) // ------------ // buf3–高位 // buf2 // buf1 // buf0–低位 // 栈顶(低地址) // 2各种Endian // 2.1 Big-Endian // 在计算机系统结构中描述多字节存储顺序的属性,这是该机制中最重要的字节(MSB)存储在最低端的低智商 // 使用这种机制的处理器IBM3700系列、PDP-10,Mortolora微处理器系列和绝大多数RISC处理器 // |0x34|<-0x00000021 // |0x12|<-0x00000020 / 图1:双字节数0x1234以Big-Endian起始地址0的方式存在x0000000020中 // 在Big-Endian中,对于bit搜索中的序号编排如下(双字节数0x8B8A为例) // bit 13 111 113 1 1515 // val[1 00 00 1 0 1 | 1 00 00 1 0 1 0 / 地址表 // 仪表支持Modbus-rtu协议中的03H命令与10H命令,03H读多个寄存器,10H为了写多个寄存器,请自行查询协议数据格式 / 下表为仪表的寄存器地址表

// 数据地址 数据名称 长度 阅读,写 备注 // Address Variable Length R/W Notes // 0000H Current total electricity 4 R

// 阅读数据 例1:阅读A相电流数据Read Phase A current data / 查询数据帧Query data 01 03 0064 0001 C5 D5 / 返回数据帧Return data 01 03 02 03 B2 38 C1 // 说明: / 01 :从机地址 Slave device address // 03:读功能码 Read function code // 02:十六进制02,十进制02,表示后面有2个字节长度的数据 // 02:Hex 02 - Decimal02 - Indicates that there are 2 bytes of data // 38 C1:循环冗余校验码 // 数据处理方法:9.1地址表中见 // Data processing method:9.1Address table // 处理如下:03 B2(十六进制)=946(十进制) // 03B2(Hex) = 946(Decimal) // Calculate计算:9460.01 = 9.46 // 单位:A unit: A // 读电压数据与读电流相似,只是起始地址不同,计算方法和地址详见9.1地址表 // 例2:读总有功电能数据Read Current total electricity // 查询数据帧Query data 01 03 0000 0002 C4 0B // 返回数据帧Return data 01 03 04 00 00 30 26 6F 9E // 数据处理:Data processiong // 高位:0000(16进制)=0(10进制)Reg Hi:00 00(Hex)=0(Decimal) // 低位:30 26(16进制)= 12326(10进制) Reg Lo:3026(Hex) = 12326(Decimal) // 因此该仪表二次测有功电能为:(0x65536+12326)0.01 =123.26 // The current total electricity on the secondary side of the instrument is : // (065536+12326)0.01 = 123.26 // 单位:kWh Unit:kWh // 无功电能做相同处理,如需依次测电能数据,请自行乘以电压、电流变比 // Reactive electric enenrgy processing is the same.If you need to measure the primary energy data // please multiply Pt and Ct by yourself // 读功率数据与读电流相似,只是起始地址和计算方式不同,计算方法和地址详见9.1地址表 // 电能表与串口助手485通信基于DLT645-2007通讯协议 // 1)拿到一个数字电表,是DDS7866杭州中奈电表,想要做485通信读取电表数据,首先要知道电表的地址域也就是通信地址 // 地址域由6个字节构成(A0~A5),每个字节2个BCD码,每块电表都有一个唯一的通信地址。这个地址域是可以更改的 // 下面两个图片是更改后的电表实际地址,出厂默认的地址是201602240158,现在更改为0000 0000 0000 0001 // 如果不知道波特率可以一个个试 // 1每个字节含8位二进制码,传输时加上一个起始位(0)、一个偶校验位和一个停止位(1) // 共11位,其传输序列如图7.D0时字节的最低有效位,D7是字节的最高有效位,先传低位,后传高位 // 传送方向 0 D0 D1 D2 D3 D4 D5 D6 D7 P 1 // 起始位 8位数据 偶校验位 停止位 // 帧格式 // 帧是传送消息的基本单元 帧格式如图8所示 // 说明 代码 // 下面是通信发送例子 // 以下的数据帧均已表地址0000 0000 0000 0001为例: // 1广播设地址 // 控制字©:15 // 数据:00 00 00 00 00 01 // 数据帧:FE FE 68 AA AA AA AA AA AA AA 68 15 06 34 33 33 33 33 1A 16 // 正确返回数据帧:68 01 00 00 00 00 00 68 95 00 66 16 // 2读取总电量 // 控制字©:11 // 数据ID(DS):00 00 00 00 // 数据帧:FE FE 68 01 00 00 00 00 00 68 11 04 33 33 33 33 33 B2 16 // 返回数据帧:68 01 00 00 00 00 00 68 91 08 33 33 33 33 33 33 33 33 02 16 // 红色的部分是电量,要减33,减后为00 00 00 00即0.00度 // 3拉闸命令 // 控制字©:1C // 数据帧:68 01 00 00 00 00 00 00 68 1C 10 35 33 33 33 44 44 44 44 4D 33 45 68 47 53 43 47 2C 16 // 正确返回帧:68 01 00 00 00 00 68 9C 00 6D 16 // 4合闸命令 // 控制字©:1C // 数据帧:68 01 00 00 00 00 00 68 1C 10 35 33 33 33 44 44 44 44 4E 33 45 // C# BCD码与十进制数的转换 // BCD码(Binary-Coded Decimal)是二进制编码的十进制数的缩写,BCD码用4位2进制数表示一位十进制数。BCD码各位的数值 // 范围为2#0000 2#1001对应于十进制数09 // / // private static byte ConvertBCD(byte b)//byte 转换为BCD码 // { // //高四位 // byte b1 = (byte)(b / 10); // //低四位 // byte b2 = (byte)(b % 10); // return (byte)((b1 << 4) | b2); // } // /// // /// 将BCD一字节数据转换到byte 十进制数据 // /// // /// 返回转换后的BCD码 // /// // public static byte ConvertBCDToInt(byte b) // { // //高四位 // byte b1 = (byte)((b >> 4) & 0xF); // //低四位 // byte b2 = (byte)(b & 0xF); // return (byte)(b1 * 10 + b2); // } // / // 以下为电能地址表 // 003FH ~0040H 吸收有功电能二次测 R 0-999999999(转化公式6.2.2) Uint32 // 0041H~0042H 释放有功能电能二次测 R 0-999999999(转换公式见6.2.2) Uint32 // 0043H~0044H 感性无功电能二次侧 R 0-999999999 Uint32 // 我用modbus rtu协议编通讯时读寄存器值,主机发的数据是01 03 00 10 00 02 crc,接收到这串数据 // 寄存器地址该怎么来处理 01是地址,03是读寄存器 00 10 是寄存器起始地址 00 02 是寄存器数量高低字节 // 可以将浮点数先转化为双整数,在上位机在进行操作。例如下位机10或者100,上位机/10或者/100 // 能否给个更清晰的思路,我是想在下位机直接处理完发送给上位机 // 从站进行回馈的时候代码应该是01 03 00 04 ****crc,其中01地址 03读操作, 0004字节数,****数据 // 如果想直接传送浮点数的话就把相应的浮点数存储到你要读取的地址中,即0010中 // BCD 0-9 ====> 4位2进制 // 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 // ASCII // HEX 0-9A-F =>4位2进制 // 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 // 8进制 0-7 // 8进制=》3位2进制 // 68 27 01 46 05 // 00 00 68 81 34 // 00 03 01 00 // 30 09 05 07 21 // 12 00 01 DD 0B // 00 00 00 00 28 // 46 46 00 00 00 // 00 6F 12 03 3B // 7B 00 2F 45 00 // 00 E8 41 00 00 // E8 41 00 00 00 // 00 80 4E 90 47 // 00 00 C0 42 B8 // 16 // 27 // 27/10 = 2<<4+27%10 // (0x27>>4)*10+(0x27&0x0F) // 帧结构 // 帧格式定义 // 帧起始符 68H // 地址域 A // 帧起始符 68JH // prvate sub Timer12_Timer() // On Error Resume Next // Dim SendStr(11) As Byte // SendStr(0) = 0 ‘交换识别号高字节’,通常为0 // SendStr(1) = 0 ‘交换识别号低字节’,通常为0 // SendStr(2) = 0 ‘协议识别号高字节’,为0 // SendStr(3) = 0 ‘协议识别号低字节’, 为0 // SendStr(4) = 0,‘字节长度高字节’ // SendStr(5) = 0 ‘以下字节长度低字节’ // SendStr(6) = &H2A ‘设备地址’ // SendStr(7) = &H4 ‘读多个字命令代码’ // SendStr(8) = &H4 ‘读多个字命令代码’ // SendStr(9) = 0 ‘读数据的起始地址低字节’ // SendStr(10) = 0 ‘数据长度高字节’ // SendStr(11) =6 ‘数据长度低字节’ // Dim aStr As String // Dim i As Integer // For i = 0 To 11 // aStr = aStr & Chr(SendStr(i)) // Next i // Winsock3.SendData aStr // End Sub // 定时器定时发数据 // 发送000006H2AH40006 发送是字符串 // 把这些数字转换成16进制然后拼接成字符串发送 // 就Modbus是PLC行业通用协议 其他协议是私立协议

// */ // int rear = 0,top; // int[] Mp, MpQueue;

// public void Player() // { // //int front = rear + 1; // // rear = 0; // // top = -1;

// // top++; // // Mp[top] = MpQueue[front - 1]; // // int direct1[4][2] = {1,0,0,1-1,-1,0 };//定义方向 // // while (front != rear) // // { // // front–; // // for (int j = 0; j < 4; j++) // // { // // if (Mp[top].x+direc1[j][0]==MpQueue[front-1].x&&Mp[top].y+direc1[j][1]MpQueue[front-1].y) // // { // // top++; // // Mp[top] = MpQueue[front - 1]; // // } // // } // // } // /* // 通讯地址表(Modbus-RTU协议)(注:单相电能表电量请读取A相数据) // 地址 参数 读写属性 数值范围 数据类型 // 0000H 保护密码 R/W 0001-9999 Uint16 // 0001H高字节 通讯地址 R/W 0001-0247 Uint16 // 0001H低字节 通讯波特率 R/W 0-3:38400\19200\9600 4800bps Uint16 // 0002H低字节 控制字 R/W 第8位-接线方式(0-三相四线\1-三相三线) // 第7位-输入电压范围(0-400V\1-100V) // 第2位-输入电流范围(0-5A\1-1A) // 0003H PT变比 R/W 1-9999 Uint16 // 0004H CT变比 R/W 1-9999 Uint16 // 0005H 第一路变送参数设置 R/W // 0006H 第一路变送参数设置 R/W -9999~9999(同变送设置菜单5.4.2中Ao.Hi) Int16 // 0007H 第一路变送参数设置 R/W -9999~9999(同变送设置菜单5.4.2中Ao.Lo) Int16 // 0008H-000AH 第二路变送参数设置 R/W 同一路变送参数设置 Uint16 // 000BH-000DH 第三路变送参数设置 R/W 同一路变送参数设置 Uint16 // 000EH-0010H 第四路变送参数设置 R/W 同一路变送参数设置 Uint16 // 0011H高字节 背光控制 R/W 仅使用LCD显示仪表,0为常量 Uint16 // 0012H rt-1时,rt-1分 R/W 高位:rt-1时,低位:rt-1分 Uint16 // 0013H rt-1费率,rt-2时 R/W 高位:rt8-rt1费率(1尖,2逢) // 变送输出选择 // 字Wort 合并之后储存 // 字节单位数据分离 字拆分为2个 // 拆分寄存器起始地址 n是2的话 如果说n是3或4的话 s或s+1 储存在第一第二当中 // 16进制讲解更好的应用 100拆分两个字节 比如说 拆三个字节 // 20 // D2002 再看一下 在触发一下 // 字节合并成一个字 触发M2 D200 两个合并成D20010 字节合并成 // 我们的Swap高低进行转换 // 三个知识点 // 1000 正向有功电能总 // 1001 正向有功电能费率1 // 1002 正向有功电能费率2 // 1003 正向有功电能费率3 // 1004 正向有功电能费率4 // 1020 正向有功电能总 // 1021 反向有功电能费率1 // 1022 反向有功电能费率2 // 1023 反向有功电能费率3 // 1024 反向有功电能费率4 // 1040 正向无功电能总 // 1041 正向无功电能费率1 // 1042 正向无功电能费率2 // 1043 正向无功电能费率3 // 1044 正向无功电能费率4 // 1060 反向无功电能总 // 1061 反向无功电能费率1 // 1062 反向无功电能费率2 // 1063 反向无功电能费率3 // 1064 反向无功电能费率4 // 1100 一象限无功电能总 // 1101 一象限无功电能费率1 // 1102 一象限无功电能费率2 // 1103 一象限无功电能费率3 // 1104 一象限无功电能费率4 // 1120 二象限无功电能总 // 1121 二象限无功无功电能费率1 // 1122 二象限无功电能费率2 // 1123 二象限无功电能费率3 // 1124 二象限无功电能费率4 // 1140 三象限无功电能总 // 1141 三象限无功电能费率1 // 1142 三象限无功电能费率2 // 1143 三象限无功电能费率3 // 1144 三象限无功电能费率4 // 1160 四象限无功电能总 // 1161 四象限无功电能费率1 // 1162 四象限无功电能费率2 // 1163 四象限无功电能费率3 // 1164 四象限无功电能费率4 // 2000 正向有功最大需量总 // 2001 正向有功最大需量费率1 // 2002 正向有功最大需量费率2 // 2003 正向有功最大需量费率3 // 2004 正向有功最大需量费率4 // 2020 反向有功最大需量总 // 2021 反向有功最大需量费率1 // 2022 反向有功最大需量费率2 // 2023 反向有功最大需量费率3 // 2024 反向有功最大需量费率4 // 2040 正向无功最大需量 // */ // /*读取无符号 // * 无符号读取 // * 创建串口对象 // * 组装报文 // * 发送报文 // * 返回报文 // * 解析报文 // List buffer = new List(); // buffer.Add(deviceAddr) // buffer.Add(funcCode) // buffer.Add(); // buffer // SerialPortBase() // 串口对象 portName串口名称 baudRate 波特率 dataBits数据为 stopBit停止位 parity校验位 // public SerialProtBase(string portName.int paudRate,int dataBits,StopBits stopBits,Parity party) // { // if(serialProt == null) // serialPort = new SerialPort(); // serialPort.ProtName = portName; // serialProt.BaudRate = baudRate; // serialPort. // } // public override bool Open() // { // if(SerialPortnull)throw(“未实例化”); // serialPort.Open(); // } // 上位机开发: // buffer.Add(BitConverter.GetBytes(startAddr)[1]); // buffer.Add(BitConverter.GetBytes(startAddr)[0]); // buffer.Add(BitConverter.GetBytes(length)[1]); // buffer.Add(BitConverter.GetBytes(length)[0]); // return buffer; // protect List GetWriteCommandBytes(byte deviceAZdddr){} // serialPort.Wirte(command.ToArray,0,command.Count); // await.Task.Delay(100); // /if(serialPort.BytesToRead == 0) await.Task.Delay(100) // ReadUint16(List result) // { // List values = new List(); // for(int i = 0 ; i<result.Count;i++) // { // List valuByte = new List(); // valueByte.add(result[i]); // valueByte.Add(result[++i]); // valueByte.Reverse(); // ushort value = BitConverter.ToUnit16(valueByte.Araray()) // ModbusRTU 创建通信对象Crete 提供通信对象Open // 读取无符号整形数据 // public overrride async Task<List> ReadUint16 // 拼装请求报文 // List readBytes = this.GetReadComandBytes(deviceAddr) // //进行RTU的封装 --添加一个CRC16校验 // readBytes = CRC16(readBytes); // List respBytes = await this.Send(readByte,Lemn); // 相应报文的校验 // if(respBytes.Count>0){ // //解析数据部分二 // respBytes.RemoveRange(0,3); // respBytes.RemoveRange(respBytes.Count-2,2); // //进行统一的方法解析 // return this… // } // List commandBytes = this.GetWriteCommandBytes(deviceAddr,funcCode,startAddr,val) // commandBytes = CRC16(commandBytes); // List respBytes =await this.Send(CommandByte);

// } // } // 读取分区数据过程实现 // 更新分区温度到数据库中 // 刷新分区列表 // $(function() // { // var url = window.location.pathname; // if(url==’/’) // { // $(".navbar-nav li first").addClass(“importantNva”); // } // $(".navbar-nav li").click(funct on() // { // $(this).addClass(“importantNav”).siblings().removeClass(); // $(".navbar-nav li:first,.navbar-nav li:nth-child(4)").removeClass(); // }) // }) // Read/Write Definition // Function // Address // Conection // Serial Settings // 255 240 322 275 290 320 209 268 390 // 仓库温度管理系统 // private void btnCheck_Click(object sender,EventArg e) // { // 仓库选择 手动选择 监测成功 // lblMsg.ForeColor = Color.White; // Task.Run(); // } // */ // }

// public void Runer() // { // Task.Run(()=> // { // this.Invoke(new Action(()=> // { // lglMsg.Text = “开始读取,请稍后”; // })); // Thread.Sleep(2000); // try // { // //读取分区数据,返回读取后的分区数据(读取到温度数据) // //刷新到分区列表 // List boxList = new List(); // //调用读取数据的方法??? // //刷新到分区列表 // if (boxList.Count > 0) // { // ShowSRegionBoxList(boxList);//重新加载盒子列表 // lblMsg.Text = “检测完成!”; // } // else // { // lblMsg.Text = “检测失败”; // lblMsg.ForeColor = Color.Red;

// } // } // catch (Exception) // { // string str = “监测错误,监测出现异常”; // throw; // } // }); // }

// public List ReadRegionTemperData() // { // List regionList = vsrtDal.GetSRegionTemperList(0);//读取全部分区数据 // ushort length = (ushort)regionList.Count;//要读取的长度 // ModbusRTU mbRTU = new ModbusRTU(“COM1”,9600,8,StopBits.One,Parity.None);//创建串口对象 // if (mbRTU.Open()) // { // Task.Run(async()=> // { // List values = await mbRTU.ReadUInt16(0,len,length);//读取温度值 // if (values!= null&&values.Count>0) // { // //温度数据存入各个分区中,当前室温 // //创建List列表,List // List regions = new List(); // for (int i = 0; i < values.Count; i++) // { // decimal temperVal = decimal.Parse((decimal)(values[i] / 10).ToString(“0.00”));//室温值 // StoreRegionInfo region = new StoreRegionInfo(_); // region.SRegionid = regionList[i].SRegionId; // region.SRTemperature = temperVal; // regionList[] // regions.Add(temperVal); // } // //将regions中分区数据更新到分区信息表里? // bool blUpdate = false;//更新结果 // if (!blUpdat) // return new List(); // } // await mbRTU.ReadUInt16(0); // }); // } // //转换为高温低温

// } // } //}

标签: 有功功率变送器校验

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司