FR8016H的串口透传实现

最近入手了一款国产蓝牙soc,这里简单调一下串口透传,大体和CC2541的套路差不多。

在官方SDK的ble_simple_peripheral例程中,我首先在“simple_gatt_service.c”加入了一个char6的特征值用来做透传使用:

/******************************* Characteristic 6 defination *******************************/
// Characteristic 6 UUID: 0xFFF6
uint8_t sp_char6_uuid[UUID_SIZE_2] =
{ 
  LO_UINT16(SP_CHAR6_UUID), HI_UINT16(SP_CHAR6_UUID)
};
// Characteristic 6 data 
#define SP_CHAR6_VALUE_LEN  50
uint8_t sp_char6_value[SP_CHAR6_VALUE_LEN] = {0};
#define SP_CHAR6_CCC_LEN   2
uint8_t sp_char6_ccc[SP_CHAR6_CCC_LEN] = {0};
// Characteristic 6 User Description
#define SP_CHAR6_DESC_LEN   17
const uint8_t sp_char6_desc[SP_CHAR6_DESC_LEN] = "Characteristic 6";

并且在“simple_gatt_service.h”中添加一个“#define SP_CHAR6_UUID            0xFFF6”

然后在“simple_profile_att_table”表中添加我们自定义的char6:

/*********************************************************************************************************************************************************************/
																								        // Characteristic 6 Declaration 
        [SP_IDX_CHAR6_DECLARATION]          =   {
                                                    { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },           /* UUID */
                                                    GATT_PROP_READ,                                             /* Permissions */
                                                    0,                                                          /* Max size of the value */
                                                    NULL,                                                       /* Value of the attribute */
                                                },
        // Characteristic 6 Value
        [SP_IDX_CHAR6_VALUE]                =   {
                                                    { UUID_SIZE_2, UUID16_ARR(SP_CHAR6_UUID) },                 /* UUID */
                                                    GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_NOTI,          /* Permissions */
                                                    SP_CHAR6_VALUE_LEN,                                         /* Max size of the value */
                                                    NULL,                                                       /* Value of the attribute */    /* Can assign a buffer here, or can be assigned in the application by user */
                                                },
				// Characteristic 6 client characteristic configuration
        [SP_IDX_CHAR6_CFG]                  =   {
                                                    { UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) },     /* UUID */
                                                    GATT_PROP_READ | GATT_PROP_WRITE,                           /* Permissions */
                                                    SP_CHAR6_CCC_LEN,                                           /* Max size of the value */
                                                    NULL,                                                       /* Value of the attribute */    /* Can assign a buffer here, or can be assigned in the application by user */
                                                }, 
        // Characteristic 6 User Description
        [SP_IDX_CHAR6_USER_DESCRIPTION]     =   {
                                                    { UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) },      /* UUID */
                                                    GATT_PROP_READ,                                             /* Permissions */
                                                    SP_CHAR6_DESC_LEN,                                          /* Max size of the value */
                                                    (uint8_t *)sp_char6_desc,                                   /* Value of the attribute */
                                                },
};

至此,这个时候我们去编译完下载后,已经可以看到我们定义的特征值了。

 

 

当然,这个时候还无法实现我们想要的效果,还有两个函数需要修改,分别是“static void sp_gatt_read_cb(uint8_t *p_read, uint16_t *len, uint16_t att_idx)”和“static void sp_gatt_write_cb(uint8_t *write_buf, uint16_t len, uint16_t att_idx)”

我这里就先照抄了上面格式了。

/*********************************************************************
 * @fn      sp_gatt_read_cb
 *
 * @brief   Simple Profile user application handles read request in this callback.
 *			应用层在这个回调函数里面处理读的请求。
 *
 * @param   p_read  - the pointer to read buffer. NOTE: It's just a pointer from lower layer, please create the buffer in application layer.
 *					  指向读缓冲区的指针。 请注意这只是一个指针,请在应用程序中分配缓冲区. 为输出函数, 因此为指针的指针.
 *          len     - the pointer to the length of read buffer. Application to assign it.
 *                    读缓冲区的长度,用户应用程序去给它赋值.
 *          att_idx - index of the attribute value in it's attribute table.
 *					  Attribute的偏移量.
 *
 * @return  读请求的长度.
 */
