FR8016H的串口透传实现

您所在的位置:网站首页 fr8016ha功耗 FR8016H的串口透传实现

FR8016H的串口透传实现

2024-07-11 19:13| 来源: 网络整理| 查看: 265

最近入手了一款国产蓝牙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操作;

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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3