52840 USB虚拟串口移植

一.测试的平台

本篇文章主要介绍将52840作为接收器,使用的工程为nRF5_SDK_15.2.0_9412b96\examples\ble_central\ble_app_uart_c\pca10056。

整个测试平台如下

环境:win10,64位,MDK集成开发环境.
SDK:nRF5_SDK_15.2
协议栈:s132_nrf52_6.1_softdevice.hex.
USB参考工程: nRF5_SDK_15.2.0_9412b96\examples\peripheral\usbd_cdc_acm\pca10056.
硬件平台:pca10056开发板.

二.Application移植

   1.USBD移植

(1)添加相关C文件

将app_usbd.c、app_usbd_core.c、app_usbd_serial_num.c、app_usbd_string_desc.c、app_usbd_cdc_acm.c、nrf_drv_usbd.c添加到工程中。

(2)添加头文件

(3)加入usb相关代码

在main.c中加入下面代码

①头文件和宏定义   

#include "nrf.h"
#include "nrf_drv_usbd.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_power.h"
#include "app_usbd_core.h"
#include "app_usbd.h"
#include "app_usbd_string_desc.h"
#include "app_usbd_cdc_acm.h"
#include "app_usbd_serial_num.h"
#define LED_USB_RESUME      (BSP_BOARD_LED_0)
#define LED_CDC_ACM_OPEN    (BSP_BOARD_LED_1)
#define LED_CDC_ACM_RX      (BSP_BOARD_LED_2)
#define LED_CDC_ACM_TX      (BSP_BOARD_LED_3)
#define BTN_CDC_DATA_SEND       0
#define BTN_CDC_NOTIFY_SEND     1
#define BTN_CDC_DATA_KEY_RELEASE        (bsp_event_t)(BSP_EVENT_KEY_LAST + 1)
#ifndef USBD_POWER_DETECTION
#define USBD_POWER_DETECTION true
#endif
static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                    app_usbd_cdc_acm_user_event_t event);
#define CDC_ACM_COMM_INTERFACE  0
#define CDC_ACM_COMM_EPIN       NRF_DRV_USBD_EPIN2
#define CDC_ACM_DATA_INTERFACE  1
#define CDC_ACM_DATA_EPIN       NRF_DRV_USBD_EPIN1
#define CDC_ACM_DATA_EPOUT      NRF_DRV_USBD_EPOUT1
//APP_TIMER_DEF(m_blink_cdc);
#define LED_BLINK_INTERVAL 800
#define LED_CDC_ACM_CONN (BSP_BOARD_LED_2)
/**
 * @brief CDC_ACM class instance
 * */
APP_USBD_CDC_ACM_GLOBAL_DEF(m_app_cdc_acm,
                            cdc_acm_user_ev_handler,
                            CDC_ACM_COMM_INTERFACE,
                            CDC_ACM_DATA_INTERFACE,
                            CDC_ACM_COMM_EPIN,
                            CDC_ACM_DATA_EPIN,
                            CDC_ACM_DATA_EPOUT,
                            APP_USBD_CDC_COMM_PROTOCOL_AT_V250
);
#define READ_SIZE 1
static char m_rx_buffer[READ_SIZE];
static char m_tx_buffer[NRF_DRV_USBD_EPSIZE];

②添加usb事件处理程序
           