static void sp_gatt_read_cb(uint8_t *p_read, uint16_t *len, uint16_t att_idx)
{
    switch (att_idx)
    {
        case SP_IDX_CHAR1_VALUE:
            for (int i = 0; i < SP_CHAR1_VALUE_LEN; i++)
                sp_char1_value[i] = sp_char1_value[0] + i + 1;
            memcpy(p_read, sp_char1_value, SP_CHAR1_VALUE_LEN);
            *len = SP_CHAR1_VALUE_LEN;
        break;

        case SP_IDX_CHAR2_VALUE:
            for (int i = 0; i < SP_CHAR2_VALUE_LEN; i++)
                sp_char2_value[i] = sp_char2_value[0] + i + 1;
            memcpy(p_read, sp_char2_value, SP_CHAR2_VALUE_LEN);
            *len = SP_CHAR2_VALUE_LEN;
       break;
        
        case SP_IDX_CHAR4_CFG:
            *len = 2;
            memcpy(p_read, sp_char4_ccc, 2);
        break;
        
        case SP_IDX_CHAR5_VALUE:
            for (int i = 0; i < SP_CHAR5_VALUE_LEN; i++)
                sp_char5_value[i] = sp_char3_value[0] + i + 1;
            memcpy(p_read, sp_char5_value, SP_CHAR5_VALUE_LEN);
           *len = SP_CHAR5_VALUE_LEN;
        break;
				
        case SP_IDX_CHAR6_VALUE:
            for (int i = 0; i < SP_CHAR6_VALUE_LEN; i++)
                sp_char5_value[i] = sp_char3_value[0] + i + 1;
            memcpy(p_read, sp_char5_value, SP_CHAR5_VALUE_LEN);
           *len = SP_CHAR5_VALUE_LEN;
				co_printf("Char6 Read: \r\n");
        break;
        
        default:
        break;
    }
    
	//co_printf("Read request: len: %d  value: 0x%x 0x%x \r\n", *len, (p_read)[0], (p_read)[*len-1]);
    
}

/*********************************************************************
 * @fn      sp_gatt_write_cb
 *
 * @brief   Simple Profile user application handles write request in this callback.
 *			应用层在这个回调函数里面处理写的请求。
 *
 * @param   write_buf   - the buffer for write
 *			              写操作的数据.
 *					  
 *          len         - the length of write buffer.
 *                        写缓冲区的长度.
 *          att_idx     - index of the attribute value in it's attribute table.
 *					      Attribute的偏移量.
 *
 * @return  写请求的长度.
 */
static void sp_gatt_write_cb(uint8_t *write_buf, uint16_t len, uint16_t att_idx)
{
	for (int i = 0; i < len; i++)
	{
	//co_printf("Write request: len: %d, 0x%x \r\n", len, write_buf[i]);
		if (att_idx == SP_IDX_CHAR1_VALUE)
				memcpy(sp_char1_value, write_buf, len);
		
		if (att_idx == SP_IDX_CHAR3_VALUE)
				memcpy(sp_char3_value, write_buf, len);
		
		if (att_idx == SP_IDX_CHAR5_VALUE)
				memcpy(sp_char5_value, write_buf, len);
		
		if (att_idx == SP_IDX_CHAR6_VALUE)
		{
			memcpy(sp_char6_value, write_buf, len);		//这里可以去读取蓝牙调试助手发送来的数据
			//co_printf("Char6 Write: \r\n");
			
			//下面代码将收到的数据再发回去
			//在接收到对端ntf使能的消息之后,通过调用gatt_notification()函数实现BLE peripheral端向手机端发送数据
			gatt_ntf_t ntf_att;
			ntf_att.att_idx = SP_IDX_CHAR6_VALUE;//0xfff0服务的第6个att:0xfff6
			ntf_att.conidx = 0;//链接号,因为是单链接,所以这里可以写死为0
			ntf_att.svc_id = sp_svc_id;//此GATT服务号
			ntf_att.data_len = len;//Notification数据的长度,根据发送的数据实时调整
			ntf_att.p_data = write_buf;//Notification数据的指针
			gatt_notification(ntf_att);//peripheral端设备向手机端执行一次notification操作;

		}
	}
	
	uint16_t uuid = BUILD_UINT16( simple_profile_att_table[att_idx].uuid.p_uuid[0], simple_profile_att_table[att_idx].uuid.p_uuid[1] );
	if (uuid == GATT_CLIENT_CHAR_CFG_UUID)
	{
		//co_printf("Notification status changed\r\n");
		if (att_idx == SP_IDX_CHAR4_CFG)
		{
				sp_char4_ccc[0] = write_buf[0];
				sp_char4_ccc[1] = write_buf[1];
				co_printf("Char4 ccc: 0x%x 0x%x \r\n", sp_char4_ccc[0], sp_char4_ccc[1]);
		}
		if (att_idx == SP_IDX_CHAR6_CFG)
		{
				sp_char6_ccc[0] = write_buf[0];
				sp_char6_ccc[1] = write_buf[1];
				co_printf("Char6 ccc: 0x%x 0x%x \r\n", sp_char6_ccc[0], sp_char6_ccc[1]);
		}
	}

}

下面将发送代码单独拎出来

//在接收到对端ntf使能的消息之后,通过调用gatt_notification()函数实现BLE peripheral端向手机端发送数据
gatt_ntf_t ntf_att;
ntf_att.att_idx = SP_IDX_CHAR6_VALUE;//0xfff0服务的第6个att:0xfff6
ntf_att.conidx = conn_idx;//链接号,因为是单链接,所以这里可以写死为0
ntf_att.svc_id = sp_svc_id;//此GATT服务号
ntf_att.data_len = 5;//Notification数据的长度,根据发送的数据实时调整
uint8_t ntf_data[] = "nihao";//虚拟数据,用户可根据需要替换成需要Notification的数据
ntf_att.p_data = ntf_data;//Notification数据的指针
gatt_notification(ntf_att);//peripheral端设备向手机端执行一次notification操作;

以上就是初步调试的过程了,如果需要使用的话还需要做修改,有什么错误的话欢迎指出。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值