Dialog14585BLE主从通信中主机服务修改

勤基科技 王泽行
本文主要讲解如何对特定BLE从机来开发主机BLE的代码调试,以实现主从机的数据通信,主从机芯片是Dialog的DA14585,并且基于官方串口透传(DSPS)的demo:
DA14585_DSPS\projects\target_apps\dsps\dsps_host\Keil_5。

该demo在官网https://support.dialog-semiconductor.com下DA14585的Reference designs板块能够下载。

一、在从机工程中,通信只有一个服务,但是这一个服务包括两个特征,一个用于接收数据,一个用于发送数据如下:

#define DEF_SVC1_UUID_128              {0xfb,0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00}
#define DEF_SVC1_ADC_VAL_1_UUID_128     {0xfb,0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xf2, 0xff, 0x00, 0x00}//R
#define DEF_SVC1_ADC_VAL_2_UUID_128      {0xfb,0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xf1, 0xff, 0x00, 0x00}//T

const struct prf_char_def spsc_sps_char_16[SVC1_CHAR_MAX] =
{
    [SVC1_ADC_VAL_1_CHAR]    = {DEF_SVC1_ADC_VAL_1_UUID_16, ATT_MANDATORY, ATT_CHAR_PROP_NTF|ATT_CHAR_PROP_RD},
    [SVC1_ADC_VAL_2_CHAR]    = {DEF_SVC1_ADC_VAL_2_UUID_16, ATT_MANDATORY, ATT_CHAR_PROP_WR|ATT_CHAR_PROP_RD},
};

SVC1_ADC_VAL_1_UUID_128用于从机发送数据给主机,且以notify方式发送
SVC1_ADC_VAL_2_UUID_128用于主机发送数据给从机,且以GATTC_WRITE方式发送

二、在通过上面第一步添加好特征UUID及句柄后,我们需要在spsc_sps_char_desc中定义针对特征的描述符,如下:

     /// State machine used to retrieve SPS service characteristic description informationconst struct prf_char_desc_def spsc_sps_char_desc[SVC1_DESC_MAX] =
     {    
     ///SPS Client Config  
       [SVC1_ADC_VAL_1_CLI_CFG]  = {ATT_DESC_CLIENT_CHAR_CFG, ATT_MANDATORY, SVC1_ADC_VAL_1_CHAR},		
       [SVC1_ADC_VAL_1_USER_CFG]  = {ATT_DESC_CHAR_USER_DESCRIPTION, ATT_MANDATORY, SVC1_ADC_VAL_1_CHAR},   
       [SVC1_ADC_VAL_2_USER_CFG]  = {ATT_DESC_CHAR_USER_DESCRIPTION, ATT_MANDATORY, SVC1_ADC_VAL_2_CHAR},
       };  
    
    /// SPS Service Characteristics
    enum
    {
    #ifndef CFG_PRF_CUS1C    
    SPSC_SRV_TX_DATA_CHAR = 0,        
    SPSC_SRV_RX_DATA_CHAR,       
     SPSC_CHAR_MAX
     #else    
     SVC1_ADC_VAL_1_CHAR = 0,    
     SVC1_ADC_VAL_2_CHAR,    
     SVC1_CHAR_MAX,#endif
     }; 


 /// SPS Service Characteristic Descriptors
    enum
    {
    #ifndef CFG_PRF_CUS1C    
    /// SPS client config    
    SPSC_SRV_TX_DATA_CLI_CFG,    
    SPSC_FLOW_CTRL_CLI_CFG,        
    SPSC_DESC_MAX,
    #else    
    SVC1_ADC_VAL_1_CLI_CFG,	  
    SVC1_ADC_VAL_1_USER_CFG,    
    SVC1_ADC_VAL_2_USER_CFG,        
    SVC1_DESC_MAX,
    #endif 
    };

