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

转载于:https://www.cnblogs.com/kinji/p/10024561.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值