精华内容
下载资源
问答
  • c#蓝牙转串口
    2020-12-19 01:45:33

    Windows 上的蓝牙编程并不方便,由于操作系统并没有提供统一的蓝牙操作接口,通常是由各个蓝牙设备商提供蓝牙栈,所以要想编程兼容这些不同的厂商蓝牙是一个问题。好在有个软件项目 32feet.NET 针对主流蓝牙协议栈提供了支持,包括 Microsfot, Widcomm, BlueSolei 等,同时还支持红外传输协议。

    蓝牙虚拟串口是一个较为常见的需求,为了兼容已有使用串口设备的程序,需要将蓝牙连接转为系统上的虚拟串口,然后提供给其他程序或库使用。32feet.NET 对此也提供了支持。

    32feet.NET 依赖 .NET 3.5 版本以上框架,支持 Windows 桌面版本、Wndows CE 以及 Windows Phone。

    安装

    如果使用 Visual Studio 2015 或者 安装有 NuGet 工具的,可以直接通过 NuGet 安装。在 NuGet 命令行中输入

    1

    Install-Package 32feet.NET

    这样 NuGet 会自动下载安装并添加到当前 .NET 项目中。可以检查项目 References 项,如果存在 InTheHand.Net.Personal 则表明已成功加入到项目中,如果没有,可以手动添加引用,NuGet 下载存放在 SolutionName\packages\32feet.NET.x.x.x.x\ 路径下。

    使用

    下面主要讲解 32feet.NET 的使用,覆盖蓝牙搜索、配对、直接连接以及虚拟串口服务。

    1. 检测系统蓝牙可用性

    如果系统没有蓝牙设备或者蓝牙设备被禁用,那么可以通过以下函数来进行检查:

    123456789101112131415

    /* 定义于类 BTHelper 中 */

    public static bool IsPlatformSupportBT()

    {

    BluetoothClient bc;

    try

    {

    bc = new BluetoothClient();

    }

    catch (PlatformNotSupportedException)

    {

    return false;

    }

    bc.Close();

    return true;

    }

    如果系统不支持蓝牙设备,那么 new BluetoothClient 会抛出 PlatformNotSupportedException 异常,通过捕获这个异常,来检测系统蓝牙设备可用性。

    2. 蓝牙搜索

    BluetoothClient 对象有个方法 DiscoverDevices 用于搜索蓝牙设备,该方法有多个重载版本,最终都是调用如下这个接口:

    1

    public BluetoothDeviceInfo[] DiscoverDevices(int maxDevices, bool authenticated, bool remembered, bool unknown, bool discoverableOnly);

    第一个参数表明搜索的最大设备数,第二个参数表示是否搜索已配对设备,第三个表示是否搜索记住的设备,第四个表示是否搜索未知设备,第五个参数表示是搜索范围内可被发现的设备。

    这里面重要的是第二和第五个参数,第二个代表搜索系统中已配对列表中的设备,即使它们现在并不在线。第五个参数 XP 系统上不支持,表示搜索范围内可被发现的设备。

    如果我们需要获得系统中已配对列表中的蓝牙设备,可以这样调用 DiscoverDevices(255, true, false, false),这里使用了4个参数的重载版本,只将第二个参数置为 true。

    如果我们需要搜索周围环境中可用的蓝牙设备,可以这样调用 DiscoverDevices(255, false, false, false, true),这个调用等同于 DiscoverDevicesInRange()。

    需要注意的是,这个调用是同步阻塞的,在搜索没有结束之前函数不会返回。所以通常我们需要将这个调用放入工作线程中。例外的是,如果只是获取系统中已配对列表中的设备,这个调用会很快完成,不会占用当前线程太多时间。

    库中同时提供了一个异步搜索方法,由类 BluetoothComponent 提供,由事件 DiscoverDevicesProgress 和 事件 DiscoverDevicesComplete 以及方法 DiscoverDevicesAsync 来实现。这个和用 BackgroundWorker 来实现 DiscoverDevices() 异步查找是一样的。

    PS: 可以通过 VS 的 Object Browser 查看 InTheHand.Net.Personal 库中的函数接口说明,说明非常翔实。

    3. 检测蓝牙设备是否在范围内

    当需要检查一个蓝牙设备是否在有效范围内,可以通过查询一个 Fake Service ID 来实现。

    如果蓝牙设备在范围内可访问,那么查询的结果是返回的服务记录为空,表示不支持此服务;如果蓝牙设备不在范围内,那么会抛出套接字异常。

    以下为检测代码:

    12345678910111213141516171819

    /* 定义于类 BTHelper 中 */

    public static bool TestingIfInRange(BluetoothAddress addr)

    {

    bool inRange = false;

    Guid fakeUuid = new Guid("{F13F471D-47CB-41d6-9609-BAD0690BF891}");

    BluetoothDeviceInfo device = new BluetoothDeviceInfo(addr);

    try

    {

    ServiceRecord[] records = device.GetServiceRecords(fakeUuid);

    Debug.Assert(records.Length == 0, "Why are we getting any records? len: " + records.Length);

    inRange = true;

    }

    catch (SocketException)

    {

    inRange = false;

    }

    return inRange;

    }

    需要注意的是,因为蓝牙设备通信需要时间,所以这个调用也需要较长时间才能完成,未完成之前进入阻塞不返回,所以这个方法也需要放入工作线程中执行。

    4. 蓝牙设备配对

    蓝牙配对功能由类 BluetoothSecurity 的静态方法 PairRequest(BluetoothAddress device, string pin) 提供,其中第一个参数是目标设备地址,第二个参数是用于配对的 Pin 码。配对成功返回 true,失败返回 false。

    解除配对是 BluetoothSecurity.RemoveDevice(BluetoothAddress device) 。

    配对操作也需要将长时间完成,所以这个方法也需要放入工作线程中执行。

    5. 蓝牙直接连接

    如果不需要蓝牙虚拟串口而直接读写蓝牙数据,那么可以使用直接连接,这个可以参照官方文档:General Bluetooth Data Connections.

    通过直接连接获取一个可读写的 System.IO.Stream 流对象,就可以直接对蓝牙进行读写数据操作了。以下为官方样例中的代码

    1234567891011

    BluetoothAddress addr = BluetoothAddress.Parse("001122334455");

    Guid serviceClass;

    serviceClass = BluetoothService.SerialPort;

    // - or - etc// serviceClass = MyConsts.MyServiceUuid//var ep = new BluetoothEndPoint(addr, serviceClass);

    var cli = new BluetoothClient();

    cli.Connect(ep);

    Stream peerStream = cli.GetStream();

    // peerStream.Write/Read ...

    6. 蓝牙虚拟串口

    这部分讲解如何实现将蓝牙连接转为系统上的虚拟串口并获取串口名,还可以参阅官方文档: Bluetooth Serial Ports.

    首先需要说明的是,虚拟串口和直接连接数据读写不能同时使用,如果已经使用了其中一个方法进行读写,那么另外的一个方法会失败。

    生成虚拟串口需要将蓝牙设备服务设置为 BluetoothService.SerialPort,官方样例代码如下:

    1234

    BluetoothAddress addr = BluetoothAddress.Parse("123456789012");

    BluetoothDeviceInfo device = new BluetoothDeviceInfo(addr); // Or from discovery etcbool state = true;

    device.SetServiceState(BluetoothService.SerialPort, state, true);

    SetServiceState 的第一个函数表示服务标识,第二个表示要设置的服务状态,true 为启用, false 为禁用,第三个参数表示如果设置失败是否抛出异常。

    但在实际使用中,某些双模蓝牙在设置时,虽然设置成功但是依然会抛出 Win32Exception 异常,所以这里建议调用此函数的重载版本 SetServiceState(System.Guid service, bool state),而想要知道是否设置成功,下面会介绍其他方法来获得。

    这个方法调用并不会告诉我们新生成的串口名,官方文档中的建议是通过设置前后的系统串口列表差异来获取新生成的串口名,而获取系统串口列表则可以调用静态方法 SerialPort.GetPortNames。

    但是不建议用这个方法来获取虚拟串口名,因为这个不可靠而且容易出错,下面介绍另外一个可靠方法,而且这个方法也可以同时告诉我们设置虚拟串口服务是否成功。

    获取蓝牙虚拟串口名

    蓝牙虚拟串口在系统中都有记录,我们可以通过检索这个记录,来找到所设置的设备的虚拟串口名,同时也可以得知我们的蓝牙虚拟串口是否设置成功。

    通过调用 WMI 查询,可以枚举出系统中每个串口的详细信息。这里可以通过 PowerShell 来查询:

    1

    C:\> Get-WmiObject -query "select DeviceID,PNPDeviceID from Win32_SerialPort"

    输出样例(其中 COM66 对应的蓝牙设备地址为 00803A686519):

    1234

    DeviceID : COM66

    PNPDeviceID : BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}\7&1D80ECD3&0&00803A686519_C00000003

    ......

    可以看出蓝牙虚拟串口的 PNPDeviceID 是以 BTHENUM 开头,并且会将蓝牙地址存放其中。

    这个查询也可以通过 C# 代码实现:

    12345678910111213

    using System.Management;

    const string Win32_SerialPort = "Win32_SerialPort";

    SelectQuery q = new SelectQuery(Win32_SerialPort);

    ManagementObjectSearcher s = new ManagementObjectSearcher(q);

    foreach (object cur in s.Get()) {

    ManagementObject mo = (ManagementObject)cur;

    object id = mo.GetPropertyValue("DeviceID");

    object pnpId = mo.GetPropertyValue("PNPDeviceID");

    console.WriteLine("DeviceID: {0} ", id);

    console.WriteLine("PNPDeviceID: {0} ", pnpId);

    console.WriteLine("");

    }//for

    综上,我们可以定义一个函数,这个函数通过 WMI 检索所有串口设备信息,然后返回一个 Hashtable,其中存储的键为蓝牙设备地址,存储的值为串口名。

    函数定义如下:

    123456789101112131415161718192021222324252627282930313233343536373839

    /* 定义于类 BTHelper 中 */

    public static Hashtable QueryBTHPorts()

    {

    const string Win32_SerialPort = "Win32_SerialPort";

    SelectQuery q = new SelectQuery(Win32_SerialPort);

    ManagementObjectSearcher s = new ManagementObjectSearcher(q);

    Hashtable hashResult = new Hashtable();

    foreach (object cur in s.Get())

    {

    ManagementObject mo = (ManagementObject)cur;

    string id = mo.GetPropertyValue("DeviceID").ToString();

    string pnpId = mo.GetPropertyValue("PNPDeviceID").ToString();

    Debug.WriteLine("WMI>>DeviceID: " + id);

    Debug.WriteLine("WMI>>PNPDeviceID: " + pnpId);

    Debug.WriteLine("");

    /* 仅处理蓝牙串口 */

    if (pnpId.StartsWith("BTHENUM"))

    {

    /* 从 PNPDeviceID 中提取出蓝牙地址,策略是逆序字符串 & 后 _ 之前 */

    /* 蓝牙地址为6字节,HEX为12位字符 */

    int rBound = pnpId.LastIndexOf('_');

    int lBound = pnpId.LastIndexOf('&');

    Debug.Assert(rBound - lBound == 13, "Get BT Addr, this will nevery happened.");

    string addr = pnpId.Substring(lBound + 1, 12);

    if (!hashResult.Contains(addr))

    {

    hashResult.Add(addr, id);

    }

    else

    {

    Debug.WriteLine("Get BT Addr, addr" + addr + " has more than 1 ports");

    }

    }

    }

    return hashResult;

    }

    同样,WMI 检索也比较耗时,所以这个函数调用需要放入工作线程中执行。

    有了这个函数,我们可以通过结果中查找我们设置的蓝牙设备地址,就可以得知对应的虚拟串口名,而如果结果中没有我们设置的蓝牙设备地址,那么就可以认定设置虚拟串口服务失败了。

    样例代码

    这里介绍通过配合使用 BackgroundWorker 来实现蓝牙设备的配对、生成虚拟串口的样例代码:

    我们通过传入蓝牙设备地址给 worker,worker 在 DoWork 中帮我们处理所有步骤,过程中报告进度,并最终告诉我们结果。

    worker 的 DoWork 事件代码:

    1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495

    /* 进行蓝牙连接操作的后台线程执行函数 */

    /* 传入 蓝牙地址字符串 作为参数 */

    /* 利用 ReportProgress 报告进度 */

    /* 利用 DoWorkEventArgs.Result 报告状态 */

    void bgworkerConnection_DoWork(object sender, DoWorkEventArgs e)

    {

    BackgroundWorker worker = sender as BackgroundWorker;

    string args = e.Argument as string;

    string finalportname = "";

    do

    {

    BluetoothAddress addr = BluetoothAddress.Parse(args);

    BluetoothDeviceInfo deviceinfo = new BluetoothDeviceInfo(addr);

    /* 检测设备是否在服务范围内,有些设备能被发现但不能被配对连接(如果已经被其他终端配对连接) */

    /* 不在范围内则报告错误信息 */

    worker.ReportProgress(10, "Testing if device in range...");

    if (!BTHelper.TestingIfInRange(addr))

    {

    string msg = string.Format("Error: Device {0}({1}) is not reachable!",

    deviceinfo.DeviceName,

    deviceinfo.DeviceAddress.ToString());

    e.Result = msg;

    return;

    }

    worker.ReportProgress(10, "Device is in range.");

    /* 检测设备是否是已配对设备 */

    if (deviceinfo.Authenticated)

    {

    /* 已配对设备枚举系统蓝牙串口,检测是否已绑定虚拟串口 */

    worker.ReportProgress(10, "Querying Bluetooth serialport...");

    Hashtable bthTable1 = BTHelper.QueryBTHPorts();

    if (bthTable1.ContainsKey(addr.ToString()))

    { /* 获取绑定串口 */

    finalportname = bthTable1[addr.ToString()] as string;

    /* !!! 跳出 !!! */

    break;

    }

    /* 此处 else 需考虑枚举结果中没有绑定串口的处理,如果没有绑定串口,那么重新设置串口服务 */

    /* 此处 else 部分会在下面的流程处理,见下方设置串口服务部分 */

    }

    else /* 需要进行配对 */

    {

    worker.ReportProgress(10, "Start pairing...");

    if (!BluetoothSecurity.PairRequest(addr, "1234"))

    { /* 配对失败 */

    string msg = string.Format("Error: Can not pair to Device {0}({1})!",

    deviceinfo.DeviceName,

    deviceinfo.DeviceAddress.ToString());

    e.Result = msg;

    return;

    }

    }

    /* 设置串口服务 */

    /* SLC蓝牙设置串口服务时,如果 SetServiceState */

    /* 第三个参数为 true (允许异常) 那么则一定会抛出异常,即使虚拟串口创建成功 */

    /* 所以这里调用2个参数的重载版本 */

    /* 之后检查串口服务是否设置成功的方法就是 设置后检索蓝牙串口 */

    worker.ReportProgress(10, "Enable serialport service...");

    deviceinfo.SetServiceState(BluetoothService.SerialPort, true);

    /* 枚举系统蓝牙串口,检查对应蓝牙是否有串口绑定 */

    Hashtable bthTable2 = BTHelper.QueryBTHPorts();

    if (bthTable2.ContainsKey(addr.ToString()))

    {

    /* 获取绑定的串口 */

    finalportname = bthTable2[addr.ToString()] as string;

    /* !!! 跳出 !!! */

    break;

    }

    else

    { /* 启用串口服务失败或者无法检测到绑定串口 */

    string msg = string.Format("Error: Failed to set Serialport service for Device {0}({1})!",

    deviceinfo.DeviceName,

    deviceinfo.DeviceAddress.ToString());

    e.Result = msg;

    return;

    }

    } while (false);

    worker.ReportProgress(10, "Open serialport...");

    Debug.WriteLine(string.Format(">>PORT NMAE: {0}", finalportname));

    /* 成功 */

    /* 将串口名放入消息中返回 */

    string okmsg = string.Format("OK: {0}", finalportname);

    e.Result = okmsg;

    }

    代码中通过灵活使用 string 作为 Result 来表明执行结果。

    worker 的 RunCompleted 事件代码:

    123456789101112

    void bgworkerConnection_RunCompleted(object sender, RunWorkerCompletedEventArgs e)

    {

    string msg = e.Result as string;

    if(msg.StartsWidth("OK"))

    { /* OK */

    MessageBox.Show(msg);

    }

    else

    { /* Error */

    MessageBox.Show(msg);

    }

    }

    后续可以通过字符串处理提取出生成的串口名。

    worker 的启动代码:

    1

    bgworkerConnection.RunWorkerAsync(addrstring);

    这样子我们就获取到了绑定的虚拟串口名,但是在使用串口中要注意的是,虚拟串口打开过程中,本质上还是发起了一个蓝牙数据连接,所以打开过程会耗时较长,所以这个虚拟串口打开过程也需要放入工作线程中处理。如果虚拟串口对应的蓝牙设备没有在线或者其他原因造成不可用,那么打开时会抛出异常,需要在代码上进行处理。

    一旦蓝牙设备经过绑定并且设置虚拟串口服务成功,那么对应的串口会一直存在与系统的串口列表中,但这并不代表它是可用的,请在打开这类串口时添加异常处理代码。

    (完)

    更多相关内容
  • 而且更强壮(robust),因为使用Winsock的Bluetooth通信可以直接监听到蓝牙设备关闭或者离开通信范围,而Bluetooth Virtual Serial Port只能通过Timeout来检查。 由于支持现有系统(Legacy System),Bluetooth ...

    在之前的两篇文章分别讲述了在.NET Compact Framework下使用Windows Embedded Source Tools for Bluetooth和32feet.NET进行Bluetooth的开发,链接如下:

    .NET Compact Framework下的Bluetooth开发 之 Windows Embedded Source Tools for Bluetooth

    .NET Compact Framework下的Bluetooth开发 之 32feet.NET

    在这篇文章讲述Bluetooth Virtual Serial Port的开发,所谓Bluetooth Virtual Serial Port,其实是从软件的角度看,把Bluetooth的通信转化成Serial Port(串口)。经过这样的转换后,使用Bluetooth的Client程序可以像使用串口一样操作Bluetooth。这个应用方式的出现是为了支持现有应用(Legacy system,遗产应用)。举个例子,在Bluetooth出现以前,大部分移动设备都是通过串口连接的GPS receiver的,基于GPS应用程序的开发也就通过的串口通信取出NMEA data。关于GPS NMEA data的开发可以参考 .NET Compact Framework下的GPS NMEA data数据分析 。串口的开发可以参考.NET Compact Framework下的串口通信。随着Bluetooth的普及,移动设备可以通过Bluetooth来连接GPS receiver了,那么原先基于GPS的应用程序需要重新开发通信部分去读取NMEA data,这为现有应用带来很多麻烦,所有的现有应用都需要重写通信部分,因此人们想出解决方法,把Bluetooth的通信转化成Serial Port(串口)。硬件上使用Bluetooth来进行通信,在软件上虚拟一个串口给应用程序,应用程序不需要任何的修改就可以支持Bluetooth的GPS Receiver了。这就像设计模式里面的Adapter模式,但是这里是为新设备提供原有的接口,使得原先的Client不需要更改。

    由于Bluetooth Virtual Serial Port的出现基于对现有系统(Legacy System)支持的需求,所以对于新的系统,MS不推荐使用Bluetooth Virtual Serial Port,而是直接使用Winsock进行通信。在使用Winsock进行Bluetooth通信需要指定服务,因此可以指定使用串口服务进行通信。Bluetooth Virtual Serial Port和Winsock的Bluetooth通信都是使用RFCOMM协议,所以两者等同。使用Winsock的Bluetooth通信比Bluetooth Virtual Serial Port更简单,不需要配置。而且更强壮(robust),因为使用Winsock的Bluetooth通信可以直接监听到蓝牙设备关闭或者离开通信范围,而Bluetooth Virtual Serial Port只能通过Timeout来检查。

    由于支持现有系统(Legacy System),Bluetooth Virtual Serial Port还是有存在的价值,下面讲述Bluetooth Virtual Serial Port的开发。在Windows Mobile下有两种方法可以建立Bluetooth Virtual Serial Port:调用API建立Bluetooth Virtual Serial Port和修改注册表建立Bluetooth Virtual Serial Port

    调用API建立Bluetooth Virtual Serial Port

    调用API建立Bluetooth Virtual Serial Port可以调用RegisterDevice

    HANDLE h=RegisterDevice (L"COM", index, L"btd.dll", (DWORD)&pp);

    建立服务端口,需要配置以下参数

    PORTEMUPortParams pp;

    memset (&pp,0,sizeof(pp));

    pp.flocal=TRUE;

    pp.channel=channel&0xff;

    服务端口flocal为true。channel可以使用RFCOMM_CHANNEL_MULTIPLE (0xfe),这样RFCOMM 会自动分配可用的信道。

    建立客户端口,需要配置以下参数

    PORTEMUPortParams pp;

    memset (&pp,0,sizeof(pp));

    pp.device=ba;

    pp.channel=channel&0xff;

    服务端口flocal为false。device为服务端地址。

    反注册端口使用以下API

    DeregisterDevice (h);

    详细可以参考MSDN文章 Creating a Connection to a Remote Device Using a Virtual COM Port,链接见参考文献。

    在32feet.net里面,这些API封装在InTheHand.Net.Ports.BluetoothSerialPort,可以直接使用。但是32feet.net的作者提醒这些API是不是可信赖的(unreliable),所以在使用之前请要谨慎考虑和详细测试。我在wince 5下测试过,不能成功建立Bluetooth Virtual Serial Port。

    使用32feet.net建立服务端口

    publicstaticvoidCreateIncomingPort()

    {

    BluetoothSerialPort port=BluetoothSerialPort.CreateServer(BluetoothService.SerialPort);

    Console.WriteLine(port.PortName);

    }

    使用32feet.net建立客户端口

    publicstaticvoidCreateIncomingPort()

    {

    BluetoothClient client=newBluetoothClient();

    BluetoothDeviceInfo[] devices=client.DiscoverDevices();

    BluetoothDeviceInfo device=null;foreach(BluetoothDeviceInfo dindevices)

    {if(d.DeviceName=="BLUETOOTH_DEVICE")

    {

    device=d;break;

    }

    }

    BluetoothEndPoint  endPoint=newBluetoothEndPoint(device.DeviceAddress, BluetoothService.SerialPort);

    BluetoothSerialPort port=BluetoothSerialPort.CreateClient(endPoint);

    Console.WriteLine(port.PortName);

    }

    修改注册表建立Bluetooth Virtual Serial Port

    由于第一种方法不是很可靠,所以可以选择第二种方法,第二种方法其实就是修改注册表,把

    HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Bluetooth\\Serial\\Ports的项进行修改。可是这个方法只是支持windows mobile5以上的系统,不支持wince5。同时,如果使用这个方法,需要重启系统。

    这是Windows Mobile的注册表,可以通过程序修改注册表的项目,通过程序修改后需要重启Windows Mobile。

    上图为Wince 5的注册表,结构不一样,在Wince5不能通过修改注册表的方式实现Bluetooth Virtual Serial Port。

    下面的代码来源自32feet.net的BluetoothDeviceInfo类里面的SetServiceState()方法。这里演示了如何修改注册表。

    if(state)

    {//write registry settings for WM5 Serial Port support//get available portsMicrosoft.Win32.RegistryKey rkPorts=Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Bluetooth\\Serial\\Ports",true);string[] supportedPorts=(string[])rkPorts.GetValue("SupportedPorts");

    System.Collections.ArrayList alPorts=newSystem.Collections.ArrayList(supportedPorts);//check availabilityforeach(stringdeviceidinrkPorts.GetSubKeyNames())

    {

    Microsoft.Win32.RegistryKey rkDevice=rkPorts.OpenSubKey(deviceid);//remove port from arraylist if unavailablestringport=rkDevice.GetValue("Port").ToString();intnullPos=port.IndexOf('\0');if(nullPos>-1)

    {

    port=port.Substring(0, nullPos);

    }if(alPorts.Contains(port))

    {

    alPorts.Remove(port);

    }

    rkDevice.Close();

    }if(alPorts.Count==0)

    {thrownewInvalidOperationException("No ports available");

    }//write port details to registryMicrosoft.Win32.RegistryKey rkNewPort=rkPorts.CreateSubKey(this.DeviceAddress.ToString("8"));

    rkNewPort.SetValue("KeepDCB",0);

    rkNewPort.SetValue("RemoteDCB",0);

    rkNewPort.SetValue("Encryption",0);

    rkNewPort.SetValue("Authentication",0);

    rkNewPort.SetValue("Port", alPorts[0]);

    rkNewPort.SetValue("Server",0);

    rkNewPort.Close();

    rkPorts.Close();//try open port nowtry{

    InTheHand.Net.Ports.BluetoothSerialPort.CreateClient(alPorts[0].ToString(),newBluetoothEndPoint(this.DeviceAddress, BluetoothService.SerialPort));

    }catch{

    }

    }else{//find and remove registry entriesMicrosoft.Win32.RegistryKey rkPorts=Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Bluetooth\\Serial\\Ports",true);foreach(stringdeviceAddressinrkPorts.GetSubKeyNames())

    {if(deviceAddress==this.DeviceAddress.ToString("8"))

    {

    rkPorts.DeleteSubKeyTree(deviceAddress);break;

    }

    }

    rkPorts.Close();

    }

    当state为true时为注册,当state为false时为反注册。

    参考文献

    展开全文
  • 1、蓝牙介绍 蓝牙技术是一种无线数据和语音通信开放的全球规范,它是基于低成本的近距离无线连接,为固定和移动设备建立通信环境的一种特殊的近距离无线技术连接。 蓝牙作为一种小范围无线连接技术,能在设备间...

    1、蓝牙介绍

    蓝牙技术是一种无线数据和语音通信开放的全球规范,它是基于低成本的近距离无线连接,为固定和移动设备建立通信环境的一种特殊的近距离无线技术连接。

    蓝牙作为一种小范围无线连接技术,能在设备间实现方便快捷、灵活安全、低成本、低功耗的数据通信和语音通信,因此它是实现无线个域网
    通信的主流技术之一。与其他网络相连接可以带来更广泛的应用。是一种尖端的开放式无线通信,能够让各种数码设备无线沟通,是无线网络传输技术的一种,原本用来取代红外
    线通信。

    2、蓝牙在项目中应用

    最近一个项目中要求采集设备和Windows平板之间需要通过无线,低功耗的设备进行传输,由于蓝牙的特点完全适合与本项目,因此选用蓝牙进行Windows计算机与下位机单片机进行通讯,在Windows下对于蓝牙的编程很小众,基本无资料,本人对蓝牙通讯做了以下的了解和使用。

    a、蓝牙设备连接和配置

    在Windows系统中,使用蓝牙设备其实作为串口设备进行通讯的,其实就是无线版的串口设备,对蓝牙操作就需要在系统中连接好蓝牙并设置蓝牙的串口,步骤见下图,①单击通知->②右击蓝牙图标,进入配置界面

    在系统中进行下位机蓝牙模块进行配对连接,配对之后需要点击右侧的“更多蓝牙选项”标签,对蓝牙设备的串口进行配置。

    单击添加按钮选择传入,配置蓝牙的串口号,注:不要与主板上其他的串口号冲突,可以到设备管理器中查看空闲的串口号

    b、蓝牙串口通讯

    前面的博文介绍了C#的SerialPort控件,在此不在赘述,此控件就是针对与串口通讯的,对于蓝牙的通讯其实就是串口的通讯了,这里要注意一下,由于蓝牙的串口是通过无线接入的,和主板自带的串口存在差别,蓝牙的串口在未连接到下位机设备时会存在Write()方法出现写超时卡顿的现象,因此需要根据发送数据的时间进行WriteTimeout写超时数据配置,这个值默认为60秒,在作者的项目中,这个值设定为5秒,防止蓝牙断开后发送数据长时间阻塞的问题,影响通讯效率,蓝牙在断开后Windows系统会自动进行重连,串口访问时无需再次调用打开串口。

    展开全文
  • C# 虚拟串口通信

    2020-12-19 01:45:35
    将主端口COM8拆分成 COM1和COM2两个...//spSend,spReceive用虚拟串口连接,它们之间可以相互传输数据。spSend发送数据SerialPort spReceive; //spReceive接受数据private delegate void MyDelegate(string indata)...

    将主端口COM8拆分成 COM1和COM2两个虚拟端口

    COM8接收的消息会传递给COM1和COM2

    SerialPort spSend;//spSend,spReceive用虚拟串口连接,它们之间可以相互传输数据。spSend发送数据

    SerialPort spReceive; //spReceive接受数据

    private delegate void MyDelegate(string indata); //委托,处理接收的数据

    private MyDelegate showDelegate = null;

    showDelegate = new MyDelegate(show);

    spReceive = new SerialPort("COM1", 19200, Parity.None, 8, StopBits.One);

    spReceive.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); //虚拟串口监听接收消息监听事件,该事件并不在主线程运行

    spReceive.Open();//打开串口,工作完成时务必关闭串口

    void show(string indata)

    {

    //处理COM1接收的消息

    }

    private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)

    {

    SerialPort sp = (SerialPort)sender;

    this.Invoke(showDelegate, new object[] { sp.ReadExisting() });

    }

    软件:Serial Splitter 4.2

    http://www.pc0359.cn/downinfo/57195.html

    展开全文
  • c#串口编程(

    2020-12-18 21:42:54
    在单片机项目开发中,上位机也是一个很重要的部分,主要用于数据显示(波形、温度等)、用户控制(LED,继电器等),下位机(单片机)与 上位机之间要进行数据通信的两种方式都是基于串口的:USB转串口 —— 上位机和下位...
  • 一、介绍 对于树莓派 3B+来说,他的UART功能有三种: 1、内部蓝牙使用; 2、控制终端使用; 3、与其他设备进行串口通信。 在树莓派基础实验35:USB TO TTL模块实验中学习了通过串口对树莓派进行控制台控制,让串口...
  • 1,界面设计 2,代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text;...
  • 为什么C#串口程序在关闭串口时候会死锁_老文章_赛迪网 http://www.ccidnet.com/2010/0524/2067861.shtml 【赛迪网讯】用过微软SerialPort类的人,都遇到过这个尴尬,关闭串口的时候会让软件死锁。天哪,我可...
  • C# 串口工具开发

    千次阅读 2021-09-07 17:00:38
    USB转串口 —— 上位机和下位机通过USB转串口连接线直接相连进行数据交互; 串口转WIFI(ESP8266) —— 上位机和下位机基于TCP/IP协议通过WIFI传输数据; 串口转蓝牙(HC-06)—— 不多用,暂不介绍;  上位机软...
  • 后续的有关通讯程序底层设计的文章会讲述一个具有丰富扩展性,但有设计简介的万能通讯库,支持网络、蓝牙、串口通讯、并口通讯。但不要指望我都实现出来了,我只是设计出这个框架。 示例代码 //append by wuyazhe @...
  • 无线串口模块为串口无线模块,可以通过无线将两个或者多个串口连接起来。串口发入模块的数据会被模块使用无线发出,收到无线数据的模块会将这个数据使用串口发出,在两个设备上使用模块就像将这两个设备用串口连接...
  • c#串口编程(傻瓜教程,手把手教你学会)

    万次阅读 多人点赞 2021-02-04 13:48:46
    USB转串口 —— 上位机和下位机通过USB转串口连接线直接相连进行数据交互; 串口转WIFI(ESP8266) —— 上位机和下位机基于TCP/IP协议通过WIFI传输数据; 串口转蓝牙(HC-06)—— 不多用,暂不介绍; 上位机软...
  • 口号与IO编号对应关系 //BCM编码 GPIO14 = TXD0 -> ttyAMA0 GPIO15 = RXD0 -> ttyAMA0 GPIO0 = TXD2 -> ttyAMA1 GPIO1 = RXD2 -> ttyAMA1 GPIO4 = TXD3 -> ttyAMA2 GPIO5 = RXD3 -> ttyAMA2 GPIO8 = TXD4 -> ...
  • 一、蓝牙模块XLBT232‐D01介绍外部设备蓝牙 1.1、蓝牙模块简介 XLBT232-D0101蓝牙模块采用CSR BlueCore 芯片配置6-8Mbit 的软件存储空间 支持AT 指令用户可根据需要更改SPP 角色主、从模式以及串口波特率、 设备...
  • 电脑浏览最佳]在单片机项目开发中,上位机也是一个很重要的部分,主要用于数据显示(波形、温度等)、用户控制(LED,继电器等),下位机(单片机)与 上位机之间要进行数据通信的两种方式都是基于串口的:USB转串口 ...
  • 我想想常规来说我会怎么做,两个USB转RS232的线,一个公头转母头的转换口,(或者两个USB转串口的小板,然后共地,TXD和RXD交叉连接)插在电脑的两个USB口,但是这样也太麻烦了点儿吧。还好,我知道有个软件:虚拟...
  • 51单片机物联网智能小车系列文章目录 第一篇:最简单DIY的51蓝牙遥控小车设计方案 第二篇:最简单DIY串口蓝牙硬件实现方案 第三篇:最简单DIY蓝牙PS2遥控器控制...第八篇:最简单DIY基于C#和51单片机上下位机一体化
  • c#串口操作系列

    千次阅读 2013-09-27 15:47:02
    我假设读者已经了解了c#的语法,本文是针对刚打算解除串口编程的朋友阅读的,作为串口编程的入门范例,也是我这个系列的基础。 我们的开发环境假定为vs2005(虽然我在用vs2010,但避免有些网友用2005,不支持...
  • 串口 i2c

    千次阅读 2017-10-13 10:44:55
    i2cdetect -y -a 1 将树莓派3的硬件串口与mini串口默认映射对换 树莓派可以配置文件来修改设备树,我的理解...为了在树莓派3中通过GPIO使用高性能的硬件串口,我们必须将分配给蓝牙使用的硬件串口与分配给IO排针的
  • this.Invoke((EventHandler)(delegate { //判断是否是显示为16禁止 if (checkBoxHexView.Checked) { //依次的拼接出16进制字符 foreach (byte b in buf) {...
  • c#串口编程

    2019-07-29 15:48:38
    c#串口编程 在单片机项目开发中,...USB转串口 —— 上位机和下位机通过USB转串口连接线直接相连进行数据交互; 串口转WIFI(ESP8266) —— 上位机和下位机基于TCP/IP协议通过WIFI传输数据; 串口转蓝牙(H...
  • 基于IAP15单片机,HC05蓝牙芯片,板载DS8B20温度传感器等设计的蓝牙温度传感器,与手机端蓝牙串口调试软件连接后,具备手机端命令控制功能,实现单条温度数据传输,与温度数据定时连续发送功能,具备可调闹钟功能,...
  • C#上位机开发(一)—— 了解上位机

    万次阅读 多人点赞 2018-06-02 16:07:00
    在单片机项目开发中,上位机也是一个很重要的部分,主要用于数据显示(波形、温度等)、用户控制(LED,继电器...USB转串口 —— 上位机和下位机通过USB转串口连接线直接相连进行数据交互; 串口转WIFI(ESP8...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 193
精华内容 77
关键字:

c#蓝牙转串口

c# 订阅