CH582-BLE-Peripheral-控制LED开关

一、控制LED灯亮灭是作为一个BLE的服务,通过修改该服务的特征值来实现开关的控制。

        实现对特征值的读写要有服务、特征声明、特征值声明。首先在gattprofile.c文件中建立属性表,表中包含服务、特征声明、特征值声明、特征用户描述(非必须);服务、特征声明、特征值声明、特征用户描述,都属于属性每个属性都有其对应的UUID;UUID又包含不同属性类型的UUID值。

》属性表定义

//定义一个服务
static const gattAttrType_t ledProfileService = {ATT_BT_UUID_SIZE, ledProfileServUUID};

//特征值初始化
// 特征值属性,读或者写
static uint8_t ledProfileCharProps = GATT_PROP_READ | GATT_PROP_WRITE;
// 值,可以向其写入数据,也可以读出数据。这里是一个字符数组
static uint8_t ledProfileChar[LEDPROFILE_CHAR_LEN] = {0};
// 用户描述,展现给用户的名字
static uint8_t ledProfileCharUserDesp[] = "Led_Contral\0";
//属性表
static gattAttribute_t ledProfileAttrTb[]=
{
        //led priofile service
        {
            {ATT_BT_UUID_SIZE,primaryServiceUUID}, //type(属性类型)   属性类型:主服务primaryServiceUUIDd为0x2800即主服务类型。 
            GATT_PERMIT_READ,                      //permissions(GATT客户端对于该属性的权限)    即客户端对于该服务的权限,GATT_PERMIT_READ客户端可以发现这个服务。
            0,                                     //handle(表中属性的索引)    即在这个属性表中的位置指明这是在这个数组中的第几个数组元素,因为这个句柄是协议栈自动分配的,因此默认初始化为0
            (uint8 *)&ledProfileService            //pValue(指向属性值的指针)    用自己定义的UUID值0xFFF0来指向这个服务
        },
        //characteristic Declaration
        {
            {ATT_BT_UUID_SIZE,characterUUID},    //属性类型:特征值  characterUUID为0x2803即特征值类型
            GATT_PERMIT_READ,                    //数组这个元素权限为可读
            0,
            &ledProfileCharProps                 //ledProfileCharProps描述的是特征值具有的属性(指读写属性),一个是权限一个是属性。
        },
        //characteristic Value
        {
            {ATT_BT_UUID_SIZE,ledProfilecharUUID},    //特征值的自定义UUID
            GATT_PERMIT_READ | GATT_PERMIT_WRITE,     //权限为可读可写,要与特征值类型描述里的ledProfileCharProps特征值属性一致。
            0,
            ledProfileChar                            //特征值存放地方,就是修改里面的内容实现特征值的读写
        },
        //charateristic User Description
        {
            {ATT_BT_UUID_SIZE,charUserDescUUID},     //特征描述的UUID
            GATT_PERMIT_READ,
            0,
            ledProfileCharUserDesp                   //描述的内容       
        },

};

》注册服务 

主要通过BLE的库函数GATTServApp_RegisterService(),将GATT表注册到BLE STACK里,以及设置读写回调函数。

//读写回调设置
gattServiceCBs_t ledProfileCBs = {
    ledProfile_ReadAttrCB,  // Read callback function pointer
    ledProfile_WriteAttrCB, // Write callback function pointer

    NULL                       // Authorization callback function pointer
};
//注册服务函数
bStatus_t LedProfile_Addservice(uint32 services)
{
    uint8 status = SUCCESS;

    if(services & LEDPROFILE_SERVICE)
    {
        status = GATTServApp_RegisterService(ledProfileAttrTb,             //属性表   
                                        GATT_NUM_ATTRS(ledProfileAttrTb),
                                        GATT_MAX_ENCRYPT_KEY_SIZE,
                                        &ledProfileCBs);                    //读写回调函数有数据读写时调到读写函数中
    }
    return (status);

}

》属性读回调 

//读写回调
static bStatus_t ledProfile_ReadAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
                                          uint8_t *pValue, uint16_t *pLen, uint16_t offset, uint16_t maxLen, uint8_t method)
{
    bStatus_t status =SUCCESS;

    if(gattPermitAuthenRead(pAttr->permissions))
    {
        return(ATT_ERR_INSUFFICIENT_AUTHOR);
    }
    if( offset > 0)
    {
        return(ATT_ERR_ATTR_NOT_LONG);
    }
    if(pAttr->type.len == ATT_BT_UUID_SIZE)
    {
        uint16 uuid = BUILD_UINT16(pAttr->type.uuid[0],pAttr->type.uuid[1]);
        switch(uuid)
        {
        case LEDPROFILE_CHAR_UUID:
             *pLen = LEDPROFILE_CHAR_LEN;
             tmos_memcpy(pValue, pAttr->pValue, LEDPROFILE_CHAR_LEN);
             printf("Led_read\r\n");
        break;
        default:
            *pLen = 0;
            status = ATT_ERR_ATTR_NOT_FOUND;
        break;
        }
    }
    else {
        *pLen = 0;
        status = ATT_ERR_INVALID_HANDLE;
    }
    return(status);
}

