精华内容
下载资源
问答
  • 带U盘功能的的USB接口设备已经越来越常见了。如果能够把产品说明书或者产品设备驱动程序做成一个USB CDROM,那该多方便... 请在手边准备好:USB2.0协议,Mass storage协议,SCSI协议(可以忽略)。此外,你需要一个deb
    带U盘功能的的USB接口设备已经越来越常见了。如果能够把产品说明书或者产品设备驱动程序做成一个USB CDROM,那该多方便。
      
       假设:
            你已经有了USB mass storage驱动。你的任务是在此基础上增加一个USB CDROM。
            请在手边准备好:USB2.0协议,Mass storage协议,SCSI协议(可以忽略)。此外,你需要一个debug工具:bushound。  
       步骤:
            1,制作CDROM image文件;
            2,处理usb device request:Get Max Lun
            3,处理SCSI命令:
                            INQUIRY_CMD,
                            READ_TOC_CMD,
                            MODE_SENSE6_CMD,
                            MODE_SENSE10_CMD,
                            READ6_CMD,
                            READ10_CMD
                           
         OK. Let's go!
         
         制作CDROM image文件:google一个PC工具,比如UltraISO,把你需要出现在光盘上的东东统统塞到一个CDROM image文件里面去。
     然后把此文件放到你的文件系统里去。
         A:什么?你木有文件系统?!这么土?
         B:就这么土!
         A:那就放到一个大的const数组里。
         B:呃...为什么放在const?
         A:真不知道?
         B:真的...
         A:打屁屁!
     
        处理从control out endpoint发来的usb device request: "Get Max Lun"(bRequest等于254,usbmassbulk_10.pdf, page 7 )
    此命令在setup阶段收到,主要是向host报告usb mass storage Logic Unit Num。注意Num=总数-1:比如1个U盘和1个CDROM,总数为2,
    应该向host报告2-1=1。这样枚举后,PC出现2个盘符。

        处理如下几条Command Block Wrapper里的SCSI命令。
        setup成功后,SCSI命令经过CBW打包,就可以通过BULK OUT端点发送到设备了(参见usbmassbulk_10.pdf, page 13)。
        SCSI命令处理流程参考usbmassbulk_10.pdf figure1.尤其需要注意的是,一定不要忘记发送CSW!
       
        B: host发给U盘和USB CDROM的命令都是通过CBW进行的。那么怎么知道哪个命令发给U盘,哪个是给USB CDROM的呢?
        A: very good question!
           请查看usbmassbulk_10.pdf, page 13,table5.1。在本案中CBW的bCBWLUN会给你两个值:0和1.
           至于0代表光盘或者1代表光盘,你的地盘你做主(木仓 在手,跟你走)
          
        Go on...
       
        SCSI命令在CBW的bCBWCB头一个字节。SCSI命令很多,但是USB CDROM只需要关注这几个SCSI命令:
       
        INQUIRY_CMD(0x12):“报告老大,我是光盘!”
        把usbcdrom_inquiry_data返回给host,注意第一个字节0x05表示CDROM,这样在PC看到的盘符就是光盘。
        请按照实际需要修改如下数据结构。
       
                       char usbcdrom_inquiry_data[] = {
                         0x05,                        /*= 5 for CDROM; 0 for usb mass storage */
                         0x80,                        /*= RMB BYTE is set by inquiry data */
                         0x02,                        /* ANSI SCSI 2 */
                         0x00,                        /*= Data format = 0,  */
                         0x33,                        /*= Additional length   */
                         0x00, 0x00, 0x00,
                         /* Manufacturer = SOMwireless.com */
                         'S', 'O', 'M', 'w', 'i', 'r', 'e', 'l', 'e', 's', 's', '.', 'c', 'o', 'm', 0x20,
                         /* Product = ISO9660 Image */
                         0x49, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x20, 0x20,
                         /* Revision = 2.31 for new transparent command */
                         0x32, 0x2E, 0x33, 0x31,
                         0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
                         0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
                         0x20,0x20,0x20,0x20
                      };
       
       
        READ_TOC_CMD(0x43):  “报告!目录结构(TOC,Table Of Content)是。。。
        把usbcdrom_read_toc_data返回给host。
        照抄就行了,不用修改。详情参见the f*cking scsi spec.你也可以用光驱读只有一个track的CDROM,用bushound抓包分析。
                       char usbcdrom_read_toc_data[] = {
                         0x00,                       
                         0x12,                        /*number of bytes below */
                         0x01,                        /* first track */
                         0x01,                        /* last track */
                         0x00,                        /*reserved*/
                         0x14,                        //(adr, control)
                         0x01,                        //(track being described)
                         0x00,                        //(reserved)
                         00, 00, 00, 00,              // (start logical block address 0)
                         0x00,              //(reserved)
                         0x14,              //(adr, control)
                         0xAA,                        // (track being described (leadout))
                         0x00,              //(reserved)
                         00, 00, 0xA2, 0x8A           //(start logical block address 41610)
                      };
      
       
        SCSI设备是按照BLOCK来组织的。我们的USB虚拟光驱只是一个文件,是虚拟的CDROM。
        可以按照实际需要定义BLOCK大小(通常是512的整数倍),比如#define CDROM_BLOCK 512
        假设我们的CDROM image文件大小为iso_image_len,那么总的BLOCK数量是block_num = (cdr_iso_len + CDROM_BLOCK - 1)/CDROM_BLOCK
        在SCSI系统中,BLOCK总是从0开始编号的,那么最后一个BLOCK号block_last = block_num - 1;
       
        ok.我们来继续看看这些SCSI命令。
       
        MODE_SENSE6_CMD(0x1A):
        MODE_SENSE10_CMD(0x5A):
        READ_CAPACITY_CMD(0x25):主要向host报告block_last和CDROM_BLOCK滴,只是细节各有不同。
        请注意:SCSI系统采用大端(big endian),通常ARM编译器都将代码编译成小端(little endian),需要把block_last和CDROM_BLOCK变成大端。
       
        USBSDMS_READ_CAPACITY_CMD需要返回的数据结构如下:
                       struct read_cap_data
                       {
                          unsigned long block_last;  //the last block number
                          unsigned long block_len;   //in bytes
                       } ;

        MODE_SENSE6_CMD需要返回的数据结构如下:
                       struct mode_sense6_data
                       {
                           char  length;               //sizeof( struct mode_sense6_data )
                           char  media_type;           //0x05 for CDROM, 0x00 for U disk
                           char  device_specific;      //0x00
                           char  block_descriptor_len; //sizeof( block_last ) + sizeof( block_len )
                           unsigned long block_last;   //the last block number
                           unsigned long block_len;    //in bytes
                       } ;
                      
        MODE_SENSE10_CMD需要返回的数据结构如下:
                       struct mode_sense10_data
                       {
                          unsigned short  length;                    //sizeof( struct mode_sense10_data )
                          char  media_type;                          //0x05 for CDROM, 0x00 for U disk
                          char  write_protect;                       //0x00
                          unsigned short  reserved;                  //0x0000
                          unsigned short  block_descriptor_len;      //sizeof( block_last ) + sizeof( block_len )
                          unsigned long block_last;                  //the last block number
                          unsigned long block_len;                   //in bytes

                       } ;



    需要处理的SCSI命令是:
        READ6_CMD(0x08):
        READ10_CMD(0x28):都是读操作,只是细节略有不同,详见SCSI手册。host传过来的主要参数是:起始的Block号,
        以及需要读取的block数(注意:不是字节数)。
        按照要求传给host就ok了。

    展开全文
  • 52840 USB虚拟串口移植

    千次阅读 2019-06-02 15:00:54
    一.测试的平台 本篇文章主要介绍将52840作为接收器,使用的工程为nRF5_SDK_15.2.0_9412b96\examples...环境:win10,64位,MDK集成开发环境.SDK:nRF5_SDK_15.2协议栈:s132_nrf52_6.1_softdevice.hex.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

     

     

     

    展开全文
  • 本RAR压缩包包含了usb cdc标准协议1.1和1.2两个版本,捆绑下载。是usb驱动之虚拟串口协议开发必备文档,下载方便,请您食用。
  • HS3、HS4、HS5、HS6 USB高速USB虚拟示波器不但具有采集卡的全部功能,还包括二次开发,Labview,Matlab调用,最主要的是 配有一套强大的多功能仪器分析软件包括(数字存储示波器,FFT频谱分析仪,任意波形发生器,瞬态\...

    HS3、HS4、HS5、HS6 USB高速USB虚拟示波器不但具有采集卡的全部功能,还包括二次开发,Labview,Matlab调用,最主要的是

    配有一套强大的多功能仪器分析软件包括(数字存储示波器,FFT频谱分析仪,任意波形发生器,瞬态\连续波形记录仪,数字多用表,I2C协议分析仪,CAN总线分析仪,串口分析仪,J1939解码,SM总线,PM总线,TWI总线,Access总线,音频分析,MIDI、DMX分析等等).下面就几种主要功能进行图解:软件www.pc17.com.cn 下载。

    HS4、HS6 USB示波器,USB虚拟示波器,多通道数据分析软件功能图解
    示波器功能:
    示波器是一种用途十分广泛的电子测量仪器。它能把肉眼看不见的电信号变换成看得见的图像,便于人们研究各种电现象的变化过程。虚拟示波器就是利用现有计算机的强大功能在结合高速采集卡采集信号的能力,可以在屏面上描绘出被测信号的瞬时值的变化曲线。利用示波器能观察各种不同信号幅度随时间变化的波形曲线,还可以用它测试各种不同的电量,如电压、电流、频率、相位差、调幅度等等。示波器用于显示采集信号的电压,与时间(YT)或对另一信号电压(XY)作图。
    多通道示波器软件中的示波器功能可以有一个或多个大的、完全可配置的图形,其中每个图可以显示信号的不同部分。测量的信号可以被复制到参考通道,以比较实时信号与较早测量的信号。

    在示波器中可用光标进行屏幕测量,以及T=0行以指示触发时刻。信号可以给出描述性的名称,并且可以使用图例来简化识别显示的信号。可以放置文本标签来标记信号的有用部分。
    为了显示测量信号的所有细节,示波器在垂直和水平方向上提供无限放大。所有的缩放动作都可以用撤销缩放功能进行。

    Oscilloscope
    HS4、HS6 USB示波器,USB虚拟示波器,多通道数据分析软件功能图解

    频谱分析仪功能

    频谱分析仪是研究电信号频谱结构的仪器,用于信号失真度、调制度、谱纯度、频率稳定度和交调失真等信号参数的测量,可用以测量放大器和滤波器等电路系统的某些参数,频谱分析仪是一种在频域上用图形显示信号幅度与频率关系的仪器。它将显示哪些频率分量存在于信号中,以及这些信号的强度。通过频谱分析仪,信号上的小谐波失真可以比示波器更好地显示。在时域中,正弦波看起来很好,但是在频域中,谐波失真是可见的。
    在示波器上,噪声信号在时域中可以看作完全随机的,在频谱分析仪的频域中可以看出主要存在一个频率。
    在频域中,从调制信号(AM或FM)确定载波频率、调制频率、调制电平和调制失真非常简单。
    HS4、HS6 USB示波器,USB虚拟示波器,多通道数据分析软件功能图解

    万用表功能:

    万用表是对信号进行测量,然后确定该信号的一个或多个特定特性并将它们显示为数值的仪器。
    万用表可用于测量或监视信号的特定特性,如RMS值、频率、最大值等。多通道示波器软件可以具有任意数量的完全可配置的显示器,或者将测量值显示为数字或使用图形万用表显示器。当使用图形万用表显示器时,针对特定特性调整电路时,例如将偏移量调整到零时,它可以非常有帮助观察。
    HS4、HS6 USB示波器,USB虚拟示波器,多通道数据分析软件功能图解
    任意波形发生器功能:

    任意波形发生器是信号源的一种,它具有信号源所有的特点。我们传统认知中都认为信号源主要给被测电路提供所需要的已知信号(各种波形),然后用其它仪表测量感兴趣的参数。现代的任意波形发生器是一种能够产生重复或单次发射信号的仪器。仿真各种测试信号,提供给被测电路,以达到测试的需要在常规函数发生器,信号可以在预定义标准形态中显示正弦波或方波。然而,信号也可以由用户自定义的任意形状。这些信号可以使用多通道示波器软件或外部程序创建,或者可以是先前由示波器测量并加载在发电机中的信号。

    函数发生器是测试电路不可缺少的工具。它可以用于将信号应用于被测试电路,以测试该电路的功能。

    任意波形发生器的一个具体应用是生成模拟某些外部条件而不需要具有实际条件信号的能力。这方面的一个例子是生成先前测量的曲轴传感器信号,并将其应用于汽车的电机管理系统。发动机管理系统中的各个部件可以在没有发动机运行的情况下进行测试。此外,依赖于串行通信信号的系统可以通过这种方式进行测试。
    HS4、HS6 USB示波器,USB虚拟示波器,多通道数据分析软件功能图解

    协议分析仪功能;

    协议分析仪是根据特定协议分析在电子设备之间通信的一个或多个信号的测量仪器。协议分析仪检查信号并对传输的信息进行解码。解码信息可以显示在图形、模拟仪表盘中和列表中。

    在开发通信总线的硬件和/或软件实现时,协议分析仪是一种有用的工具。在调试设备或总线故障时也可以使用。

    多通道示波器软件包含以下协议分析器:

    CAN总线分析仪

    J1939×××

    I2C分析仪

    串行RS232分析器

    SPI×××
    HS4、HS6 USB示波器,USB虚拟示波器,多通道数据分析软件功能图解

    数据记录仪功能

    数据记录仪是一种直接记录数据信号的仪器,用于显示信号电压,其根据时间(Yt)或另一信号电压(XY)绘制。

    数据记录仪是测量缓慢变化的信号的理想仪器,例如房间的温度变化。在捕获整个过程的同时,对输入信号的任何改变都是立即可见的。

    数据记录仪的另一个应用是测量长的非重复信号,例如串行通信信号,该信号将持续太长而不能在硬件的内部存储器中捕获。

    HS4、HS6 USB示波器,USB虚拟示波器,多通道数据分析软件功能图解

    总之HS系列HS4、HS5、HS6虚拟示波器 多通道数据分析软件功能很全面,每一个功能都很完善、强大,几乎能解决任何测量问题,结合HS系列USB数据采集卡的二次开发库,几乎能进行所有采集分析显示。

    支持二次开发。支持的有C/C++、C语言、Delphi、Java、LabVIEW、Matlab、Python、VB.NET等,自由UD库-封装低层协议。

    如果进一步了解请:www.pc17.com.cn

    转载于:https://blog.51cto.com/14035633/2307271

    展开全文
  • 史上最全USB HID开发资料 史上最全USB HID开发资料,悉心整理一个月,亲自测试。涉及STM32 C51 8051F例子都有源码,VC上位机例子以及源码,USB协议,HID协议...内容截图:内容简介:STM32_USB_Demo例子:USB虚拟串...

    史上最全USB HID开发资料

    史上最全USB HID开发资料,悉心整理一个月,亲自测试。 
    涉及STM32 C51 8051F例子都有源码,VC上位机例子以及源码,USB协议,HID协议,USB抓包工具,开发文档,开发过程文档。 
    有了这个资料包,你再说开发不了USB HID,打死我都不信!好资料当然一分都不能少! 
     
    内容截图: 

      
    内容简介:  
    STM32_USB_Demo例子:USB虚拟串口、HID、游戏手柄、USB音频传输等demo源码。 
    STM32_USB_HID_PC_demo:USB HID Demonstrator Release软件和文档 
    STM32_USB_HID_分析:STM32 USB HID 固件学习分析 
    STM32_USB_HID_例子:STM32 USB HID方式收发例子。 
    STM32_USB_HID_学习心得:基于STM32 的USB程序开发笔记、修改STM32的USB例程为自己所用、初涉USB,初学者USB入门总结——枚举。 
    STM32_固件库说明文档:STM32_USB_Demo例子的中文说明文档。 
    STM32F107 鼠标USB改 HID数据发送程序。 
    USB_HID_8051F例子。 
    USB_HID_C51源码。 
    USB_HID_PC_源码:PC端打开HID设备、读写操作实例。 
    USB_HID_PC接收发送工具:用于调试USB HID设备,就相当于串口工具啦。自己写好了HID设备,用它接收发送调试非常方便。 
    USB_HID_PC通信详解:PC端HID读写操作说明。 
    USB_HID_VC++6.0_入门级例子:简单读写USB HID设备,很好的参考作用。 
    USB_HID_VC++6.0_入门级例子开发步骤(图解说明,真详细啊!):一步一步手把把手教你开发VC++6.0 USB HID程序。 
    USB_HID_VC++6.0读写设备源码:简单打开HID设备,读写源码,参考的好例子。 
    USB_HID_VC++6.0源码:出具雏形的VC++6.0 USB HID 工具源码。非常完善了,可以直接当工具使用,关键是有源码! 
    USB_HID_开发过程详细说明:长篇论文一篇,详细说明HID开发过程,包括下位机、上位机、HID驱动的开发,牛! 
    USB_HID协议(英文)。 
    USB_STM32_HID开发笔记:里面有USB设备枚举的详细过程,抓包说明的哦。当然包括开发过程啦。令牌包、握手包、数据包中的数据都看得到。 
    USB_URB分析:抓包工具抓到的数据包的详细解析。 
    USB_VC教程:短论文一篇,用VC++编写USB接口通信程序,简洁扼要说明VC++6.0开发步骤,提纲挈领,值得一看! 
    USB2.0协议(英文)。 
    USB技术规范(中文):中文的USB技术规范说明,中文的! 
    USB抓包软件:两种抓包工具,bushound和usbtrace。都是破解版,哈哈,自己偷着乐吧! 
    深入解析STM32_USB库:STM32 USB的库说明。 
     
    上述出处:http://bbs.baiquwang.com/read.php?tid=3626  但是没有给资料
    资料是我在上网搜的
     
     
     

    转载于:https://www.cnblogs.com/flyheart33/p/3603381.html

    展开全文
  • STM32 USB 系列之 虚拟串口(VPC)

    千次阅读 2020-05-14 00:20:22
    STM32 USB系列之虚拟串口 这段时间缓慢更新一下stm32 usb系列的博客,前段时间在多个地方零零散散的学习和使用USB协议,在网上查找的资料也是零零散散的,整理一下写成博客。 1. 开发环境 使用stm32f103c8t6,HAL库...
  • 云桌面/虚拟开发工程师招聘要求

    千次阅读 2017-08-25 10:06:46
    岗位要求1: 三年以上Windows C/C++开发工作经验 熟练掌握windows进程、线程、内存管理、消息机制,熟悉网络编程以及...有云计算相关工作经验及spice tools、qxl驱动、virtio驱动、USB驱动开发经验者优先岗位要求2:
  • Linux 蓝牙协议栈的USB+设备驱动

    热门讨论 2010-12-28 15:16:53
    给出实现蓝牙设备驱动的重要数据结构和流程,并总结Linux 下开发蓝牙USB 设备驱动的一般方法和关键技术。 关键词:Linux 系统;蓝牙协议栈;设备驱动 USB Device Driver for Linux Bluetooth Stack LIANG Jun-xue...
  •   这些芯片就是用来连接PC和单片机的桥梁,完成ttl通信协议usb通信协议的相互转换。完成这个功能就需要使用这一类物理芯片,一般情况下就是一个芯片完成一路串口的转化。多路串口也有,不过价格会比较贵。   ...
  • STM32-USB-HID-PC上位机源码

    热门讨论 2014-09-03 11:41:47
    STM32 USB虚拟串口,hid,游戏手柄等源码 stm32 usb hid 收发源码 STM32-USB-HID例子,学习心得,分析说明文档,开发笔记,源码 STM32-usb-hid双向数据传输 usb协议 USB HID PC上位机源码,通信详解 USB HID协议 USB...
  • USB DataPipe是新大陆公司自定义协议,采用这种方式的优点是数据传输速度快,且通过对主机端使用此协议开发库的调用可以快速集成到应用系统中。 3、USB虚拟串口 当使用USB连接,而同时又希望主机端采用串口方式...
  • jsr80 java 访问 usb

    2015-02-14 08:52:01
    正如您所看到的,像 USB 这样的协议为使用 Java 这种强调平台和硬件无关性的语言的开发人员提出了挑战。现在让我们看两个试图解决这个问题的项目。 回页首 jUSB API jUSB 项目是由 Mojo Jojo 和 David Brownell 于 ...
  • 详细的开发协议文档,BIOVO MINI提供2个UART和1个USB接口与主机通讯,UART接口为TTL异步信号,USB虚拟CD免驱动。
  • USB驱动之CDC类的介绍与应用20160905

    千次阅读 2019-02-01 11:38:02
    我们知道USB可以用来接U盘,声卡,读卡器,鼠标键盘等等,这里主要是讲USB接口用来当虚拟串口使用,这个VCP(虚拟串口)是通过USB的CDC(通信设备类)类来实现的,本文是基于CPU是STM32F4的USB来讲解的: ...
  • usb_bootloader.zip

    2020-04-29 21:45:33
    Bootloader模拟成MSD设备,构建FAT16虚拟文件系统,U盘名为”Bootloader”,容量为100M,但具体实际可用空间,根据用户MCU来确定,建议不要复制除APP之外的无关文件 当用户复制文件到U盘时,Bootloader会判断文件...
  • 目前仪器设备大都采用RS232接口与计算机通信,但随着...另一种方案是采用USB/RS232桥接器件如CP2102,CP2103进行设计,计算机通过USB接口虚拟一个RS232接口,与传统设备器件连接,设备对计算机接口的形式为USB接口。
  • 可以根据协议,将自己开发的硬件加入我们的软件环境。  多功能虚拟信号分析仪 v3.6.0.0更新:  1、重新设计简化版,增加颜色调整,波形移动等,易用性大幅提升  2、重新设计专业版,去除声卡、串口捕获,让...
  • wince系统盘点机一般简单应用都采用USB方式...本方案采用 socket-tcp协议,改用WIFI网络模式上传文件,支持多机器同时上传,提供wince端二次开发的dll,以及开发使用示范代码。免费,无任何限制。从此USB线 bye 了!
  • J-Link简介 ...其连接到计算机用的是USB接口,而到目标板内部用的还是jtag协议。它完成了一个从软件到硬件转换的工作。配合IAR EWAR,ADS,KEIL,WINARM,RealView等集成开发环境支持所有ARM7/ARM9/ARM...
  • 14.2为Android开发虚拟驱动virtualio 14.3 Android集成C程序访问virtualio 14.4 Android通过HAL访问virtualio 14.4.1 virtualio HAL模块实现 14.4.2实现访问virtualio HAL模块JN 14.4.3在Framework层增加virtualio...
  • 其连接到计算机用的是USB接口,而到目标板内部用的还是jtag协议。它完成了一个从软件到硬件转换的工作。配合IAR EWAR,ADS,KEIL,WINARM,RealView等集成开发环境支持所有ARM7/ARM9/ARM11,Cortex M0/M1/M3/M4, C....
  • GPIB 即IEEE-488,上世纪末为自动测试设备开发的总线标准,至今仍广泛使用,最多能连接14个设备。  visa 虚拟仪器软件架构(Virtual Instrument Software Architecture),PC与仪器通信API,各家公司...
  • PCI、USB虚拟串口、虚拟摄像头、SDIO等驱动程序的开发,归纳了多种调试驱动程序的高级技巧,如 用WinDBG和VMWARE软件对驱动进行源码级调试,深入Windows操作系统的底层和内核,透析Windows驱动 开发的本质。 ...
  •  从Windows最基本的两类驱动程序的编译、安装、调试入手讲解,非常容易上手,用实例详细讲解PCI、USB虚拟串口、虚拟摄像头、SDIO等驱动程序的开发,归纳了多种调试驱动程序的高级技巧,如用WinDBG和VMWARE软件对...
  • 版权声明:本文为博主原创文章,欢迎转载,并请注明出处。... 不少仪器/设备都提供了数据采集的接口,其中不少是串口或网络的MODBUS/TCP协议。 串口是比较简单,但是较为古老的接口...还好有前辈开发虚拟串口软件...

空空如也

空空如也

1 2 3 4
收藏数 77
精华内容 30
关键字:

usb虚拟协议开发