{"id":242,"date":"2020-03-24T01:31:12","date_gmt":"2020-03-23T17:31:12","guid":{"rendered":"http:\/\/zechs.taipei\/?p=242"},"modified":"2020-03-24T01:31:13","modified_gmt":"2020-03-23T17:31:13","slug":"%e8%bd%89nordic-sdk15-2-0-nus-multilink-with-pca10040","status":"publish","type":"post","link":"https:\/\/zechs.taipei\/?p=242","title":{"rendered":"[\u8f49]Nordic SDK15.2.0 NUS Multilink with PCA10040"},"content":{"rendered":"<p>\u5982\u4f55\u5728Nordic 52832 Central \u591a\u91cd\u9023\u63a5peripher<\/p>\n\n\n\n<p>\u539f\u6587\u7db2\u5740<br> <a href=\"https:\/\/devzone.nordicsemi.com\/f\/nordic-q-a\/39480\/sdk15-2-0-nus-multilink-with-pca10040\">https:\/\/devzone.nordicsemi.com\/f\/nordic-q-a\/39480\/sdk15-2-0-nus-multilink-with-pca10040<\/a> <\/p>\n\n\n\n<p>Setup: nRF5_SDK_15.2.0_9412b96 \/ s132_nrf52_6.1.0_softdevice \/ nrf52832<\/p>\n\n\n\n<p>I tried to make a multilink nus central (PCA10040) with 2 peripherals (PCA10028) connected to it. The peripheral devices run the code on the ble_app_uart example, the central device runs my code based on the ble_app_uart_c example modified according to the multilink example. I followed the steps from this<a href=\"https:\/\/devzone.nordicsemi.com\/f\/nordic-q-a\/22215\/how-to-send-message-from-two-slave-to-one-master-in-nrf52\">&nbsp;link<\/a>&nbsp;getting a compiling code with no errors. I think I did all the steps properly but I cannot get a working code.&nbsp;<\/p>\n\n\n\n<p>For getting Multilink NUS I used all of these functions:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/**\n * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n *    list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form, except as embedded into a Nordic\n *    Semiconductor ASA integrated circuit in a product or a software update for\n *    such product, must reproduce the above copyright notice, this list of\n *    conditions and the following disclaimer in the documentation and\/or other\n *    materials provided with the distribution.\n *\n * 3. Neither the name of Nordic Semiconductor ASA nor the names of its\n *    contributors may be used to endorse or promote products derived from this\n *    software without specific prior written permission.\n *\n * 4. This software, with or without modification, must only be used with a\n *    Nordic Semiconductor ASA integrated circuit.\n *\n * 5. Any software provided in binary form under this license must not be reverse\n *    engineered, decompiled, modified and\/or disassembled.\n *\n * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA \"AS IS\" AND ANY EXPRESS\n * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE\n * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT\n * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n *\/\n\/**\n * @brief BLE LED Button Service central and client application main file.\n *\n * This example can be a central for up to 8 peripherals.\n * The peripheral is called ble_app_blinky and can be found in the ble_peripheral\n * folder.\n *\/\n\n#include &lt;stdint.h>\n#include &lt;stdio.h>\n#include &lt;string.h>\n#include \"nordic_common.h\"\n#include \"app_uart.h\"\n#include \"nrf_sdh.h\"\n#include \"nrf_sdh_ble.h\"\n#include \"app_timer.h\"\n#include \"bsp_btn_ble.h\"\n#include \"ble.h\"\n#include \"ble_hci.h\"\n#include \"ble_advdata.h\"\n#include \"ble_advertising.h\"\n#include \"ble_conn_params.h\"\n#include \"ble_db_discovery.h\"\n#include \"ble_nus_c.h\"\n#include \"ble_conn_state.h\"\n#include \"nrf_ble_gatt.h\"\n#include \"nrf_pwr_mgmt.h\"\n#include \"nrf_ble_scan.h\"\n#include \"app_uart.h\"\n#include \"app_timer.h\"\n\n#include \"nrf_log.h\"\n#include \"nrf_log_ctrl.h\"\n#include \"nrf_log_default_backends.h\"\n\n\n#define APP_BLE_CONN_CFG_TAG      1                                     \/**&lt; Tag that refers to the BLE stack configuration that is set with @ref sd_ble_cfg_set. The default tag is @ref APP_BLE_CONN_CFG_TAG. *\/\n#define APP_BLE_OBSERVER_PRIO     3                                     \/**&lt; BLE observer priority of the application. There is no need to modify this value. *\/\n\n#define CENTRAL_SCANNING_LED      BSP_BOARD_LED_0\n#define CENTRAL_CONNECTED_LED     BSP_BOARD_LED_1\n#define LEDBUTTON_LED             BSP_BOARD_LED_2                       \/**&lt; LED to indicate a change of state of the Button characteristic on the peer. *\/\n\nNRF_BLE_GATT_DEF(m_gatt);                                               \/**&lt; GATT module instance. *\/\nBLE_NUS_C_ARRAY_DEF(m_ble_nus_c, NRF_SDH_BLE_CENTRAL_LINK_COUNT);           \/**&lt; LED button client instances. *\/\nBLE_DB_DISCOVERY_DEF(m_db_disc);  \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\/**&lt; Database discovery module instances. *\/\nNRF_BLE_SCAN_DEF(m_scan);                                               \/**&lt; Scanning Module instance. *\/\n\nstatic char const m_target_periph_name[] = \"Nordic_UART\";             \/**&lt; Name of the device to try to connect to. This name is searched for in the scanning report data. *\/\nstatic uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH; \/**&lt; Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. *\/\n#define UART_TX_BUF_SIZE        256                                     \/**&lt; UART TX buffer size. *\/\n#define UART_RX_BUF_SIZE        256                                     \/**&lt; UART RX buffer size. *\/\n\n#define NUS_SERVICE_UUID_TYPE   BLE_UUID_TYPE_VENDOR_BEGIN              \/**&lt; UUID type for the Nordic UART Service (vendor specific). *\/\n#define ECHOBACK_BLE_UART_DATA  1                                       \/**&lt; Echo the UART data that is received over the Nordic UART Service (NUS) back to the sender. *\/\n\n\n\n\n\/**@brief Function for handling asserts in the SoftDevice.\n *\n * @details This function is called in case of an assert in the SoftDevice.\n *\n * @warning This handler is only an example and is not meant for the final product. You need to analyze\n *          how your product is supposed to react in case of an assert.\n * @warning On assert from the SoftDevice, the system can only recover on reset.\n *\n * @param[in] line_num     Line number of the failing assert call.\n * @param[in] p_file_name  File name of the failing assert call.\n *\/\nvoid assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)\n{\n    app_error_handler(0xDEADBEEF, line_num, p_file_name);\n}\n\n\n\/**@brief Function for initializing the LEDs.\n *\n * @details Initializes all LEDs used by the application.\n *\/\nstatic void leds_init(void)\n{\n    bsp_board_init(BSP_INIT_LEDS);\n}\n\n\/**@brief Function for starting scanning. *\/\nstatic void scan_start(void)\n{\n    ret_code_t ret;\n\n    NRF_LOG_INFO(\"Start scanning for device name %s.\", (uint32_t)m_target_periph_name);\n    ret = nrf_ble_scan_start(&amp;m_scan);\n    APP_ERROR_CHECK(ret);\n    \/\/ Turn on the LED to signal scanning.\n    bsp_board_led_on(CENTRAL_SCANNING_LED);\n}\n\n\/**@brief Function for handling Scanning Module events.\n *\/\nstatic void scan_evt_handler(scan_evt_t const * p_scan_evt)\n{\n    ret_code_t err_code;\n\n    switch(p_scan_evt->scan_evt_id)\n    {\n         case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:\n         {\n              err_code = p_scan_evt->params.connecting_err.err_code;\n              APP_ERROR_CHECK(err_code);\n         } break;\n\n         case NRF_BLE_SCAN_EVT_CONNECTED:\n         {\n              \n\t\t\t\t\t\t ble_gap_evt_connected_t const * p_connected =\n                               p_scan_evt->params.connected.p_connected;\n             \/\/ Scan is automatically stopped by the connection.\n             NRF_LOG_INFO(\"Connecting to target %02x%02x%02x%02x%02x%02x\",\n                      p_connected->peer_addr.addr[0],\n                      p_connected->peer_addr.addr[1],\n                      p_connected->peer_addr.addr[2],\n                      p_connected->peer_addr.addr[3],\n                      p_connected->peer_addr.addr[4],\n                      p_connected->peer_addr.addr[5]\n                      );\n         } break;\n\n         case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:\n         {\n             NRF_LOG_INFO(\"Scan timed out.\");\n             scan_start();\n         } break;\n\n         default:\n             break;\n    }\n}\n\n\/**@brief Function for initializing the scanning and setting the filters.\n *\/\nstatic void scan_init(void)\n{\n    ret_code_t          err_code;\n    nrf_ble_scan_init_t init_scan;\n\n    memset(&amp;init_scan, 0, sizeof(init_scan));\n\n    init_scan.connect_if_match = true;\n    init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;\n\n    err_code = nrf_ble_scan_init(&amp;m_scan, &amp;init_scan, scan_evt_handler);\n    APP_ERROR_CHECK(err_code);\n\n    err_code = nrf_ble_scan_filter_set(&amp;m_scan, SCAN_NAME_FILTER, m_target_periph_name);\n    APP_ERROR_CHECK(err_code);\n\n    err_code = nrf_ble_scan_filters_enable(&amp;m_scan, NRF_BLE_SCAN_NAME_FILTER, false);\n    APP_ERROR_CHECK(err_code);\n}\n\n\/**@brief Function for handling characters received by the Nordic UART Service (NUS).\n *\n * @details This function takes a list of characters of length data_len and prints the characters out on UART.\n *          If @ref ECHOBACK_BLE_UART_DATA is set, the data is sent back to sender.\n *\/\nstatic void ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len)\n{\n    ret_code_t ret_val;\n\n    NRF_LOG_DEBUG(\"Receiving data.\");\n    NRF_LOG_HEXDUMP_DEBUG(p_data, data_len);\n\n    for (uint32_t i = 0; i &lt; data_len; i++)\n    {\n        do\n        {\n            ret_val = app_uart_put(p_data[i]);\n            if ((ret_val != NRF_SUCCESS) &amp;&amp; (ret_val != NRF_ERROR_BUSY))\n            {\n                NRF_LOG_ERROR(\"app_uart_put failed for index 0x%04x.\", i);\n                APP_ERROR_CHECK(ret_val);\n            }\n        } while (ret_val == NRF_ERROR_BUSY);\n    }\n    if (p_data[data_len-1] == '\\r')\n    {\n        while (app_uart_put('\\n') == NRF_ERROR_BUSY);\n    }\n    if (ECHOBACK_BLE_UART_DATA)\n    {\n        \/\/ Send data back to the peripheral.\n        do\n        {\n         \t for (uint32_t i = 0; i &lt; NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)\n\t\t\t\t\t\t{ \n\t\t\t\t\t\tret_val = ble_nus_c_string_send(&amp;m_ble_nus_c[i], p_data, data_len);\n            if ((ret_val != NRF_SUCCESS) &amp;&amp; (ret_val != NRF_ERROR_BUSY))\n            {\n                NRF_LOG_ERROR(\"Failed sending NUS message. Error 0x%x. \", ret_val);\n                APP_ERROR_CHECK(ret_val);\n            }\n\t\t\t\t\t\t}\n        } while (ret_val == NRF_ERROR_BUSY);\n    }\n}\n\n\/**@brief Function for handling BLE events.\n *\n * @param[in]   p_ble_evt   Bluetooth stack event.\n * @param[in]   p_context   Unused.\n *\/\nstatic void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)\n{\n    ret_code_t            err_code;\n    ble_gap_evt_t const * p_gap_evt = &amp;p_ble_evt->evt.gap_evt;\n\n    switch (p_ble_evt->header.evt_id)\n    {\n        case BLE_GAP_EVT_CONNECTED:\n            err_code = ble_nus_c_handles_assign(&amp;m_ble_nus_c[p_gap_evt->conn_handle], p_ble_evt->evt.gap_evt.conn_handle, NULL);\n            APP_ERROR_CHECK(err_code);\n\n            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);\n            APP_ERROR_CHECK(err_code);\n\n            \/\/ start discovery of services. The NUS Client waits for a discovery result\n            err_code = ble_db_discovery_start(&amp;m_db_disc, p_ble_evt->evt.gap_evt.conn_handle);\n            APP_ERROR_CHECK(err_code);\n        if (err_code != NRF_ERROR_BUSY)\n            {\n                APP_ERROR_CHECK(err_code);\n            }\n\n            \/\/ Update LEDs status and check whether it is needed to look for more\n            \/\/ peripherals to connect to.\n            bsp_board_led_on(CENTRAL_CONNECTED_LED);\n            if (ble_conn_state_central_conn_count() == NRF_SDH_BLE_CENTRAL_LINK_COUNT)\n            {\n                bsp_board_led_off(CENTRAL_SCANNING_LED);\n            }\n            else\n            {\n                \/\/ Resume scanning.\n                bsp_board_led_on(CENTRAL_SCANNING_LED);\n                scan_start();\n            }    \n\t\t\t\tbreak;\n\n        case BLE_GAP_EVT_DISCONNECTED:\n\n            NRF_LOG_INFO(\"Disconnected. conn_handle: 0x%x, reason: 0x%x\",\n                         p_gap_evt->conn_handle,\n                         p_gap_evt->params.disconnected.reason);\n            break;\n\n        case BLE_GAP_EVT_TIMEOUT:\n            if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)\n            {\n                NRF_LOG_INFO(\"Connection Request timed out.\");\n\t\t\t\t\t\t\t\tscan_start();\n            }\n            break;\n\n        case BLE_GAP_EVT_SEC_PARAMS_REQUEST:\n            \/\/ Pairing not supported.\n            err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);\n            APP_ERROR_CHECK(err_code);\n            break;\n\n        case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:\n            \/\/ Accepting parameters requested by peer.\n            err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,\n                                                    &amp;p_gap_evt->params.conn_param_update_request.conn_params);\n            APP_ERROR_CHECK(err_code);\n            break;\n\n        case BLE_GAP_EVT_PHY_UPDATE_REQUEST:\n        {\n            NRF_LOG_DEBUG(\"PHY update request.\");\n            ble_gap_phys_t const phys =\n            {\n                .rx_phys = BLE_GAP_PHY_AUTO,\n                .tx_phys = BLE_GAP_PHY_AUTO,\n            };\n            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &amp;phys);\n            APP_ERROR_CHECK(err_code);\n        } break;\n\n        case BLE_GATTC_EVT_TIMEOUT:\n            \/\/ Disconnect on GATT Client timeout event.\n            NRF_LOG_DEBUG(\"GATT Client Timeout.\");\n            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,\n                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);\n            APP_ERROR_CHECK(err_code);\n            break;\n\n        case BLE_GATTS_EVT_TIMEOUT:\n            \/\/ Disconnect on GATT Server timeout event.\n            NRF_LOG_DEBUG(\"GATT Server Timeout.\");\n            err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,\n                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);\n            APP_ERROR_CHECK(err_code);\n            break;\n\n        default:\n            break;\n    }\n}\n\n\/**@brief Function for handling BLE events.\n *\n * @param[in]   p_ble_evt   Bluetooth stack event.\n * @param[in]   p_context   Unused.\n *\/\nstatic void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt)\n{\n    switch (p_ble_nus_evt->evt_type)\n    {\n        case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:\n        {\n            ret_code_t err_code;\n\n            NRF_LOG_INFO(\"LED Button Service discovered on conn_handle 0x%x\",\n                         p_ble_nus_evt->conn_handle);\n\n\t\t\t\t\t\terr_code = ble_nus_c_handles_assign(p_ble_nus_c, p_ble_nus_evt->conn_handle, &amp;p_ble_nus_evt->handles);\n\t\t\t\t\t\tAPP_ERROR_CHECK(err_code);\n            \/\/ LED Button Service discovered. Enable notification of Button.\n            err_code = ble_nus_c_tx_notif_enable(p_ble_nus_c);;\n            APP_ERROR_CHECK(err_code);\n        } break; \/\/ BLE_NUS_C_EVT_DISCOVERY_COMPLETE\n\n        case BLE_NUS_C_EVT_NUS_TX_EVT:\n            ble_nus_chars_received_uart_print(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);\n            break;\n\n        case BLE_NUS_C_EVT_DISCONNECTED:\n            NRF_LOG_INFO(\"Disconnected.\");\n            scan_start();\n            break;\n\t\t}\n}\n\n\/**@brief Function for handling events from the GATT library. *\/\nvoid gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)\n{\n    if (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)\n    {\n        NRF_LOG_INFO(\"ATT MTU exchange completed.\");\n\n        m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;\n        NRF_LOG_INFO(\"Ble NUS max data length set to 0x%X(%d)\", m_ble_nus_max_data_len, m_ble_nus_max_data_len);\n    }\n}\n\n\/**@brief   Function for handling app_uart events.\n *\n * @details This function receives a single character from the app_uart module and appends it to\n *          a string. The string is sent over BLE when the last character received is a\n *          'new line' '\\n' (hex 0x0A) or if the string reaches the maximum data length.\n *\/\nvoid uart_event_handle(app_uart_evt_t * p_event)\n{\n    static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];\n    static uint16_t index = 0;\n    uint32_t ret_val;\n\n    switch (p_event->evt_type)\n    {\n        \/**@snippet [Handling data from UART] *\/\n        case APP_UART_DATA_READY:\n            UNUSED_VARIABLE(app_uart_get(&amp;data_array[index]));\n            index++;\n\n            if ((data_array[index - 1] == '\\n') || (index >= (m_ble_nus_max_data_len)))\n            {\n                NRF_LOG_DEBUG(\"Ready to send data over BLE NUS\");\n                NRF_LOG_HEXDUMP_DEBUG(data_array, index);\n\t\t\t\t\t\t    \n                do\n                {\n\t\t\t\t\t\t\t\t\t for (uint32_t i = 0; i &lt; NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)\n\t\t\t\t\t\t\t\t\t{ \n                    ret_val = ble_nus_c_string_send(&amp;m_ble_nus_c[i], data_array, index);\n                    if ( (ret_val != NRF_ERROR_INVALID_STATE) &amp;&amp; (ret_val != NRF_ERROR_RESOURCES) )\n                    {\n                        APP_ERROR_CHECK(ret_val);\n                    }\n\t\t\t\t\t\t\t\t\t}\t\n                } while (ret_val == NRF_ERROR_BUSY);\n\n                index = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\n            break;\n\n        \/**@snippet [Handling data from UART] *\/\n        case APP_UART_COMMUNICATION_ERROR:\n            NRF_LOG_ERROR(\"Communication error occurred while handling UART.\");\n            APP_ERROR_HANDLER(p_event->data.error_communication);\n            break;\n\n        case APP_UART_FIFO_ERROR:\n            NRF_LOG_ERROR(\"Error occurred in FIFO module used by UART.\");\n            APP_ERROR_HANDLER(p_event->data.error_code);\n            break;\n\n        default:\n            break;\n    }\n}\n\n\/**@brief Function for initializing the UART. *\/\nstatic void uart_init(void)\n{\n    ret_code_t err_code;\n\n    app_uart_comm_params_t const comm_params =\n    {\n        .rx_pin_no    = RX_PIN_NUMBER,\n        .tx_pin_no    = TX_PIN_NUMBER,\n        .rts_pin_no   = RTS_PIN_NUMBER,\n        .cts_pin_no   = CTS_PIN_NUMBER,\n        .flow_control = APP_UART_FLOW_CONTROL_DISABLED,\n        .use_parity   = false,\n        .baud_rate    = UART_BAUDRATE_BAUDRATE_Baud115200\n    };\n\n    APP_UART_FIFO_INIT(&amp;comm_params,\n                       UART_RX_BUF_SIZE,\n                       UART_TX_BUF_SIZE,\n                       uart_event_handle,\n                       APP_IRQ_PRIORITY_LOWEST,\n                       err_code);\n\n    APP_ERROR_CHECK(err_code);\n}\n\n\/**@brief LED Button collector initialization. *\/\nstatic void nus_c_init(void)\n{\n    ret_code_t       err_code;\n    ble_nus_c_init_t init;\n\n    init.evt_handler = ble_nus_c_evt_handler;\n\n    for (uint32_t i = 0; i &lt; NRF_SDH_BLE_CENTRAL_LINK_COUNT; i++)\n    {\n        err_code = ble_nus_c_init(&amp;m_ble_nus_c[i], &amp;init);\n        APP_ERROR_CHECK(err_code);\n    }\n}\n\n\n\/**@brief Function for initializing the BLE stack.\n *\n * @details Initializes the SoftDevice and the BLE event interrupts.\n *\/\nstatic void ble_stack_init(void)\n{\n    ret_code_t err_code;\n\n    err_code = nrf_sdh_enable_request();\n    APP_ERROR_CHECK(err_code);\n\n    \/\/ Configure the BLE stack using the default settings.\n    \/\/ Fetch the start address of the application RAM.\n    uint32_t ram_start = 0;\n    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &amp;ram_start);\n    APP_ERROR_CHECK(err_code);\n\n    \/\/ Enable BLE stack.\n    err_code = nrf_sdh_ble_enable(&amp;ram_start);\n    APP_ERROR_CHECK(err_code);\n\n    \/\/ Register a handler for BLE events.\n    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);\n}\n\n\n\n\n\/**@brief Function for handling database discovery events.\n *\n * @details This function is a callback function to handle events from the database discovery module.\n *          Depending on the UUIDs that are discovered, this function forwards the events\n *          to their respective services.\n *\n * @param[in] p_event  Pointer to the database discovery event.\n *\/\nstatic void db_disc_handler(ble_db_discovery_evt_t * p_evt)\n{\n    NRF_LOG_DEBUG(\"call to ble_nus_on_db_disc_evt for instance %d and link 0x%x!\",\n                  p_evt->conn_handle,\n                  p_evt->conn_handle);\n\n    ble_nus_c_on_db_disc_evt(&amp;m_ble_nus_c[p_evt->conn_handle], p_evt);\n}\n\n\n\/** @brief Database discovery initialization.\n *\/\nstatic void db_discovery_init(void)\n{\n    ret_code_t err_code = ble_db_discovery_init(db_disc_handler);\n    APP_ERROR_CHECK(err_code);\n}\n\n\n\/**@brief Function for initializing power management.\n *\/\nstatic void power_management_init(void)\n{\n    ret_code_t err_code;\n    err_code = nrf_pwr_mgmt_init();\n    APP_ERROR_CHECK(err_code);\n}\n\n\n\/**@brief Function for handling the idle state (main loop).\n *\n * @details This function handles any pending log operations, then sleeps until the next event occurs.\n *\/\nstatic void idle_state_handle(void)\n{\n    if (NRF_LOG_PROCESS() == false)\n    {\n        nrf_pwr_mgmt_run();\n    }\n}\n\n\n\/** @brief Function for initializing the log module.\n *\/\nstatic void log_init(void)\n{\n    ret_code_t err_code = NRF_LOG_INIT(NULL);\n    APP_ERROR_CHECK(err_code);\n\n    NRF_LOG_DEFAULT_BACKENDS_INIT();\n}\n\n\n\/** @brief Function for initializing the timer.\n *\/\nstatic void timer_init(void)\n{\n    ret_code_t err_code = app_timer_init();\n    APP_ERROR_CHECK(err_code);\n}\n\n\n\/**@brief Function for initializing the GATT module.\n *\/\nstatic void gatt_init(void)\n{\n    ret_code_t err_code = nrf_ble_gatt_init(&amp;m_gatt, NULL);\n    APP_ERROR_CHECK(err_code);\n}\n\n\nint main(void)\n{\n    \/\/ Initialize.\n    log_init();\n    timer_init();\n    leds_init();\n    uart_init();\n\tpower_management_init();\n    db_discovery_init();\n\tble_stack_init();\n    gatt_init();\n    nus_c_init();\n    ble_conn_state_init();\n    scan_init();\n\n    \/\/ Start execution.\n    NRF_LOG_INFO(\"Multilink NUS example started.\");\n    scan_start();\n\n    for (;;)\n    {\n        idle_state_handle();\n    }\n}\n<\/pre>","protected":false},"excerpt":{"rendered":"<p>\u5982\u4f55\u5728Nordic 52832 Central \u591a\u91cd\u9023\u63a5peripher \u539f\u6587\u7db2\u5740 https:\/\/devzo &#8230; <a title=\"[\u8f49]Nordic SDK15.2.0 NUS Multilink with PCA10040\" class=\"read-more\" href=\"https:\/\/zechs.taipei\/?p=242\" aria-label=\"\u95b1\u8b80\u3008[\u8f49]Nordic SDK15.2.0 NUS Multilink with PCA10040\u3009\u5168\u6587\">\u95b1\u8b80\u5168\u6587<\/a><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-242","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/zechs.taipei\/index.php?rest_route=\/wp\/v2\/posts\/242","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zechs.taipei\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zechs.taipei\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zechs.taipei\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zechs.taipei\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=242"}],"version-history":[{"count":1,"href":"https:\/\/zechs.taipei\/index.php?rest_route=\/wp\/v2\/posts\/242\/revisions"}],"predecessor-version":[{"id":243,"href":"https:\/\/zechs.taipei\/index.php?rest_route=\/wp\/v2\/posts\/242\/revisions\/243"}],"wp:attachment":[{"href":"https:\/\/zechs.taipei\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zechs.taipei\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zechs.taipei\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}