static bStatus_t ledProfile_WriteAttrCB(uint16_t connHandle, gattAttribute_t *pAttr,
                                           uint8_t *pValue, uint16_t len, uint16_t offset, uint8_t method)
{
    bStatus_t status =SUCCESS;
    uint8 notifyApp = 0xFF;

    if(gattPermitAuthenWrite(pAttr->permissions))
    {
        return(ATT_ERR_INSUFFICIENT_AUTHOR);
    }

    if(pAttr->type.len == ATT_BT_UUID_SIZE)
    {
        uint16 uuid = BUILD_UINT16(pAttr->type.uuid[0],pAttr->type.uuid[1]);
        switch(uuid)
        {
        case LEDPROFILE_CHAR_UUID:
            if(offset == 0)
            {
                if(len > LEDPROFILE_CHAR_LEN)
                {
                    status = ATT_ERR_INVALID_VALUE_SIZE;
                }
            }
            else {
                status = ATT_ERR_ATTR_NOT_LONG;
            }

            if(status == SUCCESS)
            {
                tmos_memcpy(pAttr->pValue, pValue, LEDPROFILE_CHAR_LEN);
                notifyApp = LEDPROFILE_CHAR;
            }
            printf("LED_write\r\n");
        break;
        default:

            status = ATT_ERR_ATTR_NOT_FOUND;
            break;
        }
    }
    else {
        status = ATT_ERR_INVALID_HANDLE;
    }
    // If a charactersitic value changed then callback function to notify application of change
    if ( (notifyApp != 0xFF ) && ledProfile_AppCBs && ledProfile_AppCBs->pfnledProfileChange )
      {
        ledProfile_AppCBs->pfnledProfileChange( notifyApp, pValue, len );
      }
      return ( status );
}

上述内容参考文章:

【BLE 5.3无线MCU CH582】11、手机app控制led亮灭 - 国产芯片交流 - 电子工程世界-论坛

 二、对于写回调函数的学习理解

//在peripheral.c 中调用注册服务函数
  LedProfile_Addservice(GATT_ALL_SERVICES);
    将ledProfileAttrTb,和回调函数ledProfileCBs注册GATT服务中。

/*****************************************************************/

//在peripheral.c 注册回调函数
 LedProfile_RegisterAppCBs(&Peripheral_ledProfileCBs);

bStatus_t LedProfile_RegisterAppCBs(ledProfileCBs_t *appCallbacks)
{
    if(appCallbacks)
    {
        ledProfile_AppCBs = appCallbacks;

        return (SUCCESS);
    }
    else
    {
        return (bleAlreadyInRequestedMode);
    }
}


执行完这个函数 相当于ledProfile_AppCBs这个函数指针指向接收数据的函数
ledProfileChangeCB(uint8 paramID,uint8 *pValue,uint16 len)

/*****************************************************************/
//对应写回调函数中的这一段
If a charactersitic value changed then callback function to notify application of change
    if ( (notifyApp != 0xFF ) && ledProfile_AppCBs && ledProfile_AppCBs->pfnledProfileChange )
      {
        ledProfile_AppCBs->pfnledProfileChange( notifyApp, pValue, len );
      }

//即在写回调函数最后跳转到 ledProfile_AppCBs指向的 ledProfileChangeCB
中对APP写入到BLE的数据进行处理
//接收主机数据进行处理
static void ledProfileChangeCB(uint8 paramID,uint8 *pValue,uint16 len)
{
    switch(paramID)
    {
    case LEDPROFILE_CHAR:
        {
            uint8 newValue[LEDPROFILE_CHAR_LEN];
            tmos_memcpy(newValue, pValue, len);
            if(newValue[0])
            {
                printf("led_on\r\n");
                GPIOB_SetBits(GPIO_Pin_6);
            }
            else {
                printf("led_off\r\n");
                GPIOB_ResetBits(GPIO_Pin_6);
            }
            break;
                }
    default:
        break;
    }

猜你喜欢

转载自blog.csdn.net/qq_45803449/article/details/127004832