三、添加好特征属性后就是该如何使用这两个特征以便在主机进行扫描的时候与特定服务的从机进行服务添加交互。
1、在sps_client_enable_req_handler中,将首要服务添加进sps_data_service_uuid

 static int sps_client_enable_req_handler(ke_msg_id_t const msgid,struct sps_client_enable_req const *param, ke_task_id_t const dest_id,ke_task_id_t const src_id)
 {
 #ifdef CONFIG_RTT    rtt_printf("sps_client_enable_req_handler()\r\n");
 #else    arch_printf("sps_client_enable_req_handler()\r\n");
 #endif   
  // SPS Client Role Task Environment   
 struct spsc_env_tag *spsc_env = PRF_ENV_GET(SPS_CLIENT, spsc);     
 if (param->con_type == PRF_CON_DISCOVERY)    
   {         
 // Start discovering SPS on peer			        
 uint8_t sps_data_service_uuid[]=DEF_SVC1_UUID_128;        
 spsc_env->last_uuid_req = ATT_DECL_PRIMARY_SERVICE;        
 memcpy(spsc_env->last_svc_req, sps_data_service_uuid, ATT_UUID_128_LEN);              
 prf_disc_svc_send_128(&spsc_env->prf_env, spsc_env->last_svc_req);
 //        uint16_t sps_data_service_uuid = DEF_SVC1_UUID_128;
 //        spsc_env->last_uuid_req = ATT_DECL_PRIMARY_SERVICE;
 //        spsc_env->last_svc_req_16 = sps_data_service_uuid;
 //        prf_disc_svc_send(&spsc_env->prf_env, param->conidx,spsc_env->last_svc_req_16);         
 // Set state to discovering        
 ke_state_set(dest_id, SPS_CLIENT_DISCOVERING );    
   }     
 return (KE_MSG_CONSUMED);
 }

2、将刚才添加的数据库spsc_sps_char_16添加进来:,如下:

static int gattc_disc_char_ind_handler(ke_msg_id_t const msgid,struct gattc_disc_char_ind const *param, ke_task_id_t const dest_id, ke_task_id_t const src_id)
{
#ifdef CONFIG_RTT    rtt_printf("gattc_disc_char_ind_handler()\r\n");
#else    arch_printf("gattc_disc_char_ind_handler()\r\n");
#endif     
// Get the address of the environment    
struct spsc_env_tag *spsc_env = PRF_ENV_GET(SPS_CLIENT, spsc);
 //    prf_search_chars_128(spsc_env->sps.svc.ehdl, SVC1_CHAR_MAX, &spsc_env->sps.chars[0], &spsc_sps_char[0], param, &spsc_env->last_char_code);    
       prf_search_chars(spsc_env->sps.svc.ehdl, SVC1_CHAR_MAX, &spsc_env->sps.chars[0], &spsc_sps_char_16[0], param, &spsc_env->last_char_code);    
       return (KE_MSG_CONSUMED);
}

3、在如下函数gattc_disc_char_desc_ind_handler将句柄总长度和数据库添加进来,如下:

static int gattc_disc_char_desc_ind_handler(ke_msg_id_t const msgid,struct gattc_disc_char_desc_ind const *param, ke_task_id_t const dest_id,ke_task_id_t const src_id)
{
#ifdef CONFIG_RTT    rtt_printf("gattc_disc_char_desc_ind_handler()\r\n");
#else    arch_printf("gattc_disc_char_desc_ind_handler()\r\n");
#endif     
// Get the address of the environment   
  struct spsc_env_tag *spsc_env = PRF_ENV_GET(SPS_CLIENT, spsc);
       // Retrieve SPS descriptors   
  prf_search_descs(SVC1_DESC_MAX, &spsc_env->sps.descs[0], &spsc_sps_char_desc[0], param, spsc_env->last_char_code);     
  return (KE_MSG_CONSUMED);
}