static bool m_usb_connected = false;
static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                    app_usbd_cdc_acm_user_event_t event)
{
    app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);

    switch (event)
    {
        case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
        {
            //bsp_board_led_on(LED_CDC_ACM_OPEN);

            /*Setup first transfer*/
            ret_code_t ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                                   m_rx_buffer,
                                                   READ_SIZE);
            UNUSED_VARIABLE(ret);
            //ret = app_timer_stop(m_blink_cdc);
            break;
        }
        case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
            if (m_usb_connected)
            {
               // ret_code_t ret = app_timer_start(m_blink_cdc,
                //                                 APP_TIMER_TICKS(LED_BLINK_INTERVAL),
                //                                 (void *) LED_CDC_ACM_CONN);
                //APP_ERROR_CHECK(ret);
            }
            //bsp_board_led_off(LED_CDC_ACM_OPEN);
            break;
        case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
            //bsp_board_led_invert(LED_CDC_ACM_TX);
            break;
        case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
        {
            ret_code_t ret;
            NRF_LOG_INFO("Bytes waiting: %d", app_usbd_cdc_acm_bytes_stored(p_cdc_acm));
            do
            {
                /*Get amount of data transfered*/
                size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);
                NRF_LOG_INFO("RX: size: %lu char: %c", size, m_rx_buffer[0]);

                /* Fetch data until internal buffer is empty */
                ret = app_usbd_cdc_acm_read(&m_app_cdc_acm,
                                            m_rx_buffer,
                                            READ_SIZE);
            } while (ret == NRF_SUCCESS);

            //bsp_board_led_invert(LED_CDC_ACM_RX);
            break;
        }
        default:
            break;
    }
}

static void usbd_user_ev_handler(app_usbd_event_type_t event)
{
    switch (event)
    {
        case APP_USBD_EVT_DRV_SUSPEND:
            //bsp_board_led_off(LED_USB_RESUME);
            break;
        case APP_USBD_EVT_DRV_RESUME:
            //bsp_board_led_on(LED_USB_RESUME);
            break;
        case APP_USBD_EVT_STARTED:
            break;
        case APP_USBD_EVT_STOPPED:
            app_usbd_disable();
            //bsp_board_leds_off();
            break;
        case APP_USBD_EVT_POWER_DETECTED:
            NRF_LOG_INFO("USB power detected");

            if (!nrf_drv_usbd_is_enabled())
            {
                app_usbd_enable();
            }
            break;
        case APP_USBD_EVT_POWER_REMOVED:
            NRF_LOG_INFO("USB power removed");
            //ret_code_t err_code = app_timer_stop(m_blink_cdc);
            //bsp_board_led_off(LED_CDC_ACM_CONN);
            m_usb_connected = false;
            app_usbd_stop();
            break;
        case APP_USBD_EVT_POWER_READY:
        {
            NRF_LOG_INFO("USB ready");
            //ret_code_t err_code = app_timer_start(m_blink_cdc,
             //                                     APP_TIMER_TICKS(LED_BLINK_INTERVAL),
             //                                     (void *) LED_CDC_ACM_CONN);
            m_usb_connected = true;
            app_usbd_start();
        }
            break;
        default:
            break;
    }
}

③在mian函数中添加初始化函数

et_code_t ret;
static const app_usbd_config_t usbd_config = {
        .ev_state_proc = usbd_user_ev_handler
    	};
app_usbd_serial_num_generate();
ret = nrf_drv_clock_init();
ret = app_usbd_init(&usbd_config);
app_usbd_class_inst_t const * class_cdc_acm =app_usbd_cdc_acm_class_inst_get(&m_app_cdc_acm);
ret = app_usbd_class_append(class_cdc_acm);
// Initialize.
nrf_drv_clock_lfclk_request(NULL);
ret = app_usbd_power_events_enable();
while(1)
{
    while (app_usbd_event_queue_process())
    {
        /* Nothing to do */
    }
}

 

(4)修改sdk_config.h
   

使能电源控制
#ifndef NRFX_POWER_ENABLED
#define NRFX_POWER_ENABLED 1
#endif

#ifndef POWER_ENABLED
#define POWER_ENABLED 1
#endif

使能USB
#ifndef USBD_ENABLED
#define USBD_ENABLED 1
#endif

#ifndef APP_USBD_ENABLED
#define APP_USBD_ENABLED 1
#endif

#ifndef APP_USBD_VID
#define APP_USBD_VID 0x1915
#endif

#ifndef APP_USBD_PID
#define APP_USBD_PID 0x521A
#endif

#ifndef APP_USBD_STRING_SERIAL_EXTERN
#define APP_USBD_STRING_SERIAL_EXTERN 1
#endif

#ifndef APP_USBD_STRING_SERIAL
#define APP_USBD_STRING_SERIAL g_extern_serial_number
#endif

