精华内容
下载资源
问答
  • Android 7.0 本文章可以参考解决绕过android下apk使用usb设备权限查询相应问题,自动获取usb权限,主要是在Android 7.0系统上,当插入USB 耳机或者音频输入设备的时候,就会报出如下对话框和消息提示,在我们开发的...

    Android 7.0 本文章可以参考解决绕过android下apk使用usb设备权限查询相应问题,自动获取usb权限,主要是在Android 7.0系统上,当插入USB 耳机或者音频输入设备的时候,就会报出如下对话框和消息提示,在我们开发的时候很不爽,需要手动去点很麻烦,如下图所示:

    提示消息即Toast,当插入USB耳机或者麦时就会弹出“USB音频输入设备接入”,当拔掉时就会弹出“切换之原始的默认通道”

    这个问题需要修改系统源码其位置在Android 7.0

    /android/device/softwinner/common/addons/framework/audio/java/AudioManagerPolicy.java

    这AudioManagerPolicy.java就是就是相关的代码源文件,而在此之前还有个xml文件来说明那就是strings_custom.xml

    其实这个位置的方法很简单只要在源码目录下使用命令:

    grep 'USB音频输入设备接入' ./ -Rn

    就能找到strings_custom.xml,其内容如下所示:

    <resources xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
        <!-- support the mouse mode -->
        <string name="enter_key_mouse_mode">进入鼠标模式</string>
        <string name="exit_key_mouse_mode">退出鼠标模式</string>
        <string name="title_key_mouse_mode">鼠标模式</string>
        <string name="detail_key_mouse_mode">当前处于鼠标模式</string>
    
        <!-- add by chenjd, message for audio -->
        <string name="usb_audio_out_plug_in_title">"USB音频输出设备接入"</string>
        <string name="usb_audio_plug_in_message">"可在‘通用设置-高级设置-提示音和通知-音频输出模式‘选择输出通道"</string>
        <string name="usb_audio_plug_out_message">"切换至原始的默认通道"</string>
        <string name="usb_audio_out_plug_out_title">"USB音频输出设备拔出"</string>
        <string name="usb_audio_in_plug_in_title">"USB音频输入设备接入"</string>
        <string name="usb_audio_in_plug_out_title">"USB音频输入设备拔出"</string>
        <string name="headphone_plug_in_title">"耳机插入"</string>
        <string name="headphone_plug_out_title">"耳机拔出"</string>
        <string name="headphone_plug_in_message">"切换至耳机"</string>
        <string name="headphone_plug_out_message">"切换至原始的默认通道"</string>
        <string name="usb_output_title">"USB音频输出选择"</string>
        <string name="usb_output_message">"USB音频输出设备已接入,请选择是否切换到USB音频设备输出,\n在 %1$s 秒后自动切换到USB音频设备"</string>
        <string name="usb_yes">"是"</string>
        <string name="usb_no">"否"</string>
        <string name="ota_title">"升级提示"</string>
        <string name="ota_accept">"确定"</string>
        <string name="ota_reject">"取消"</string>
        <string name="ota_error_title">"错误提示"</string>
    </resources>

    看到没有所有字符串对应的变量都列举出来了,在根据对应的字符串变量,来搜索Java源码文件:

    grep 'usb_audio_in_plug_in_title' ./ -Rn

    这样就找到了AudioManagerPolicy.java,其他Android系统版本也可以用这个方法去做,下面来看这个源码怎么修改,其实很简单,看字面意思就能看懂,先去掉对话框

    1.在代码的527行有段方法:private void chooseUsbAudioDeviceDialog(final ArrayList<String> usb_device)这个方法就是弹出的对话框,下面来分析以下这个对话框:

     private void chooseUsbAudioDeviceDialog(final ArrayList<String> usb_device)
        {
            String str = mCtx.getResources().getString(com.android.internal.R.string.usb_output_message);
    //获取对话框的内容,也就是在上面那个xml内usb_output_message对应的:USB音频输出设备已接入,请选择是否切换到USB音频设备输出,\n在 %1$s 秒后自动切换到USB音频设备
            alertDialog = new AlertDialog.Builder(mCtx).//创建对话框
                    setTitle(com.android.internal.R.string.usb_output_title).//设置对话框的标题为"USB音频输出选择"
                    setMessage(String.format(str, Integer.toString(USB_TOAST_TIME))).
                    setPositiveButton(com.android.internal.R.string.usb_yes, new DialogInterface.OnClickListener() {//设置当点击“是”按钮的监听时间
                         @Override
                         public void onClick(DialogInterface dialog, int which) {
                               // TODO Auto-generated method stub
                               mAudioManagerEx.setAudioDeviceActive(usb_device, AudioManagerEx.AUDIO_OUTPUT_ACTIVE);//设置为usb为音频输入设备
                         }
                    }).
                    setNegativeButton(com.android.internal.R.string.usb_no, new DialogInterface.OnClickListener() {/设置当点击“否”按钮的监听时间
                         @Override
                         public void onClick(DialogInterface dialog, int which) {
                               // TODO Auto-generated method stub
                               //Log.v(TAG, "setNegativeButton ");
                               String message = mCtx.getResources().getString(R.string.usb_audio_plug_in_message);
                               toastPlugInNotification(message, AUDIO_OUT_NOTIFY);
    //点击“否”,弹出提示消息:"可在‘通用设置-高级设置-提示音和通知-音频输出模式‘选择输出通道"
                         }
                    }).
                    create();
            alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
            alertDialog.show();//喷出对话框
            new AsyncTask() {
                @Override
                protected Object doInBackground(Object... arg0) {
                    int time = USB_TOAST_TIME;//设置10秒等待时间
                    while(time >= 0 && alertDialog != null && alertDialog.isShowing()){
                        publishProgress(time);
                        try {
                            Thread.sleep(1000);
                        } catch(Exception e) {
                            // do nothing
                        }
                        time--;
                    }
                    return null;
                }
                @Override
                protected void onPostExecute(Object result) {//当超过10秒没有点击时触发
                    super.onPostExecute(result);
                    if (alertDialog != null && alertDialog.isShowing()) {
                        alertDialog.dismiss();
                        mAudioManagerEx.setAudioDeviceActive(usb_device, AudioManagerEx.AUDIO_OUTPUT_ACTIVE);//设置为USB 设备为输入设备,这个逻辑很关键,是默认的情况,当去掉对话框时这个陆机要保留
                        alertDialog = null;
                    }
                }
                @Override
                protected void onProgressUpdate(Object... values) {
                    super.onProgressUpdate(values);
                    int time = (Integer)values[0];
                    String str = mCtx.getResources().getString(com.android.internal.R.string.usb_output_message);
                    if(alertDialog != null)
                        alertDialog.setMessage(String.format(str, Integer.toString(time)));
                }
           }.execute();
        }
    

    根据上面的对话框的代码,我们知道,对话框是默认点击“是”按钮的因此,我们需要在代码中也要保持这个逻辑:

    那么这个对话框方法调用的位置在方法handleExternalDevice内,这个代码看着很长,但很简单,我就不分析了,把主要的贴出来,在634行调用了这个方法因此只要注释掉并添加一行:

     //chooseUsbAudioDeviceDialog(audio_out);
    mAudioManagerEx.setAudioDeviceActive(audio_out, AudioManagerEx.AUDIO_OUTPUT_ACTIVE);

    添加的就是跳过对话框而直接设置usb音频设备为输入设备

    2.去掉相关的提示信息

    在上面去掉对话框是就已经去掉了 

    <string name="usb_audio_plug_in_message">"可在‘通用设置-高级设置-提示音和通知-音频输出模式‘选择输出通道"</string>

    对方法handleExternalDevice分析可知,每一个对应的消息都会调用方法 toastPlugInNotification和toastPlugOutNotification

    这两个方法从字面意思就知道是:挂在消息通知和挂出消息通知,源码如下:

    private void toastPlugOutNotification(String title,String mng, int id){
    
            NotificationManager notificationManager = (NotificationManager) mCtx
                .getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.cancel(id);
            handleToastMessage(mng);
        }
    
        private void toastPlugInNotification(String title, int id){
            Notification notification = new Notification(com.android.internal.R.drawable.stat_sys_data_usb,
                    title,System.currentTimeMillis());
            String contentTitle = title;
            String contextText = title;
            notification.setLatestEventInfo(mCtx, contentTitle, contextText, null);
    
            notification.defaults &= ~Notification.DEFAULT_SOUND;
            notification.flags = Notification.FLAG_AUTO_CANCEL;
    
            NotificationManager notificationManager = (NotificationManager) mCtx
                .getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.notify(id, notification);
    
            handleToastMessage(title);
        }
    

    其实到这里解决消息通知的方法就有很多了,你可以在AudioManagerPolicy.java搜索这两个方法,只要调用了这两个方法,就统统注释了就可以了,但是我在此的 做法是去研究这段代码,这两个代码内都有方法handleToastMessage,而这个方法如下:

     private void handleToastMessage(String message){
            if(mHandler == null) return;
            Message mng = mHandler.obtainMessage();
            mng.obj = message;
            mHandler.sendMessage(mng);//发送消息
        }

    然后去找mHandler如下:

    private void toastMessage(String message){//产生Toast,并喷发出来
            Toast.makeText(mCtx, message, Toast.LENGTH_LONG).show();
        }
     private Handler mHandler = new Handler(){
            @Override
            public void handleMessage(Message msg){
                String message = (String)msg.obj;
                //toastMessage(message);//屏蔽这个Toast的喷发
            }
        };

    因此我们就可以找到着个最内层的一句话,Toast.makeText(mCtx, message, Toast.LENGTH_LONG).show(); 屏蔽掉,所有的相关音频输入的消息通知都没有了

    展开全文
  • VGA输入接口:VGA 接口采用非对称分布的15pin 连接方式,其工作原理:是将显存内以数字格式存储的图像( 帧) 信号在RAMDAC 里经过模拟调制成模拟高频信号,然后再输出到等离子成像,这样VGA信号在输入端(LED显示屏内)...


    VGA输入接口:VGA 接口采用非对称分布的15pin 连接方式,其工作原理:是将显存内以数字格式存储的图像( 帧) 信号在RAMDAC 里经过模拟调制成模拟高频信号,然后再输出到等离子成像,这样VGA信号在输入端(LED显示屏内) ,就不必像其它视频信号那样还要经过矩阵解码电路的换算。从前面的视频成像原理可知VGA的视频传输过程是最短的,所以VGA 接口拥有许多的优点,如无串扰无电路合成分离损耗等。

     

    DVI输入接口:DVI接口主要用于与具有数字显示输出功能的计算机显卡相连接,显示计算机的RGB信号。DVI(Digital Visual Interface)数字显示接口,是由1998年9月,在Intel开发者论坛上成立的数字显示工作小组(Digital Display Working Group简称DDWG),所制定的数字显示接口标准。

    DVI数字端子比标准VGA端子信号要好,数字接口保证了全部内容采用数字格式传输,保证了主机到监视器的传输过程中数据的完整性(无干扰信号引入),可以得到更清晰的图像。

     

    标准视频输入(RCA)接口:也称AV 接口,通常都是成对的白色的音频接口和黄色的视频接口,它通常采用RCA(俗称莲花头)进行连接,使用时只需要将带莲花头的标准AV 线缆与相应接口连接起来即可。AV接口实现了音频和视频的分离传输,这就避免了因为音/视频混合干扰而导致的图像质量下降,但由于AV 接口传输的仍然是一种亮度/色度(Y/C)混合的视频信号,仍然需要显示设备对其进行亮/ 色分离和色度解码才能成像,这种先混合再分离的过程必然会造成色彩信号的损失,色度信号和亮度信号也会有很大的机会相互干扰从而影响最终输出的图像质量。AV还具有一定生命力,但由于它本身Y/C混合这一不可克服的缺点因此无法在一些追求视觉极限的场合中使用。

     

    S视频输入:S-Video具体英文全称叫Separate Video,为了达到更好的视频效果,人们开始探求一种更快捷优秀清晰度更高的视频传输方式,这就是当前如日中天的S-Video(也称二分量视频接口),Separate Video 的意义就是将Video 信号分开传送,也就是在AV接口的基础上将色度信号C 和亮度信号Y进行分离,再分别以不同的通道进行传输,它出现并发展于上世纪90年代后期通常采用标准的4芯(不含音效) 或者扩展的7芯( 含音效)。带S-Video接口的显卡和视频设备( 譬如模拟视频采集/ 编辑卡电视机和准专业级监视器电视卡/电视盒及视频投影设备等) 当前已经比较普遍,同AV 接口相比由于它不再进行Y/C混合传输因此也就无需再进行亮色分离和解码工作,而且使用各自独立的传输通道在很大程度上避免了视频设备内信号串扰而产生的图像失真,极大地提高了图像的清晰度,但S-Video 仍要将两路色差信号(Cr Cb)混合为一路色度信号C,进行传输然后再在显示设备内解码为Cb 和Cr 进行处理,这样多少仍会带来一定信号损失而产生失真(这种失真很小但在严格的广播级视频设备下进行测试时仍能发现) ,而且由于Cr Cb 的混合导致色度信号的带宽也有一定的限制,所以S -Video 虽然已经比较优秀但离完美还相去甚远,S-Video虽不是最好的,但考虑到目前的市场状况和综合成本等其它因素,它还是应用最普遍的视频接口。

     

    视频色差输入接口:目前可以在一些专业级视频工作站/编辑卡专业级视频设备或高档影碟机等家电上看到有YUV YCbCr Y/B-Y/B-Y等标记的接口标识,虽然其标记方法和接头外形各异但都是指的同一种接口色差端口( 也称分量视频接口) 。它通常采用YPbPr 和YCbCr两种标识,前者表示逐行扫描色差输出,后者表示隔行扫描色差输出。由上述关系可知,我们只需知道Y Cr Cb的值就能够得到G 的值( 即第四个等式不是必要的),所以在视频输出和颜色处理过程中就统一忽略绿色差Cg 而只保留Y Cr Cb ,这便是色差输出的基本定义。作为S-Video的进阶产品色差输出将S-Video传输的色度信号C分解为色差Cr和Cb,这样就避免了两路色差混合解码并再次分离的过程,也保持了色度通道的最大带宽,只需要经过反矩阵解码电路就可以还原为RGB三原色信号而成像,这就最大限度地缩短了视频源到显示器成像之间的视频信号通道,避免了因繁琐的传输过程所带来的图像失真,所以色差输出的接口方式是目前各种视频输出接口中最好的一种。

     

    HDMI接口:HDMI是基于DVI(Digital Visual Interface)制定的,可以看作是DVI的强化与延伸,两者可以兼容。HDMI在保持高品质的情况下能够以数码形式传输未经压缩的高分辨率视频和多声道音频数据,最高数据传输速度为5Gbps。HDMI能够支持所有的ATSC HDTV标准,不仅可以满足目前最高画质1080p的分辨率,还能支持DVD Audio等最先进的数字音频格式,支持八声道96kHz或立体声192kHz数码音频传送,而且只用一条HDMI线连接,免除数码音频接线。同时HDMI标准所具备的额外空间可以应用在日后升级的音视频格式中。与DVI相比HDMI接口的体积更小而且可同时传输音频及视频信号。DVI的线缆长度不能超过8米否则将影响画面质量,而HDMI基本没有线缆的长度限制。只要一条HDMI缆线,就可以取代最多13条模拟传输线,能有效解决家庭娱乐系统背后连线杂乱纠结的问题。HDMI可搭配宽带数字内容保护(High-bandwidth DigitalContent Protection;HDCP),以防止具著作权的影音内容遭到未经授权的复制。正是由于HDMI内嵌HDCP内容保护机制,所以对好莱坞具有特别的吸引力。HDMI规格包含针对消费电子用的Type A连接器和PC用的Type B连接器两种,相信不久HDMI将会被PC业界采用。

     

    BNC 端口:通常用于工作站和同轴电缆连接的连接器,标准专业视频设备输入、输出端口。BNC电缆有5个连接头用于接收红、绿、蓝、水平同步和垂直同步信号。BNC接头有别于普通15针D-SUB标准接头的特殊显示器接口。由R、G、B三原色信号及行同步、场同步五个独立信号接头组成。主要用于连接工作站等对扫描频率要求很高的系统。BNC接头可以隔绝视频输入信号,使信号相互间干扰减少,且信号频宽较普通D-SUB大,可达到最佳信号响应效果。

     

    RS232C串口:RS-232C标准(协议)的全称是EIA-RS-232C标准,其中EIA(Electronic IndustryAssociation)代表美国电子工业协会,RS(ecommeded standard)代表推荐标准,232是标识号,C代表RS232的最新一次修改(1969),在这之前,有RS232B、RS232A。。它规定连接电缆和机械、电气特性、信号功能及传送过程。常用物理标准还有有EIA&#0;RS-232-C、EIA&#0;RS-422-A、EIA&#0;RS-423A、EIA&#0;RS-485.这里只介绍EIA&#0;RS-232-C(简称232,RS232)。计算机输入输出接口,是最为常见的串行接口,RS-232C规标准接口有25条线,4条数据线、11条控制线、3条定时线、7条备用和未定义线,常用的只有9根,常用于与25-pin D-sub端口一同使用,其最大传输速率为20kbps,线缆最长为15米。RS232C端口被用于将计算机信号输入控制LED显示屏。

     

    AV接口又称(RCARCA)可以算是TV的改进型接口,外观方面有了很大不同。分为了3条线,分别为:音频接口(红色与白色线,组成左右声道)和视频接口(黄色)。

     

    由于AV输出仍然是将亮度与色度混合的视频信号,所以依旧需要显示设备进行亮度和色彩分离,并且解码才能成像。这样的做法必然对画质会造成损失,所以AV接口的画质依然不能让人满意。在连接方面非常的简单,只需将3种颜色的AV线与电视端的3种颜色的接口对应连接即可。

    总体来说,AV接口实现了音频和视频的分离传输,在成像方面可以避免音频与视频互相干扰而导致的画质下降。AV接口在电视与DVD连接中使用的比较广,是每台电视必备的接口之一。

     

    USB是英文Universal Serial Bus的缩写,中文含义是“通用串行总线”。它是一种应用在PC领域的新型接口技术。早在1995年,就已经有PC机带有USB接口了,但由于缺乏软件及硬件设备的支持,这些PC机的USB接口都闲置未用。1998年后,随着微软在Windows 98中内置了对USB接口的支持模块,加上USB设备的日渐增多,USB接口才逐步走进了实用阶段。

     

    这几年,随着大量支持USB的个人电脑的普及,USB逐步成为PC机的标准接口已经是大势所趋。在主机(host)端,最新推出的PC机几乎100%支持USB;而在外设(device)端,使用USB接口的设备也与日俱增,例如数码相机、扫描仪、游戏杆、磁带和软驱、图像设备、打印机、键盘、鼠标等等。

     

    USB设备之所以会被大量应用,主要具有以下优点:

     

    1、可以热插拔。这就让用户在使用外接设备时,不需要重复“关机à将并口或串口电缆接上à再开机”这样的动作,而是直接在PC开机时,就可以将USB电缆插上使用。

     

    2、携带方便。USB设备大多以“小、轻、薄”见长,对用户来说,同样20G的硬盘,USB硬盘比IDE硬盘要轻一半的重量,在想要随身携带大量数据时,当然USB硬盘会是首要之选了。

     

    3、标准统一。大家常见的是IDE接口的硬盘,串口的鼠标键盘,并口的打印机扫描仪,可是有了USB之后,这些应用外设统统可以用同样的标准与PC连接,这时就有了USB硬盘、USB鼠标、USB打印机,等等。

     

    4、可以连接多个设备。USB在PC上往往具有多个接口,可以同时连接几个设备,如果接上一个有4个端口的USB HUB时,就可以再连上4个USB设备,以此类推,尽可以连下去,将你家的设备都同时连在一台PC上而不会有任何问题(注:最高可连接至127个设备)。


    展开全文
  • 大众奥迪DIY数码碟盒增加USB和蓝牙播放音乐功能前言1、设计指标2、方案设计2.1、外壳选择2.2、蓝牙方案2.3、MCU方案3、原理图设计4、PCB设计5、程序设计6、打板焊接调试7、模块引脚及功能7.1、模块引脚定义7.2、模块...

    全网首发!大众奥迪DIY数码碟盒增加USB和蓝牙播放音乐功能

    前言

    ​ 1、之前写过两篇关于车机增加音频输入的方法,第一种方式:车载音频处理芯片一般和主CPU之间是IIC通信协议,而IIC总线物理层运行在总线上挂载多个设备,通过监听IIC总线发现,只有音频信号发生改变的时候主芯片才会控制音频处理芯片,根据这个原理,卡硬件bug模拟主CPU 的指令,强制控制音频处理器切换输入信号源切换到碟盒音频上,这时主机即可播放碟盒信道的音频了。链接如下:

    07宝来经典车机CD收音机(RC668)改装增加蓝牙播放音乐
    ​ 2、在这之后虽然可以听音乐了,但是当时选择的蓝牙音质一般,而且蓝牙输出带载能力较弱,导致输出声音小。为了解决这问题,所以研究了碟盒的和主机的通信协议,通过抓取之间的数据,分析出了通信格式,进而可以通过单片机模拟碟盒和主机通信,当主机按下按钮时,单片机根据协议解析出内容,就可以知道哪个按钮按下,然后控制蓝牙动作。链接如下

    全网首发!老大众奥迪碟盒通信协议破解,可以模拟数码碟盒,外接AUX蓝牙U盘等音频设备
    ​ 3、我以为我的教程写的和通俗易懂了,但是有一些朋友找到我,让我教他们怎么改装,这时我意识到一个问题,我认为简单的事,对于爱好者来说还是很难,所以综合了一些朋友的意见,觉得做一个可以使用蓝牙和U盘播放音乐的模块。

    1、设计指标

    ​ 和一些朋友聊天,又调查了一番发现,有此需求的人大多是喜欢折腾有一定动手能力的人,但是老车嘛,又不想投入太多的资金改装,毕竟现在也有成熟产品在卖。我个人喜欢用蓝牙听音乐,导航啥的,可是有些朋友又喜欢用U盘听歌,AUX也有一些再用。

    ​ 因为我很少用AUX听歌所以决定把AUX砍掉,这样就可以减小电路板体积和系统复杂度(喜欢AUX的朋友 不要着急 有时间会出AUX版本的)。高音质高性能意味着高成本,大家都希望功能多成本少,体积还小,但是现实是做不到的,性能和是成本正比的。在结合朋友的意见,最终要实现如下功能。

    在这里插入图片描述
    模块规格如下:

    输入电压11V-14.6V/DC
    工作电流200mA
    工作温度-40℃~+80℃
    信噪比95dB
    频率响应20HZ-20KHZ

    2、方案设计

    2.1、外壳选择

    ​ 经过几天筛选找到了下面这个外壳 ,长x宽x高 = 6x4x2 CM 还算小巧,上面有一个按键孔和一个5mmLED孔,安排一些功能将这两个孔堵上,侧面是MINIUSB和10PIN牛角座。
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

    2.2、蓝牙方案

    ​ 蓝牙选用的是定制款WR201蓝牙双模音频芯片,音频程序深度优化,减少底噪。片内集成USB 2.0主站,可以读取U盘内的音频文件进行播放,真是性能小钢炮,性价比特别高。
    在这里插入图片描述

    2.3、MCU方案

    ​ 数码碟盒和主机通信频率并不高,所以IO模拟输出时序,用定时器捕获分析输入的时序,加加上串口,IO口就可以了,根据这个需求,选择了NV32F102,至于为啥选这个呢,因为最近申请了一批样片正好这个芯片符合要求,顺道帮厂家宣传下。
    在这里插入图片描述

    3、原理图设计

    根据以上需求,绘制原理图,放个 按钮 放个LED指示灯,把外壳上的窟窿堵上。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    ​ 要注意的事,这里面使用78l05线性稳压降压, 由于压差比较大,78l05发热会很严重所以串联一个功率电阻,分担耗散功能,提供系统的稳定性。

    4、PCB设计

    在这里插入图片描述
    在这里插入图片描述
    要想音质好,地分割隔离少不了,再打上多多的过孔,特批是射频部分一定要多打孔。
    在这里插入图片描述

    放上伪3D效果图。

    5、程序设计

    ​ 1、移植OSAL系统框架到NV32F102上,如图所示。替换timer.c定时器的内容。移植基本工作完成。
    在这里插入图片描述

    void PIT1_IRQHandler(void)
    {
    	
    
    	PIT_ChannelClrFlags(PIT_CHANNEL1); 
      osal_update_timers();
    
    }
    
    /**
     * @brief 硬件定时器初始化,设定系统时钟
     */
    void OSAL_TIMER_TICKINIT(void)
    {
    	uint32_t        u32LoadValue0;     
        PIT_ConfigType  sPITConfig;    
        PIT_ConfigType  *pPIT_Config   =&sPITConfig; 
    
        u32LoadValue0   = 48000 - 1;          //定时器时钟为总线时钟48M,定时1S
      
        pPIT_Config->u32LoadValue      = u32LoadValue0;
        pPIT_Config->bFreeze           = FALSE;    
        pPIT_Config->bModuleDis        = FALSE;    
        pPIT_Config->bInterruptEn      = TRUE;    
        pPIT_Config->bChainMode        = FALSE; 
        pPIT_Config->bETMerEn          = TRUE;     // 打开定时器
    
        PIT_Init(PIT_CHANNEL1, pPIT_Config);          
    
    }
    
    

    ​ 2、移植底层驱动

    根据上一篇博文的时序编写底层驱动程序,使用NV32f102 ETM2模块用来捕获输入脉冲。

    初始化

        SIM->SCGC  |= SIM_SCGC_ETM2_MASK;//选通ETM1门控时钟
    	ETM2->CONTROLS[5].CnSC |= ETM_CnSC_ELSB_MASK; 								//下降沿沿捕捉
    	ETM_ClockSet(ETM2, ETM_CLOCK_SYSTEMCLOCK, 					ETM_CLOCK_PS_DIV16); //ETM1时钟设置-48M	/16 = 3M	
    	NVIC_EnableIRQ(ETM2_IRQn);
    	ETM2->CONTROLS[5].CnSC |= ETM_CnSC_CHIE_MASK;//使能中断
    	  ETM_EnableOverflowInt(ETM2);									//开启TOF溢出中断
    

    捕获脉冲

    /*捕捉中断*/
    void ETM2_IRQHandler(void)
    {
    	 if(ETM2->SC & ETM_SC_TOF_MASK)	//清除溢出标志位
        {
             ETM2->SC &= ~ETM_SC_TOF_MASK;
    		TIM_ICUserValueStructure.Capture_Period ++;        
        }
    
    	if(ETM2->CONTROLS[5].CnSC & ETM_CnSC_CHF_MASK )//输入信号边沿变化
    	{
    		ETM2->CONTROLS[5].CnSC &= ~ETM_CnSC_CHF_MASK;
            if ( TIM_ICUserValueStructure.Capture_StartFlag == 0 )         // 第一次捕获下降沿捕获
            {
                // 计数器清0
    		ETM2->CNT=0; //清零计数器
                // 自动重装载寄存器更新标志清0
            TIM_ICUserValueStructure.Capture_Period = 0;
          // 存捕获比较寄存器的值的变量的值清0            
            TIM_ICUserValueStructure.Capture_CcrValue = 0;
                // 当第一次捕获到下降沿之后,就把捕获边沿配置为上升沿
    		ETM2->CONTROLS[5].CnSC &= ~ETM_CnSC_ELSB_MASK; 								//去除下降沿沿捕捉
    		ETM2->CONTROLS[5].CnSC |= ETM_CnSC_ELSA_MASK; 								//上升沿沿捕捉
          // 开始捕获标准置1            
             TIM_ICUserValueStructure.Capture_StartFlag = 1;
            }
            // 上升沿捕获中断
            else // 第二次捕获
            {
          // 获取捕获比较寄存器的值,这个值就是捕获到的低电平的时间的值
    														     		TIM_ICUserValueStructure.Capture_CcrValue = ETM2->CONTROLS[5].CnV;
    capturedLowPulse(TIM_ICUserValueStructure.Capture_CcrValue/3);  //3M /3 = 1us
                // 当第二次捕获到上升沿之后,就把捕获边沿配置为上升沿,好开启新的一轮捕获
    	ETM2->CONTROLS[5].CnSC &= ~ETM_CnSC_ELSA_MASK; 								//去除上升沿捕捉
    	ETM2->CONTROLS[5].CnSC |= ETM_CnSC_ELSB_MASK; 								//下降沿沿捕捉
          // 开始捕获标志清0        
        TIM_ICUserValueStructure.Capture_StartFlag = 0;
          // 捕获完成标志置1            
        TIM_ICUserValueStructure.Capture_FinishFlag = 1;        
            }
    
    	}
    
    	if(ETM2->CONTROLS[5].CnSC & ETM_CnSC_CHF_MASK )//输入信号上升沿
    	{
    		ETM2->CONTROLS[5].CnSC &= ~ETM_CnSC_CHF_MASK;
    
    	}
    }
    

    定义结构体 用于保存车机播放音乐相关信息。

    /** 
      * @brief U盘发送报文状态结构体定义
      */ 
    typedef struct
    {
    	uint8		currentTruck;	/*!< 	当前曲目*/
    	uint8		playMode;		/*!< 	播放模式  循环 随机*/
    	uint16		fileNum;		/*!<   	有效音频文件数量*/
    	uint16		trickTime;		/*!<   	当期音频总时间*/
    	uint16		trickRunTime;	/*!<   	当期音频播放了时间*/
    
    }UDISK_STRUCT; 
    	
    /** 
      * @brief muxVwcdc发送报文状态结构体定义
      */ 
    typedef struct
    {
    	
    	UDISK_STRUCT		musicDisk;
    	
    	uint8	btCarPower;			/*!< 汽车电源*/
    	uint8	btReset;			/*!< bt复位*/
    	uint8	btPlay;				/*!< 播放/停止*/
    	uint8	btNext;				/*!< 下一曲*/
    	uint8	btPre;				/*!< 上一曲*/
    	uint8	btMode;				/*!< u盘 蓝牙模式*/
    	uint8	fpoweren;			/*!< 电源使能*/
    	uint8	frst;				/*!< 复位*/
    	uint8	fPlay;				/*!< 播放/停止*/
    	uint8	fnext;				/*!< 下一曲*/
    	uint8	fpre;				/*!< 下一曲*/
    	uint8	fbutton_flag;		/*!<   按键标志*/
    	uint8	fbutton_value;		/*!<   当前处理键值*/
    
    }AUDIO_BLE_STRUCT; 
    
    

    定义按键事件

    #define			U_COMMEND_RST	   			0
    #define			U_COMMEND_POWER   		1
    #define			U_COMMEND_PLAY   			2
    #define			U_COMMEND_PUSE   			3
    #define			U_COMMEND_NEXT   			4
    #define			U_COMMEND_PRE	   			5
    #define			U_COMMEND_UDISK	   		6   //U盘模式
    #define			U_COMMEND_BLE		   		7   //蓝牙模式
    #define			U_COMMEND_REPEAT		  8   //循环播放
    #define			U_COMMEND_SHUFFLE		  9   //随机播放
    
    

    编写接接收到cd按钮事件后向主线程发送按键消息函数

    void sendVwcdcMsg( uint8 button)
    {
    		general_msg_data_t *msg;
    								            //向统计任务发送消息
    			msg = (general_msg_data_t*)osal_msg_allocate(sizeof(general_msg_data_t) + sizeof(int));
    			if(msg != NULL)
    			{
    						//消息结构体的data数据指针偏移至申请到的内存的数据段
    						//msg->data = (unsigned char*)( msg + sizeof(osal_event_hdr_t) );
    						msg->data = (unsigned char*)(msg + 1);
    
    						msg->hdr.event = button;
    						msg->hdr.status = 0;
    						*msg->data = button;
    
    						osal_msg_send(userApp_task_id, (uint8*)msg);
    				}
    
    }
    

    按键消息处理函数

    /***********用户处理消息函数***********/
    void uCommend_ProcessOSALMsg( uint8 task_id,osal_sys_msg_t *msg_pkt )
    {
    				uint8 *pda;
    
    				static uint8 tap_count = 0;
    				static uint8 tap_flag = 0;
    
    	        while(msg_pkt)
            {
                switch(msg_pkt->hdr.event)      //判断该消息事件类型
                {
    
                    case U_COMMEND_RST:
    								{
    									btReset();
    								
    								} break;
    
                    case U_COMMEND_PLAY:
    								{
    									 btPlayPuse();
    								
    								} break;
                    case U_COMMEND_PUSE:
    								{
    									 
    									 btPlayPuse();
    								
    								} break;
                    case U_COMMEND_NEXT:
    								{
    									printf("next \n");
    
    									 btNext();
    								
    								} break;
                    case U_COMMEND_PRE:
    								{
    									 
    										btPre();								
    								} break;
                    case U_COMMEND_UDISK:
    								{
    									 
    										btUdiskMode();
    										setVwcdcTrack(0x00);  // U盘模式 显示00
    										setVwcdcTime(0);        // 时间归零
    
    								} break;	
                    case U_COMMEND_BLE:
    								{
    									 
    										btBleMode();		
    										setVwcdcTrack(0x88);  // 蓝牙模式 显示88
    										setVwcdcTime(0);        // 时间归零
    
    								} break;	
                    case U_COMMEND_REPEAT:
    								{
    									 
    										btRepeat();								
    								
    								} break;
                    case U_COMMEND_SHUFFLE:
    								{
    									 
    										btShuffle();								
    								
    								} break;
    
    								
                    default:
                        break;
                }
    
                osal_msg_deallocate((uint8 *)msg_pkt);                  //释放消息内存
                msg_pkt = (osal_sys_msg_t *)osal_msg_receive(task_id);  //读取下一条消息
            }
    }
    
    

    ​ 在系统中起两个任务,一个是用户线程,实现业务逻辑功能,另外一个任务是用来和车机进行通信监听车机按键事件的,有按键按下,就将按键消息发送到住任务里。

        osal_add_Task(vwcd_task_init, vwcd_task_event_process, 4);			//车机任务
        osal_add_Task(userApp_task_init, userApp_task_event_process, 5);    // 用户主任务
    

    启动OSAL系统抽象层

        //添加的任务统一进行初始化
        osal_Task_init();
    
        osal_mem_kick();
    
        //允许中断
        HAL_ENABLE_INTERRUPTS();
    
        //设置初始任务事件,上电就需要自动轮询的任务事件可在此添加
    
        //启动osal系统,不会再返回
        osal_start_system();
    

    用户任务

    /**
     * @brief 当前任务的事件回调处理函数
     * @param task_id       [任务ID]
     * @param task_event    [收到的本任务事件]
     * @return uint16       [未处理的事件]
     */
    uint16 userApp_task_event_process(uint8 task_id, uint16 task_event)
    {
    
        if(task_event & SYS_EVENT_MSG)       //判断是否为系统消息事件
        {
           osal_sys_msg_t *msg_pkt;
    		msg_pkt = (osal_sys_msg_t *)osal_msg_receive(task_id);      //从消息队列获取一条消息
    
    			uCommend_ProcessOSALMsg(task_id,msg_pkt);
    
            // return unprocessed events
            return (task_event ^ SYS_EVENT_MSG);
        }
    	
        if(task_event & USERAPP_INIT_EVENT)
        {
    	
    		osal_start_reload_timer(userApp_task_id, USERAPP_EVENT, 20 / TICK_PERIOD_MS);
    
            return task_event ^ USERAPP_INIT_EVENT; //处理完后需要清除事件位
        }
    		
        if(task_event & BLE_UART_RX_EVENT)
        {
            BLE_UART_Rx.lenth = BLE_UART_Rx.u8RxCnt;
            BLE_UART_Rx.flag = 1;
            BLE_UART_Rx.u8RxCnt = 0;
    
            bleBtReceiveServer(1);
    			
    
            return task_event ^ BLE_UART_RX_EVENT; //处理完后需要清除事件位
        }
    	
        if(task_event & USERAPP_EVENT)
        {
    			key_function_sever();
    			
    			#ifndef WDEBUG
    				WDOG_Feed();									// 喂狗
    			#endif	
    			
            return task_event ^ USERAPP_EVENT; //处理完后需要清除事件位
        }
    		
        if(task_event & USERAPP_BUTTON_EVENT)
        {
    			
            return task_event ^ USERAPP_BUTTON_EVENT; //处理完后需要清除事件位
        }
    		
    
        return 0;
    }
    

    ​ 车机任务函数

    /**
     * @brief 当前任务的事件回调处理函数
     * @param task_id       [任务ID]
     * @param task_event    [收到的本任务事件]
     * @return uint16       [未处理的事件]
     */
    uint16 vwcd_task_event_process(uint8 task_id, uint16 task_event)
    {
    	static unsigned char led_flag = 0;
    	
        if(task_event & VWCD_RECE_EVENT)
        {
    			  	flag_50ms = TRUE;
    				vwcdSever();
    				PTC5_OUT_TOGGLE;
    				sendPacketSever(NULL);
    
            return task_event ^ VWCD_RECE_EVENT; //处理完后需要清除事件位
        }
    		
    		
        return 0;
    }
    

    6、打板焊接调试

    测试开关电源不稳定加个680uF电容滤波。
    在这里插入图片描述

    7、模块引脚及功能

    7.1、模块引脚定义

    在这里插入图片描述

    模块引脚对照表

    引脚名称引脚功能
    L音频左声道输出
    R音频右声道输出
    AG音频模拟地
    AG音频模拟地
    IN模块数据输入
    CLK模块时钟输出
    HU开关机检测输入
    OUT模块数据输出
    12V模块电源输入
    DG数字地 需要搭铁在车机外壳上

    备注:数字地和模拟地不能连接到一起

    7.2、模块连接到车机方法

    ​ 大众系车机常见有两种接头,8针 MINI-ISO接口和12针ISO接口。

    8针插座接口定义如图所示。
    在这里插入图片描述

    7.4、模块与8针车机连接方法

    车机与模块引脚连接对应关系表

    模块引脚车机引脚模块引脚车机引脚
    L19脚 左声道R20脚 右声道
    AG18 模拟地AG18脚 模拟地
    IN14脚数据输出CLK15脚 时钟
    HU17脚开机信号OUT13脚数据输入
    12V16脚12V电源DG搭铁到车机壳上

    备注: 数字地和模拟地不能连接到一起

    12针如图所示。
    在这里插入图片描述

    7.5、模块与12车机连接方法

    车机与模块引脚连接对应关系表

    模块引脚车机引脚模块引脚车机引脚
    L8脚 左声道R9脚 右声道
    AG2 模拟地AG2脚 模拟地
    IN6脚数据输出CLK12脚 时钟
    HU10脚开机信号OUT11脚数据输入
    12V4脚12V电源DG搭铁到车机壳上

    备注: 数字地和模拟地不能连接到一起

    8、安装方法

    1、将汽车停在安全地方熄火,拔下车钥匙;

    2、根据实际情况取出汽车CD车机;

    3、使用配套的线束或者根据上文接口定义自己DIY线束,通过线束将模块和车机连起来;

    4、将数字地与车机外壳牢固搭铁;

    5、插入钥匙打开钥匙 按车上(CD、CDC、DISC、SOURCE、SRC、MODE等按钮进入碟盒模式开始播放音乐;

    6、调试没有问题后,如果不使用蓝牙,可以将模块放在车机的后方放回去,或者将模块放到手套箱中,自己喜欢放到哪都行。然后将车机放回即可安装完成;

    注意:改装有风险,下手需谨慎,因车型的不同,难易程度不同,当你选择下手的时候,强烈建议找个老司机带你。

    9、 使用方法

    9.1 CD车机按钮功能定义

    ​ 由于有些大众车型车机没有mix按钮,而车机都有CD-Cd6这六个按钮,为了保证通用性,将按钮功能做了如下映射。

    车机按钮映射表

    车机按钮模块功能
    CD1空置
    CD2播放/停止
    CD3随机播放/顺序播放
    CD4U盘模式
    CD5蓝牙模式
    CD6复位
    上一曲上一曲
    下一曲下一曲
    MIX随机播放/顺序播放(不是所有车型都有)

    ​ 注意事项:大众系车机上的CD1-CD6按钮,是相互锁定和自锁的关系,比如默认是CD1模式,此时按CD1按钮是不好使的,因为在当前模式下CD1被自己锁定状态不能被改变,再次按下CD1按钮CD车机不会有动作。比如我想停止播放,那么按下CD2按钮,此时停止播放,如果想要继续播放,就有先跳入别的CD模式 由于CD2-CD6都被分配了功能,而CD1按钮没有功能,所以如果想重复进入一直CD模式,可以按下CD1在按对应的按钮就可以了。比如 停止 CD2 播放 CD+CD2 其他按钮功能类似。

    9.2 模块指示灯定义

    ​ 红灯为U盘蓝牙状态指示灯,蓝灯为模块运行状态指示灯。

    指示灯状态表

    灯闪烁方式模块状态
    蓝灯熄灭不可以和车机通信
    蓝灯快闪可以和车机通信
    红灯快闪进入蓝牙
    红灯常亮连接成功
    红灯慢闪正在播放
    红灯关闭进入关机模式

    9.3 模块工作原理

    ​ 模块上电后会优先检查是否插入U盘,插入则屏幕会显示TRACK77如果有音乐文件则开始播放音乐,屏幕显示当前正在播放的音乐序号。否则自动进入蓝牙模式等待连接。第一次进入蓝牙模式屏幕会显示TRACK88.总得来说蓝牙模式的优先级高于U盘模式。

    状态改变说明表

    条件动作
    正在播放音乐,此时连接蓝牙音乐停止播放,进入蓝牙模式等待播放音乐
    蓝牙模式,按下U盘模式按钮开始播放音乐
    蓝牙连接上,正在播放U盘音乐蓝牙发出声音自动切换到蓝牙模式

    9.4 示例演示

    以迈腾CD300为例进行升级改造。

    第一步 准备好改装套件。
    在这里插入图片描述
    第二步 关闭车机电源,将插头插入对应的接口中,并将负极搭铁到车机外壳上,然后通过排线将车机和模块连接起来。
    在这里插入图片描述
    第三步 检测连接没有问题后,打开电源,按下CD切换按钮,如果是开机状态(不建议开机安装)安装,需要按电源按钮关机5s以上,重新打开电源,按下CD切换按钮即可进入CD模式。TRACK 77 显示当前进入了U盘模式,播放音乐后TRACK XX 即为当前正在播放音乐的序号。模式切换后显示TRACK 88则是进入了蓝牙模式。在使用车机按钮控制手机播放音乐前,要通过手机先播放音乐,否则车机不能控制。在蓝牙模式播放音乐,TRACK XX和播放的音乐序号无关。
    在这里插入图片描述
    在这里插入图片描述

    第四步 之后既可正常操作车机了,按钮CD1-CD6功能可以参考5.1按钮功能定义。

    10、常见问题集锦

    1. 问题 为什么按CD切换按钮,显示“NO DISC”,不能进入CD播放模式?

    ​ 答疑:1、请尝试关闭电源5s以上重新打开电源,在按CD切换按钮

    ​ 2、请检查状态指示灯是否正确

    ​ 3、请检查线缆是否损坏

    2. 问题 为什么车机上一曲、下一曲、停止/播放按钮,不能控制手机播放音乐?

    ​ 答疑:1、重新连接蓝牙车机是没有控制权,这是蓝牙协议规定的,必须用在手机端操作播放,之后才能用车机面板控制

    11、 联系我

    下面准备好了DIY套件,感觉动手吃力的朋友可以下单购买。
    在这里插入图片描述
    模块链接: 数码碟盒专用大众奥迪斯柯达蓝牙改装DIY U盘无损FLAC音乐播放

    升级服务

    ​ 产品定制升级

    ​ 商务合作

    ​ 汽车电子开发

    ​ 电子产品开发

    联系方式
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • C++获取所有USB接口的vid、pid等信息

    千次阅读 2019-08-14 18:20:52
    最近项目要写一个MFC的外挂程序,要分别获取电脑上所有扫描枪的输入信息,这时我们就需要根据扫描枪的vid和pid进行区分,有一些同批次同型号的输入设备vid和pid会相同,我们可能需要设备实例路径进行区分,可以在...

    最近项目要写一个MFC的外挂程序,要分别获取电脑上所有扫描枪的输入信息,这时我们就需要根据扫描枪的vid和pid进行区分,有一些同批次同型号的输入设备vid和pid会相同,我们可能需要设备实例路径进行区分,可以在设备管理器->键盘->点击设备查看,如图:
    在这里插入图片描述
    这里记录一下获取USB信息的代码,因为涉及到公司业务,只给出这部分我封装好的类,这是MFC下继承CDialogEx的类,C++只需要略作修改,核心代码为HID_FindAllDevices函数,我对记录pid,vid的vector进行了去重,设备有pid,vid相同的需要修改。

    ScannerDlg.h

    #pragma once
    #include <vector>
    #include <algorithm>
    #include "afxwin.h"
    
    // CScannerDlg 对话框
    struct _VID_PID_
    {
    	USHORT V_ID;
    	USHORT P_ID;
    	_VID_PID_(USHORT vid, USHORT pid)
    	{
    		V_ID = vid;
    		P_ID = pid;
    	}
    	bool operator==(const _VID_PID_ &other)
    	{
    		if (V_ID == other.V_ID && P_ID == other.P_ID)
    			return true;
    		return false;
    	}
    };
    
    class CScannerDlg : public CDialogEx
    {
    	DECLARE_DYNAMIC(CScannerDlg)
    
    public:
    	CScannerDlg(CWnd* pParent = NULL);   // 标准构造函数
    	virtual ~CScannerDlg();
    
    // 对话框数据
    #ifdef AFX_DESIGN_TIME
    	enum { IDD = IDD_SCANNER_DIALOG };
    #endif
    
    protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
    
    	DECLARE_MESSAGE_MAP()
    
    private:
    	std::vector<_VID_PID_> vecVidPid;
    	void HID_FindAllDevices(unsigned short *FIFO_Length);
    public:
    	CComboBox m_combo_scanner;
    	afx_msg void OnCbnDropdownComboScanner();
    	afx_msg void OnBnClickedOk();
    };
    

    ScannerDlg.cpp

    // ScannerDlg.cpp : 实现文件
    //
    
    #include "stdafx.h"
    #include "ScannerDlg.h"
    #include "afxdialogex.h"
    #include <iostream>  
    #include <string>  
    #include <fstream>
    #include <setupapi.h>
    #include <devguid.h>
    #include <winioctl.h>
    #include <regstr.h>
    #include <conio.h>
    
    #pragma comment(lib,"setupapi.lib")
    extern "C" {
    #include <hidsdi.h> 
    };
    // CScannerDlg 对话框
    
    IMPLEMENT_DYNAMIC(CScannerDlg, CDialogEx)
    
    CScannerDlg::CScannerDlg(CWnd* pParent /*=NULL*/)
    	: CDialogEx(IDD_SCANNER_DIALOG, pParent)
    {
    }
    
    CScannerDlg::~CScannerDlg()
    {
    }
    
    void CScannerDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialogEx::DoDataExchange(pDX);
    	DDX_Control(pDX, IDC_COMBO_SCANNER, m_combo_scanner);
    }
    
    
    BEGIN_MESSAGE_MAP(CScannerDlg, CDialogEx)
    	ON_CBN_DROPDOWN(IDC_COMBO_SCANNER, &CScannerDlg::OnCbnDropdownComboScanner)
    	ON_BN_CLICKED(IDOK, &CScannerDlg::OnBnClickedOk)
    END_MESSAGE_MAP()
    
    
    // CScannerDlg 消息处理程序
    //查找所有vidpid
    void CScannerDlg::HID_FindAllDevices(unsigned short *FIFO_Length)
    {
    	GUID                             HidGuid;
    	HDEVINFO                         DevInfo;
    	HIDD_ATTRIBUTES					 DevAttributes;
    	SP_DEVICE_INTERFACE_DATA         DevData;
    	PSP_DEVICE_INTERFACE_DETAIL_DATA DevDetail;
    	PHIDP_PREPARSED_DATA          PreparsedData;
    	HIDP_CAPS                   Capabilities;
    	ULONG                            Length;
    	int                              Index;
    
    	BOOL                             ok;
    	HANDLE DevHandle;
    	int DevCount = 0;
    	vecVidPid.clear();
    	/* Get GUID for all System HIDs */
    	HidD_GetHidGuid(&HidGuid);
    	/* Get Device Information for all present devices */
    	DevInfo = SetupDiGetClassDevs(&HidGuid,
    		NULL,
    		NULL,
    		(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)
    		);
    	DevData.cbSize = sizeof(DevData);
    	DevDetail = NULL;
    	Index = -1;
    	*FIFO_Length = 0;
    	/* Scan all Devices */
    	do {
    		Index++;
    		/* Device Interface Element of a Device Information set */
    		ok = SetupDiEnumDeviceInterfaces(DevInfo,
    			0,
    			&HidGuid,
    			Index,
    			&DevData
    			);
    		if (!ok) break;
    		/* Get Device Interface Details - Get Length */
    		ok = SetupDiGetDeviceInterfaceDetail(DevInfo,
    			&DevData,
    			NULL,
    			0,
    			&Length,
    			NULL
    			);
    
    		/* Allocate memory for Device Detailed Data */
    		DevDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);
    		/* Set cbSize in the DevDetail structure */
    		DevDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
    		/* Get Device Interface Details */
    		ok = SetupDiGetDeviceInterfaceDetail(DevInfo,
    			&DevData,
    			DevDetail,
    			Length,
    			NULL,
    			NULL
    			);
    		if (!ok)
    		{
    			free(DevDetail);
    			DevDetail = NULL;
    			continue;
    		}
    
    		/* Create File for Device Read/Write */
    		DevHandle = CreateFile(DevDetail->DevicePath,
    			0,
    			FILE_SHARE_READ | FILE_SHARE_WRITE,
    			(LPSECURITY_ATTRIBUTES)NULL,
    			OPEN_EXISTING,
    			0,
    			NULL
    			);
    		if (DevHandle == INVALID_HANDLE_VALUE)
    		{
    			free(DevDetail);
    			DevDetail = NULL;
    			continue;
    		}
    
    		DevAttributes.Size = sizeof(DevAttributes);
    		ok = HidD_GetAttributes(DevHandle, &DevAttributes);
    		if (!ok)
    		{
    			free(DevDetail);
    			CloseHandle(DevHandle);
    			DevDetail = NULL;
    			continue;
    		}
    
    		if (find(vecVidPid.begin(), vecVidPid.end(), _VID_PID_(DevAttributes.VendorID, DevAttributes.ProductID)) == vecVidPid.end())
    		{
    			vecVidPid.push_back(_VID_PID_(DevAttributes.VendorID, DevAttributes.ProductID));
    			free(DevDetail);
    			CloseHandle(DevHandle);
    			DevDetail = NULL;
    		}
    	} while (DevCount < 20);
    	SetupDiDestroyDeviceInfoList(DevInfo);
    	return;
    }
    
    void CScannerDlg::OnCbnDropdownComboScanner()
    {
    	// TODO: 在此添加控件通知处理程序代码
    	unsigned short* a;
    	a = new unsigned short[100];
    	memset(a, 0x00, 100);
    	vecVidPid.clear();
    	m_combo_scanner.ResetContent();
    
    	HID_FindAllDevices(a);
    	delete a;
    	int i = 0;
    	for (auto it = vecVidPid.begin(); it != vecVidPid.end(); it++)
    	{
    		CString strTmp;
    		strTmp.Format(_T("VID:%04x,PID:%04x"), it->V_ID, it->P_ID);
    		m_combo_scanner.InsertString(i, strTmp);
    		i++;
    	}
    }
    
    
    void CScannerDlg::OnBnClickedOk()
    {
    	// TODO: 在此添加控件通知处理程序代码
    	CString strTmp;
    	int nSel = m_combo_scanner.GetCurSel();
    	if (nSel != -1)
    	{
    		strTmp.Format(_T("%04x"), vecVidPid.at(nSel).V_ID);
    		gParams.SetVID(strTmp);
    		strTmp.Format(_T("%04x"), vecVidPid.at(nSel).P_ID);
    		gParams.SetPID(strTmp);
    		gParams.SaveXml();
    	}
    	else
    	{
    		gParams.SetVID(_T("FFFF"));
    		gParams.SetPID(_T("FFFF"));
    		gParams.SaveXml();
    	}
    	CDialogEx::OnOK();
    }
    
    

    窗口展示
    在这里插入图片描述

    展开全文
  • Windows下usb接口驱动技术

    千次阅读 2019-08-16 09:57:38
    一、USB概述 USB的英文全称为Universal Serial Bus,中文含义是通用串行总线,是由Conpaq、DEC、IBM、Inter、Microsoft、NEC和Northen Telecom等公司为简化PC与外设之间...现在生产的PC几乎都配备了USB接口,Micros...
  • linux usb接口音频设备

    万次阅读 2013-11-06 18:43:05
    在Linux中,先后出现了音频设备的两种框架OSS和ALSA,本节将在介绍数字音频设备及音频设备硬件接口的基础上,展现OSS和ALSA驱动的结构。 17.1~17.2节讲解了音频设备及PCM、IIS和AC97硬件接口。 17.3节阐述了Linux ...
  • 这一章从主机侧角度看到的USB 主机控制器驱动和设备驱动从主机侧的角度而言,需要编写的USB 驱动程序包括主机控制器驱动和设备驱动两类,USB 主机控制器驱动程序控制插入其中的USB 设备,而USB 设备驱动程序控制该...
  • 输入/输出通路选择是Android音频中非常重要的一个内容,正常的一个Android系统,会支持喇叭,外放,USB设备或者蓝牙等等输出模组,所以,经常会有项目需要改变原有的策略选择,这类问题通常让人头大,在Android 5.1...
  • USB声卡驱动(二)USB音频设备描述符 本篇笔记,分两部分,第一部分,是基本知识的记录。第二部分是一个实际的例子。 一.基本知识 一个音频设备(Audio Device)含有多个音频功能(Audio Function),而音频功能...
  • 我们先来看看WebRTC中提供音频设备输入输出功能的类结构: 从上图中我们看到: AudioDeviceModule接口类是音频设备模型的基类,该接口类及其子类并不提供任何针对音频的实际操作,实际操作都是由...
  • USB音频类描述符总结

    千次阅读 2019-09-09 12:23:43
    最近在学习USB音频描述符,下面是对音频类描述符的一些个人理解: 参考博客:https://blog.csdn.net/Z_HUALIN/article/details/80732036 先上代码: const unsigned char CONFIGURATION_Descriptor[] = { //...
  • 报表描述符和 USB 的其他描述符是不一样的,它不是一个简单的表格, 报表描述符是 USB 所有描述符中最复杂的 。报表描述符非常复杂而有弹性,因为它需要处理各种用途的设备。报表的数据必须以简洁的格式来储存,这样...
  • 因为接口问题,需要在RK3399的板子上使用USB音频接音箱外放,从网上购买了USB音频模块,在电脑上和手机上测试接音箱都可以正常播放,但是接到RK3399时,没有声音,从网上查资料发现,原来是RK3399默认没有打开...
  • USB设备开发流程

    千次阅读 2019-01-05 17:41:01
    USB设备的开发一般包括主机端(上位机)驱动程序的开发(如果您的USB设备符合某一标准设备类且主机端已经提供了此类设备的驱动程序的话,则可以省掉此步骤)和USB设备端驱动程序的开发,有时还可能包...
  • STM32Cube的STM32 USB设备音频流软件扩展,由ST提供 请参阅X-CUBE-USB-AUDIO ST站点 X-CUBE-USB-AUDIO扩展包包括STM32F446E-EVAL和STM32F769IDISCOVERY板的库和应用示例,用作USB扬声器和录音机。 X-CUBE-USB-AUDIO...
  • STM32 USB音频麦克风实现

    千次阅读 热门讨论 2021-04-26 11:37:37
    STM32 USB音频麦克风实现 调试工具 资料书籍 音频描述符中的简称及分类 接口描述符 STM32配置 实现部分 如何使用 测试正弦音频 测试工程 USB缓冲区设置 参考引用 最近项目进入收尾阶段,USB Microphone 部分代码不是...
  • USB基础知识介绍

    2020-06-07 16:38:42
    1,USB的简单介绍 ...常见的USB设备:U盘、鼠标、MP3、移动硬盘、数码相机、键盘、游戏杆、USB摄像头、USB打印机、USB扫描仪、USB话筒、USB网卡、USB显示器等。 1.3 USB优缺点 优点:容易使用、方便携带...
  • linux alsa-utils测试音频输入输出

    千次阅读 2018-09-04 16:21:40
    amixer可以从应用层来修改音频芯片的寄存器值,决定采用Mic输入USB输入或者Line输入。 $ amixer controls # show all controls for given card $ amixer cget numid=10,iface=MIXER,name='Playback Volume' ...
  • FPGA基础入门【17】开发板音频接口控制配置

    千次阅读 多人点赞 2019-09-03 23:20:56
    FPGA基础入门【17】开发板音频接口控制配置开发板音频控制麦克风接口简介音频输出接口简介逻辑设计结果 开发板音频控制 NEXYS 4文档中写着它的麦克风芯片是Analog Device的ADMP421,从前面两篇教程可以看出,NE...
  • 树莓派 + USB麦克风 >>> 录音

    千次阅读 2019-11-21 14:51:36
    又到期末了,课程设计又来了,我打算搞一个简易版家庭语音助手,然后前几天在搞百度的语音识别和语音合成,正好今天淘宝买的麦克风到了,我就开始搞拾音部分 关于语音识别和语音合成可参见: 树莓派 >>> ...
  • 入门学习Linux常用必会60个命令实例详解doc/txt

    千次下载 热门讨论 2011-06-09 00:08:45
    -m: 将系统为单用户模式。 -i:关机时显示系统信息。 4.命令说明 shutdown 命令可以安全地将系统关机。有些用户会使用直接断掉电源的方式来关闭Linux系统,这是十分危险的。因为Linux与Windows不同,其后台...
  • USB即通用串行总线,接口、引脚定义及电平在不同代有不同的...USB1和USB2可能用到接口类型有Type A、mini A, micro A、B、mini B、micro B,USB 3.x接口类型为了A、B、micro B 和 C。2007起,Mini-A和Mini-AB接...
  • USB1.1 协议开发

    2019-03-29 16:52:05
    USB(Universal Serial Bus)是一种总线的接口形式,协议 1.1 版本由 Microsoft、Intel、IBM 等 7 家公司于 1998 年共同制定。所有设备在设计、生产及制造的过程中都必须严格遵守协议规定。下面分别从几个方面对协议...
  • USB Audio设计与实现

    万次阅读 多人点赞 2016-11-10 20:50:16
    本文将基于STM32F4 Discovery板,从零开始设计并实现一个USB Audio的例子。
  • 公司采购了一块USB声卡(MiniStreamer),想要实现在Linux系统下的数字和模拟音频输入功能,由于MiniStreamer的生产商明确说明,其产品只提供windows和mac系统下的支持,Linux系统下不提供技术支持。本人在google上...
  • 电子设备常见的音视频接口

    千次阅读 2019-09-18 06:38:11
    倘若花了大价钱买了一些电子设备,却不知道其中的接口怎么使用,是不是非常苦恼。感觉浪费了一半的功能,笔者也不是很清楚,于是就查阅一些资料,总结一下。因为电子设备的更新换代又那么的快,我只能说现阶段的常见...
  • 树莓派

    千次阅读 2019-03-03 23:17:41
    树莓派 树莓派是什么 树莓派(英文名为Raspberry Pi,简写为RasPi/RPi/RPI) 是为学生计算机编程教育而设计,只有信用卡大小的微型电脑...别看其外表“娇小”,内“心”却很强大,视频、音频等功能通通皆有,可谓是...
  • adb命令大全

    千次阅读 多人点赞 2019-06-03 22:19:07
    4.2.3 WLAN 连接(无需借助 USB 线) 4.2.4 WiFi 连接转为 USB 连接 4.3 应用管理 4.3.1 查看应用列表 4.3.1.1 查看所有应用 4.3.1.2 查看系统应用 4.3.1.3 查看第三方应用 4.3.1.4 包名包含某字符串的应用 4.3.2 ...
  • 新增usb还涉及到了音频部分,先看下audio_policy.conf usb { outputs { usb_accessory { sampling_rates 44100 channel_masks AUDIO_CHANNEL_OUT_STEREO formats AUDIO_FORMAT_PCM_16_BIT ...
  • Linux USB基础之描述符(一) 1 USB描述符 1.1 设备描述符:struct usb_device_descriptor 设备代表一个USB设备,它由一个或多个配置组成。设备描述符用于说明设备的总体信息,并指明其所含的配置的个数。一个USB...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,119
精华内容 2,847
关键字:

usb接口改音频输入