[STM32F401]08、BlueNRG-MS蓝牙4.1
http://blog.sina.com.cn/s/blog_7e7fa4c80102waxr.html
介绍了BlueNRG-MS蓝牙4.1 ,这篇主要介绍驱动以与配置过程
- #include "bluenrg_sdk_api.h"
- #define DEBUG_REPORT_EN
- #include "error.h"
- uint8_t bnrgExpansionBoard = BNRG_EXPANION_BOARD_BLUENRG; /* at startup, suppose the X-NUCLEO-IDB04A1 is used */
- #define SERVER_ROLE
- #if defined SERVER_ROLE
- BLE_RoleTypeDef BLE_Role = SERVER;
- #elif defined CLIENT_ROLE
- BLE_RoleTypeDef BLE_Role = CLIENT;
- #else
- #error "Please define SERVER_ROLE OR CLIENT_ROLE in bluenrg_sdk_api.c"
- #endif
- volatile int connected = FALSE;
- //extern volatile int connected; //sensor_service.c
- volatile uint16_t connection_handle = 0;
- //extern volatile uint16_t connection_handle;//sensor_service.c
- volatile uint8_t set_connectable = TRUE; /*用于自动连接 */
- //extern volatile uint8_t set_connectable; //sensor_service.c
- volatile uint8_t notification_enabled = FALSE; /*用于广播*/
- /**
- *@brief send char uuid handle
- *@param None
- *@retval ret
- */
- __weak tBleStatus ble_device_user_add_service(void)
- {
- /**<
- 添加用户UUID 被 ble_device_init调用
- */
- tBleStatus ret=BLE_STATUS_SUCCESS;
- /* USER CODE BEGIN */
- /* USER CODE END */
- if(ret != BLE_STATUS_SUCCESS) {
- PRINTF("Error while adding service.rn");
- return BLE_STATUS_ERROR ;
- }
- PRINTF("Service added successfully.rn");
- return BLE_STATUS_SUCCESS;
- }
- /**
- *@brief Board Initializition
- *@param None
- *@retval ret
- */
- tBleStatus ble_device_init(void)
- {
- #define BDADDR_SIZE 6
- const char *name = "BlueNRG";
- uint8_t SERVER_BDADDR[] = {0xaa, 0x00, 0x00, 0xE1, 0x80, 0x02};/*Peripheral (server) {0x12, 0x34, 0x00, 0xE1, 0x80, 0x03}*/
- uint8_t CLIENT_BDADDR[] = {0xbb, 0x00, 0x00, 0xE1, 0x80, 0x02};/*Central (client)*/
- uint16_t service_handle, dev_name_char_handle, appearance_char_handle;
- uint8_t hwVersion;
- uint16_t fwVersion;
- uint8_t bdaddr[BDADDR_SIZE];
- tBleStatus ret;
- /* Initialize the BlueNRG SPI driver */
- BNRG_SPI_Init();
- /* Initialize the BlueNRG HCI */
- HCI_Init();
- /* Reset BlueNRG hardware */
- BlueNRG_RST();
- /* get the BlueNRG HW and FW versions */
- getBlueNRGVersion(&hwVersion, &fwVersion);
- /*
- * Reset BlueNRG again otherwise we won't
- * be able to change its MAC address.
- * aci_hal_write_config_data() must be the first
- * command after reset otherwise it will fail.
- */
- BlueNRG_RST();
- PRINTF("HWver %d, FWver %d", hwVersion, fwVersion);
- #if 0
- if (hwVersion > 0x30) { /* X-NUCLEO-IDB05A1 expansion board is used */
- bnrgExpansionBoard = BNRG_EXPANION_BOARD_BlueNRG_MS;
- /*
- * Change the MAC address to avoid issues with Android cache:
- * if different boards have the same MAC address, Android
- * applications unless you restart Bluetooth on tablet/phone
- */
- SERVER_BDADDR[5] = 0x02;
- }
- /* The Nucleo board must be configured as SERVER */
- Osal_MemCpy(bdaddr, SERVER_BDADDR, sizeof(SERVER_BDADDR));
- #else
- if (hwVersion > 0x30) { /* X-NUCLEO-IDB05A1 expansion board is used */
- bnrgExpansionBoard = BNRG_EXPANION_BOARD_BlueNRG_MS;
- }
- if(BLE_Role == CLIENT) {
- Osal_MemCpy(bdaddr, CLIENT_BDADDR, sizeof(CLIENT_BDADDR));
- } else {
- Osal_MemCpy(bdaddr, SERVER_BDADDR, sizeof(SERVER_BDADDR));
- }
- #endif
- ret = aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET,
- CONFIG_DATA_PUBADDR_LEN,
- bdaddr);
- if(ret) {
- PRINTF("Setting BD_ADDR failed.rn");
- return BLE_SET_BD_ADDR_FAILED;
- }
- /*gatt_Init*/
- ret = aci_gatt_init();
- if(ret) {
- PRINTF("GATT_Init failed.rn");
- return BLE_GATT_INIT_FAILED;
- }
- if(BLE_Role == SERVER) {
- /**< GAP Peripheral role */
- if (bnrgExpansionBoard == BNRG_EXPANION_BOARD_BlueNRG_MS) {
- ret = aci_gap_init_IDB05A1(GAP_PERIPHERAL_ROLE_IDB05A1, 0, 0x07/*strlen(name)*/, &service_handle, &dev_name_char_handle, &appearance_char_handle);
- } else {
- ret = aci_gap_init_IDB04A1(GAP_PERIPHERAL_ROLE_IDB04A1, &service_handle, &dev_name_char_handle, &appearance_char_handle);
- }
- } else {
- /**< GAP Central role */
- if (bnrgExpansionBoard == BNRG_EXPANION_BOARD_BlueNRG_MS) {
- ret = aci_gap_init_IDB05A1(GAP_CENTRAL_ROLE_IDB05A1, 0, 0x07/*strlen(name)*/, &service_handle, &dev_name_char_handle, &appearance_char_handle);
- } else {
- ret = aci_gap_init_IDB04A1(GAP_CENTRAL_ROLE_IDB04A1, &service_handle, &dev_name_char_handle, &appearance_char_handle);
- }
- }
- if(ret != BLE_STATUS_SUCCESS) {
- PRINTF("GAP_Init failed.rn");
- return BLE_GAP_INIT_FAILED;
- }
- ret = aci_gatt_update_char_value(service_handle, dev_name_char_handle, 0,
- strlen(name), (uint8_t *)name);
- if(ret!= BLE_STATUS_SUCCESS) {
- PRINTF("aci_gatt_update_char_value failed.rn");
- return BLE_GATT_UPDATE_CHAR_FAILED;
- }
- ret = aci_gap_set_auth_requirement(MITM_PROTECTION_REQUIRED,
- OOB_AUTH_DATA_ABSENT,
- NULL,
- 7,
- 16,
- USE_FIXED_PIN_FOR_PAIRING,
- 123456,
- BONDING);
- if (ret != BLE_STATUS_SUCCESS) {
- PRINTF("BLE Stack Initialized failed.rn");
- return BLE_STACK_INIT_FAILED;
- } else {
- PRINTF("BLE Stack Initialized Successfully.rn");
- }
- if(BLE_Role == SERVER) {
- /**< GAP Peripheral role */
- PRINTF("SERVER: BLE Stack Initializedrn");
- ret = ble_device_user_add_service();
- if(ret != BLE_STATUS_SUCCESS) {
- PRINTF("Service added failed.rn");
- return BLE_ADD_SERVICE_FAILED;
- } else {
- PRINTF("Service added successfully.rn");
- }
- } else {
- /**< GAP Central role */
- PRINTF("CLIENT: BLE Stack Initializedrn");
- }
- set_connectable = TRUE; //确保其值为TRUE,以便广播
- return BLE_STATUS_SUCCESS;
- }
- /**
- *@brief Set Tx Power level
- *@param Level
- *@retval ret
- */
- tBleStatus ble_device_set_tx_power(uint8_t level)
- {
- /**< 数值范围为0~7,对应8个等级的发射功率。缺省值为7,表示设置为最大发射功率(8dBm)。*/
- tBleStatus ret;
- /* Set output power level */
- ret = aci_hal_set_tx_power_level(1,level);
- return ret;
- }
- /**
- *@brief Start To Adv
- *@param None
- *@retval ret
- */
- tBleStatus ble_device_start_advertising(void)
- {
- tBleStatus ret;
- const char local_name[] = {AD_TYPE_COMPLETE_LOCAL_NAME,'B','l','u','e','N','R','G'};
- /* disable scan response */
- hci_le_set_scan_resp_data(0,NULL);
- PRINTF("General Discoverable Mode.rn");
- ret = aci_gap_set_discoverable(ADV_IND, 0, 0, PUBLIC_ADDR, NO_WHITE_LIST_USE,
- sizeof(local_name), local_name, 0, NULL, 0, 0);
- if (ret != BLE_STATUS_SUCCESS) {
- PRINTF("Error while setting discoverable mode (%d)rn", ret);
- }
- return ret;
- }
- /**
- *@brief Stop Adv
- *@param None
- *@retval ret
- */
- tBleStatus ble_device_stop_advertising(void)
- {
- tBleStatus ret;
- ret = aci_gap_set_non_discoverable();
- return ret;
- }
- /**********************************************************/
- /*connection config*/
- /**
- * @brief Scan param
- */
- #define SCAN_P (0x4000)
- #define SCAN_L (0x4000)
- /**
- * @brief Supervision timeout, arg in msec.
- */
- #define SUPERV_TIMEOUT (60)
- /**
- * @brief Connection period, arg in msec.
- */
- #define CONN_P(x) ((int)((x)/1.25f))
- /**
- * @brief Connection length, arg in msec.
- */
- #define CONN_L(x) ((int)((x)/0.625f))
- //#define CONN_P1 (CONN_P(10))
- //#define CONN_P2 (CONN_P(10))
- #define CONN_P1 (CONN_P(50))
- #define CONN_P2 (CONN_P(50))
- #define CONN_L1 (CONN_L(1250))
- #define CONN_L2 (CONN_L(1250))
- /*host creat connection*/
- //tBleStatus ble_host_connect(tBDAddr bdaddr)
- tBleStatus ble_host_connect(void)
- {
- tBleStatus ret;
- if(set_connectable == TRUE) {
- PRINTF("Client Create Connectionn");
- tBDAddr bdaddr = {0xaa, 0x00, 0x00, 0xE1, 0x80, 0x02};
- //BSP_LED_On(LED2); //To indicate the start of the connection and discovery phase
- /*
- Scan_Interval, Scan_Window, Peer_Address_Type, Peer_Address, Own_Address_Type, Conn_Interval_Min,
- Conn_Interval_Max, Conn_Latency, Supervision_Timeout, Conn_Len_Min, Conn_Len_Max
- */
- ret = aci_gap_create_connection(SCAN_P, SCAN_L, PUBLIC_ADDR, bdaddr, PUBLIC_ADDR, CONN_P1, CONN_P2, 0,
- SUPERV_TIMEOUT, CONN_L1 , CONN_L2);
- if (ret != 0) {
- PRINTF("Error while starting connection.n");
- Clock_Wait(100);
- }
- }
- /*discover device*/
- //ble_host_discover_char();
- return ret;
- }
- void ble_on_connect_cb( uint8_t addr[6], uint16_t handle )
- {
- connected = TRUE;
- connection_handle = handle;
- PRINTF("Connected to device:");
- for(int i = 5; i > 0; i--) {
- PRINTF("%02X-", addr[i]);
- }
- PRINTF("%02Xrn", addr[0]);
- PRINTF("Connection handle: %drn", connection_handle);
- /* USER CODE BEGIN */
- /* USER CODE END */
- }
- void ble_on_disconnect_cb(uint8_t reason)
- {
- connected = FALSE;
- PRINTF("Disconnectedrn");
- /* Make the device connectable again. */
- set_connectable = TRUE;
- notification_enabled = FALSE;
- /* USER CODE BEGIN */
-
- /* USER CODE END */
- /* Make the device connectable again. */
- //ble_device_start_advertising();//because set_connectable = TRUE; ble_process while auto advertising
- }
- /**
- *@brief To disconnect Ble Connection
- *@param None
- *@retval ret
- */
- tBleStatus ble_device_user_disconnect(void)
- {
- /**< 用户主动断开连接 ,不会自动广播 set_connectable
- */
- tBleStatus ret;
- connected = FALSE;
- PRINTF("Disconnectedrn");
- /* Make the device connectable again. */
- set_connectable = FALSE;
- notification_enabled = FALSE;
- ret = aci_gap_terminate(connection_handle, HCI_OE_USER_ENDED_CONNECTION);
- connection_handle = 0;
- /* Add user code */
- return ret;
- }
- tBleStatus ble_device_user_connect(void)
- {
- /* 用于 ble_device_user_disconnect 后,重新激活广播*/
- set_connectable = TRUE;
- return BLE_STATUS_SUCCESS;
- }
- /**
- *@brief To disconnect Ble Connection
- *@param None
- *@retval ret
- */
- tBleStatus ble_device_is_connected(void)
- {
- /**< 查询连接状态 */
- return connected;
- }
- /**
- * @brief This function is called attribute value corresponding to
- *
- * @param Handle of the attribute
- * @param Size of the modified attribute data
- * @param Pointer to the modified attribute data
- * @retval None
- */
- void ble_on_attribute_modified_cb(uint16_t handle, uint8_t data_length, uint8_t *att_data)
- {
- /* USER CODE BEGIN */
- /* USER CODE END */
- }
- /**
- *@brief send char uuid handle
- *@param None
- *@retval ret
- */
- tBleStatus ble_device_user_send(uint16_t servHandle,
- uint16_t charHandle,
- uint8_t charValOffset,
- uint8_t charValueLen,
- const uint8_t *charValue)
- {
- tBleStatus ret;
- ret=aci_gatt_update_char_value(servHandle, charHandle, charValOffset, charValueLen, charValue);
- if (ret != BLE_STATUS_SUCCESS) {
- PRINTF("Error while updating server %o handle characteristic %o handle.rn",servHandle,charHandle) ;
- return BLE_STATUS_ERROR ;
- }
- return BLE_STATUS_SUCCESS;
- }
- void ble_on_gatt_notification_cb(uint16_t attr_handle, uint8_t attr_len, uint8_t *attr_value)
- {
- /* USER CODE BEGIN */
- /* USER CODE END */
- }
- void ble_on_gatt_dis_read_char_by_uuid_resp_cb(evt_gatt_disc_read_char_by_uuid_resp *resp)
- {
- /* USER CODE BEGIN */
- /* USER CODE END */
- }
- void ble_on_gatt_procedure_complete_cb( evt_gatt_procedure_complete *pr)
- {
- /* USER CODE BEGIN */
- /* USER CODE END */
- }
- void ble_on_gatt_read_permit_cb(uint16_t handle)
- {
- /* USER CODE BEGIN */
- /* USER CODE END */
- //EXIT:
- if(connection_handle != 0)
- aci_gatt_allow_read(connection_handle);
- }
- /**
- * @brief Callback processing the ACI events.
- * [url=home.php?mod=space&uid=1902110]@NOTE[/url] Inside this function each event must be identified and correctly
- * parsed.
- * @param void* Pointer to the ACI packet
- * @retval None
- */
- void HCI_Event_CB(void *pckt)
- {
- hci_uart_pckt *hci_pckt = pckt;
- /* obtain event packet */
- hci_event_pckt *event_pckt = (hci_event_pckt*)hci_pckt->data;
- if(hci_pckt->type != HCI_EVENT_PKT)
- return;
- switch(event_pckt->evt) {
- case EVT_DISCONN_COMPLETE: { /* BlueNRG disconnection event */
- /* Add user code for handling BLE disconnect event based on
- application scenarios */
- DEBUG_REPORT("HCI_Event EVT_DISCONN_COMPLETE.rn");
- /*Host*/
- //GAP_DisconnectionComplete_CB();
- ble_on_disconnect_cb(event_pckt->data[3]);
- }
- break;
- case EVT_LE_META_EVENT: {
- /* Get the meta event data */
- evt_le_meta_event *evt = (void *)event_pckt->data;
- DEBUG_REPORT("HCI_Event EVT_LE_META_EVENT.rn");
- /* Analyze the specific sub event */
- switch(evt->subevent) {
- case EVT_LE_CONN_COMPLETE: {/*GATT_SERVER*/
- /* BlueNRG connection event */
- /* connection complete event: get the related data */
- evt_le_connection_complete *cc = (void *)evt->data;
- /* Connection parameters:
- cc->status: connection status (0x00: Connection successfully
- completed);
- cc->handle: connection handle to be used for the communication during the connection;
- cc->role: BLE device role (0x01: master; 0x02: slave);
- cc->peer_bdaddr_type: connected device address type (0x00: public; 0x01: random);
- cc->peer_bdaddr: connected device address;
- cc->interval: connection interval;
- cc->latency: connection latency;
- cc->supervision_timeout: connection supervision timeout;
- cc->master_clock_accuracy: master clock accuracy;
- */
- /* Add user code for handling connection event based on application
- scenarios */
- DEBUG_REPORT("HCI_Event EVT_LE_CONN_COMPLETE.rn");
- //GAP_ConnectionComplete_CB(cc->peer_bdaddr, cc->handle);
- ble_on_connect_cb(cc->peer_bdaddr, cc->handle);
- }
- break;
- case EVT_LE_ADVERTISING_REPORT: {/*GATT_CLIENT*/
- /* Add user code for handling connection event based on application
- scenarios */
- DEBUG_REPORT("HCI_Event EVT_LE_ADVERTISING_REPORT.rn");
- //le_advertising_info *pr = (void *)(evt->data+1); /* evt->data[0] is number of reports (On BlueNRG-MS is always 1) */
- //ble_host_device_found(adv_data);
- }
- break;
- }
- }
- break;
- case EVT_VENDOR: {
- /* Get the vendor event data */
- evt_blue_aci *blue_evt = (void*)event_pckt->data;
- DEBUG_REPORT("HCI_Event EVT_VENDOR.rn");
- switch(blue_evt->ecode) {
- case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED: { /*GATT_SERVER*/
- /* Get attribute modification event data */
- /* this callback is invoked when a GATT attribute is modified
- extract callback data and pass to suitable handler function */
- DEBUG_REPORT("HCI_Event EVT_BLUE_GATT_ATTRIBUTE_MODIFIED.rn");
- if (bnrgExpansionBoard == BNRG_EXPANION_BOARD_BlueNRG_MS) {
- evt_gatt_attr_modified_IDB05A1 *evt = (evt_gatt_attr_modified_IDB05A1*)blue_evt->data;
- ble_on_attribute_modified_cb(evt->attr_handle, evt->data_length, evt->att_data);
- } else {
- evt_gatt_attr_modified_IDB04A1 *evt = (evt_gatt_attr_modified_IDB04A1*)blue_evt->data;
- ble_on_attribute_modified_cb(evt->attr_handle, evt->data_length, evt->att_data);
- }
- /*
- evt->conn_handle: the connection handle which modified the attribute;
- evt->attr_handle: handle of the attribute that was modified;
- evt->data_length: the length of the data;
- evt->att_data: pointer to the new value (length is data_length)
- */
- /* Add user code for handling attribute modification event based on
- application scenarios */
- //ble_on_attribute_modified_cb(evt->attr_handle, evt->data_length, evt->att_data);//move into if
- }
- break;
- case EVT_BLUE_GATT_NOTIFICATION: { /*GATT_CLIENT*/
- /* Get attribute notification event data */
- evt_gatt_attr_notification *evt = (evt_gatt_attr_notification*)blue_evt->data;
- /*
- evt->conn_handle: the connection handle which notified the attribute;
- evt->event_data_length: length of attribute value + handle (2 bytes);
- evt->attr_handle: attribute handle;
- evt->attr_value: pointer to attribute value (length is
- event_data_length – 2).*/
- /* Add user code for handling attribute notification event based on
- application scenarios */
- DEBUG_REPORT("HCI_Event EVT_BLUE_GATT_NOTIFICATION.rn");
- ble_on_gatt_notification_cb(evt->attr_handle, evt->event_data_length - 2, evt->attr_value);
- }/* EVT_BLUE_GATT_NOTIFICATION */
- break;
- case EVT_BLUE_GATT_DISC_READ_CHAR_BY_UUID_RESP:
- if(BLE_Role == CLIENT) {
- DEBUG_REPORT("EVT_BLUE_GATT_DISC_READ_CHAR_BY_UUID_RESP.rn");
- evt_gatt_disc_read_char_by_uuid_resp *resp = (void*)blue_evt->data;
- ble_on_gatt_dis_read_char_by_uuid_resp_cb( (evt_gatt_disc_read_char_by_uuid_resp *)resp);
- }
- break;
- case EVT_BLUE_GATT_PROCEDURE_COMPLETE:
- if(BLE_Role == CLIENT) {
- DEBUG_REPORT("EVT_BLUE_GATT_PROCEDURE_COMPLETE.rn");
- /* Wait for gatt procedure complete event trigger related to Discovery Charac by UUID */
- evt_gatt_procedure_complete *pr = (void*)blue_evt->data;
- ble_on_gatt_procedure_complete_cb( (evt_gatt_procedure_complete *)pr);
- }
- break;
- case EVT_BLUE_GATT_READ_PERMIT_REQ: {
- evt_gatt_read_permit_req *pr = (void*)blue_evt->data;
- /* Add user code for handling attribute notification event based on
- application scenarios */
- DEBUG_REPORT("HCI_Event EVT_BLUE_GATT_READ_PERMIT_REQ.rn");
- ble_on_gatt_read_permit_cb(pr->attr_handle);
- }
- break;
- }
- }
- break;
- }
- }
- void ble_user_process(void)
- {
- }
- void ble_process(void)
- {
- /**<
- 添加到while循环,是ble的处理程序
- */
- HCI_Process();
- if(set_connectable) {
- if(BLE_Role == CLIENT) {
- ble_host_connect();
- } else {
- ble_device_start_advertising();
- }
- set_connectable = FALSE;
- }
- ble_user_process();
- }
复制代码
在GAT的设置模式,通过宏定义进行选择
#define SERVER_ROLE
#define CLIENT_ROLE
用户函数
- int main(void)
- {
- 其他的初始化
- /*Configure the ble */
- ble_device_init();
- ble_device_set_tx_power(4);/* Set output power level */
- while(1) {
- ble_process();
- 其他的用户程序
- }
- }
- void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
- {/* BlueNRG-MS 中断函数*/
- HCI_Isr();
- }
复制代码
|