#ifndef APP_USBD_CDC_ACM_ENABLED
#define APP_USBD_CDC_ACM_ENABLED 1
#endif

    (5)写指令

app_usbd_cdc_acm_write(&m_app_cdc_acm, p_ble_nus_evt->p_data, p_ble_nus_evt->data_len);

2.移植扫描程序

/**@brief Function for searching a given addr in the advertisement packets.
 *
 * @details Use this function to parse received advertising data and to find a given
 * addr in them.
 *
 * @param[in]   p_adv_report   advertising data to parse.
 * @param[in]   p_addr   name to search.
 * @return   true if the given name was found, false otherwise.
 */
static bool find_peer_addr(const ble_gap_evt_adv_report_t * p_adv_report,
                           const ble_gap_addr_t           * p_addr)
{
    if (p_addr->addr_type == p_adv_report->peer_addr.addr_type)
    {
        if (memcmp(p_addr->addr, p_adv_report->peer_addr.addr,
                   sizeof(p_adv_report->peer_addr.addr)) == 0)
        {
            return true;
        }
    }
    return false;
}


static bool find_adv_name(const ble_gap_evt_adv_report_t * p_adv_report,const char * name_to_find)
{
      uint32_t err_code;
      uint8_array_t adv_data;
      uint8_array_t dev_name;
     
      adv_data.p_data = (uint8_t *)p_adv_report->data;
      adv_data.size = p_adv_report->dlen;

      err_code = adv_report_parse(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME,&adv_data,&dev_name);
      if(err_code == NRF_SUCCESS)
      {
            if(memcmp(name_to_find,dev_name.p_data,dev_name.size)==0)
            {
                  return true;
            }
      }
      return false;
}

static bool find_adv_uuid(const ble_gap_evt_adv_report_t * p_adv_report,const uint16_t uuid_to_find)
{
      uint32_t err_code;
      uint8_array_t adv_data;
      uint8_array_t type_data;

      adv_data.p_data = (uint8_t *)p_adv_report->data;
      adv_data.size = p_adv_report->dlen;

      err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,&adv_data,&type_data);

      if(err_code != NRF_SUCCESS)
      {
            err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,&adv_data,&type_data);
            if(err_code != NRF_SUCCESS)
            {
                  return false;
            }
      }

      for(uint32_t u_index = 0;u_index < (type_data.size/sizeof(uint16_t));u_index++)
      {
            ble_uuid_t extraced_uuid;
            //UUID16_EXTRACT(&extraced_uuid,&type_data.p_data[u_index * sizeof(uint16_t)]);
            sd_ble_uuid_decode(  UUID16_SIZE, &type_data.p_data[u_index * UUID16_SIZE], &extraced_uuid);
            if (err_code == NRF_SUCCESS)
            {
                  if (extraced_uuid.uuid == uuid_to_find)
                  {
                        return true;
                  }
            }
      }
      return false;
}

/**@brief Function for handling the advertising report BLE event.
 *
 * @param[in] p_adv_report  Advertising report from the SoftDevice.
 */
static void on_adv_report(ble_gap_evt_adv_report_t const * p_adv_report)
{
    ret_code_t err_code;
    bool do_connect = false;

    if (is_connect_per_addr && find_peer_addr(p_adv_report, &m_target_periph_addr))
    {
        //NRF_LOG_INFO("Address match, send connect_request.");
        do_connect = true;
    }
    else if (find_adv_name(p_adv_report,m_target_periph_name))
    {
        //NRF_LOG_INFO("Name match, send connect_request.");
        do_connect = true;
        printf("connect\n");
    }
    else if (find_adv_uuid(p_adv_report,m_nus_uuid.uuid))
    {
        //NRF_LOG_INFO("UUID match, send connect_request.");
        do_connect = true;                      
    }
    if (do_connect)
    {
        // Stop scanning.
        (void) sd_ble_gap_scan_stop();
        //m_scan_params.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL;
        // Initiate connection.
        err_code = sd_ble_gap_connect(&p_adv_report->peer_addr,
                                      &m_scan_params,
                                      &m_connection_param);
        //m_whitelist_disabled = false;
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Connection Request Failed, reason %d.", err_code);
        }
    }
    else
    {
        err_code = sd_ble_gap_scan_start(&m_scan_params);
        APP_ERROR_CHECK(err_code);
    }
}
/**@brief Reads an advertising report and checks if a uuid is present in the service list.
 *
 * @details The function is able to search for 16-bit, 32-bit and 128-bit service uuids.
 *          To see the format of a advertisement packet, see
 *          https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm
 *
 * @param[in]   p_target_uuid The uuid to search fir
 * @param[in]   p_adv_report  Pointer to the advertisement report.
 *
 * @retval      true if the UUID is present in the advertisement report. Otherwise false 
 */
