SDK下載地址:https://gitee.com/freqchip/FR801xH-SDK
開發版使用FRECHIP DEV1.2
專案目錄:E:\ziliao\FREQCHIP\FR801xH-SDK-master\FR801xH-SDK-master\examples\dev1.0\ble_simple_peripheral
1.服務及及特性新增,新增之後可以透過藍芽除錯助手檢視到藍芽服務UUID,藍芽描述服務UUID,藍芽特徵值UUID,以及客戶端配置UUID(此用於警告與提示)
特徵值宣告(Characteristic Declaration)這個屬性不顯示
* Service UUID Value of the attribute
* Characteristic value uuid
* Characteristic value Permissions
* Characteristic 4 client characteristic configuration UUID
* Characteristic 1 User Description UUID
const gatt_attribute_t simple_profile_att_table[SP_IDX_NB] = { // Simple gatt Service Declaration [SP_IDX_SERVICE] = { { UUID_SIZE_2, UUID16_ARR(GATT_PRIMARY_SERVICE_UUID) }, /* UUID */ GATT_PROP_READ, /* Permissions */ UUID_SIZE_2, /* Max size of the value */ /* Service UUID size in service declaration */ (uint8_t*)sp_svc_uuid, /* Value of the attribute */ /* Service UUID value in service declaration */ }, // Characteristic 1 Declaration [SP_IDX_CHAR1_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 1 Value [SP_IDX_CHAR1_VALUE] = { { UUID_SIZE_16, SP_CHAR1_TX_UUID }, /* UUID */ GATT_PROP_READ | GATT_PROP_NOTI, /* Permissions */ SP_CHAR1_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 1 client characteristic configuration [SP_IDX_CHAR1_CFG] = { { UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) }, /* UUID */ GATT_PROP_READ | GATT_PROP_WRITE, /* Permissions */ 2, /* 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 1 User Description [SP_IDX_CHAR1_USER_DESCRIPTION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) }, /* UUID */ GATT_PROP_READ, /* Permissions */ SP_CHAR1_DESC_LEN, /* Max size of the value */ (uint8_t *)sp_char1_desc, /* Value of the attribute */ }, // Characteristic 2 Declaration [SP_IDX_CHAR2_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 2 Value [SP_IDX_CHAR2_VALUE] = { { UUID_SIZE_16, SP_CHAR2_RX_UUID }, /* UUID */ GATT_PROP_READ | GATT_PROP_WRITE, /* Permissions */ SP_CHAR2_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 2 User Description [SP_IDX_CHAR2_USER_DESCRIPTION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) }, /* UUID */ GATT_PROP_READ, /* Permissions */ SP_CHAR2_DESC_LEN, /* Max size of the value */ (uint8_t *)sp_char2_desc, /* Value of the attribute */ }, // Characteristic 3 Declaration [SP_IDX_CHAR3_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 3 Value [SP_IDX_CHAR3_VALUE] = { { UUID_SIZE_2, UUID16_ARR(SP_CHAR3_UUID) }, /* UUID */ GATT_PROP_WRITE, /* Permissions */ SP_CHAR3_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 3 User Description [SP_IDX_CHAR3_USER_DESCRIPTION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) }, /* UUID */ GATT_PROP_READ, /* Permissions */ SP_CHAR3_DESC_LEN, /* Max size of the value */ (uint8_t *)sp_char3_desc, /* Value of the attribute */ }, // Characteristic 4 Declaration [SP_IDX_CHAR4_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 4 Value [SP_IDX_CHAR4_VALUE] = { { UUID_SIZE_2, UUID16_ARR(SP_CHAR4_UUID) }, /* UUID */ GATT_PROP_WRITE | GATT_PROP_NOTI, /* Permissions */ SP_CHAR4_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 4 client characteristic configuration [SP_IDX_CHAR4_CFG] = { { UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) }, /* UUID */ GATT_PROP_READ | GATT_PROP_WRITE, /* Permissions */ SP_CHAR4_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 4 User Description [SP_IDX_CHAR4_USER_DESCRIPTION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) }, /* UUID */ GATT_PROP_READ, /* Permissions */ SP_CHAR4_DESC_LEN, /* Max size of the value */ (uint8_t *)sp_char4_desc, /* Value of the attribute */ }, // Characteristic 5 Declaration [SP_IDX_CHAR5_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 5 Value [SP_IDX_CHAR5_VALUE] = { { UUID_SIZE_2, UUID16_ARR(SP_CHAR5_UUID) }, /* UUID */ GATT_PROP_WRITE | GATT_PROP_READ, /* Permissions */ SP_CHAR5_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 5 User Description [SP_IDX_CHAR5_USER_DESCRIPTION] = { { UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) }, /* UUID */ GATT_PROP_READ, /* Permissions */ SP_CHAR5_DESC_LEN, /* Max size of the value */ (uint8_t *)sp_char5_desc, /* Value of the attribute */ }, };
2.對特徵值讀寫操作的響應函式定義,對特徵值的讀寫操作會觸發呼叫回撥函式,並觸發相應的事件。
static uint16_t sp_gatt_msg_handler(gatt_msg_t *p_msg) { switch(p_msg->msg_evt) { case GATTC_MSG_READ_REQ: sp_gatt_read_cb((uint8_t *)(p_msg->param.msg.p_msg_data), &(p_msg->param.msg.msg_len), p_msg->att_idx,p_msg->conn_idx ); break; case GATTC_MSG_WRITE_REQ: sp_gatt_write_cb((uint8_t*)(p_msg->param.msg.p_msg_data), (p_msg->param.msg.msg_len), p_msg->att_idx,p_msg->conn_idx); break; default: break; } return p_msg->param.msg.msg_len; }
3.讀寫函式具體定義
static void sp_gatt_read_cb(uint8_t *p_read, uint16_t *len, uint16_t att_idx,uint8_t conn_idx ) { switch (att_idx) { case SPEAKER_IDX_ONOFF_VALUE: for (int i = 0; i < SPEAKER_ONOFF_VALUE_LEN; i++) speaker_onoff_value[i] = speaker_onoff_value[0] + i + 1; memcpy(p_read, speaker_onoff_value, SPEAKER_ONOFF_VALUE_LEN); *len = SPEAKER_ONOFF_VALUE_LEN; break; case SPEAKER_IDX_STATUS_REPORT_VALUE: for (int i = 0; i < SPEAKER_STATUS_REPORT_VALUE_LEN; i++) speaker_status_report_value[i] = speaker_status_report_value[0] + i + 1; memcpy(p_read, speaker_status_report_value, SPEAKER_STATUS_REPORT_VALUE_LEN); *len = SPEAKER_STATUS_REPORT_VALUE_LEN; break; default: break; } co_printf("Read request: len: %d value: 0x%x 0x%x \r\n", *len, (p_read)[0], (p_read)[*len-1]); }
二.主機讀寫操作
E:\ziliao\FREQCHIP\FR801xH-SDK-master\FR801xH-SDK-master\examples\dev1.0\ble_simple_central
1.定義需要操作的特徵值UUID
#define SP_CHAR1_UUID 0xFFF1 #define SP_CHAR2_UUID 0xFFF2 const gatt_uuid_t client_att_tb[] = { [0] = { UUID_SIZE_2, UUID16_ARR(SP_CHAR1_UUID)}, [1] = { UUID_SIZE_2, UUID16_ARR(SP_CHAR2_UUID)}, };
2.定義需要主動操作的步驟
read.att_idx 為需要讀寫的特徵值UUID
gatt_client_read(read);資料讀操作
gatt_client_write_cmd(write); 資料寫操作
gatt_client_enable_ntf(ntf_enable); 資料提示
static uint16_t simple_central_msg_handler(gatt_msg_t *p_msg) { co_printf("CCC:%x\r\n",p_msg->msg_evt); switch(p_msg->msg_evt) { case GATTC_MSG_NTF_REQ: { if(p_msg->att_idx == 0) { show_reg(p_msg->param.msg.p_msg_data,p_msg->param.msg.msg_len,1); } } break; case GATTC_MSG_READ_IND: { if(p_msg->att_idx == 0) { show_reg(p_msg->param.msg.p_msg_data,p_msg->param.msg.msg_len,1); } } break; case GATTC_MSG_CMP_EVT: { co_printf("op:%d done\r\n",p_msg->param.op.operation); if(p_msg->param.op.operation == GATT_OP_PEER_SVC_REGISTERED) { uint16_t att_handles[2]; memcpy(att_handles,p_msg->param.op.arg,4); show_reg((uint8_t *)att_handles,4,1); gatt_client_enable_ntf_t ntf_enable; ntf_enable.conidx = p_msg->conn_idx; ntf_enable.client_id = client_id; ntf_enable.att_idx = 0; //TX gatt_client_enable_ntf(ntf_enable); gatt_client_write_t write; write.conidx = p_msg->conn_idx; write.client_id = client_id; write.att_idx = 1; //RX write.p_data = "\x1\x2\x3\x4\x5\x6\x7"; write.data_len = 7; gatt_client_write_cmd(write); gatt_client_read_t read; read.conidx = p_msg->conn_idx; read.client_id = client_id; read.att_idx = 0; //TX gatt_client_read(read); } } break; default: break; } return 0; }
總結:不用去糾結藍芽協議的底層邏輯,學會應用,目標明確,會定義服務UUID,特徵值UUID,
知道怎樣讀寫資料即可。
程式最大的難點再於對藍芽協議層初始化,需要掌握協議的知識,大部分應用在此基礎上修改就好
void simple_central_init(void) { // set local device name uint8_t local_name[] = "Simple Central"; gap_set_dev_name(local_name, sizeof(local_name)); gap_set_cb_func(app_gap_evt_cb); // Initialize security related settings. gap_bond_manager_init(BLE_BONDING_INFO_SAVE_ADDR, BLE_REMOTE_SERVICE_SAVE_ADDR, 8, true); // gap_bond_manager_delete_all(); gap_security_param_t param = { .mitm = false, .ble_secure_conn = false, .io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT, .pair_init_mode = GAP_PAIRING_MODE_WAIT_FOR_REQ, .bond_auth = true, .password = 0, }; gap_security_param_init(¶m); // Initialize GATT gatt_client_t client; client.p_att_tb = client_att_tb; client.att_nb = 2; client.gatt_msg_handler = simple_central_msg_handler; client_id = gatt_add_client(&client); simple_central_start_scan(); }