为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

C sharp 蓝牙模块设计

2017-09-21 11页 doc 38KB 16阅读

用户头像

is_495010

暂无简介

举报
C sharp 蓝牙模块设计C sharp 蓝牙模块设计 C#CF Visual Studio 2008 win CE测试通过,仅需根据自己境况调用不同参数,请仔细使用。 关键代码汇总: // 查找本地蓝牙DeviceID 是一串以“:”分隔的16进制数字 [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthReadLocalAddr(byte[] pba); // 初始化查找周围设备 [DllImport("Btdrt.dll", SetLas...
C sharp 蓝牙模块设计
C sharp 蓝牙模块设计 C#CF Visual Studio 2008 win CE测试通过,仅需根据自己境况调用不同参数,请仔细使用。 关键代码汇总: // 查找本地蓝牙DeviceID 是一串以“:”分隔的16进制数字 [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthReadLocalAddr(byte[] pba); // 初始化查找周围设备 [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthNsLookupServiceBegin( byte[] pQuerySet,// Pointer to the search criteria LUP_CONTAINERS or LUP_RES_SERVICE string dwFlags,// ref int lphLookup);//[out] Handle to be used when calling the BthNsLookupServiceNext function to start retrieving the results set // 开始查找蓝牙设备 [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthNsLookupServiceNext( int hLookup,// Handle obtained from BthNsLookupServiceBegin string dwFlags,// LUP_RETURN_NAME, LUP_RETURN_ADDR, LUP_RETURN_BLOB, BTHNS_LUP_RESET_ITERATOR or BTHNS_LUP_NO_ADVANCE ref int lpdwBufferLength,//[in, out] On input, the number of bytes contained in the buffer that pResults points to //On output, this parameter contains the minimum number of bytes the pResults parameter uses to retrieve the record, //providing the function fails and the error is BthNsEFAULT. byte[] pResults);// Points to a block of memory where the result set is stored as a int structure on return. // 查找周围蓝牙设备结束 [DllImport("Btdrt.dll", SetLastError = true)] public static extern int BthNsLookupServiceEnd(int hLookup);// Handle obtained from BthNsLookupServiceBegin // 获取配对码请求 [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthGetPINRequest(byte[] pba);// Pointer to the Bluetooth address // 设置配对码 Tangmei007@foxmail.com [DllImport("btdrt.dll", SetLastError=true)] public static extern int BthSetPIN(byte[] pba, int cPinLength, byte[] ppin); // 创建ACL连接 [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthCreateACLConnection(byte[] pbt, ref ushort phandle); // 配对码验证 [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthAuthenticate(byte[] pbt); // 关闭认证连接 [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthCloseConnection(ushort handle); //BthGetHardwareStatus [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthGetHardwareStatus(ref int pistatus); //BthRevokePin [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthRevokePIN(byte[] pba); [DllImport("ws2.dll", EntryPoint="WSAGetLastError", SetLastError=true)] public static extern int CeGetLastError(); [DllImport("ws2_32.dll", EntryPoint="WSAGetLastError", SetLastError=true)] public static extern int XpGetLastError(); //SetService [DllImport("Btdrt.dll",SetLastError=true)] public static extern int BthNsSetService( byte[] lpqsRegInfo, int essoperation, int dwControlFlags); 一. 基本要点 1本文档时在VS2008中通过,其他VISUAL STUDIO 版本暂不知结果怎样。 2:需要熟悉非托管代码的调用。其实很简单,直接用就是的。 第一步:c#创建智能设备,目标平台windows CE 第二步:添加引用using System.Runtime.InteropServices; 二. 关于蓝牙 网上关于蓝牙开发的文章,很多人在.net CF开发中把蓝牙通信当作一个串行通信来处理,这也是不 Tangmei007@foxmail.com 错的,但是我不是很喜欢,因为这样做的话,并不是针对蓝牙来开发的,换言之,在使用过程中,需要先 手动开启蓝牙,配对,连接,建立串行通道,然后开启应用程序使用,你还要在应用程序中设置串行端口, 对最终用户来讲,这是非常麻烦的。我觉得,这样的解决冠上蓝牙通信的名头简直就是……不多说了, 书归正传。 蓝牙设备的DeviceID是一串以“:”分隔的16进制数字。 蓝牙有开启、关闭、可发现三种状态。 蓝牙有安全设置,所以我们需要对蓝牙设备进行配对。 在.net的Socket地址族里有IrDA,但是没有蓝牙相关的地址族,这是我们需要解决的问题。 三. 获取设备ID 1.获取本地设备的ID IDBthReadLocalAddr 第三步:用托管代码进行包装: [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthReadLocalAddr(byte[] pba); 2.获取远程设备的ID 其实谈到获取远程设备的ID就涉及到如何去发现远程设备了,所以这里就一并把发现设备的也 说明了吧。 发现设备需要用到三个Winsock API,分别是WSALookupServiceBegin、 WSALookupServiceNext和WSALookupServiceEnd,最多有七个可以连接。 WSALookupServiceBegin的数原形是这样的: INT WSALookupServiceBegin( LPWSAQUERYSET lpqsRestrictions, DWORD dwControlFlags, LPHANDLE lphLookup ); 第四步:用托管代码进行包装: [DllImport("ws2.dll", EntryPoint="WSALookupServiceBegin", SetLastError=true)] public static extern int CeLookupServiceBegin(byte[] pQuerySet, string dwFlags, ref int lphLookup); 可以看到,本来lpqsRestrictions是一个struct,经过包装后在托管代码中成为了byte[],我们计 算好该struct大概要占用多少个byte,struct中每一个成员在byte数组中的位置是怎样的,装配出来就好了。 装配pQuerySet: byte[] buffer1 = new byte[0x400]; BitConverter.GetBytes(60).CopyTo(buffer1, 0); GCHandle handle1 = GCHandle.Alloc(blob1.ToByteArray(), GCHandleType.Pinned); Tangmei007@foxmail.com IntPtr ptr1 = handle1.AddrOfPinnedObject(); BitConverter.GetBytes((int) (ptr1.ToInt32() + 4)).CopyTo(buffer1, 0x38); 另外的两个API也照类似方法调用即可。 在调用了WSALookupServiceNext之后,bytes数组pQuerySet中便包含了远程设备的地址信息, 下面我们需要把它找出来: int num5 = BitConverter.ToInt32(buffer1, 0x30); int num6 = Marshal.ReadInt32((IntPtr) num5, 8); int num7 = Marshal.ReadInt32((IntPtr) num5, 12); SocketAddress address1 = new SocketAddress(AddressFamily.Unspecified, num7); 因为.net框架的地址族里面没有蓝牙,所以我们这里用的是AddressFamily.Unspecified。然后的 工作就是从中获取远程设备的ID了: 前面我们已经计算出,这个Address里面的前六个字节是byte数组形式的设备ID,第七到第二十二 个字节是蓝牙的Service Guid,在后面四个字节是端口号,所以我们只需要分别提取出来即可。 四. 监听服务 监听服务调用的是非托管API WSASetService,其原型是 INT WSASetService( LPWSAQUERYSET lpqsRegInfo, WSAESETSERVICEOP essoperation, DWORD dwControlFlags ); 可以看到关键也是第一个参数,lpqsRegInfo,这也是一个struct,我们的包装方法与前面的发现设 备采用的方法类似,做蓝牙通信时要注意其成员要如下设置: lpqsRegInfo dwSize sizeof(WSAQUERYSET) lpszServiceInstanceName Not supported on Windows CE. Set to 0. lpServiceClassId Not supported on Windows CE. Set to 0. dwNameSpace NS_BTH. dwNumberOfCsAddrs Not supported on Windows CE. Set to 0. IpcsaBuffer Not supported on Windows CE. Set to 0. lpBlob Points to a BTHNS_SETBLOB structure, containing information about the service to be added. All other WSAQUERYSET fields are ignored. Tangmei007@foxmail.com 五. 连接 我们知道,IrDA中连接远程服务是使用方法System.Net.Sockets.IrDAClient类中的Connect方法。而这个方法又是调用的Socket类中的Connect方法。而Socket类是一个比较抽象的类,它并不绑 定某个具体的地址族、SocketType和protocolType,所以在实例化的时候,需要指定这三个参数。我们 也知道,在IrDA中,这三个参数分别是AddressFamily.Irda, SocketType.Stream,和ProtocolType.IP,那么在蓝牙中这三个参数分别是什么呢?我们好像找不到。 且慢,真是这样吗?我们知道在.net中,这三个参数都是枚举值,而枚举在默认情况下,你可以认为就是int值的替代现。 我们该如何知道这三个参数到底是什么呢? 还是先看Socket类的Connect方法。 我们查查有关资料,可以知道这个方法实际上是调用的一个非托管函数: [DllImport("mscoree", EntryPoint="@339")] public static extern int connect(int s, byte[] name, int namelen); 也就是非托管的Socket API。 我们看Windows CE 4.2的SDK,可以看到,在使用蓝牙进行连接的时候,需要使用WinSock扩展。我们还可以看到,在使用蓝牙进行连接的时候,三个参数分别应当是AF_BTH、SOCK_STREAM和BTHPROTO_RFCOMM,至于这三个参数分别代表什么,我们就要查看相关的头文件了。 我们找到ws2bth.h头文件,可以看到AF_BTH代表十进制数32,而BTHPROTO_RFCOMM代表十六进制数0x0003,恰好和ProtocolType.Ggp代表的数值是一致的。所以,我们在实例化Socket时是这么写的: new Socket((AddressFamily) 0x20, SocketType.Stream, ProtocolType.Ggp); Socket实例化出来了,其他的当然就都好说了,这里不再赘述。 六. 蓝牙的安全设置 蓝牙比红外多了安全方面的设置,所以就需要多一些代码来处理这些。具体也就不多说了,其实也就 是一些非托管代码的包装调用,这些API在Btdrt.dll中: 获取配对码请求: [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthGetPINRequest(byte[] pba); 设置配对码: [DllImport("btdrt.dll", SetLastError=true)] public static extern int BthSetPIN(byte[] pba, int cPinLength, byte[] ppin); 比较麻烦点的是配对,总共有三步操作: 首先是创建ACL连接: [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthCreateACLConnection(byte[] pbt, ref ushort phandle); Tangmei007@foxmail.com 然后是配对码验证: [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthAuthenticate(byte[] pbt); 然后一定要关闭连接: [DllImport("Btdrt.dll", SetLastError=true)] public static extern int BthCloseConnection(ushort handle); 七. 设置蓝牙无线电状态 我们知道,蓝牙无线电有打开、关闭、可发现三种状态,那么我们如何实现编程控制呢? 先写一个枚举: public enum RadioMode { Connectable = 1, Discoverable = 2, PowerOff = 0 } 然后写一个函数调用非托管代码即可: [DllImport("BthUtil.dll", SetLastError=true)] public static extern int BthSetMode(RadioMode dwMode); 获取无线电状态的话就用下面的函数: [DllImport("BthUtil.dll", SetLastError=true)] public static extern int BthGetMode(ref RadioMode dwMode); Tangmei007@foxmail.com
/
本文档为【C sharp 蓝牙模块设计】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索