【WCH蓝牙系列芯片】-基于CH592开发板—修改应用蓝牙从机的Indicate属性

-------------------------------------------------------------------------------------------------------------------------------------

  在蓝牙服务属性中,蓝牙Notify和Indicate都是低功耗蓝牙BLE中的两种数据传输方式,这两种数据传输方式都是蓝牙从机设备往蓝牙主机设备进行发送数据。虽然两者都是传输数据,但是传输过程中也是有差别。

1、Notify(通知)方式

  一种单向通信机制,蓝牙从机向蓝牙主机发送数据,但不需要主机设备对这些数据进行确认响应。意味着一旦蓝牙从机设备发送了Notify数据,它就不再关心蓝牙主机设备是否已经接收到这些数据。

  适用于传感器数据更新使用,比如温度传感器,需要实时更新数据,但对数据丢失的容忍度较高。如:当服务器(从机设备)的特征值(温度传感器数据)发生变化,并且该特征配置了通知属性(GATT_PROP_NOTIFY),服务器(从机设备)可以发送一个通知数据包给客户端(主机设备)。客户端(主机设备)接收到通知数据后,无需发送任何确认响应。服务器(从机设备)发送数据后,不会等待客户端(主机设备)的确认,直接认为数据已经成功发送。

  由于没有确认机制,服务器(从机设备)无法知道客户端(主机设备)是否成功接收数据,适用于可靠性要求不高的场景。

 

2、Indicate (指示)方式

一种双向通信机制,

  • 服务器(从机设备)发送数据:当服务器(从机设备)的某个特征值发生变化,并且该特征配置了指示属性(GATT_PROP_INDICATE),服务器(从机设备)可以发送一个指示数据包给客户端(主机设备)。

  • 客户端(主机设备)接收并确认:客户端(主机设备)接收到指示数据后,必须发送一个确认响应(Confirmation)给服务器(从机设备)。服务器(从机设备)在收到确认响应后,才能发送下一条指示数据。

  适用于设备的蓝牙控制命令或者重要状态信息,需要确保数据要被主机设备接收到。需要确保数据完整性和可靠性。适用于可靠性要求较高的场景。有确认机制,服务器(从机设备)可以确保数据被客户端(主机设备)成功接收。

 

 

 

3、CH592添加Indication属性的特征值程序

  在基于CH592芯片在Peripheral(从机程序)上添加实现Indication功能。

一、将特征指4属性修改,将原先的Notify属性改为indication属性

在特征定义表格中,特征值4的读写属性中,与Notify的配置的属性表一样

二、在特征值4中修改indication属性数据发送函数

  在gattprofile.c中,仿造simpleProfile_Notify改写一个simpleProfile_Indicate函数,先是取客户端特征配置,判断是否启用了指示功能,然后设置数据句柄,发送indication数据。

bStatus_t simpleProfile_Indicate(uint16_t connHandle, attHandleValueInd_t *pInd, uint8_t taskId)
{
    uint16_t value = GATTServApp_ReadCharCfg(connHandle, simpleProfileChar4Config);   // 读取客户端特征配置,以确定是否启用了指示
    printf(" value = %02x \r\n",value);

    // If notifications enabled
    if(value & GATT_CLIENT_CFG_INDICATE)  // 如果指示已启用
    {
        // Set the handle
        pInd->handle = simpleProfileAttrTbl[SIMPLEPROFILE_CHAR4_VALUE_POS].handle;   // 设置指示数据的句柄

        // Send the notification
        return GATT_Indication(connHandle, pInd, FALSE, taskId);  // 发送指示
    }
    return bleIncorrectMode;   // 如果指示未启用,返回错误状态
}

  在gattprofile.c中simpleProfile_WriteAttrCB写操作中进行修改,改为GATT_CLIENT_CFG_INDICATE

三、在peripheral.c文件中,添加修改indication属性数据函数,根据peripheralChar4Notify函数重新添加一个peripheralChar4Indicate函数

  这里是原本notify的功能修改为Indication。Indication和Notification的区别之处,就是在进行参数传递的时候多传递了一个taskId,这是蓝牙协议规定Indication发送后,对方必须发送一个确认响应(Confirmation)返回。这个确认必须要有一个对应的实体也就是task去接收并且处理(也可以不处理,只是当作一个Indication成功的通知,接收这个动作是必须的)。所以Indication发送的时候必须要提前制定确认消息的接收task ID。这里就会通过simpleProfile_Indicate() 被应用层调用来指定发送的Indication的值和接收确认消息的task ID,一般就由应用层task本身接收,这里taskId的含义是即将被Indication响应的任务。

//修改为Indication
static void peripheralChar4Indicate(uint8_t *pValue, uint16_t len)
{
    bStatus_t rs;  // 定义一个状态变量,用于存储函数返回值
    attHandleValueInd_t indi;  // 定义一个 attHandleValueInd_t 结构体,用于指示消息
    indi.len = len;  // 设置指示数据的长度
    indi.pValue = GATT_bm_alloc( peripheralConnList.connHandle, ATT_HANDLE_VALUE_IND, indi.len, NULL,0);  // 分配内存用于存储指示数据
    if(indi.pValue)  // 如果内存分配成功
    {
        tmos_memcpy(indi.pValue, pValue, indi.len);  // 将要发送的数据复制到分配的内存中
        if(simpleProfile_Indicate(peripheralConnList.connHandle, &indi, Peripheral_TaskID) != SUCCESS)  // 调用 simpleProfile_Indicate 函数发送指示
        {
            GATT_bm_free((gattMsg_t *)&indi, ATT_HANDLE_VALUE_IND); // 如果发送指示失败,释放分配的内存
        }
    }
}

  在利用TMOS任务,通过发送performPeriodicTask()函数,将peripheralChar4Indicate(notiData, SIMPLEPROFILE_CHAR4_LEN)函数,把notiData定义的数值的数发送出去。实现1秒一次通过Indication发送数据。

4、将手机作为蓝牙主机,通过蓝牙调试助手去连接蓝牙从机,接收Indication属性发送的数据,验证Indication属性的功能。

  将修改好的从机程序烧录程序在芯片中,用NRF_CONNECT调试工具连接,在UUID为0xFFE4上,可以看到具有Indication属性,并且能够获取到从机Indication属性发送的数据(0x11,0x22,0x33,0x44)

 

5、在蓝牙主机中Central中,添加程序接收从机Indication数据

  在主机程序中,连接从机之后,进行枚举服务,使能启动写入CCCD操作

  在TMOS事件中,对CCCD写入操作中,按照接收NOTIFY的程序改造一下,其中更具协议规定, 将req.pValue的值得更改。

  req.pValue[0] = 2;

  req.pValue[1] = 0;

  这样就可以使能Indication的属性,来接收从机发来的Indication数据

  在centralProcessGATTMsg函数中,添加接收Indication数据,并打印每一个字节,接收完数据之后,由于Indication属性在发送完数据之后,就得进行回应确认状态,所以调用 ATT_HandleValueCfm 函数发送确认响应。函数返回 Confirmation_status 状态值,0 表示确认发送成功。

  如果不进行状态回复确认,就无法发送下一次的Indication属性数据。

  在从机程序中, 也可以添加函数,进行接收主机已经接收到Indication属性数据的应答操作,从而从机进行下一包的数据的发送。

  添加传递任务消息函数,主机Confirmation应答回复后,从机会进入peripheralProcessGATTMsg函数,进行确认。

  通过串口打印的方式,观察整个主机和从机的运行情况,交互数据,并且看应答过程

 

 

posted on 2025-03-28 19:13  凡仕  阅读(301)  评论(0)    收藏  举报