static bool is_uuid_present(const ble_uuid_t *p_target_uuid,
                            const ble_gap_evt_adv_report_t *p_adv_report)
{
    uint32_t err_code;
    uint32_t index = 0;
    uint8_t *p_data = (uint8_t *)p_adv_report->data;
    ble_uuid_t extracted_uuid;

    while (index < p_adv_report->dlen)
    {
        uint8_t field_length = p_data[index];
        uint8_t field_type   = p_data[index+1];

        if ( (field_type == BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE)
           || (field_type == BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE)
           )
        {
            for (uint32_t u_index = 0; u_index < (field_length/UUID16_SIZE); u_index++)
            {
                err_code = sd_ble_uuid_decode(  UUID16_SIZE,
                                                &p_data[u_index * UUID16_SIZE + index + 2],
                                                &extracted_uuid);
                if (err_code == NRF_SUCCESS)
                {
                    //printf("16extracted_uuid:%d\n",extracted_uuid.uuid);
                              //printf("extracted_uuid:%d\n",extracted_uuid.type);
                    #if 1
                    if ((extracted_uuid.uuid == p_target_uuid->uuid)
                        && (extracted_uuid.type == p_target_uuid->type))
                    {
                        return true;
                    }
                    #else
                    if ((extracted_uuid.uuid == 0xfef5)
                        && (extracted_uuid.type == 0x01))
                    {
                        return true;
                    }
                    #endif
                }
            }
        }
        else if ( (field_type == BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE)
                || (field_type == BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE)
                )
        {
            for (uint32_t u_index = 0; u_index < (field_length/UUID32_SIZE); u_index++)
            {
                err_code = sd_ble_uuid_decode(UUID16_SIZE,
                                &p_data[u_index * UUID32_SIZE + index + 2],
                                &extracted_uuid);
                if (err_code == NRF_SUCCESS)
                {
                    printf("32extracted_uuid:%d\n",extracted_uuid.uuid);
                    printf("extracted_uuid:%d\n",extracted_uuid.type);
                    if ((extracted_uuid.uuid == p_target_uuid->uuid)
                        && (extracted_uuid.type == p_target_uuid->type))
                    {
                        return true;
                    }
                }
            }
        }
        else if ( (field_type == BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE)
                || (field_type == BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE)
                )
        {
            err_code = sd_ble_uuid_decode(UUID128_SIZE,
                                          &p_data[index + 2],
                                          &extracted_uuid);
            if (err_code == NRF_SUCCESS)
            {
                printf("128extracted_uuid:%d\n",extracted_uuid.uuid);
                printf("extracted_uuid:%d\n",extracted_uuid.type);
                if ((extracted_uuid.uuid == p_target_uuid->uuid)
                    && (extracted_uuid.type == p_target_uuid->type))
                {
                    return true;
                }
            }
        }
        index += field_length + 1;
    }
    return false;
}

3.修改扫描服务UUID

根据设备的服务UUID,修改NUS_BASE_UUID,默认数值为

{{0xfb,0x34,0x9b,0x5f,0x80,0x00,0x00,0x80,0x00,0x10,0x00,0x00,0XF0,0XFF,0x00,0x00}}

   

三.驱动安装

   nRF5_SDK_15.2.0_9412b96\examples\usb_drivers

 

 

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值