基于Windows CE的蓝牙通讯模块实现

基于Windows CE的蓝牙通讯模块实现,第1张

  在Windows C++E.NET的开发上,目前采用微软公司2005年年底推出的Visual Studio 2005是最理想的选择。用 Visual Studio 2005可以进行利用C#,或VB.NET等语言开发基于.NET Compact Framework 2.0或1.0的 托管码WinCE程序,也可以利用C++语言来开发基于MFC,ATL或Win32API的本机码WinCE程序。

  因为在微软最新的.NET Compact Framework 2.0的类库中还未包含针对蓝牙通讯模块的类库,而且目前关于在Windows CE中开发蓝牙通讯模块应用程序的介绍还很少,同时开发蓝牙通讯技术的应用需要十分广泛,所以本文将就此进行一些讨论。

  1 基于托管码开发蓝牙通讯模块

  基于托管码的开发就是使用一套运行时环境(run-TIme environment)的应用程序接口来开发。

  一般情况下,托管码应用程序的开发会比较简单和快速,并且可跨软件平台和处理器来运行,所以开发出的托管码也能重新使用并有较高的可移植性。

  另外,内存管理、资源管理、资源收集、安全性管理等琐碎工作都由运行时环境来处理。应用程序开发工程师不必费心处理。托管应用程序在目标机器上运行,是通过目标机器端的实时编译器来实时把托管码编译成目标机器码后在目标机器上执行。

  由于在.NET平台下,采用CLR(公共语言运行时)可以用不同的语言来调用.NET Compact Framework来开发相同功能的应用程序,所以本文托管码部分仅采用C#语言为例来介绍蓝牙通讯模块开发。

  1.1 利用P/Invoke方法编写蓝牙通讯模块

  蓝牙通讯模块是一个涉及到驱动硬件的应用程序开发,而.NET Compact Framework并不是一个对Win32API进行了完整封装的类库。所以在基于托管码开发蓝牙通讯模块中必须利用到托管代码如何与非托管代码交互技术。P/Invoke全称为Platform Invoke,是.NET开发平台下允许托管代码调用DLL库的本地代码函数的服务,类似于JA-VA中的GNI的概念。图1说明了P/Invoke方法的工作原理。首先用相应语言的编译器将托管的源代码编译成Assembly的形式,其中包括元数据和中间语言代码。而此时P/Invoke的声明会以元数据的形式存在于 Assembly中,当Assembly被CLR调用的时候,CLR会根据元数据的声明在对应的DLL函数中查找DLL的实现。如果找到,就将其加载到内存中,并定位此DLL函数的人口点。将托管的参数人栈,并将函数的人口点指向对应的naTIve dll,从而完成了托管代码调用非托管代码的DLL。

  利用P/Invoke方法编写蓝牙通讯模块,DllI-port属性非常有用。下面的代码将用例子说明此通用方案,例中托管程序将调用MessageBox(位于User32.lib中):

  using

  using namespace System:: RunTIme::InteropSer-vices;

  namespace SysWin32

  {

  [DllImport ( "user32. dll", EntryPoint = "MessageBox", CharSet = Unicode)]

  int MessageBox(void * hWnd, wchar_t * lpText,wchar_t * lpCapTIon, unsigned int uType);

  }

  int main()

  SysWin32 :: MessageBox(0, L" Hello world ! ", L"Greetings", 0)

  }

  注意包含DllImport的代码行。此代码行根据参数值通知编译器,使之声明位于User32.dll中的函数,并将签名中出现的所有字符串(如参数或返回值)视为Unicode字符串。如果缺少EntryPoint参数,则默认值为函数名。另外,由于CharSet参数指定Unicode,因此公共语言运行库将首先查找称为MessageBoxW的函数。如果运行库未找到此函数,它将根据调用约定查找MessageBox以及相应的修饰名。

  当调用用户定义的DLL中所包含的函数时,有必要将extern"C"添加在DLL函数声明之前,如下所示:

  extern"C"SAMPLEDLL_API int fnSam-pleDLL(void);

  在调用非本机码时,需要注意的是要将非结构化参数由托管封送处理为本机码形式。可以利用CharSet参数值的作用,将参数中字符串(string*类型)都自动转换为wchar_t*。同样,所有Int32参数类型转换为非托管int,UInt32参数类型转换为非托管unsignedint,而 Intl6参数类型转换为了short int。char*用于[in]参数的为String*(CharSet=Ansi),用于[out]参数或返回值的为Text::StringBuilder*。wchar-t*用于[in]参数为String*(CharSet=Unicode),用于 [out]参数或返回值的为Text::StringBuilder*。需要注意的是函数指针必须具有_stdcall调用约定,这是因为这是 DllImport支持的唯一类型。对于数组来说数组(如wchar_t*[ ]),CharSet参数仅应用于函数参数的根类型。因此,无论 CharSet的值是什么,String*_ _gc[ ]将被封送处理为wchar_t*[]。除简单类型外,运行库还提供了一种机制,可以将简单结构由托管上下文封送处理为非托管上下文。简单结构不包含任何内部数据成员指针、结构化类型的成员或其他元素。

  在做一个关于蓝牙通讯程序前,还需要一些关于蓝牙的基础知识。一个蓝牙模块程序需要包含开启蓝牙,配对,连接,建立串行通道,然后开启通讯过程,还需要在应用程序中设置串行端口。因为蓝牙技术有安全方面的设置,所以需要对蓝牙设备进行配对。蓝牙的工作状态总共有3种,分别为开启、关闭、可发现。并且所有的通讯设备都必须有一个对应的DeviceID,蓝牙也不例外,蓝牙的DeviceID是一串以“:”分隔的16进制的数字。有了上述知识,就可以在托管码中利用P/Invoke方法开始编写蓝牙通讯模块了。

  对应的每一步需要调用的基本函数如下:

  •获取本地设备的ID

  [DllImport ( "Btdrt. dll", SetLastError = true) ]

  public static extern int BthReadLocalAddr (byte[]PBa)

  •获取远程设备的ID

  [DllImport( "ws2. dll", EntryPoint = "WSALook-upServiceBegin", SetLastError= true)]

  public static extern int CeLookupServiceBegin(byte[ ] pQuerySet, LookupFlags dwFlags, ref intlphLookup)

  •监听服务

  [DllImport (" ws2. dll", EntryPoint = "WSASetSer-vice", SetLastError= true)]

  public static extern int CeSetService

  (byte[ ] pQuerySet, RNRSERVICE_REGISTER,LookupFlags dwFlags)

  •连接

  [DllImport ( "mscoree", EntryPoint = "@ 339" )]

  public static extern int connect (int s, byte []name, int namelen)

  •蓝牙的安全设置

  获取配对码请求

  [DllImport("Btdrt. dll", SetLastError= true)]

  public static extern int BthGetPINRequest(byte[]pba)

  设置配对码

  [DllImport( "btdrt. dll", SetLastError= true)

  public static extern int BthSetPIN(byte[] pba, intcPinLength, 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(ushorthandle);

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/dianzi/2713090.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-08-17
下一篇 2022-08-17

发表评论

登录后才能评论

评论列表(0条)

保存