본문으로 바로가기

[nRF52] ble_app_uart 프로젝트

category Nordic_nRF52 2023. 3. 16. 17:00

:  이 프로젝트는 BLE 위에서 Serial 포트를 구현한 예제로 NUS (Nordic Uart Service) 어플리케이션이다.

 

목차

    0> 개요

      :이 프로젝트는 BLE 를 통해 들어온 데이타를 시리얼로 데이터 전송및

       Serial 로 들어온 데이타를 BLE 로 보내는 예제입니다.advertise 시 이름은 "nRF UART" 이고 

       스마프폰에 nRF Connect 이나 nRF Toolbox  앱을 설치해서 제어가 가능합니다.

    1> 프로젝트 위치

      : <InstallFolder>\examples\ble_peripheral\ble_app_uart

    2> 노르딕 다큐먼트

    https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.2/ble_sdk_app_nus_eval.html

     

    nRF5 SDK v17.0.2: UART/Serial Port Emulation over BLE

    This example requires one of the following SoftDevices: S112, S113, S132, S140 Important: Before you run this example, make sure to program the SoftDevice. Note: You can run this example on nRF52833 with the S140 SoftDevice. The Nordic UART Service (NUS) A

    infocenter.nordicsemi.com

     

    3> UART 통신 테스트

     3-1> nRF Toolbox 사용하기

    ▶ nRF52 DK 보드 리셋시 시리얼 메시지

     

    ▶  nRF Toolbox 실행후 Utils services 의 UART  를 선택해 줍니다.

     

    ▶ Nordic_UART 를 선택해 줍니다.

    ▶ Serial 창에 한개 실행후 양쪽에서 데이타를 보내면 동작 확인 가능합니다.

    PC Teraterm 화면

      3-2> nRF Connect 사용해 UART 통신하기

      ▶ nRF Connect 앱 실행후 Nordic_UART 를 찾아 연결해 줍니다.

     

      ▶ 연결완료후 Nordic UART Service 선택하기

      ▶ TX 테스트 는 RX Characteristic 의 Write 버튼을 클릭후 데이타를 전송해 봅니다.

        ==> PC 의 터미널창에 들어오는 데이타 확인하기

      ▶RX 테스트 는 TX Characteristic 의 notify 를 Enable 한후 PC에서 데이타(asdf) 를 전송해 봅니다.

       ==>  시리얼창에 엔터키를 넣어야 화면에 표시가 됩니다.

     

     

     

     4> 상세분석

      ▶  UART  및 nus (Nordic UART Service) 초기화

    static void uart_init(void)
    {
        app_uart_comm_params_t const comm_params =
        {
            .rx_pin_no    = RX_PIN_NUMBER,
            .tx_pin_no    = TX_PIN_NUMBER,
            .rts_pin_no   = RTS_PIN_NUMBER,
            .cts_pin_no   = CTS_PIN_NUMBER,
            .flow_control = APP_UART_FLOW_CONTROL_DISABLED,
            .use_parity   = false,
            .baud_rate    = NRF_UART_BAUDRATE_115200
        };
        APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE,  UART_TX_BUF_SIZE,
                           uart_event_handle,
                           APP_IRQ_PRIORITY_LOWEST, err_code);
    }
    static void services_init(void)
    {
      ~~~~ 중략 ~~~~
       nus_init.data_handler = nus_data_handler;
       err_code = ble_nus_init(&m_nus, &nus_init);
    }

      ▶ Nordic UART Service 등록

        ==>  ble_nus_init() 함수 중 일부 발췌

    // 1>  Add a custom base UUID.
    sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type);
    
    // 2> Add the service.
     ble_uuid.type = p_nus->uuid_type;
     ble_uuid.uuid = BLE_UUID_NUS_SERVICE;
     sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,&ble_uuid,&p_nus->service_handle);

     

      ▶ Nordic UART Service  characteristic 등록

    tx /rx characteristics 관련코드 
    // 해석의 편의를 위해 불필요한 코드는 제거 했습니다.
    // 1> Add the RX Characteristic.
    add_char_params.uuid                     = BLE_UUID_NUS_RX_CHARACTERISTIC;
    add_char_params.uuid_type                = p_nus->uuid_type;
    add_char_params.max_len                  = BLE_NUS_MAX_RX_CHAR_LEN;
    add_char_params.init_len                 = sizeof(uint8_t);
    add_char_params.is_var_len               = true;
    add_char_params.char_props.write         = 1;
    add_char_params.char_props.write_wo_resp = 1;
    
    add_char_params.read_access  = SEC_OPEN;
    add_char_params.write_access = SEC_OPEN;
    
    characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles);
    
    // 2> Add the TX Characteristic.
    add_char_params.uuid              = BLE_UUID_NUS_TX_CHARACTERISTIC;
    add_char_params.uuid_type         = p_nus->uuid_type;
    add_char_params.max_len           = BLE_NUS_MAX_TX_CHAR_LEN;
    add_char_params.init_len          = sizeof(uint8_t);
    add_char_params.is_var_len        = true;
    add_char_params.char_props.notify = 1;
    
    add_char_params.read_access       = SEC_OPEN;
    add_char_params.write_access      = SEC_OPEN;
    add_char_params.cccd_write_access = SEC_OPEN;
    characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles);

     

      ▶ RX data flow  ( BLE ==> UART TX)

    void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
    {  
       ~~~~ 중략 ~~~~  
       switch (p_ble_evt->header.evt_id)
    ~~~~ 중략 ~~~~  
    
    }
    
    
    // ble_nus.c
    void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
    {
       ~~~~ 중략 ~~~~
       evt.type                  = BLE_NUS_EVT_RX_DATA;
       evt.params.rx_data.p_data = p_evt_write->data;
       evt.params.rx_data.length = p_evt_write->len;
    
       p_nus->data_handler(&evt);
       ~~~~ 중략 ~~~~
    
    }
    
    void nus_data_handler(ble_nus_evt_t * p_evt)
    {
       ~~~~ 중략 ~~~~
       app_uart_put(p_evt->params.rx_data.p_data[i]);
       ~~~~ 중략 ~~~~
    }

     

      ▶ TX data flow ( UART RX ==> BLE  )

    void uart_event_handle(app_uart_evt_t * p_event)
    {
        ~~~~ 중략 ~~~~~
        case APP_UART_DATA_READY:
        app_uart_get(&data_array[index])
        ~~~~ 중략 ~~~~~
        ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle);
       ~~~~ 중략 ~~~~~
     
    }
    
    
    uint32_t ble_nus_data_send(ble_nus_t *p_nus, uint8_t *p_data, uint16_t *p_length, uint16_t conn_handle)
    {
        ~~~~ 중략 ~~~~~
        ble_gatts_hvx_params_t     hvx_params;
        hvx_params.handle = p_nus->tx_handles.value_handle;
        hvx_params.p_data = p_data;
        hvx_params.p_len  = p_length;
        hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
    
        return sd_ble_gatts_hvx(conn_handle, &hvx_params);
    }

     

     

    < 기타 >

      A> NUS 예제에 사용되는  UUID

        6E400001-B5A3-F393-E0A9-E50E24DCCA9E    ==> Service

        6E400002-B5A3-F393-E0A9-E50E24DCCA9E    ==> Rx Characteristic

        6E400003-B5A3-F393-E0A9-E50E24DCCA9E    ==> Tx Characteristic

     

     B> LED 표시

      ▶ Advertising mode  : LED1 깜박임

     

      ▶ Connected mode  : LED1 ON

     

     C> Advertise  data

    nRF Connect ==> Scanner 탭

     

     

       ==> 위 그림의 네모박스의 Service UUID 를 보고 앱이 동작합니다.

      

     

    반응형