4、sps_client_enable_cfm_send返回服务添加确认消息,如下:

 void sps_client_enable_cfm_send(struct spsc_env_tag *spsc_env, uint8_t conidx, uint8_t status)
    {
    #ifdef CONFIG_RTT    rtt_printf( "sps_client_enable_cfm_send()\r\n");
    #else    arch_printf( "sps_client_enable_cfm_send()\r\n");
    #endif     struct sps_client_enable_cfm * cfm = KE_MSG_ALLOC(SPS_CLIENT_ENABLE_CFM, TASK_APP,  prf_src_task_get(&(spsc_env->prf_env), conidx),                                    sps_client_enable_cfm);     
    cfm->status = status;    
     if (status == ATT_ERR_NO_ERROR)   
      {
      //        uint8_t flow;         
      cfm->sps  = spsc_env->sps;         
      // Register SPS_CLIENT task in gatt for indication/notifications         
      prf_register_atthdl2gatt(&(spsc_env->prf_env), conidx, NULL);         
      //Set value 0x0001 to CFG        
      prf_gatt_write_ntf_ind(&spsc_env->prf_env, conidx, spsc_env->sps.descs[SVC1_ADC_VAL_1_CLI_CFG].desc_hdl, PRF_CLI_START_NTF);
      // prf_gatt_write_ntf_ind(&spsc_env->prf_env, conidx, spsc_env->sps.descs[SVC1_ADC_VAL_2_CLI_CFG].desc_hdl, PRF_CLI_START_NTF);         
      //Place in connected state after discover state       
       ke_state_set(spsc_env->prf_env.prf_task, SPS_CLIENT_CONNECTED);
       #ifdef CONFIG_RTT        rtt_printf( "CLIENT ENABLED\r\n");
       #else        arch_printf( "CLIENT ENABLED\r\n");
       #endif     
       }   
        else   
      {
   #ifdef CONFIG_RTT        rtt_printf( "CLIENT ENABLE ERROR\r\n");
   #else        arch_printf( "CLIENT ENABLE ERROR\r\n");
   #endif    
      }      
   ke_msg_send(cfm);
  }

返回状态status=ATT_ERR_NO_ERROR表示服务添加成功。

四、与从机的数据收发函数接口

int user_sps_client_data_rx_ind_handler(ke_msg_id_t const msgid,struct sps_client_data_rx_ind const *param,ke_task_id_t const dest_id, ke_task_id_t const src_id)
{    
uint8_t i;     
if (param->length == 0) 
return (KE_MSG_CONSUMED); 
#ifdef CONFIG_RTT    rtt_printf("Ble received: ");    
for (i = 0; i < param->length; i++)   
 {        
 rtt_printf("%02x ", param->data[i]);    
 }    
 rtt_printf("\r\n");
 #else    arch_printf("Ble received: ");
 #endif 
 #ifdef DATA_RTT    rtt_printf("Ble received: ");    
 for (i = 0; i < param->length; i++)    
 {        
 rtt_printf("%02x ", param->data[i]);    
 }    
 rtt_printf("\r\n");
 #endif    
  user_ble_push((uint8_t *)param->data,param->length);     
  return (KE_MSG_CONSUMED);
  }

user_sps_client_data_rx_ind_handler用于接收来自从机的消息,包括数据和数据长度。

 void user_send_ble_data(const uint8_t *data, uint16_t length)
  {    
  arch_printf("user_send_ble_data()\r\n");    
  struct sps_client_data_tx_req * req = KE_MSG_ALLOC_DYN_NO_INIT(SPS_CLIENT_DATA_TX_REQ,prf_get_task_from_id,SK_ID_SPS_CLIENT),                                          TASK_APP,                                          sps_client_data_tx_req,                                          length);        
  req->length = length;  
  memcpy(&req->data[0], data, length);    
  ke_msg_send(req);
  }

user_send_ble_data用于发送数据。至此,服务添加完毕,这个时候我们就可以通过调用这两个接口函数与从机进行数据通信了。

Dialog技术讨论,QQ群871600668

你可能感兴趣的:(Dialog,DA14585开发设计)