最大履带式运输车:wince下的蓝牙串口通信(上) - Lynn_doo - 博客园

来源:百度文库 编辑:偶看新闻 时间:2024/04/29 01:42:07

wince下的蓝牙串口通信(上)

     两周前开始在M8上开发五子棋蓝牙对战版,准确的说是把之前的WiFi对战版修改一下。虽然之前没搞过蓝牙,但其上层应用都是网络编程,差别不大。

     看了近一周的《yamazaki》之后,再加上汤q的指导,用一周的时间终于搞定(本人资质较差)。在这里与大家分享下,因为发现网上的东西实在不多,特别是与SDP服务相关的资料。棋牌类对战,设备间传输的主要是自定义命令与坐标,都可看做是传输文本。如何确保传输中不丢失数据,就要看自己如何订协议,在这里就不做说明。本文主要谈下两台设备间的通信过程和相关的API。其上层既可以用Socket通讯也可以用串口,因为之前WiFi做的是socket,这里就尝试下串口。

     开发平台与集成环境:M8SDK,wince6.0,VS2005.

     服务端:

         一 创建虚拟串口:    

              1: 加载可用的串口设备。(0~9为蓝牙可用)

PORTEMUPortParams pp;
TCHAR szCommPort[6];
unsigned char nChannel = 0xfe; //系统选择一个可用的通道
memset (&pp, 0, sizeof (pp));
pp.channel = nChannel & 0xff;
pp.flocal = TRUE;
for (i = 9; i >= 0; i--) 
{
    m_hDevice = RegisterDevice (L"COM", i, L"btd.dll", (DWORD)&pp);
    if (m_hDevice != 0)
        break;

 

 

               2:用CreateFile函数打开这个串口

m_hCommPort = CreateFile (szCommPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);

 

 

               3:查看蓝牙串口通道号,这一步操作不是必须的。这里的通道号是系统分配的,但是对于客户端必须与服务端的通道号相同,随后会介绍客户端如何通过查询SDP获得服务端的通道号。

//获得其通道号
DWORD port = 0;
DWORD dwSizeOut = 0;
if (! DeviceIoControl (m_hCommPort, IOCTL_BLUETOOTH_GET_RFCOMM_CHANNEL, NULL, 0, &port, sizeof(port), &dwSizeOut, NULL))
{
    printf("Server line %d\n", __LINE__);
    return -3;
}

 

 

               4:记得在程序退出(正常退出和异常处理)时用DeregisterDevice (m_hDevice);取消注册串口设备,否则串口资源将被一直占用

 

 

          二、接收数据。

               在创建串口之后,创建一个线程监听端口,等待读事件发生。

               1:设置当前设备要监听的事件。

SetCommMask (m_hCommPort, EV_RXCHAR|EV_RLSD);//m_hCommPort指创建的虚拟串口句柄

               EV_RXCHAR表示接收到字符串事件。

               EV_RLSD 表示串口的状态改变事件,此事件可以响应到远程断开事件

 

               2:监听或者说等待事件发生

while(true)
{
        if (! WaitCommEvent (pBTClient->m_hCommPort, &ModemState, NULL))
        {
                //添加错误处理代码
                break;
        }
        wprintf (L"Read thread woke up, ModemState = 0x%08x!\n", ModemState);
        if (ModemState & EV_RXCHAR) 
        {
               //以下是读操作的具体实现。
               int iError;
            DWORD cBytes = 0;
           DWORD cTheBytes = 0;
           while (cBytes < cReadBuf)      //cReadBuf表示一共要接受多少个字节,此处cReadBuf可以是外部传进来的
           {
               if (! ReadFile(hCommPort, (char *)(readBuf+cBytes), cReadBuf-cBytes,&cTheBytes, NULL))
               {
                   iError = GetLastError();
                   cBytes += cTheBytes;
                    *pNumOfRecv = cBytes;
                   return FALSE;
                       }
        }
         }
        else if (ModemState & EV_RLSD)
    {
        //响应到远程断开的处理
    }
}

              这里用API ReadFile接收数据,可以参看MSDN中ReadFile的用法详解。

 

         三、发送数据。发送数据时用WriteFile,其用法与ReadFile类似。

         呵呵 明天继续客户端