发帖数

53

原创数

53

关注者

11

阅读数

11164

点赞数

1

黄忠

  • 什么是USB的描述符?


    USB只是一个总线,只提供一个数据通路而已。USB总线驱动程序并不知道一个设备具体如何操作,有哪些行为。具体的一个设备实现什么功能,要由设备自己来决定。那么,USB主机是如何知道一个设备的功能以及行为呢?这就要通过描述符来实现了。那么什么是USB的描述符呢?其实就是一些传递的协议信息,比如设备的类型、厂商ID、产品ID、端点情况、版本号等信息。

    既然描述符是协议信息,那么不同的版本也会有所不同,比如USB1.1协议定义的标准描述符有设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符、类特殊描述符以及厂商自定义的描述符。那么USB2.0协议中又增加了两个新的标准描述符有设备限定符描述符和其他速度配置描述符。随着USB协议版本的提升,大家知道都是为了提升速度和可靠度,让用户有更快更高效的体验。那么USB1.1是全速设备,现在我们一起看下USB1.1协议定义的描述符吧。

    一个USB设备只有一个设备描述符。设备描述符里决定了该设备有多少种配置,每种配置都有一个配置描述符;而在每个配置描述符中又决定了该配置里有多少个接口,每个接口都有一个接口描述符;在接口描述符里又定义了该接口有多少个端点,每个端点都有一个端点描述符;端点描述符定义了端点的大小、类型等。如果有类特殊描述符,它跟在相应的接口描述符之后。由此可以看出,USB的描述符之间的关系是一层一层的,最上一层是设备描述符,接下来是配置描述符,再下来是接口描述符,最下面是端点描述符。在主机获取描述符时,首先获取设备描述符,接着再获取配置描述符,然后根据配置描述符中的配置集合的总长度,一次将配置描述符、接口描述符、类特殊描述符(如果有)、端点描述符一次读回。对于字符串描述符,是单独获取的。主机通过发送获取字符串描述符的请求以及描述符的索引号、语言ID来获取对应的字符串描述符。

    设备描述符主要记录的信息有:设备所使用的USB协议版本号、设备类型、端点0的最大包大小、厂商IDVID)和产品IDPID)、设备版本号、厂商字符串索引、产品字符串索引、设备序列号索引、可能的配置数等。

    配置描述符主要记录的信息有:配置所包含的接口数、配置的编号、供电方式、是否支持远程唤醒、电流需求量等。

    接口描述符主要记录的信息有:接口的编号、接口的端点数、接口所使用的类、子类、协议等。

    端点描述符主要记录的信息有:端点号及方向、端点的传输类型、最大包长度、查寻时间间隔等。

    字符串描述符主要是提供一些方便人们阅读的信息,它不是必需的。

    说了半天,也许你还没搞清楚到底设备、配置、接口、端点等这些是什么东西。不要急,这些东西的确是有点晕人。特别是刚接触时,这么多的内容很容易让人搞混,或者似乎是懂了,然后再想想,似乎又没懂……这些所说的设备,就是一个实实在在的USB设备,例如一个USB鼠标。设备有一个设备地址,USB主机依靠这个设备地址来访问设备。而在设备内部还会分的更细。它会分出一些端点出来,例如端点0、端点1等。就是说,如果USB主机要和USB设备通信,光有设备地址是不够的,还需要一个端点地址。有了设备地址和端点地址,就能准确地对端点发送和读取数据了。好比你要去找8号教学楼的605教室,8号楼就是设备地址,而605教室就是端点地址。而配置和接口,是为了更方便地管理端点而抽象出来的概念。一个设备可以有多个配置,但是同一时刻只能有一个配置有效。每个配置下又可以有多个接口。当我们需要不同的功能时,只要选择不同的配置即可。拿刚才的教学楼来说,我们可以把它分成两个配置:平时上课用和考试用。考试用时,全部的教室都拿来作考场(即该配置下只有一个接口,接口下有很多端点---教室);而平时上课用时,分成两类(即该配置下有两个接口,每个接口下有一些端点---教室):教师休息室和上课的课室。教师休息室和课室是不能共用的(这在USB中也是如此,同一个端点号不能出现在同一个配置下的两个或者更多个不同的接口中)。但是平时用来做课室或者休息室的教室,考试时都可以拿来作考场(这在USB中也是如此,同一个端点号可用在不同的配置中)。具有多个接口并由接口来实现功能的设备把它叫做USB复合设备,例如一个USB音频设备,它具有一个音频控制接口,另外还可能具有一到多个音频流或MIDI流接口。在主机端会把USB复合设备的每个接口当作一个功能设备来看待。像常见的USB鼠标、U盘等,通常是单一的设备,即一个设备下只有一个配置描述符、一个接口描述符。

    总结一下:由端点构成一个接口(或者反过来说,接口是端点的集合),由接口又构成一个配置(反过来说,配置是接口的集合),再由配置构成一个设备(设备是配置的集合)。学习USB,一定要把这些关系理清楚了,才能按照需要构造出一个合格的USB设备。如果一个设备的各种描述符成功返回了,那么可以说已经成功了大半。相反,只要描述符出现一点问题,哪怕只是一个bit的错误,都可能造成设备无法识别或者无法正常工作。


    收藏 0 回复 0 浏览 96
  • 51单片机DIY抽奖-技术分享(三)

    PCB设计

    前情提要:上一篇我介绍了我做这个小产品的原理图设计思路,通过对原理图部分的设计说明,大家可能觉得没什么东西,当你动手实现了整个过程,再回过头去看,其实收货还是比想象的多,每一次的历练都不是徒劳的,当你收获多个小产品的经验后,有一天你接手一个大项目就不会感觉束手无措,会感觉自己平时的经验都能用的上了,话不多说,下面就分享我的PCB设计过程,PCB设计首先就是定义板框,我这里想到抽奖的小产品,那么模样也不能差太多了吧,话说我从网上搜了下抽奖转盘图片,常规我们看到的都是类似下面这种吧?

    image.png


    那设计开始吧,板框设计,由于这是一个实验品,不需要做成像平时我们见到的那么大吧,所以我只需要自定义一个能把所有元器件放下的就可以了。


    image02.png


    板框实现了,就是把原理图导入到PCB了,接下来就是实现PCB的设计实现过程了。在这里呢,我主要分享我的实现过程,还有过程中我碰到的一些小问题,我会给大家分享出来,做个提示,如果碰到同样问题,那就可以少走弯路了。

    具体实现细节大家可以持续关注下,后续我会把实现的过程视频分享给大家,互相学习嘛,有需要借鉴的就可以少走弯路,有我需要改进的欢迎大家来跟我交流哈。

    那继续看下PCB设计前应该做的事情吧,首先就是规则设置了,无规矩不成方圆,这个也同理了,所以在布局前先把规则设置好,后面所有的事情做起来就只要守规矩就好了,否则会做出警示了。那么设置规则有没有讲究呢,就请跟着我的设置来看下我常规的经验,这个只是我个人常规使用,也可以根据自己实际情况调整的。



    接下来一起看下规则设置:

    先是间距设置,常规我设置线的间距(线和线,线和过孔等的距离)是0.2mm,这是经验值;然后我会设置敷铜间距,单独添加间距规则设置敷铜的间距,这个我设置的0.3mm,根据实际情况来定,这个也是我的经验值。

    image03.pngimage04.png


    2、接下来就是线宽了,线宽推荐值我不变,最小线宽设置为0.2mm,最大设置为2mm,一般情况下布线常规线宽就是推荐值,电源和地线会用大点,所以这里规则要先设置好。

    image05.png


    3、接着就是设置过孔,对于过孔来说,有内径大小和外径大小,都有相应的最小值、推荐值和最大值,在这里我只改变内径最小值(0.3mm)和外径的最小值(0.6mm),其他就是默认就可以了。

    image06.png


    4、接下来就是我会设置下敷铜连接方式,单独新建规则来设置过孔的连接方式,常规默认是十字连接,这里我设置为直连就可以了。

    image07.png


    5、后面的设置就是孔到孔的间距、最小阻焊的间距、丝印到阻焊的间距、丝印到丝印的间距、元件的间距,这些我一般都会全部设置为0,主要靠自己布局把握了。

    主要的规则设置就上面这些了,具体的可以在实际过程中根据需求再设置就好了,规则设置好方便布局和走线的规范性,做事还是规范点好,不然真的好麻烦啊。

    规则设置好了,就可以开始布局了,布局的讲究除了看起来合理,产品出来用起来顺手,还要考虑走线等等,真的不是随便摆摆就好了,我只是分享我的思路,还是那句,方法很多,可以借鉴感觉别人优势的地方。

    既然像转盘转起来的感觉,我做的是个电子产品,有转起来的感觉就可以了,那么就把这个圆盘做了一圈的LED,然后通过程序来实现循环点亮,逐渐加快速度,同时把两位数码管(LED组成)数据循环显示(速度快无法分辨当前实际数值),两位数码管就放在上面正中间了。

    image08.png


    由于是USB供电,所以要在端口处(最下面),既然上面显示,那么USB供电上面就可以放置两个按键,一个开始,一个停止。是不是简单多了。也可以通过按键的长按或者组合实现调整数据等操作,所以这里两个按键就够用了。

    image09.png


    因为这个产品元器件不多,所以除了蜂鸣器我放在底层,其他都放在顶层,这样对于走线也方便。

    针对模块化,我们先来看下,

    第一部分就是单片机部分了,单片机连接了数码管驱动芯片以及蜂鸣器部分。

    那么先把单片机涉及的部分放在中间,模块化布局可以把原理图放置在平行界面,当选中模块后,对应的PCB模块部分就可以选中来组合了,下图中所示:

    image10.png


    那么针对前面说到的数码管显示放在上面,按键放在下面,自然就是数码管驱动芯片放在显示和按键中间合理了吧,又有和单片机的连接,所以看下图:

    image11.png


    那么剩下的就是蜂鸣器部分了,一起看下显然就是放在单片机左侧了,然而我说了选择放在底层,所以合理放置就可以了。

    image12.png

    布局就这样实现了,是不是挺简单的,接下来就是走线了,走线根据实际情况要不断的调整,顶层无法走了需要打过孔来走底层。这是最繁琐的一个过程了,也是考验细致和耐心的过程。具体走线细节可以关注后面的视频,这个看的过程中如果感兴趣还是需要实践下的,不实际操作看了真的没什么效果。

    那么走线就不具体说了,走线完成还有敷铜,DRC检测,出图等很多流程,这里就不详细说了,主要在于设计过程的分享,还有注意事项,最后还有一项需要提醒的是泪滴,这个是对焊接时焊盘连接线的保护,还是要注意下的。

    最终效果图看下吧:

    image13.png


    对于抽奖DIY的PCB设计部分就这些,是不是看起来也不难呢。其实实现起来真的没你想的那么简单,每个实践过程都会有很大收获的,后续会分享我的程序实现过程以及效果。都会经历不同的坎坷啊。当你遇到不同的问题的时候慢慢解决了才是经验的积累过程。这个抽奖DIY小产品PCB设计就完成了,大家可以看下我的实现有没有需要改进的地方呢?随时欢迎交流啊,或者有更好玩的产品一起探讨实现啊,每个都有每个的特点,都能学到不一样的知识点。如果你能在我这有所启发是最好了,分享和交流的过程就是成长的过程。后面我会陆续更新,下面一篇就是对程序的实现了,感谢大家对我的持续关注,还希望能给出更多的意见和建议啊。


    收藏 0 回复 0 浏览 83
  • 程序的链接过程和存储区解读

    大家好,我们张飞实战电子黄忠老师,今天我们讲解程序的链接和存储区的解读。

    根据C语言的特点,每一个源程序生成的目标代码将包含源程序所需要表达的所有信息和功能。有些时候很有必要从这些段中来分析实际使用情况和改进空间。目标代码中各段生成情况如下:

    1、代码段(Code

    代码段由程序中各个函数产生,函数的每一个语句将最终经过编译和汇编生成二进制机器代码(具体生成哪种体系结构的机器代码由编译器决定)

    2、只读数据段(RO Data

    只读数据段由程序中所使用的数据产生,该部分数据的特点是在运行中不需要改变,因此编译器会将该数据放入只读的部分中。C语言的一些语法将生成只读数据段。

    ① 只读全局变量

    例如:定义全局变量 const char a[100]={ABCDEFG};

    这个是生成大小为100个字节的只读数据区,并使用字符串“ABCDEFG”初始化。如果定义的时候没有指定大小,那么根据初始化的字符串长度生成相应大小的只读数据段。

    ② 只读局部变量

    例如:在函数内部定义的只读变量 const char b[100]={9876543210};

    ③ 程序中使用的常量

    例如:在程序中使用printfinformation n,其中“information n”是字符串常量, 编译器会自动把常量放入只读数据区。

    注意:上面两个变量定义,定义100个大小的区域,但是只初始化前面几个字节,实际后面的字节没有初始化,但是在程序中也不能写,实际是没有任何用处的。所以定义只读的时候需要做完全的初始化。

    3、读写数据段(RW Data

    读写数据段表示了在目标文件中一部分可以读也可以写的数据区,在某些场合它们又被称为已初始化数据段。这部分是属于程序中的静态区域。

    ①已初始化全局静态变量

    在函数外部定义的全局的变量,并且初始化。(static是限制作用域的)

    ②已初始化局部静态变量

    在函数中定义的由static定义并且已经初始化的数据或者数组。

    注意:定义的变量要有初始化才会在读写数据区。

    4、未初始化数据段(BSS

    这个段也属于静态数据区。但是没有初始化,所以在目标文件中会有标识,而不会真正称为目标文件中的一个段,这个段会在运行时产生,所以它的大小不会影响目标文件的大小。

    图片33.png 

    比如上面这个图就是通常我们编译后获得的。当你的方案选型是一个空间很小的处理器的时候很有必要了解这些存储的区域都存的是什么,方便处理冗余或者修改方案。

    上面我们了解了程序对应的存储空间,程序是怎么对号入座到这些存储区的呢?一起来看下吧,也没想象的那么神秘。

    我们每一个C语言源程序(*.c)经过编译生成目标文件(.o),目标文件就包含前面我们说的代码段、只读数据段、读写数据段。未初始化数据段、堆和栈不会占用目标文件的空间。

    那么可执行程序是由各个目标文件经过链接而成,链接就是把各个目标文件的代码段、只读数据段、读写数据段经过了重新的排列组合。

    图片34.png

    需要注意的是未初始化数据段是怎么样的,在链接的过程中,链接器可以得到未初始化数据段的大小,它也是各个目标文件的各个未初始化数据段之和,但是这个段是不影响可执行程序大小的。在C语言使用的角度,读写数据段和未初始化数据段都是可读写的。实质上,在目标文件中未初始化数据段和读写数据段的区别也在于此,读写数据段占用目标文件的容量,而未初始化数据段只是一个标识,不需要占用实际的空间。

    在链接过程之前,各个源文件生成目标文件相互没有关系。在链接之后,各目标文件函数和变量可以相互调用和访问,从而被联系在一起。比如函数调用,链接过程就是要有函数调用的地方还需要找到真正的函数定义才可以完成链接,链接器会根据需要根据实际的情况修改编译器生成的机器代码,完成正确的跳转。全局变量的访问也是同理。

    再来了解下链接过程中常见的错误:

    1、符号未找到

    (1) 只要符号被声明,编译就可以通过,但是在链接过程中符号必须具有具体的实现才可以成功链接。

    (2) 由于数据仅能在文件内部使用(static),导致符号未定义错误。

    2、符号重定义

    (1) 在多个文件中定义全局的同名函数和变量(static的重名了是正确的)。

    (2) 在头文件中定义已经初始化数据,在头文件被多个文件包含的时候,将发生错误。同样在头文件中也不应该定义只读数据段的常量。

    再有在头文件中不应该使用静态的变量,无论它有没有初值,这样虽然不会引起链接错误,但是在各个源文件中各自产生变量,不但占用空间,而且在逻辑上是不对的,也违背了头文件的使用原则。

    C语言程序设计的角度,不应该在头文件中定义变量或者函数。对于函数,在头文件中只是声明,需要在源文件中定义;对于变量,无论何种性质,最好的方式是在C语言的源文件中定义,在头文件中使用extern声明使用。

    编译,链接后面就是执行了,后面我会跟大家再分享程序运行过程,这个其实都是C语言定的一些规则,只要守规则就会顺利完成想要实现的结果。

     

     


    收藏 0 回复 0 浏览 81
  • 51单片机DIY抽奖-技术分享(二)

    1 原理图设计

    前情提要:上一篇我介绍了我做这个小产品的想法和准备工作,其实很有动手的必要,有时候不要觉得简单就不做,每一个产品实现的过程都不是一帆风顺的,都会增加不同的经验,我是深有体会的。话不多说,只要能让大家想起来我的需求和想法就好了,现在就是实现过程了,先来做原理图设计了。

    看我的标题明确的说了DIY抽奖,所以对这个数码管显示数字部分我用的LED(红色---目的就是压降低),一圈旋转的灯就是黄绿蓝三色切换,一共用了18个。

    image.png

    我只做了两位显示,最大到99,有需要做三位以及四位都是可以添加的。我这里就是实现了两位的,主要功能实现了,其他都不问题了是吧。

    我选择了USB供电,USB供电进来我加了一个保险丝(9V/200mA),起到一个保护作用。

    因为我要实现的功能相对简单,主要靠编程实现效果,所以电路设计就比较容易实现了,但是还是需要想下用最少的资源实现最强的效果了。

    接下来看下单片机模块的实现,先看下我设计的电路图:

    image02.png

    选用了8脚单片机,电源端加了一个滤波电容,一个储能电容,这个没什么问题。然后就是一个蜂鸣器,我想当抽奖停止一次就通过蜂鸣器唱歌,然后有一个蜂鸣器端口,可以通过PWM输出不同的频率来实现歌曲的调子。这个还要研究下歌曲呢,谱子啥的,瞬间感觉自己都高能了。

    右边部分就是I2C接口了,连接的按键显示芯片的端口。下面两个是串口通讯口,这里是单片机下载程序用的。这几个端口的10R电阻是防震荡作用的。

    接下来我们看下按键显示模块的实现,先上图吧:

    image03.png

    图中可以很清晰的看出显示的段和位部分,这里的100R电阻是对LED限流用的,这个电阻可以根据实际情况调节的。I2C端口的4.7K电阻是接口需求,这个可以查阅相关I2C标准,我就不多说了。下面这两个电容是电源端的滤波电容和储能电容。按键由于是共阴设计,所以加一个电阻是限流作用了。这一部分就设计完成了,是不是还挺简单的。

    接下来就剩下的是蜂鸣器部分了,我选用的是无源压电式蜂鸣器,先上图看下设计思路吧:

    image04.png

    电源端的电容就是滤波电容和储能电容了,上面这个10R电阻就是限流作用了,因为选用的是压电式无源蜂鸣器,所以下面这个R15就是为蜂鸣器放电用的了,因为我是要给蜂鸣器PWM实现唱歌,所以BEEP就是单片机给出的相当于信号了,所以下面加了一个三极管,R16作用就是限流电阻了,R17就是对三极管结电容加速关断的作用了。这样蜂鸣器部分就设计完成了。

    对于抽奖DIY的原理图设计部分就这些,是不是看起来很简单呢。其实好玩的在后面呢,PCB设计像转盘一样的抽奖样式,程序实现效果。都要动一番心思的。我实现了这样的一个小产品,大家可以看下我的原理图部分有没有需要改进的地方呢?随时欢迎交流啊,或者有更好玩的产品一起探讨实现啊,每个都有每个的特点,都能学到不一样的知识点。如果你能在我这有所启发是最好了,分享和交流的过程就是成长的过程。后面我会陆续更新,下面一篇就是对PCB的实现了,感谢大家对我的持续关注,还希望能给出更多的意见和建议啊。



    收藏 0 回复 0 浏览 53
  • 一文带你读懂RFID

    大家好,我是张飞实战电子的黄忠老师,今天我们来了解下什么是RFID。

    RFID又称无线射频识别,通过无线电信号识别并读写特定目标数据,很容易就可完成识别与读写数据。RFID技术已经存在于我们生活中的方方面面,比如门禁卡、鸿蒙一碰传等等。       
           
    电子标签,比如说我们拿的卡门禁卡,进入天线磁场后,若接收到读写器发出的特殊射频信号,就能凭借感应电流所获得的能量发送出存储在芯片中的产品信息(无源标签,即不带电源),或者主动发送某一频率的信号(有源标签,即带电源),读写器读取信息并解码后,送至MCU系统进行有关数据处理。
                                   
    图片35.png
    关于RFID有几大产品:
     
    1. 无源RFID产品:
       
    无源RFID标签,被称为被动RFID标签这类产品需要近距离接触式读卡器来进行识别,比如房卡、银行卡等,当无源RFID标签靠近RFID读卡器时,无源RFID标签的天线将接收到的电磁波能量转化成电能,激活RFID标签中的芯片,并将RFID芯片中的数据发送出来。具有抗干扰能力,用户可自定义读写标准数据,在专门的应用系统效率更加快捷。无源RFID标签的性能受标签大小(影响到天线的参数),调制形式,电路Q值、器件功耗以及调制深度等影响。这类产品也是我们生活中比较常见,也是发展比较早的产品。价格相对有源RFID便宜,且使用寿命相对较长。其识别距离比有源系统要小,一般为几米到十几米,且需要较大的读卡器来发射功率。
    2. 有源RFID产品:
           
    有源电子标签是指标签工作的能量由电池提供,电池、内存与天线一起构成有源电子标签,不同于被动射频的激活方式,一直通过设定频段主动外发信息。这类型的产品则具有远距离自动识别的特性,所以相应地应用到一些大型环境下,比如智能停车场、智慧城市、智慧交通及物联网等领域。识别距离较长,通常可达几十米甚至上百米,缺点是成本高寿命有限,不易做成薄卡。       
    3. 半有源RFID产品:
         
     半有源电子标签顾名思义就是有源RFID产品和无源RFID产品的结合,内有电池,但电池只对标签内部电路供电,并不主动发射信号,其能量传递方式与无源系统类似,因此其工作寿命比一般有源系统标签要长许多。它结合二者的优点,只有在其进入低频读卡器的激活信号范围时,标签被激活后,才开始工作。解决了有源RFID产品和无源RFID产品不能解决的问题,比如门禁出入管理、区域定位管理及安防报警等方面的应用,近距离激活定位、远距离传输数据。
           
    RFID运用领域举例:
    1.仓库/运输/物资管理:给货品嵌入RFID芯片,管理人员就可以在系统迅速查询货品信息,防丢弃,提高货品交接速度,提高准确率,防止窜货和防伪。
    2.门禁/考勤
    3.固定资产管理:像图书馆、艺术馆及博物馆等资产庞大或者物品贵重的一些场所,当书籍或者贵重物品的存放信息有异常变动,就会第一时间在系统里提醒管理员,从而处理相关情况。


    收藏 0 回复 0 浏览 53
×
黄忠