低消費電力Bluetooth 4.0 BLEプログラミング-nrf 51822開発(11)-Bluetoothシリアルポートコード分析


コードインスタンス:クリックしてリンクを開く
    実装される機能は、uartポートから別のブルートゥースシリアルポートにデータを送信するか、ブルートゥースからデータを読み出してuartを介してデータを印刷することである.
   
int main(void)
{
    // Initialize
    leds_init();
    timers_init();
    buttons_init();
    uart_init();
    ble_stack_init();
    gap_params_init();
    services_init();
    advertising_init();
    conn_params_init();
    sec_params_init();
    
    simple_uart_putstring(START_STRING);
    
    advertising_start();
    
    // Enter main loop
    for (;;)
    {
        power_manage();
    }
}

uart_Initはuartのハードウェアを初期化します.
uartにデータがある場合、uart割り込み処理に入ります.
/**@brief   Function for handling UART interrupts.
 *
 * @details This function will receive a single character from the UART and append it to a string.
 *          The string will be be sent over BLE when the last character received was a 'new line'
 *          i.e '
' (hex 0x0D) or if the string has reached a length of @ref NUS_MAX_DATA_LENGTH. */ void UART0_IRQHandler(void) { static uint8_t data_array[BLE_NUS_MAX_DATA_LEN]; static uint8_t index = 0; uint32_t err_code; /**@snippet [Handling the data received over UART] */ data_array[index] = simple_uart_get(); index++; if ((data_array[index - 1] == '
') || (index >= (BLE_NUS_MAX_DATA_LEN - 1))) { err_code = ble_nus_send_string(&m_nus, data_array, index + 1); if (err_code != NRF_ERROR_INVALID_STATE) { APP_ERROR_CHECK(err_code); } index = 0; } /**@snippet [Handling the data received over UART] */ }

data_arrayはデータバッファであり、改行を受信したときに入力が終了したか、バッファに達した最大バイト数とみなされる.
ble_nus_send_string関数はuartから入力したデータをBluetoothで送信します.
この例では、次のようなサービスが確立されています.
/**@brief Function for initializing services that will be used by the application.
 */
static void services_init(void)
{
    uint32_t         err_code;
    ble_nus_init_t   nus_init;
    
    memset(&nus_init, 0, sizeof(nus_init));

    nus_init.data_handler = nus_data_handler;
    
    err_code = ble_nus_init(&m_nus, &nus_init);
    APP_ERROR_CHECK(err_code);
}

 
uint32_t ble_nus_init(ble_nus_t * p_nus, const ble_nus_init_t * p_nus_init)
{
    uint32_t        err_code;
    ble_uuid_t      ble_uuid;
    ble_uuid128_t   nus_base_uuid = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0,
                                     0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E};

    if ((p_nus == NULL) || (p_nus_init == NULL))
    {
        return NRF_ERROR_NULL;
    }
    
    // Initialize service structure.
    p_nus->conn_handle              = BLE_CONN_HANDLE_INVALID;
    p_nus->data_handler             = p_nus_init->data_handler;
    p_nus->is_notification_enabled  = false;
    

    /**@snippet [Adding proprietary Service to S110 SoftDevice] */

    // Add custom base UUID.
    err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    ble_uuid.type = p_nus->uuid_type;
    ble_uuid.uuid = BLE_UUID_NUS_SERVICE;

    // Add service.
    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                                        &ble_uuid,
                                        &p_nus->service_handle);
    /**@snippet [Adding proprietary Service to S110 SoftDevice] */
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    
    // Add RX Characteristic.
    err_code = rx_char_add(p_nus, p_nus_init);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    // Add TX Characteristic.
    err_code = tx_char_add(p_nus, p_nus_init);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }
    
    return NRF_SUCCESS;
}

rx_char_add()は受信特性を追加し、tx_char_add()は送信特性を追加した.
Bluetoothからデータを受信すると、シリアルポートを介してデータが印刷されます.
/**@brief     Function for handling the @ref BLE_GATTS_EVT_WRITE event from the S110 SoftDevice.
 *
 * @param[in] p_dfu     Nordic UART Service structure.
 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
 */
static void on_write(ble_nus_t * p_nus, ble_evt_t * p_ble_evt)
{
    ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    
    if (
        (p_evt_write->handle == p_nus->rx_handles.cccd_handle)
        &&
        (p_evt_write->len == 2)
       )
    {
        if (ble_srv_is_notification_enabled(p_evt_write->data))
        {
            p_nus->is_notification_enabled = true;
        }
        else
        {
            p_nus->is_notification_enabled = false;
        }
    }
    else if (
             (p_evt_write->handle == p_nus->tx_handles.value_handle)
             &&
             (p_nus->data_handler != NULL)
            )
    {
        p_nus->data_handler(p_nus, p_evt_write->data, p_evt_write->len);
    }
    else
    {
        // Do Nothing. This event is not relevant to this service.
    }
}