可乐zzZ

个性签名:

嵌入式、汇编语言等免费视频<

  • 2021-08-23
  • 发表了主题帖: Python如何链接MySQL?

    连接MYSQL需要3步 1、安装 必须先安装MySQL驱动。和PHP不一样,Python只默认安装了SQLite的驱动。最常用的包是MySQLdb但是用easy_install安装很困难。 对于Window用户,你可以获取MySQLdb的exe。 对于Linux,可以下载python-mysqldb(可以用sudo apt-get install python-mysqldb命令直接在命令行下载) 对于Mac用户,可以用Macport下载MySQLdb 2、使用 装完之后重启。这样做可以减少问题。 然后就像用其他包一样: #!/usr/bin/python importMySQLdb db =MySQLdb.connect(host="localhost",# your host, usually localhost user="john",# your username passwd="megajonhy",# your password db="jonhydb")# name of the data base # you must create a Cursor object. It will let # you execute all the queries you need cur = db.cursor() # Use all the SQL you like cur.execute("SELECT * FROM YOUR_TABLE_NAME") # print all the first cell of all the rows for row in cur.fetchall(): print row[0] 还有很多用法和选项,这里只举了一个基本的例子。 3、高级用法 一旦你知道它是如何工作的,你可能想用ORM来避免手动写入SQL,来把表变成Python对象。Python中最有名的ORM叫做SQLAlchemy(强烈推荐) 最近又在Python里发现了一个好东西:peewee。它是个非常轻巧的ORM,非常容易安装和使用。一些小项目和独立app都可以使用它,像SQLLAlchemy或者Django用在这里有点小题大做了: import peewee from peewee import* db =MySQLDatabase('jonhydb', user='john',passwd='megajonhy') classBook(peewee.Model): author = peewee.CharField() title = peewee.TextField() classMeta: database = db Book.create_table() book =Book(author="me", title='Peewee is cool') book.save() for book inBook.filter(author="me"): print book.title Peeweeis cool 按上边操作即可运行,除了peewee(pip install peewee)不需要别的的操作。安装非常简单。     丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 2021-08-20
  • 发表了主题帖: C语言初学者常见错误 | 总结22点

    一.语言使用错误 在打代码的过程中,经常需要在中文与英文中进行转换,因此常出现一些符号一不小心就用错,用成中文。例如:“;”中文中的分号占用了两个字节,而英文中“;”分号只占用一个字节。编译器只能识别英文。因此会报错。在报错后检查这些字符时最需要眼力和时间的。因此打代码是需注意。 二.忘打分号 分号是C语言是语句的标志,在C中无分号不成语句,无语句不能识别。在编译中如果没有分号,编译器就会将,b=2合到上一个语句a=1中,进而出现语法错误。    三.多打分号 复合语句中,花括号后不应再加分号,虽然不会有什么影响,但是多此一举,毫无意义。    另外,if(a == 0)后不应加分号,if(a ==0)后加分号就会是语句提前结束,而使用if的目的就是为了控制其后的语句,加了分号之后。程序将永远执行i++,不论a是否等于0.    for()后不应加分号。    本意是输入4个数,每输入一个数后再将它输出。由于for()后多加了个分号,导致循环变成空语句,此时就变成只能输入一个数并输出了。 四.变量命名的错误 C语言规定,标示符由字母,数字和下划线“_"组成,它的第一个字母必须是字母或下划线。在C语言中变量的命名不允许出现的情况有以下三种:1.以数字开头进行开头;2.不能包含运算符;3.不能与系统保留字(即关键字重名)。一旦出现这三种情况之一,编译器就会报错。如下图所示:    这里附上C语言中的关键字,即用作专用的定义符,也称为保留字。    作为C语言的初学者,变量的命名往往是简单单调的。而程序员大佬往往用具有特定意义的英文单词进行命名,并形成了一套自己的命名法则:业界目前共有四种命名法则;驼峰命名法,匈牙利命名法,帕斯卡命名法和下划线命名法。其中前三种是比较流行的命名法。1.驼峰命名法是将每个单词(逻辑断点)用大写字母区分开。2.匈牙利命名法通过在变量名前面加上小写字母的符号标识作为前缀,标识出变量的作用域,类型等。3.帕斯卡命名法。与驼峰命名法类似,只不过将开头首字母换成了大写字母。4.下划线命名法是将每个单词(逻辑断点)用下划线隔开。    五.忽略大小写字母的区别    出现这种情况编译器会将a和A认为是两个不同的变量,因而报错。因此在定义变量和输出变量的同时要注意大小写字母的一致性。因为C会将大写字母和小写字母看成是不同的字符。 六.数据类型的使用错误 例如:我们要输出一个a = 3.1415的情形。如果数据类型使用错误,将得不到我们想要的结果。使用整型,将只输出3。必须使用浮点型float,double,long double。       七.“/”运算时,和“%”时计算结果的错误 “/”运算时,参与运算的两个数均为整型时,结果为舍去小数的整型数,例如;    尽管定义了浮点型但是结果却是1.0,而不是我们想要的1.5。为得到1.5的结果,我们必须将3/2改成3.0/2,或者是3/2.0.才能输出1.5的结果。    如果除数和被除数中有一个为负值,其结果与具体实现有关。例如:“-9/7”在有的系统中计算结果为-2,有的系统计算结果为-1,这是对小数部分的舍入处理不同造成的。“%”要求参与的运算操作数均为整型,计算结果的符号与“%”左侧运算对象的符号相同,如“-9/4"的结果为-1。一旦非整型,编译器将报错。    也就是说整型变量a和b可以进行求余运算,而实型变量则不允许进行“求余”运算。 八.字符常量和字符串常量的表示错误 字符变量是用类型符char定义字符变量,字符常量是由一对单引号扣起来的单个字符;字符串常量是用双引号括起来的字符序列,在C中通常以“/”作为结束标志。像下面的字符串"a",实际上包含两个字符'a'和'',这把它们赋给一个变量是不行的。    九.“=”与“==”的混淆 在C语言中“=”是赋值运算符,而“==”则是关系运算符。命名的不同者也就意味着作用不同和优先级的不同。关系运算符的的优先级高于赋值运算符。      if()括号中的语句是进行判断的内容,判断a是否等于4,所以说里面的符号应该用关系运算符“==”而不是赋值运算符“=”。正确的表示如下:    十.scanf()括号中忘记加地址运算符“&”    这样的书写时不合法的。scanf函数是格式输入函数,它从标准输入设备(键盘)读取输入信息。也就是按照啊a,b在内存的地址将a,b的值存进去,“&a”就是指a在内存中的地址。 搜索公众号C语言中文社区,后台回复“资源”,免费获取200G编程资料。 十一.间隔符的不注意 scanf()函数一般以空格键,Tab键或Enter键作为分隔符,当格式中字符传中存在非格式字符时,输入时也需要一并输入。例如:    应当输入:    十二.输入数据时结束情况的不熟悉 C语言中,输入数据时,遇到以下3种情况则认为该数据结束:1.遇空格键,Tab键,或Enter键;2.有指定数据长度时,系统自动按长度截取;3.遇非法输入。 十三.输入字符的格式与要求不一致 在C中,在用“%c”输入时,空格和转义字符均作为有效字符。    字符“a”赋给c1,字符“ ”赋给c2,字符“b”送给c3,因为%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。   40G的百度网盘C语言、C++、Linux从入门、进阶到精通 覆盖所有知识点,还有视频教程讲解、C语言的项目源码大全 https://sourl.cn/KxhkMP 十四.输入数据时规定精度    输入数据时企图规定精度,这样做在C中是不合法的。 十五.使用switch语句中漏写break语句 例如:打印学生成绩        如果漏写break语句,case只起标号作用,而不起判断作用。也就是假如输入A,就会直接执行到最后一个printf语句,而不会在第一个printf语句执行后截止。因此必须在每个printf语句后加上break.例如:    十六.数组的部分错误 1.数组后面的元素个数应与声明的一致。如果与声明不一致,超出声明后面的数字默认为0。    2.必须声明元素个数。    十七.忽略了while和do-while语句在细节上的区别       如图所示,当输入i大于10时二者的结果就不同了。这是因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数,while语句中编译器不循环循环体,而do-while语句编译器则要执行一次循环体。 十八.定义数组时误用变量    数组后面用方括号括起来的是常量表达式,可以包含常量和符号常量。即C不允许对数组的大小作动态定义。 十九.多加了地址运算符“&”    C语言中,scanf函数中的输入是字符数组名时,就不必在加地址符&。需改为:    二十.同时定义了形参和函数中的局部变量    形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:    二十一.在定义数组时将定义的“元素个数”误以为是可使的最大下标值    C语言规定:定义时用a[10],表示数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。 二十二.二维数组的定义 1.C语言中,不能使用一次方括号来表示二维数组的元素,表示非法的例子如下:    2.另外,由于系统不会检查二维数组元素的下标是否越界,以此需要编程人员注意限制下标不要越界。例如:         丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨     

  • 发表了主题帖: PCB拼板技巧

    拼板指的是将一张张小的PCB板让厂家直接给拼做成一整块。   一、为什么要拼板呢,也就是说拼板的好处是什么?   1.为了满足生产的需求。有些PCB板太小,不满足做夹具的要求,所以需要拼在一起进行生产。   2.提高SMT贴片的焊接效率。只需要过一次SMT即可完成多块PCB的焊接。   3.提高成本利用率。有些PCB板是异形的,拼板可以更高效率的利用PCB板面积,减少浪费,提高成本的利用率。     二、拼板设计有哪几种方式?   1.V-CUT       V-CUT是在两个板子的连接处画一个槽,只要将两个板子拼在一起,之间留点空隙即可(一般0.4mm),但这个地方板子的连接就比较薄,容易掰断,拼板时需将两个板子的边缘合并在一起。   V-CUT一般都是直线,不会有弯曲圆弧等复杂的走线,在拼板时尽量在一条直线上。   2.邮票孔       对于不规则的PCB板,比如圆形的,V-CUT是做不到的,这个时候就需要使用到邮票孔来进行拼板连接,因此邮票孔一般在异形板中使用的较多。   在两个板子的边缘通过一小块板材进行连接,而这一小块板材与两块板的连接处有许多小孔,这样容易掰断。掰断之后板子的边缘像邮票的边缘,因此这种拼板方式被称为邮票孔。   3.空心连接条       空心连接条在有半孔工艺的板子中使用较多,是使用很窄的板材进行连接,和邮票孔有些类似,区别在于连接条的连接部分更窄一点,而且两边没有过孔。   空心连接条的拼板方式有一个缺点:板子掰开之后会有一个很明显的凸点。邮票孔也有凸点,因为被过孔分开所以不怎么明显。   有人可能会觉得直接用邮票孔不就好了,为啥还要用空心连接条?这是因为在做四周都是半孔模块的时候,邮票孔和V-CUT都无法使用的,只能通过空心连接条在模块四个角进行连接。     三、拼板的原则是什么?   为了方便生产,尽可能让拼板后的板子保持正方形的形状。总之不要让长宽比例差距太大。   四、间距要求:   1.对于元器件最外侧距离板边缘<3mm的PCB必须加工艺边,通常以较长边作为工艺边;   2.元器件与V—CUT之间应预留>0.5mm的空间,以保证刀具正常运行。     丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨  

  • 2021-08-19
  • 发表了主题帖: 电源缓启动原理

    现在大多数电子系统都要支持热插拔功能,所谓热插拔,也就是在系统正常工作时,带电对系统的某个单元进行插拔操作,且不对系统产生任何影响。 热插拔对系统的影响主要有两方面: 其一,热插拔时,连接器的机械触点在接触瞬间会出现弹跳,引起电源振荡,如下图所示:     这个振荡过程会引起系统电源跌落,引起误码,或系统重启,也可能会引起连接器打火,引发火灾。 解决的办法就是延迟连接器的通电时间,在连接器抖动的那十几毫秒内((t1至t2)不给连接器通电,等插入稳定后(t2后)再通电,即防抖动延时。 其二,热插拔时,由于系统大容量储能电容的充电效应,系统中会出现很大的冲击电流,大家都知道,电容在充电时,电流呈指数趋势下降(左下图),所以在刚开始充电的时候,其冲击电流是非常大的。     此冲击电流可能会烧毁设备电源保险管,所以在热插拔时必须对冲击电流进行控制,使其按理想的趋势变化,如右上图所示,图中0~t1为电源缓启动时间。 综上所述,缓启动电路主要的作用是实现两项功能: 1).防抖动延时上电; 2).控制输入电流的上升斜率和幅值。 缓启动电路有两种类型:电压斜率型和电流斜率型。 电压斜率型缓启动电路结构简单,但是其输出电流的变化受负载阻抗的影响较大,而电流斜率型缓启动电路的输出电流变化不受负载影响,但是电路结构复杂。 下面重点介绍电压型缓启动电路。 设计中通常使用MOS管来设计缓启动电路的。MOS管有导通阻抗Rds低和驱动简单的特点,在周围加上少量元器件就可以构成缓慢启动电路。通常情况下,在正电源中用PMOS,在负电源中使用NMOS。 下图是用NMOS搭建的一个-48V电源缓启动电路,我们来分析下缓启动电路的工作原理。     1).D1是嵌位二极管,防止输入电压过大损坏后级电路; 2).R2和C1的作用是实现防抖动延时功能,实际应用中R2一般选20K欧姆,C1选4.7uF左右; 3).R1的作用是给C1提供一个快速放电通道,要求R1的分压值大于D3的稳压值,实际应用中,R1一般选10K左右; 4).R3和C2用来控制上电电流的上升斜率,实际应用中,R3一般选200K欧姆左右,C2取值为10 nF~100nF; 5).R4和R5的作用是防止MOS管自激振荡,要求R4、R5lt;<R3,R4取值一般为10~50欧姆之间,R5一般为2K欧姆; 6).嵌位二极管D3的作用是保护MOS管Q1的栅-源极不被高压击穿;D2的作用是在MOS管导通后对R2、C1构成的防抖动延时电路和R3、C2构成的上电斜率控制电路进行隔离,防止MOS栅极充电过程受C1的影响。   下面来分析下该电路的缓启动原理: 假设MOS管Q1的栅-源极间的寄生电容为Cgs,栅-漏极间的寄生电容为Cgd,漏-源极间的寄生电容为Cds,栅-漏极外部并联了电容C2 (C2gt;>Cgd),所以栅-漏极的总电容C’gd=C2+ Cgd,由于相对于C2 来说,Cgd的容值几乎可忽略不计,所以C’gd≈C2,MOS管栅极的开启电压为Vth,正常工作时,MOS管栅源电压为Vw(此电压等于稳压管D3的嵌位电压),电容C1充电的时间常数t=(R1//R2//R3)C1,由于R3通常比R1、R2大很多,所以t≈(R1//R2)C1。 下面分三个阶段来分析上述电压缓启动电路的工作原理: 第一阶段:-48V电源对C1充电,充电公式如下。 Uc=48*R1/(R1+R2)[1-exp(-T/t)],其中T是电容C1电压上升到Uc的时间,时间常数t=(R1//R2)C1。所以,从上电到MOS管开启所需要的时间为:Tth=-t*ln[1-(Uc*(R1+R2)/(48*R1))] 第二阶段:MOS管开启后,漏极电流开始增大,其变化速度跟MOS管的跨导和栅源电压变化率成正比,具体关系为:dIdrain/dt = gfm *dVgs/dt,其中gfm为MOS管的跨导,是一个固定值,Idrain为漏极电流,Vgs为MOS管的栅源电压,此期间体现为栅源电压对漏源电流的恒定控制,MOS管被归纳为压控型器件也是由此而来的。 第三阶段:当漏源电流Idrain达到最大负载电流时,漏源电压也达到饱和,同时,栅源电压进入平台期,设电压幅度为Vplt。由于这段时间内漏源电流Ids保持恒定,栅源电压Vplt=Vth+(Ids/gfm),同时,由于固定的栅源电压使栅极电流全部通过反馈电容C’gd,则栅极电流为Ig=(Vw-Vplt)/(R3+R5),由于R5相对于R3可以忽略不计,所以Ig≈(Vw-Vplt)/R3。因为栅极电流Ig≈Icgd,所以,Icgd=Cgd*dVgd/dt。由于栅源电压在这段时间内保持恒定,所以栅源电压和漏源电压的变化率相等。故有:dVds/dt=dVgd/dt=(Vw-Vplt)/(R3*C2)。 由此公式可以得知,漏源电压变化斜率与R3*C2的值有关,对于负载恒定的系统,只要控制住R3*C2的值,就能控制住热插拔冲击电流的上升斜率。 缓启动阶段,栅源电压Vgs,漏源电压Vds和漏源电流Ids的变化示意图如下所示。   在0~t1阶段,肖特基二极管D2尚未开启,所以Vgs等于0,在这段时间内,-48V电源通过R3、R5对C2充电,等C2的电压升高到D2的开启电压,MOS管的栅极电压开始升高,等栅源电压升高到MOS管的开启电压Vth时,MOS管导通,漏源电流Ids开始增大,等MOS管的栅源电压升高到平台电压Vplt时,漏源电流Ids也达到最大,此时,漏源电压Vds进入饱和,开始下降,平台电压Vplt结束时,MOS管完全导通,漏源电压降到最低,MOS管的导通电阻Rds最小。       在电信工业和微波电路设计领域,普遍使用MOS管控制冲击电流的方达到电流缓启动的目的。MOS管有导通阻抗Rds_on低和驱动简单的特点,在周围加上少量元器件就可以构成缓慢启动电路。虽然电路比较简单,但只有吃透MOS管的相关开关特性后才能对这个电路有深入的理解。 本文首先从MOSFET的开通过程进行叙述: 尽管MOSFET在开关电源、电机控制等一些电子系统中得到广泛的应用,但是许多电子工程师并没有十分清楚的理解MOSFET开关过程,以及MOSFET在开关过程中所处的状态一般来说,电子工程师通常基于栅极电荷理解MOSFET的开通的过程,如图1所示此图在MOSFET数据表中可以查到     图1 AOT460栅极电荷特性   MOSFET的D和S极加电压为VDD,当驱动开通脉冲加到MOSFET的G和S极时,输入电容Ciss充电,G和S极电压Vgs线性上升并到达门槛电压VGS(th),Vgs上升到VGS(th)之前漏极电流Id≈0A,没有漏极电流流过,Vds的电压保持VDD不变。 当Vgs到达VGS(th)时,漏极开始流过电流Id,然后Vgs继续上升,Id也逐渐上升,Vds仍然保持VDD当Vgs到达米勒平台电压VGS(pl)时,Id也上升到负载电流最大值ID,Vds的电压开始从VDD下降。 米勒平台期间,Id电流维持ID,Vds电压不断降低。 米勒平台结束时刻,Id电流仍然维持ID,Vds电压降低到一个较低的值米勒平台结束后,Id电流仍然维持ID,Vds电压继续降低,但此时降低的斜率很小,因此降低的幅度也很小,最后稳定在Vds=Id×Rds(on)因此通常可以认为米勒平台结束后MOSFET基本上已经导通。 于上述的过程,理解难点在于为什么在米勒平台区,Vgs的电压恒定?驱动电路仍然对栅极提供驱动电流,仍然对栅极电容充电,为什么栅极的电压不上升?而且栅极电荷特性对于形象的理解MOSFET的开通过程并不直观因此,下面将基于漏极导通特性理解MOSFET开通过程。 MOSFET的漏极导通特性与开关过程。   MOSFET的漏极导通特性如图2所示MOSFET与三极管一样,当MOSFET应用于放大电路时,通常要使用此曲线研究其放大特性只是三极管使用的基极电流、集电极电流和放大倍数,而MOSFET使用栅极电压、漏极电流和跨导。     图2 AOT460的漏极导通特性 三极管有三个工作区:截止区、放大区和饱和区,MOSFET对应是关断区、恒流区和可变电阻区注意:MOSFET恒流区有时也称饱和区或放大区当驱动开通脉冲加到MOSFET的G和S极时,Vgs的电压逐渐升高时,MOSFET的开通轨迹A-B-C-D如图3中的路线所示     图3 AOT460的开通轨迹   开通前,MOSFET起始工作点位于图3的右下角A点,AOT460的VDD电压为48V,Vgs的电压逐渐升高,Id电流为0,Vgs的电压达到VGS(th),Id电流从0开始逐渐增大 A-B就是Vgs的电压从VGS(th)增加到VGS(pl)的过程从A到B点的过程中,可以非常直观的发现,此过程工作于MOSFET的恒流区,也就是Vgs电压和Id电流自动找平衡的过程,即Vgs电压的变化伴随着Id电流相应的变化,其变化关系就是MOSFET的跨导:Gfs=Id/Vgs,跨导可以在MOSFET数据表中查到 当Id电流达到负载的最大允许电流ID时,此时对应的栅级电压Vgs(pl)=Id/gFS由于此时Id电流恒定,因此栅极Vgs电压也恒定不变,见图3中的B-C,此时MOSFET处于相对稳定的恒流区,工作于放大器的状态 开通前,Vgd的电压为Vgs-Vds,为负压,进入米勒平台,Vgd的负电压绝对值不断下降,过0后转为正电压驱动电路的电流绝大部分流过CGD,以扫除米勒电容的电荷,因此栅极的电压基本维持不变Vds电压降低到很低的值后,米勒电容的电荷基本上被扫除,即图3中的C点,于是,栅极的电压在驱动电流的充电下又开始升高,如图3中的C-D,使MOSFET进一步完全导通 C-D为可变电阻区,相应的Vgs电压对应着一定的Vds电压Vgs电压达到最大值,Vds电压达到最小值,由于Id电流为ID恒定,因此Vds的电压即为ID和MOSFET的导通电阻的乘积 基于MOSFET的漏极导通特性曲线可以直观的理解MOSFET开通时,跨越关断区、恒流区和可变电阻区的过程米勒平台即为恒流区,MOSFET工作于放大状态,Id电流为Vgs电压和跨导乘积 电路原理详细说明: MOS管是电压控制器件,其极间电容等效电路如图4所示。   图4. 带外接电容C2的N型MOS管极间电容等效电路 MOS管的极间电容栅漏电容Cgd、栅源电容Cgs、漏源电容Cds可以由以下公式确定:       公式中MOS管的反馈电容Crss,输入电容Ciss和输出电容Coss的数值在MOS管的手册上可以查到。 电容充放电快慢决定MOS管开通和关断的快慢,Vgs首先给Cgs 充电,随着Vgs的上升,使得MOS管从截止区进入可变电阻区。进入可变电阻区后,Ids电流增大,但是Vds电压不变。随着Vgs的持续增大,MOS管进入米勒平台区,在米勒平台区,Vgs维持不变,电荷都给Cgd 充电,Ids不变,Vds持续降低。在米勒平台后期,MOS管Vds非常小,MOS进入了饱和导通期。为确保MOS管状态间转换是线性的和可预知的,外接电容C2并联在Cgd上,如果外接电容C2比MOS管内部栅漏电容Cgd大很多,就会减小MOS管内部非线性栅漏电容Cgd在状态间转换时的作用,另外可以达到增大米勒平台时间,减缓电压下降的速度的目的。外接电容C2被用来作为积分器对MOS管的开关特性进行精确控制。控制了漏极电压线性度就能精确控制冲击电流。 电路描述: 图5所示为基于MOS管的自启动有源冲击电流限制法电路。MOS管 Q1放在DC/DC电源模块的负电压输入端,在上电瞬间,DC/DC电源模块的第1脚电平和第4脚一样,然后控制电路按一定的速率将它降到负电压,电压下降的速度由时间常数C2*R2决定,这个斜率决定了最大冲击电流。 C2可以按以下公式选定:   R2由允许冲击电流决定:     其中Vmax为最大输入电压,Cload为C3和DC/DC电源模块内部电容的总和,Iinrush为允许冲击电流的幅度。     图5 有源冲击电流限制法电路   D1是一个稳压二极管,用来限制MOS管 Q1的栅源电压。元器件R1,C1和D2用来保证MOS管Q1在刚上电时保持关断状态。具体情况是: 上电后,MOS管的栅极电压要慢慢上升,当栅源电压Vgs高到一定程度后,二极管D2导通,这样所有的电荷都给电容C1以时间常数R1×C1充电,栅源电压Vgs以相同的速度上升,直到MOS管Q1导通产生冲击电流。   以下是计算C1和R1的公式:     其中Vth为MOS管Q1的最小门槛电压,VD2为二极管D2的正向导通压降,Vplt为产生Iinrush冲击电流时的栅源电压。Vplt可以在MOS管供应商所提供的产品资料里找到。 MOS管选择 以下参数对于有源冲击电流限制电路的MOS管选择非常重要: l 漏极击穿电压 Vds   必须选择Vds比最大输入电压Vmax和最大输入瞬态电压还要高的MOS管,对于通讯系统中用的MOS管,一般选择Vds≥100V。 l 栅源电压Vgs   稳压管D1是用来保护MOS管Q1的栅极以防止其过压击穿,显然MOS管Q1的栅源电压Vgs必须高于稳压管D1的最大反向击穿电压。一般MOS管的栅源电压Vgs为20V,推荐12V的稳压二极管。 l 导通电阻Rds_on. MOS管必须能够耗散导通电阻Rds_on所引起的热量,热耗计算公式为:    其中Idc为DC/DC电源的最大输入电流,Idc由以下公式确定:   其中Pout为DC/DC电源的最大输出功率,Vmin为最小输入电压,η为DC/DC电源在输入电压为Vmin输出功率为Pout时的效率。η可以在DC/DC电源供应商所提供的数据手册里查到。MOS管的Rds_on必须很小,它所引起的压降和输入电压相比才可以忽略。     图6. 有源冲击电流限制电路在75V输入,DC/DC输出空载时的波形     设计举例   已知:Vmax=72V Iinrush=3A 选择MOS管Q1为IRF540S 选择二极管D2为BAS21   按公式(4)计算:C2>>1700pF。选择 C2=0.01μF;   按公式(5)计算:R2=252.5kW。选择 R2=240kW,选择R3=270W<<r2;   按公式(7)计算:C1=0.75μF。选择 C1=1μF;   按公式(8)计算:R1=499.5W。选择 R1=1kW   图6所示为图5 电路的实测波形,其中DC/DC电源输出为空载。     丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨  

  • 发表了主题帖: 总结电容知识

    本帖最后由 可乐zzZ 于 2021-8-19 17:25 编辑       电容是电路设计中最为普通常用的器件,是无源元件之一,有源器件简单地说就是需能(电)源的器件叫有源器件, 无需能(电)源的器件就是无源器件。电容也常常在高速电路中扮演重要角色。     电容的作用和用途,一般都有好多种。如:在旁路、去藕、滤波、储能方面的作用;在完成振荡、同步以及时间常数的作用……     下面来详细分析一下: 1、隔直流     作用是阻止直流通过而让交流通过。   2、旁路(去耦)     为交流电路中某些并联的元件提供低阻抗通路。            旁路电容:旁路电容,又称为退耦电容,是为某个器件提供能量的储能器件,它利用了电容的频率阻抗特性(理想电容的频率特性随频率的升高,阻抗降低),就像一个水塘,它能使输出电压输出均匀,降低负载电压波动。旁路电容要尽量靠近负载器件的供电电源管脚和地管脚,这是阻抗要求,在画PCB时候特别要注意,只有靠近某个元器件时候才能抑制电压或其他输信号因过大而导致的地电位抬高和噪声,说白了就是把直流电源中的交流分量,通过电容耦合到电源地中,起到了净化直流电源的作用。如下图为旁路电容,画图时候要尽量靠近IC1。           去藕电容:去耦电容,是把输出信号的干扰作为滤除对象,去耦电容相当于电池,利用其充放电,使得放大后的信号不会因电流的突变而受干扰。它的容量根据信号的频率、抑制波纹程度而定,去藕电容就是起到一个“电池”的作用,满足驱动电路电流的变化,避免相互间的耦合干扰。     旁路电容实际也是去藕合的,只是旁路电容一般是指高频旁路,也就是给高频的开关噪声提高一条低阻抗泄防途径。高频旁路电容一般比较小,根据谐振频率一般取 0.1F、0.01F 等;而去耦合电容的容量一般较大,可能是 10F 或者更大,依据电路中分布参数、以及驱动电流的变化大小来确定。如下图为去耦电容。           它们的区别:旁路是把输入信号中的干扰作为滤除对象,而去耦是把输出信号的干扰作为滤除对象,防止干扰信号返回电源。 3、耦合     作为两个电路之间的连接,允许交流信号通过并传输到下一级电路 。               用电容做耦合的元件,是为了将前级信号传递到后一级,并且隔断前一级的直流对后一级的影响,使电路调试简单,性能稳定。     如果不加电容交流信号放大不会改变,只是各级工作点需重新设计,由于前后级影响,调试工作点非常困难,在多级时几乎无法实现。 4、滤波     这个对电路而言很重要,CPU背后的电容基本都是这个作用。           即频率f越大,电容的阻抗Z越小。当低频时,电容C由于阻抗Z比较大,有用信号可以顺利通过;当高频时,电容C由于阻抗Z已经很小了,相当于把高频噪声短路到GND上去了。     滤波作用:理想电容,电容越大,阻抗越小,通过的频率也越高。电解电容一般都是超过 1uF ,其中的电感成份很大,因此频率高后反而阻抗会大。我们经常看见有时会看到有一个电容量较大电解电容并联了一个小电容,其实大的电容通低频,小电容通高频,这样才能充分滤除高低频。电容频率越高时候则衰减越大,电容像一个水塘,几滴水不足以引起它的很大变化,也就是说电压波动不是你很大时候电压可以缓冲,如下图。     5、温度补偿     针对其它元件对温度的适应性不够带来的影响,而进行补偿,改善电路的稳定性。       分析:由于定时电容的容量决定了行振荡器的振荡频率,所以要求定时电容的容量非常稳定,不随环境湿度变化而变化,这样才能使行振荡器的振荡频率稳定。因此采用正、负温度系数的电容释联,进行温度互补。     当工作温度升高时,Cl的容量在增大,而C2的容量在减小,两只电容并联后的总容量为两只电容容量之和,由于一个容量在增大而另一个在减小,所以总容量基本不变。     同理,在温度降低时,一个电容的容量在减小而另一个在增大,总的容量基本不变,稳定了振荡频率,实现温度补偿目的。 6、计时     电容器与电阻器配合使用,确定电路的时间常数。       输入信号由低向高跳变时,经过缓冲1后输入RC电路。电容充电的特性使B点的信号并不会跟随输入信号立即跳变,而是有一个逐渐变大的过程。当变大到一定程度时,缓冲2翻转,在输出端得到了一个延迟的由低向高的跳变。     时间常数:以常见的 RC 串联构成积分电路为例,当输入信号电压加在输入端时,电容上的电压逐渐上升。而其充电电流则随着电压的上升而减小,电阻R和电容C串联接入输入信号VI,由电容C输出信号V0,当RC (τ)数值与输入方波宽度tW之间满足:τ》》tW,这种电路称为积分电路 7、调谐     对与频率相关的电路进行系统调谐,比如手机、收音机、电视机。       上图,变容二极管的调谐电路。     因为lc调谐的振荡电路的谐振频率是lc的函数,我们发现振荡电路的最大与最小谐振频率之比随着电容比的平方根变化。此处电容比是指反偏电压最小时的电容与反偏电压最大时的电容之比。因而,电路的调谐特征曲线(偏压一谐振频率)基本上是一条抛物线。 8、整流     在预定的时间开或者关半闭导体开关元件。           9、储能     储存电能,用于必须要的时候释放。     例如相机闪光灯,加热设备等等.(如今某些电容的储能水平己经接近锂电池的水准,一个电容储存的电能可以供一个手机使用一天。         储能作用:一般地,电解电容都会有储能的作用。对于专门的储能作用的电容,电容储能的机理为双电层电容以及法拉第电容,其主要形式为超级电容储能,其中超级电容器是利用双电层原理的电容器,当外加电压加到超级电容器的两个极板上时,与普通电容器一样,极板的正电极存储正电荷,负极板存储负电荷,在超级电容器的两极板上电荷产生的电场作用下,在电解液与电极间的界面上形成相反的电荷,以平衡电解液的内电场,这种正电荷与负电荷在两个不同相之间的接触面上,以正负电荷之间极短间隙排列在相反的位置上,这个电荷分布层叫做双电层,因此电容量非常大。     丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨      

  • 2021-08-18
  • 发表了主题帖: 超全!嵌入式系统词汇速查手册

      A ASIC(专用集成电路) Application-Specific Integrated Circuit. A piece of custom-designed hardware in a chip. 专用集成电路。一个在一个芯片上定制设计的硬件。 address bus (地址总线) A set of electrical lines connected to the processor and all of the peripherals withwhich itcommunicates. The address bus is used by the processor to select aspecific memory location or register within a particular peripheral. If the address bus contains n electrical lines, the processor can uniquely address up to 2^n such locations. 一个连接处理器与所有外设的,用来通讯的电子线路集。地址总线被处理器用来选择在特定外设中的存储器地址或寄存器。如果地址总线有n条电子线路,处理器能唯一寻址高达2^n的地址空间。 application software(应用软件) Describes software modules specific to a particular embedded project. Theapplication software is unlikely to be reusable across embedded platforms, simplybecause each embedded system has a different application. 用来描述一个特定的嵌入式项目中的某一软件模块。应用软件不象可重用的交叉嵌入式平台,只是因为每一个嵌入式系统有不同的应用软件。 assembler(汇编编译器) A software development tool that translates human-readable assembly languageprograms into machine-language instructions that the processor can understandand execute. 一个能把人可读的汇编语言程序转换到处理器可理解和运行的机器指令的软件开发工具。 assembly language(汇编语言) A human-readable form of a processor"s instruction set. Most processor-specific functions must be written in assembly language. 一种人可读的处理器指令集的形式。大多数处理器相关的功能必须用汇编语言编写。 B   BSP(板卡支持包) See board support package. 见board support package。 binary semaphore(二元信号) A type of semaphore with just two states. Also called a mutex. 一种只有两种状态的信号。也叫互斥信号。 board support package(板卡支持包) Part of a software package that is processor or platform-dependent. Typically,sample source code for the board support package is provided by the package developer. The sample code must be modified as necessary, compiled, and linked with the remainder of the software package. 软件包的具有平台依赖性的那一部分。典型地,板卡支持包的样例源程序由包开发者提供。样例源程序必须能在需要时被修改、编译并与软件包的剩下的部分连接起来。 bond-out processor (外合处理器) A special version of a processor that has some of the internal signals brought out to external pins. A bond-out processor is most often found within an emulator and is never intended to be used in a production system. 一种特殊版本的处理器,它有一些,内部的信号能传达到外置的针脚上。一个外合处理器绝大多数情况下只用在模拟器上,从来不会被特意用在产品系统上。 Breakpoint (断点) A location in a program at which execution is to be stopped and control of the processor switched to the debugger. Mechanisms for creating and removing breakpoints are provided by most debugging tools. 一个在程序中的地址,在那里程序的执行被停止,并且处理器的控制转换到了除错程序。大多数除错工具提供增加与删除一个断点的机制。 C   CISC(复杂指令集计算机) Complex Instruction Set Computer. Describes the architecture of a processor family. CISC processors generally feature variable-length instructions, multiple addressing formats, and contain only a small number of general-purpose registers. Intel"s 80x86 family is the quintessential example of CISC. Contrast with RISC. 复杂指令集计算机。对一种处理器架构的描述。CISC处理器一般产生变长的指令,多种地址格式,并且仅仅有少量的通用寄存器。Intel的80x86家族是是典型的CISC处理器。相对于RISC而言。 CPU(中央处理器) Central Processing Unit. The part of a processor that executes instructions. 中央处理器。处理器中执行指令的那一部分。 Compiler(编译器) A software development tool that translates high-level language programs into the machine-language instructions that a particular processor can understand and execute. 把高级编程语言程序转换到只有特定的处理器能了解和执行的机器指令的一种软件开发包。 context (上下文) The current state of the processor"s registers and flags. 处理器当前的状态和标志。 context switch(上下文切换) The process of switching from one task to another in a multitasking operating system. A context switch involves saving the context of the running task and restoring the previously-saved context of the other. The piece of code that does this is necessarily processor-specific. 在多任务操作系统中我一个任务切换到另一个的过程。上下文切换包括保存正在运行的任务的上下文和恢复早先保存的另一个任务的上下文。做这个工作的一段代码必须具有处理器特权。 counting semaphore(计数信号) A type of semaphore that is used to track multiple resources of the same type. An attempt to take a counting semaphore is blocked only if all of the available resources are in use. Contrast with binary semaphore. 一种用来跟踪多个相同类型资源的信号灯。仅仅在所有可用的资源都被用完了时才阻塞。相对二元信号而言。 critical section(临界段) A block of code that must be executed in sequence and without interruption to guarantee correct operation of the software. See also race condition. 一段必须按次序执行的代码,并且不能被中断,否则不能保证软件正确地操作。参照:竞争状况。 cross-compiler(交叉编译器) A compiler that runs on a different platform than the one for which it produces object code. A cross-compiler runs on a host computer and produces object code for the target. 一个运行在不同的平台上的编译器,其中之一能产生目标代码。交叉编译器在主机上运行并且产生目标机的目标代码。 D   DMA(直接内存访问) Direct Memory Access. A technique for transferring data directly between two peripherals (usually memory and an I/O device) with only minimal intervention by the processor. DMA transfers are managed by a third peripheral called a DMA controller. 直接内存访问。一种直接在两个外设(通常是内存和I/O设备)之间进行数据传输的技术,它只要处理器最少的介入。DMA传输由叫DMA控制器的第三方外设进行管理。 DRAM(动态随机访问存储器) Dynamic Random-Access Memory. A type of RAM that maintains its contents only as long as the data stored in the device is refreshed at regular intervals. The refresh cycles are usually performed by a peripheral called a DRAM controller. 动态随机访问存储器。一种RAM,存储在其设备中的数据被定期刷新时才能保存它的内容。刷新周期一般由一个叫DRAM控制器的外设完成。 Data bus(数据总线) A set of electrical lines connected to the processor and all of the peripherals with which it communicates. When the processor wants to read (write) the contents of a memory location or register within a particular peripheral, it sets the address bus pins appropriately and receives (transmits) the contents on the data bus. 连接处理器与所有外设进行通讯的电子线路集。当一个处理器想去写(读)某一特定外设中的存储器地址或寄存器中的内容时,处理器设置地址总线并在数据总线上接收(传输)内容。 Deadline(死线) The time at which a particular set of computations must be completed. See also real-time system. 一个特定计算必须被完成的时间。请看实时系统。 Deadlock(死锁) An unwanted software situation in which an entire set of tasks is blocked, waiting for an event that only a task within the same set can cause. If a deadlock occurs, the only solution is to reset the hardware. However, it is usually possible to prevent deadlocks altogether by following certain software design practices. 一种不希望出现的软件状态,在这个状态下,所有的任务因为等待一个只有在这些被阻塞任务之一才能产生的事件而被阻塞。如果死锁发生,唯一解决的方法是重启动硬件。但是,通过可靠的软件设计实践活动通常可以防止死锁的发生。 debug monitor(除错监视程序) A piece of embedded software that has been designed specifically for use as a debugging tool. It usually resides in ROM and communicates with a debugger via a serial port or network connection. The debug monitor provides a set of primitive commands to view and modify memory locations and registers, create and remove breakpoints, and execute your program. The debugger combines these primitives to fulfill higher-level requests like program download and single-step. 嵌入式软件被特殊设计来作为除错工具的一部分。它一般被放在ROM中,通过串口或网络与除错器进行通讯。除错监视程序提供一个简单的命令集来显示和内存地址和寄存器、建立和移除断点,并且运行你的程序。除错监视器组合这些简单的命令去实现象程序下载各单步调试等高端的请求。 Debugger(除错器) A software development tool used to test and debug embedded software. The debugger runs on a host computer and connects to the target through a serial port or network connection. Using a debugger you can download software to the target for immediate execution. You can also set breakpoints and examine the contents of specific memory locations and registers. 一个软件开发工具,被用来对嵌入式软件进行测试和除错。除错器在宿主机上运行并且通过串口或网络连接到目标机上。你能使用除错器下载软件到目标机并直接运行。你也可以设置断点并检查特定内存地址或寄存器的内容。 device driver(设备驱动程序) A software module that hides the details of a particular peripheral and provides a high-level programming interface to it. 一个软件模块,它隐藏特定外设的细节并提供高级的外设编程接口。 device programmer(设备编程器) A tool for programming non-volatile memories and other electrically-programmable devices. Typically, the programmable device is inserted into a socket on the device programmer and the contents of a memory buffer are then transferred into it. 一种用来对不挥发内存和其他电可编程设备进行编程的工具。典型地,可编程设备被插到设备编程器的接口上,接着内存缓存器中的内容被传送到它里面。 digital signal processor(数字信号处理器) A device that is similar to a microprocessor, except that the internal CPU has been optimized for use in applications involving discrete-time signal processing. In addition to standard microprocessor instructions, DSPs usually support a set of complex instructions to perform common signal-processing computations quickly.Common DSP families are TI"s 320Cxx and Motorola"s 5600x series. 一种类似于微处理器的的设备,不同的是它内部的CPU被优化,用于特定的应用,如离散信号处理。除了标准的微处理器指令外,DSP常常支持复杂指令集去非常快地完成通用的信号处理计算。通用DSP家庭是TI的320Cxx和Motorola的5600x系列。 E   EEPROM(电可擦的,可编程的只读存储器) Electrically Erasable, Programmable Read-Only Memory. (Pronounced"Double-E"-PROM.) A type of ROM that can be erased electronically. 电可擦的,可编程的只读存储器。一种ROM能被电擦除。 EPROM(可擦的,可编程的只读存储器) Erasable, Programmable Read-Only Memory. A type of ROM that can be erased by exposing it to ultraviolet light. Once erased, an EPROM can be reprogrammed with the help of a device programmer. 一种可用紫外线擦除的存储器。一次擦除后,EPROM可以在设备编程器的帮助下被重编程。 embedded system(嵌入式系统) A combination of computer hardware and software, and perhaps additional mechanical or other parts, designed to perform a dedicated function. In some cases, embedded systems are part of a larger system or product, as is the case of an anti-lock braking system in a car. Contrast with general-purpose computer. 计算机硬件和软件的结合体,或许还加上机械等其他部分,被设计来完成专门的功能。在一些情况下,嵌入式系统是一个大的系统或产品的一部分,就象汽车上的防抱死装置。与通用计算机相对。 Emulator(仿真器) Short for In-Circuit Emulator (ICE). A debugging tool that takes the placeof-emulates-the processor on your target board. Emulators frequently incorporate a special "bond-out" version of the target processor that allows you to observe and record its internal state as your program is executing . 在线仿真器的简写。一个在你的目标板上放置仿真的处理器的调试工具。仿真器经常和一目标处理器的一种“外合”版本合在一起,这个版本的的处理器充许你运行程序时观察和记录它的内部状态。 Executable(可执行的) A file containing object code that is ready for execution on the target. All that remains is to place the object code into a ROM or download it via a debugging tool. 一个包含准备在目标机上运行的目标代码的文件。放置目标代码到ROM中或通过调试工具下载。 F   Firmware(固件) Embedded software that is stored as object code within a ROM. This name is most common among the users of digital signal processors. 是作为目标代码存贮在ROM中的嵌入式软件。这个名字在数字信号处理器的用户中相当流行。 flash memory (闪存) A RAM-ROM hybrid that can be erased and rewritten under software control. Such devices are divided into blocks, called sectors, that are individually-erasable. Flash memory is common in systems that require nonvolatile data storage at very low cost. In some cases, a large fash memory may even be used instead of a disk-drive. 一种RAM-ROM的混血儿,它能在软件的控制下被擦除和重写。一些设备被分成叫段组的块,能个别地可擦。闪存用在需要很便宜的非易失数据存贮器的地方,一个大容量的闪存甚至被用作磁盘驱动器。 G   general-purpose computer(通用计算机) A combination of computer hardware and software that serves as a general-purpose computing platform. For example, a personal computer. Contrast with embedded system. 当作通用计算平台的计算机硬件与软件的组合。例如,PC。相对于嵌入式计算机。 H   HLL See high-level language. 查阅高级语言。 Heap(堆) An area of memory that is used for dynamic memory allocation. Calls to malloc and free and the C++ operators new and delete result in run-time manipulation of the heap. 一块被用作动态内存分配的内存区域。调用malloc和free、C++的操作符new、delete在运行时进行堆的操作。 high-level language(高级语言) A language, such as C or C++, that is processor-independent. When programming in a high-level language, it is possible to concentrate on algorithms and applications without worrying about the details of a particular processor. 一种语言,象C或C++,是处理器独立的。当在高级语言上编程时,不需要考虑特定处理器的细节,只用关心算法和应用。 Host(主机) A general-purpose computer that communicates with the target via a serial port or network connection. This term is usually used to distinguish the computer on which the debugger is running from the embedded system that is being developed. 一台通用计算机,它通过串口或网络连接与目标机通讯。这处名词一般用来区别调试程序运行的计算机和被开发的嵌入式系统。 I   ICE In-Circuit Emulator. See emulator. 在线仿真器。查阅仿真器。 I/O(输入/输出) Input/Output. The interface between a processor and the world around it. The simplest examples are switches (inputs) and LEDs (outputs). 输入/输出。处理器与外界的交互界面。最简单的例子是开关(输入)和发光二级管(输出)。 I/O device(IO设备) A piece of hardware that interfaces between the processor and the outside world. Common examples are switches and LEDs, serial ports, and network controllers. 一种介于处理器和外界之间的硬件设备。一般的实例是开关、LED、串口和网络控制器。 I/O map(I/O映射) A table or diagram containing the name and address range of each peripheral addressable by the processor within the I/O space. I/O maps are a helpful aid in getting to know the target. 一张包含每个外设的名字和地址的表格或图表,可由处理器在I/O空间中设定地址。I/O映射对得知目标机情况非常有利。 I/O space(I/O空间) A special memory region provided by some processors and generally reserved for the attachment of I/O devices. Memory locations and registers within an I/O space can be accessed only via special instructions. For example, processors in the 80x86 family have special I/O space instructions called in and out. Contrast with memory space. 一个由处理器提供的特殊内存区域,一般为为I/O设备的附件保留。在I/O空间的内存位置和寄存器只能通过特殊的指定进行访问。例如:80X86家族的处理器有叫做in / out的特殊的I/O空间指令。相对内存空间而言。 ISR(中断服务程序) See interrupt service routine. instruction pointer(指令指针) A register in the processor that contains the address of the next instruction to be executed. Also known as a program counter. 包含下一条要执行指令地址的处理器中的寄存器。也叫程序计数器。 Interrupt(中断) An asynchronous electrical signal from a peripheral to the processor. When the peripheral asserts this signal, we say that an interrupt occurs. When an interrupt occurs, the current state of the processor is saved and an interrupt service routine is executed. When the interrupt service routine exits, control of the processor is returned to whatever part of the software was previously running. 一个从外设到处理器的异步电信号。当外设发出这个信号,我们说一个中断发生。当一个中断发生,当前的处理器状态被保存并且中断服务程序开始运行。当中断服务程序退出,对处理器的控制权转到先前运行的那个软件上。 interrupt latency(中断延迟) The amount of time between the assertion of an interrupt and the start of the associated interrupt service routine. 在中断发生和相关的中断服务程序运行之间的时间长短。 interrupt service routine(中断服务程序) A piece of software executed in response to a particular interrupt. 响应特定中断而运行的一小段软件。 interrupt type(中断类型) A unique number associated with each interrupt. 和每一个中断相关联的唯一数字。 interrupt vector (中断向量) The address of an interrupt service routine. 中断服务程序所在的地址。 interrupt vector table(中断向量表) A table containing interrupt vectors and indexed by interrupt type. This table contains the processor"s mapping between interrupts and interrupt service routines and must be initialized by the programmer. 一个表格,包含由中断类型决定的中断向量和索引。这个表格包含中断与中断服务程序之间的处理器的映射,必须由程序员进行初始化。 intertask communication(进程间通讯) A mechanism used by tasks and interrupt service routines to share information and synchronize their access to shared resources. The most common building blocks of intertask communication are semaphores and mutexes. 一种被用来在任务和中断服务程序之间共享信息和同步它们对共享资源访问的机制。大部分进程间通讯的建立的基石是信号灯和互斥。   分享一些 基于STM32物联网开发资料零基础到实战、STM32热门项目合集 内含STM32的设计理念、开发原理、项目实施过程、全国电赛优秀作品合集、物联网理论与实践、IoT-ARM、ESP32教程、四轴飞行器设计制作等资料合集 https://sourl.cn/GVmj3B K   Kernel(内核) An essential part of any multitasking operating system, the kernel contains just the scheduler and context-switch routine. 任何多任务操作系统的本质部分,内核仅仅包含调度程序和上下文切换进程。 L   Linker(连接程序) A software development tool that accepts one or more object files as input and outputs a relocatable program. The linker is thus run after all of the source files have been compiled or assembled. 一种能把一个或更多目标文件组合成可输入和输出的可重定位程序的开发工具。连接程序在所有的源文件都被编译或汇编之后运行。 Locator(定位程序) A software development tool that assigns physical addresses to the relocatable program produced by the linker. This is the last step in the preparation of software for execution by an embedded system and the resulting file is called an executable. In some cases, the locator"s function may be hidden within the linker. 一种分配物理地址给连接程序处理过的可重定位程序的软件开发工具。这是准备一个软件在嵌入式系统中运行的最后一步,并且结果文件叫做可执行的。在一些情况下,定位程序功能隐藏在连接程序中。 logic analyzer(逻辑分析仪) A hardware debugging tool that can be used to capture the logic levels (0 or 1) of dozens, or even hundreds, of electrical signals in real-time. Logic analyzers can be quite helpful for debugging hardware problems and complex processor-peripheral interactions. 一种硬件调试工具,能捕获实时电信号的许多逻辑电平(0或1),逻辑分析仪在调试硬件问题和复杂的处理外设交互时相当有用。 M   memory map(内存映射) A table or diagram containing the name and address range of each peripheral addressable by the processor within the memory space. Memory maps are a helpful aid in getting to know the target. 一个在内存空间中的,包含每个外设的名字和可由处理器设置的地址范围的表格或图表。内存映射有助于了解目标机情况。 memory-mapped I/O(内存映射I/O) An increasingly common hardware design methodology in which I/O devices are placed into the memory space rather than the I/O space. From the processor"s point of view, memory-mapped I/O devices look very much like memory devices. 一种日益流行的硬件设计方法,在这种方法中,I/O设备被放置在内存空间而不是I/O空间。从处理器的观点看,内存映射I/O设备看上去很象内存一样。 memory space(内存空间) A processor"s standard address space. Contrast with I/O space. 一个处理器的标准地址空间。相对I/O空间。 Microcontroller(微控制器) A microcontroller is very similar to a microprocessor. The main difference is that a microcontroller is designed specifically for use in embedded systems Microcontrollers typically include a CPU, memory (a small amount of RAM and/or ROM), and other peripherals on the same chip. Common examples are the 8051, Intel"s 80196, and Motorola"s 68HCxx series. 微控制器很像微处理器。主要的差别在于微控制器被特殊设计用在嵌入式系统中。微控制器典型地包括CPU、内存(很小的RAM或ROM),还有其他的外设,它们在同一块芯片上。常见的例子是:8051、Intel80196、Motorola68HCxx系列。 Microprocessor(微处理器) A piece of silicon containing a general-purpose CPU. The most common examples are Intel"s 80x86 and Motorola"s 680x0 families. 一片包含通用CPU的硅片。常见的例子是:Intel80x86、Motorola 680x0系列。 Monitor(监视器) In the context of this book, a debug monitor. However, there is a second meaning for this word that is associated with intertask communication. In that context, a monitor is a language-level synchronization feature. 在这本书的上下文中,是指调试监视器。然而,第二个意思与任务间通讯相关联。在那个上下文中,监视器是高级同步机制的特性。 Multiprocessing(多处理) The use of more than one processor in a single computer system. So-called "multiprocessor systems" usually have a common memory space through which the processors can communicate and share data. In addition, some multiprocessor systems support parallel processing. 在单个的计算机系统中有多个处理器。被叫作“多处理器系统”的一般有公用的内存空间,处理器通过它们进行通讯和共享数据。另外,一些多处理器系统支持并行处理。 Multitasking (多任务) The execution of multiple software routines in pseudo-parallel. Each routine represents a separate "thread of execution" and is referred to as a task. The operating system is responsible for simulating parallelism by parceling out the processor"s time. 伪并行运行的多个软件程序。每一个程序表现得像分开的“执行的线程”并且被看作是一个任务。操作系统通过分配处理器时间来模拟并行方式。 Mutex(互斥) A data structure for mutual exclusion, also known as a binary semaphore. A mutex is basically just a multitasking-aware binary flag that can be used to synchronize the activities of multiple tasks. As such, it can be used to protect critical sections of the code from interruption and shared resources from simultaneous use. 表现互斥现象的数据结构,也被当作二元信号灯。一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同步使用的资源。 mutual exclusion(互斥现象) A guarantee of exclusive access to a shared resource. In embedded systems, the shared resource is typically a block of memory, a global variable, or a set of registers. Mutual exclusion can be achieved with the use of a semaphore or mutex. 唯一访问共享资源的保证。在嵌入式系统中,共享的资源典型的有内存块或寄存器组。互斥现象能由使用信号灯或互斥完成。 N   NVRAM Non-Volatile Random-Access Memory. A type of RAM that retains its data even when the system is powered down. NVRAM frequently consists of an SRAM and a long-life battery. 非易失的随机访问存储器。一种能在系统关机的情况下保持它的数据的RAM。NVRAM常常由SRAM和长寿命电池组成。 O   OTP See one-time programmable. object code(目标代码) A set of processor-readable opcodes and data. The output of compilers,assemblers, linkers, and locators are files containing object code. 处理器能读的操作码和数据。编译器、汇编器、连接器和定位器的输出文件都含有目标代码。 object file(目标文件) A file containing object code. The output of a compiler or assembler. 包含目标代码的文件。编译器或汇编器的输出。 one-time programmable(一次可编程的) Any programmable device, like a PROM, that can be programmed just once by the end user. However, this term is used almost exclusively to refer to microcontrollers with on-chip PROM. 任一可编程的设备,像PROM,仅仅能被最终用户编程一次。然而,这个术语一般被专有地使用在拥有片上PROM的微控制器上。 opcode A sequence of bits that is recognized by the processor as one of the instructions in its instruction set. 一串被处理器验证过的二进制位的序列,它作为其指令集的一个子集。 operating system(操作系统) A piece of software that makes multitasking possible. An operating system typically consists of a set of function calls, or software interrupts, and a periodic clock tick. The operating system is responsible for deciding which task should be using the processor at a given time and for controlling access to shared resources. 使多任务能够实现的一个软件。一个操作系统典型地由一个函数调用集、软件中断和定期时钟周期组成。一个操作系统负责决定哪一个任务在给定的时间将使用处理器,并且控制对共享资源的访问。 Oscilloscope(示波器) A hardware debugging tool that allows you to view the voltage on one or more electrical lines. For example, you might use an oscilloscope to determine if a particular interrupt is currently asserted. 一种硬件调试工具,它让你能观察到一个或更多电路上的电压。例如:如果一个特殊的中断发生,你可以用一个示波器去检测它。 P   PROM(可编程只读存储器) Programmable Read-Only Memory. A type of ROM that can be written (programmed) with a device programmer. These memory devices can be programmed only once, so they are sometimes referred to as write-once or one-time programmable devices. 可编程只读存储器。能被设备编程器写的一种ROM。这种内存设备可以被编程一次,所以它们有时被作为写一次或一次性编程设备来看待。 parallel processing(并行进程) The ability to apply two or more processors to a single computation. 一种在单个计算机上运行两个或多个程序的能力。 Peripheral (外设) A piece of hardware other than the processor, usually memory or an I/O device. The peripheral may reside within the same chip as the processor, in which case it is called an internal peripheral. 一种不同于处理器的硬件设备,常指内存或I/O设备。外设经常和处理器在一片芯片上,在这种情况下,它被称为集成外设。 physical address(物理地址) The actual address that is placed on the address bus when accessing a memory location or register. 当访问内存位置或寄存器时,在地址总线上的真实的地址。 Preemptive(抢先) A scheduler is said to be preemptive if it allows the running task to be suspended when a higher-priority task becomes ready. Non-preemptive schedulers are easier to implement but less appropriate for embedded systems. 当一个高优先级的任务准备好时,充许正在运行的任务被挂起的调度策略被称为优先。无优先的调度策略更容易实现一些但适合在嵌入式系统中使用。 Polling(轮询) A method of interfacing with hardware that involves repeatedly reading a status register until the device has reached the awaited state. Device drivers are either polling or interrupt-driven, with the latter being more generally preferred. 一种硬件交互方法,不断读状态寄存器,直到设备进入等待状态。设备驱动程序不是轮询的就是中断驱动的,后一种越来越成为首选的。 Priority(优先) The relative importance of one task compared to another. 一个任务与其他任务相比的重要关系。 priority inversion(优先转置) An unwanted software situation in which a high-priority task is delayed while waiting for access to a shared resource that is not even being used at the time. For all practical purposes, the priority of this task has been lowered during the delay period. 一种不希望发生的软件状态,在此状态一个高优先级任务因为等待访问一个那时不再使用的共享资源而被延迟。在所有的实践目标中,这个任务的优先级在延迟周期内都被降低。 Process(进程) A word that is often confused with task or thread. The crucial distinction is that all of the tasks in a system share a common memory space. Processes, on the other hand, always have their own private memory space. Processes are common in multi-user systems but are rarely, if ever, found in embedded systems. 这个名词经常与任务或线程混淆。至关重要的差别在于系统中的所有任务共享公共的内存空间。进程,另一方面,常常有它们自己的私有内存空间。进程在多用户系统中,但少有地,如有可能,也可在嵌入式系统中。 Processor(处理器) A generic term that does not distinction between microprocessor, microcontroller, and digital signal processor. 一个对于微处理器、微控制器他数字信号处器无差别的通用术语。 processor family(处理器族) A set of related processors, usually successive generations from the same manufacturer. For example, Intel"s 80x86 family began with the 8086 and now includes the 80186, 286, 386, 486, Pentium, and many others. The later models in a family are typically backwards-compatible with the ones that came before. 一个相关的处理器集,常常连续地从一个生产商产生。例如:Intel"s 80x86族开始从8086开始,现在有80186, 286, 386, 486, Pentium及其他。在一个族中,稍后的产品典型地向后兼容在它以前生产的产品。 processor-independent(处理器无关) A piece of software that is independent of the processor on which it will be run. Most programs that can be written in a high-level language are processor-independent. Contrast with processor-specific. 一个与处理器无关的,并能在其上运行的软件。大多数用高级语言编写程序是处理器无关的。相对于处理器定制。 processor-specific(处理器定制) A piece of software that is highly dependent on the processor on which it will be run. Such code must usually be written in assembly language. Contrast with processor-independent. 一个高度依赖处理器的软件,在上其才能运行。一些代码必须用汇编语言编写。相对于处理器无关。 Profiler(明细观察程序) A software development tool that collects and reports execution statistics for your programs. These statistics include the number of calls to each subroutine and the total amount of time spent within each. This data can be used to learn which subroutines are the most critical and, therefore, demand the greatest code efficiency. 一种报告你的程序运行统计数据的软件调试工具。这些统计数据包括调用每个子程序的次数和用去的时间。这些数据常被用来了解哪些子程序是最关键的,并且,由此要求使最好的代码有效率。 program counter See instruction pointer. R   RAM(随机访问存储器) Random-Access Memory. A broad classification of memory devices that includes all devices in which individual memory locations may be read or written as required. 随机访问存储器。一个包含了所有每个地址能被按需读写的存储设备的粗略分类。 RISC(精简指令集计算机) Reduced Instruction Set Computer. Describes the architecture of a processor family. RISC processors generally feature fixed-length instructions, a load-store memory architecture, and a large number of general-purpose registers and/or register windows. The MIPS processor family is an excellent example. Contrast with CISC. 精简指令集计算机。一个处理器族的描述。RISC处理器一般的特征是固定长度的指令集,一个负载储备存储结构,和大量通用寄存器,及寄存器窗口。MIPS处理器族是极好的例子。相对CISC而言。 ROM(只读存储器) Read-Only Memory. A broad classification of memory devices that includes all devices in which the individual memory locations may be read, but not written. 只读存储器。一个包括所的的每个地址只能被读,不能被写的存储器的大概分类。 ROM emulator(ROM模拟器) A debugging tool that takes the place of-or emulates-the ROM on your target board. A ROM emulator acts very much like a debug monitor, except that it includes its own serial or network connection to the host. 一种在你的目标板上代替或模拟ROM的调试工具。ROM模拟器动作起来象一个除错监视器,除了它包含自己连到主机上的串口或网络外。 ROM monitor See debug monitor. RTOS(实时操作系统) Real-Time Operating System. An operating system designed specifically for use in real-time systems. 实时操作系统。一种被特殊设计来用在实时系统中的操作系统。 race condition(竞争状态) A situation in which the outcome of a program may be affected by the exact order in which the instructions are executed. Race conditions are only an issue where interrupts and/or preemption are possible and where critical sections exist. 一种程序运行的结果可能被指令执行的顺序影响的情形。竞争状态仅仅有一种情况下产生,在此处中断或(和)优先抢占是充许的并且有一个临界区存在。 real-time system(实时系统) Any computer system, embedded or otherwise, that has deadlines. The following question can be used to distinguish real-time systems from the rest: "Is a late answer as bad, or even worse, than a wrong answer?" In other words, what happens if the computation doesn"t finish in time? If nothing bad happens, it"s not a real-time system. If someone dies or the mission fails, it"s generally considered "hard" real-time, which is meant to imply that the system has "hard" deadlines. Everything in between is "soft" real-time. 任何计算机系统,嵌入的或其他的,有一个死线。以下的问题可经被用来区分实时系统与其他的系统:“是迟到的回答坏,还是一个错误的回答坏?”换句话说,如果计算机没有在指定时间内完成它的工作会发生什么?如果什么也没有发生,它不是一个实时系统。如果一些人死或任务失败,它被认为是“硬”实时系统,意思是系统有一个“硬”死线。介于两者之间的是“软”实时系统。 Recursive(递归) Said of software that calls itself. Recursion should generally be avoided in an embedded system, since it frequently requires a large stack. 自己调用自己的程序的说法。递归一般在嵌入式系统中是不充许的,因为它常常占有大量的堆栈空间。 Reentrant(可再入的) Said of software that can be executed multiple times simultaneously. A reentrant function can be safely called recursively or from multiple tasks. The key to making code reentrant is to ensure mutual exclusion whenever accessing global variables or shared registers. 可同时多次运行的程序的说法。可再入的函数可以被安全地递归调用或由多任务多次调用。使代码可再入的关键在于确保在访问全局变量或共享寄存器时互斥现象发生。 Register(寄存器) A memory location that is part of a processor or an I/O device. In other words, it"s not normal memory. Generally, each bit or set of bits within the register controls some behavior of the larger device. 是处理器或I/O设备一部分的储存器的地址。换句话说,不是标准的储存器。一般地,在寄存器控制每一二进制位或二进制位的集控制大量设备的一些行为。 Relocatable(可重定位的) A file containing object code that is almost ready for execution on the target. The final step is to use a locator to fix the remaining relocatable addresses within the code. The result of that process is an executable. 包含几乎可以准备好在目标机上运行的目标代码的文件。最后一步是使用定位程序去整理保留在代码中的可重定位地址。这个步骤的结果是一个可执行的程序。 reset address(重启地址) The address from which the first instruction will be fetched after the processor is powered on or reset. 一个处理器上电或重启后第一个指令能被从之取出来的地址。 reset code(重启代码) A small piece of code that is placed at the reset address. The reset code is usually written in assembly language and may simply be the equivalent of "jump to the startup code." 一段被放置在重启地址的代码。重启代码一般用汇编语言编写并且可能相当简单,只是与”跳转到开始代码”这样的意思相同。 reset vector See reset address. S   SRAM(静态随机访问储存器) Static Random-Access Memory. A type of RAM that retains its contents as long as the system is powered on. Data stored in an SRAM is lost when the system is powered down or reset. 静态随机访问储存器。一种在系统上电时以保持它的内容的储存器。当系统断电或重启时,保存在SRAM中的内容将丢失。 Scheduler(调度程序) The part of an operating system that decides which task to run next. This decision is based on the readiness of each task, their relative priorities, and the specific scheduling algorithm implemented. 操作系统中决定下一次哪个任务运行的那部分。决定基于每一个任务的就绪,它们的优先级关系,和特殊调度算法的实现。 Semaphore(信号灯) A data structure that is used for intertask synchronization. Semaphores are usually provided by the operating system. 用于进程间同步的数据结构。信号灯常常由操作系统提供。 Simulator(仿真器) A debugging tool that runs on the host and pretends to be the target processor. A simulator can be used to test pieces of the software before the embedded hardware is available. Unfortunately, attempts to simulate interactions with complex peripherals are often more trouble than they are worth. 一种运行在主机上,装作目标机处理器的调试工具。仿真器一般用来测试嵌入式硬件可用之前的软件。不幸地,与模拟与复杂地外设进行交互的尝试常常比它们做到的更差。 software interrupt(软件中断) An interruption of a program that is initiated by a software instruction. Software interrupts are commonly used to implement breakpoints and operating system entry points. Unlike true interrupts, they occur synchronously with respect to program execution. In other words, software interrupts always occur at the beginning of an instruction execution cycle. 由软件指令发起的的一个程序的中断。软件中断被用来实现中断点他操作系统进入点。不象真实的中断,那些中断在不防碍程序执行时同步发生。换句话说,软件中断常常在指令运行周期的开始发生。 Stack(堆栈) An area of memory that contains a last-in-first-out queue of storage for parameters, automatic variables, return addresses, and other information that must be maintained across function calls. In multitasking situations, each task generally has its own stack. 一个包含后进先出队列的内存区域,用来存储参数、自动变量、返回地址和其他一些必须在函数调用中进行维护的信息。在多任务情况下,每一个任务一般都有自己的堆栈区。 stack frame(堆栈帧) An area of the stack associated with a particular function call. 一个关联特殊函数调用的堆栈区域。 startup code(启动代码) A piece of assembly language code that prepares the way for software written in a high-level language. Most C/C++ cross-compilers come with startup code that you can modify, compile, and link with your embedded programs. 一个汇编语言代码,它为高级语言写的软件准备好运行的前期工作。大多数C/C++交叉编译器在你可以修改、编译他连接你的嵌入式程序时与启动代码一起来到。 T   Target(目标机) Another name for the embedded system. This term is usually used during software development, to distinguish the embedded system from the host with which it communicates. 嵌入式系统的另一个名字。这个术语常常在软件开发期间使用,用来区别与嵌入式系统通讯的主机。 Task(任务) The central abstraction of an operating system. Each task must maintain its own copy of the instruction pointer and general-purpose registers. Unlike processes, tasks share a common memory space and must be careful to avoid overwriting each other"s code and data. Thread(线程) Another name for a task. This name is more common in operating systems that support processes. A task is simply a thread in a single-process system. Tracepoint (跟踪点) Like a breakpoint except that a counter is incremented rather than stopping the program. Tracepoints are not supported by all debugging tools. 象中断点,除了停止程序时,计数器还被增加外。跟踪点不是被所有的调试工具支持。 Trap(陷入) An interruption of a program that is triggered by the processor"s own internal hardware. For example, the processor might trap if an illegal opcode is found within the program. Compare with software interrupt. 一个由处理器内部硬件触发的程序中断。例如,处理器可能在一个错误的代码在程序中被发现时陷入。对比软件中断。 V   volatile(动态) A value that may change without the intervention of software is said to be volatile. For example, values within the registers of some I/O devices may change in response to external events. C"s volatile keyword should be used to warn your compiler about any pointers that point to such registers. This will ensure that the actual value is reread each time the data is used. 一个可能不需要软件的的干涉就可改变的值被叫作动态。例如:在一些I/O设备的寄存器的值可能在响应外部事件时被改变。C语言中的volatile关键字被用来警告你的编译器那是一个指向一些寄存器的指针,请不要优化它。这个将确认在数据使用中的每一时间实际的值是要重新读入的。 W   watchdog timer(看门狗定时器) A hardware timer that is periodically reset by software. If the software crashesor hangs, the watchdog timer will expire, and the entire system will be reset automatically. 一种由软件定时重设的硬件定时器。如果软件被破坏而挂起,看门狗定时器将超时,整个系统将自动重启。   丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨    

  • 发表了主题帖: 16条Java的代码规范

      背景:如何更规范化编写Java代码的重要性想必毋需多言,其中最重要的几点当属提高代码性能、使代码远离Bug、令代码更优雅。 一、MyBatis不要为了多个查询条件而写1=1 当遇到多个查询条件,使用where 1=1 可以很方便的解决我们的问题,但是这样很可能会造成非常大的性能损失,因为添加了 “where 1=1 ”的过滤条件之后,数据库系统就无法使用索引等查询优化策略,数据库系统将会被迫对每行数据进行扫描(即全表扫描) 以比较此行是否满足过滤条件,当表中的数据量较大时查询速度会非常慢;此外,还会存在SQL 注入的风险。 反例: <select id="queryBookInfo" parameterType="com.tjt.platform.entity.BookInfo" resultType="java.lang.Integer">  select count(*) from t_rule_BookInfo t where 1=1 <if test="title !=null and title !='' ">  AND title = #{title} </if> <if test="author !=null and author !='' ">  AND author = #{author} </if> </select>   正例: <select id="queryBookInfo" parameterType="com.tjt.platform.entity.BookInfo" resultType="java.lang.Integer">  select count(*) from t_rule_BookInfo t <where> <if test="title !=null and title !='' ">  title = #{title} </if> <if test="author !=null and author !='' ">  AND author = #{author} </if> </where> </select>   UPDATE 操作也一样,可以用<set> 标记代替 1=1。 二、迭代entrySet()获取Map的key和value 当循环中只需要获取Map 的主键key时,迭代keySet() 是正确的;但是,当需要主键key 和取值value 时,迭代entrySet() 才是更高效的做法,其比先迭代keySet() 后再去通过get 取值性能更佳。 反例: //Map 获取value 反例: HashMap<String, String> map = new HashMap<>(); for (String key : map.keySet()){ String value = map.get(key); }   正例:   //Map 获取key & value 正例: HashMap<String, String> map = new HashMap<>();  for (Map.Entry<String,String> entry : map.entrySet()){      String key = entry.getKey();      String value = entry.getValue(); } 三、使用Collection.isEmpty()检测空 使用Collection.size() 来检测是否为空在逻辑上没有问题,但是使用Collection.isEmpty() 使得代码更易读,并且可以获得更好的性能;除此之外,任何Collection.isEmpty() 实现的时间复杂度都是O(1) ,不需要多次循环遍历,但是某些通过Collection.size() 方法实现的时间复杂度可能是O(n)。O(1)纬度减少循环次数例子。 反例: LinkedList<Object> collection = new LinkedList<>(); if (collection.size() == 0){   System.out.println("collection is empty.");  }     正例: LinkedList<Object> collection = new LinkedList<>();   if (collection.isEmpty()){       System.out.println("collection is empty.");   }     //检测是否为null 可以使用CollectionUtils.isEmpty()   if (CollectionUtils.isEmpty(collection)){       System.out.println("collection is null.");     } 四、初始化集合时尽量指定其大小 尽量在初始化时指定集合的大小,能有效减少集合的扩容次数,因为集合每次扩容的时间复杂度很可能时O(n),耗费时间和性能。 反例: //初始化list,往list 中添加元素反例: int[] arr = new int[]{1,2,3,4}; List<Integer> list = new ArrayList<>(); for (int i : arr){   list.add(i); }   正例: //初始化list,往list 中添加元素正例:   int[] arr = new int[]{1,2,3,4};   //指定集合list 的容量大小   List<Integer> list = new ArrayList<>(arr.length);   for (int i : arr){       list.add(i);   }   五、使用StringBuilder拼接字符串 一般的字符串拼接在编译期Java 会对其进行优化,但是在循环中字符串的拼接Java 编译期无法执行优化,所以需要使用StringBuilder 进行替换。 反例: //在循环中拼接字符串反例 String str = ""; for (int i = 0; i < 10; i++){   //在循环中字符串拼接Java 不会对其进行优化   str += i; }   正例: //在循环中拼接字符串正例  String str1 = "Love";  String str2 = "Courage";  String strConcat = str1 + str2;  //Java 编译器会对该普通模式的字符串拼接进行优化   StringBuilder sb = new StringBuilder();   for (int i = 0; i < 10; i++){      //在循环中,Java 编译器无法进行优化,所以要手动使用StringBuilder       sb.append(i);   }   六、若需频繁调用Collection.contains方法则使用Set       在Java 集合类库中,List的contains 方法普遍时间复杂度为O(n),若代码中需要频繁调用contains 方法查找数据则先将集合list 转换成HashSet 实现,将O(n) 的时间复杂度将为O(1)。 反例: //频繁调用Collection.contains() 反例 List<Object> list = new ArrayList<>(); for (int i = 0; i <= Integer.MAX_VALUE; i++){   //时间复杂度为O(n)   if (list.contains(i))   System.out.println("list contains "+ i);  }   正例: //频繁调用Collection.contains() 正例   List<Object> list = new ArrayList<>();   Set<Object> set = new HashSet<>();   for (int i = 0; i <= Integer.MAX_VALUE; i++){       //时间复杂度为O(1)       if (set.contains(i)){           System.out.println("list contains "+ i);       }   }   七、使用静态代码块实现赋值静态成员变量 对于集合类型的静态成员变量,应该使用静态代码块赋值,而不是使用集合实现来赋值。       反例: //赋值静态成员变量反例     private static Map<String, Integer> map = new HashMap<String, Integer>(){         {             map.put("Leo",1);             map.put("Family-loving",2);             map.put("Cold on the out side passionate on the inside",3);         }     };     private static List<String> list = new ArrayList<>(){         {             list.add("Sagittarius");             list.add("Charming");             list.add("Perfectionist");         }     };   正例: //赋值静态成员变量正例 private static Map<String, Integer> map = new HashMap<String, Integer>();     static {         map.put("Leo",1);         map.put("Family-loving",2);         map.put("Cold on the out side passionate on the inside",3);     }   private static List<String> list = new ArrayList<>();     static {         list.add("Sagittarius");         list.add("Charming");         list.add("Perfectionist");     }   八、删除未使用的局部变量、方法参数、私有方法、字段和多余的括号。     九、工具类中屏蔽构造函数 工具类是一堆静态字段和函数的集合,其不应该被实例化;但是,Java 为每个没有明确定义构造函数的类添加了一个隐式公有构造函数,为了避免不必要的实例化,应该显式定义私有构造函数来屏蔽这个隐式公有构造函数。 反例: public class PasswordUtils {   //工具类构造函数反例   private static final Logger LOG = LoggerFactory.getLogger(PasswordUtils.class);     public static final String DEFAULT_CRYPT_ALGO = "PBEWithMD5AndDES";     public static String encryptPassword(String aPassword) throws IOException {       return new PasswordUtils(aPassword).encrypt();   }   正例: public class PasswordUtils {   //工具类构造函数正例   private static final Logger LOG = LoggerFactory.getLogger(PasswordUtils.class);     //定义私有构造函数来屏蔽这个隐式公有构造函数   private PasswordUtils(){}     public static final String DEFAULT_CRYPT_ALGO = "PBEWithMD5AndDES";     public static String encryptPassword(String aPassword) throws IOException {       return new PasswordUtils(aPassword).encrypt();   }   十、删除多余的异常捕获并抛出       用catch 语句捕获异常后,若什么也不进行处理,就只是让异常重新抛出,这跟不捕获异常的效果一样,可以删除这块代码或添加别的处理。 反例: //多余异常反例 private static String fileReader(String fileName)throws IOException{       try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {         String line;         StringBuilder builder = new StringBuilder();         while ((line = reader.readLine()) != null) {             builder.append(line);         }         return builder.toString();     } catch (Exception e) {         //仅仅是重复抛异常 未作任何处理         throw e;     } }   正例:   //多余异常正例 private static String fileReader(String fileName)throws IOException{       try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {         String line;         StringBuilder builder = new StringBuilder();         while ((line = reader.readLine()) != null) {             builder.append(line);         }         return builder.toString();         //删除多余的抛异常,或增加其他处理:         /*catch (Exception e) {             return "fileReader exception";         }*/     } }     十一、字符串转化使用String.valueOf(value)代替""+value 把其它对象或类型转化为字符串时,使用String.valueOf(value) 比 ""+value 的效率更高。 反例: //把其它对象或类型转化为字符串反例: int num = 520; // "" + value String strLove = "" + num;   正例: //把其它对象或类型转化为字符串正例: int num = 520; // String.valueOf() 效率更高 String strLove = String.valueOf(num);   十二、避免使用BigDecimal(double) BigDecimal(double) 存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。 反例:   // BigDecimal 反例 BigDecimal bigDecimal = new BigDecimal(0.11D);   正例: // BigDecimal 正例 BigDecimal bigDecimal1 = bigDecimal.valueOf(0.11D);     失去精度 十三、返回空数组和集合而非null 若程序运行返回null,需要调用方强制检测null,否则就会抛出空指针异常;返回空数组或空集合,有效地避免了调用方因为未检测null 而抛出空指针异常的情况,还可以删除调用方检测null 的语句使代码更简洁。 反例: //返回null 反例 public static Result[] getResults() {     return null; }   public static List<Result> getResultList() {     return null; }   public static Map<String, Result> getResultMap() {     return null; }   正例: //返回空数组和空集正例 public static Result[] getResults() {     return new Result[0]; }   public static List<Result> getResultList() {     return Collections.emptyList(); }   public static Map<String, Result> getResultMap() {     return Collections.emptyMap(); }   十四、优先使用常量或确定值调用equals方法 对象的equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals 方法。 反例:  //调用 equals 方法反例 private static boolean fileReader(String fileName)throws IOException{    // 可能抛空指针异常    return fileName.equals("Charming");  }   正例: //调用 equals 方法正例 private static boolean fileReader(String fileName)throws IOException{       // 使用常量或确定有值的对象来调用 equals 方法     return "Charming".equals(fileName);       //或使用:java.util.Objects.equals() 方法    return Objects.equals("Charming",fileName);  }   十五、枚举的属性字段必须是私有且不可变 枚举通常被当做常量使用,如果枚举中存在公共属性字段或设置字段方法,那么这些枚举常量的属性很容易被修改;理想情况下,枚举中的属性字段是私有的,并在私有构造函数中赋值,没有对应的Setter 方法,最好加上final 修饰符。 反例: public enum SwitchStatus {     // 枚举的属性字段反例     DISABLED(0, "禁用"),     ENABLED(1, "启用");       public int value;     private String description;       private SwitchStatus(int value, String description) {         this.value = value;         this.description = description;     }       public String getDescription() {         return description;     }       public void setDescription(String description) {         this.description = description;     } }   正例: public enum SwitchStatus {     // 枚举的属性字段正例     DISABLED(0, "禁用"),     ENABLED(1, "启用");       // final 修饰     private final int value;     private final String description;       private SwitchStatus(int value, String description) {         this.value = value;         this.description = description;     }       // 没有Setter 方法     public int getValue() {         return value;     }       public String getDescription() {         return description;     } }   十六、tring.split(String regex)部分关键字需要转译 使用字符串String 的plit 方法时,传入的分隔字符串是正则表达式,则部分关键字(比如 .[]()\| 等)需要转义。 反例:  // String.split(String regex) 反例 String[] split = "a.ab.abc".split("."); System.out.println(Arrays.toString(split));   // 结果为[] String[] split1 = "a|ab|abc".split("|"); System.out.println(Arrays.toString(split1));  // 结果为["a", "|", "a", "b", "|", "a", "b", "c"]   正例: // String.split(String regex) 正例 // . 需要转译 String[] split2 = "a.ab.abc".split("\\."); System.out.println(Arrays.toString(split2));  // 结果为["a", "ab", "abc"]   // | 需要转译 String[] split3 = "a|ab|abc".split("\\|"); System.out.println(Arrays.toString(split3));  // 结果为["a", "ab", "abc"]     图2. String.split(String regex) 正反例     丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 2021-08-17
  • 发表了主题帖: 获取STM32代码运行时间的技巧

    前言     测试代码的运行时间的两种方法: 1、使用单片机内部定时器,在待测程序段的开始启动定时器,在待测程序段的结尾关闭定时器。为了测量的准确性,要进行多次测量,并进行平均取值。 2、借助示波器的方法是:在待测程序段的开始阶段使单片机的一个GPIO输出高电平,在待测程序段的结尾阶段再令这个GPIO输出低电平。用示波器通过检查高电平的时间长度,就知道了这段代码的运行时间。显然,借助于示波器的方法更为简便。 借助示波器方法的实例     Delay_us函数使用STM32系统滴答定时器实现: #include "systick.h" /* SystemFrequency / 1000    1ms中断一次  * SystemFrequency / 100000     10us中断一次  * SystemFrequency / 1000000 1us中断一次  */ #define SYSTICKPERIOD                    0.000001 #define SYSTICKFREQUENCY            (1/SYSTICKPERIOD) /**   * @brief  读取SysTick的状态位COUNTFLAG   * @param  无   * @retval The new state of USART_FLAG (SET or RESET).   */ static FlagStatus SysTick_GetFlagStatus(void) {     if(SysTick->CTRL&SysTick_CTRL_COUNTFLAG_Msk)     {         return SET;     }     else     {         return RESET;     } } /**   * @brief  配置系统滴答定时器 SysTick   * @param  无   * @retval 1 = failed, 0 = successful   */ uint32_t SysTick_Init(void) {        /* 设置定时周期为1us  */     if (SysTick_Config(SystemCoreClock / SYSTICKFREQUENCY))     {         /* Capture error */         return (1);     }     /* 关闭滴答定时器且禁止中断  */     SysTick->CTRL &= ~ (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);                                                       return (0); } /**   * @brief   us延时程序,10us为一个单位   * @param     *        @arg nTime: Delay_us( 10 ) 则实现的延时为 10 * 1us = 10us   * @retval  无   */ void Delay_us(__IO uint32_t nTime) {          /* 清零计数器并使能滴答定时器 */       SysTick->VAL   = 0;       SysTick->CTRL |=  SysTick_CTRL_ENABLE_Msk;          for( ; nTime > 0 ; nTime--)     {      /* 等待一个延时单位的结束 */      while(SysTick_GetFlagStatus() != SET);     }     /* 关闭滴答定时器 */     SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk; }     检验Delay_us执行时间中用到的GPIO(gpio.h、gpio.c)的配置: #ifndef __GPIO_H #define    __GPIO_H #include "stm32f10x.h" #define     LOW          0 #define     HIGH         1 /* 带参宏,可以像内联函数一样使用 */ #define TX(a)                if (a)    \                                             GPIO_SetBits(GPIOB,GPIO_Pin_0);\                                         else        \                                             GPIO_ResetBits(GPIOB,GPIO_Pin_0) void GPIO_Config(void); #endif #include "gpio.h"     /**   * @brief  初始化GPIO   * @param  无   * @retval 无   */ void GPIO_Config(void) {                 /*定义一个GPIO_InitTypeDef类型的结构体*/         GPIO_InitTypeDef GPIO_InitStructure;         /*开启LED的外设时钟*/         RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);                                                                     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;             GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;              GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         GPIO_Init(GPIOB, &GPIO_InitStructure);     }    在main函数中检验Delay_us的执行时间:   #include "systick.h" #include "gpio.h" /**   * @brief  主函数   * @param  无     * @retval 无   */ int main(void) {         GPIO_Config();     /* 配置SysTick定时周期为1us */     SysTick_Init();     for(;;)     {         TX(HIGH);         Delay_us(1);         TX(LOW);         Delay_us(100);     }      }   示波器的观察结果:         可见Delay_us(100),执行了大概102us,而Delay_us(1)执行了2.2us。     更改一下main函数的延时参数:   int main(void) {         /* LED 端口初始化 */     GPIO_Config();     /* 配置SysTick定时周期为1us */     SysTick_Init();     for(;;)     {         TX(HIGH);         Delay_us(10);         TX(LOW);         Delay_us(100);     }      }     示波器的观察结果:         可见Delay_us(100),执行了大概101us,而Delay_us(10)执行了11.4us。     结论:此延时函数基本上还是可靠的。 使用定时器方法的实例     Delay_us函数使用STM32定时器2实现:   #include "timer.h" /* SystemFrequency / 1000            1ms中断一次  * SystemFrequency / 100000     10us中断一次  * SystemFrequency / 1000000         1us中断一次  */ #define SYSTICKPERIOD                    0.000001 #define SYSTICKFREQUENCY            (1/SYSTICKPERIOD) /**   * @brief  定时器2的初始化,,定时周期1uS   * @param  无   * @retval 无   */ void TIM2_Init(void) {     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;     /*AHB = 72MHz,RCC_CFGR的PPRE1 = 2,所以APB1 = 36MHz,TIM2CLK = APB1*2 = 72MHz */     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);          /* Time base configuration */              TIM_TimeBaseStructure.TIM_Period = SystemCoreClock/SYSTICKFREQUENCY -1;     TIM_TimeBaseStructure.TIM_Prescaler = 0;     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;     TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);          TIM_ARRPreloadConfig(TIM2, ENABLE);          /* 设置更新请求源只在计数器上溢或下溢时产生中断 */     TIM_UpdateRequestConfig(TIM2,TIM_UpdateSource_Global);     TIM_ClearFlag(TIM2, TIM_FLAG_Update); } /**   * @brief   us延时程序,10us为一个单位   * @param     *        @arg nTime: Delay_us( 10 ) 则实现的延时为 10 * 1us = 10us   * @retval  无   */ void Delay_us(__IO uint32_t nTime) {          /* 清零计数器并使能滴答定时器 */       TIM2->CNT   = 0;       TIM_Cmd(TIM2, ENABLE);          for( ; nTime > 0 ; nTime--)     {      /* 等待一个延时单位的结束 */      while(TIM_GetFlagStatus(TIM2, TIM_FLAG_Update) != SET);      TIM_ClearFlag(TIM2, TIM_FLAG_Update);     }     TIM_Cmd(TIM2, DISABLE); }  在main函数中检验Delay_us的执行时间: #include "stm32f10x.h" #include "Timer_Drive.h" #include "gpio.h" #include "systick.h" TimingVarTypeDef Time; int main(void) {         TIM2_Init();         SysTick_Init();     SysTick_Time_Init(&Time);          for(;;)     {         SysTick_Time_Start();         Delay_us(1000);         SysTick_Time_Stop();     }      }     怎么去看检测结果呢?用调试的办法,打开调试界面后,将Time变量添加到Watch一栏中。然后全速运行程序,既可以看到Time中保存变量的变化情况,其中TimeWidthAvrage就是最终的结果。       可以看到TimeWidthAvrage的值等于0x119B8,十进制数对应72120,滴答定时器的一个滴答为1/72M(s),所以Delay_us(1000)的执行时间就是72120*1/72M (s) = 0.001001s,也就是1ms。验证成功。     备注:定时器方法输出检测结果有待改善,你可以把得到的TimeWidthAvrage转换成时间(以us、ms、s)为单位,然后通过串口打印出来,不过这部分工作对于经常使用调试的人员来说也可有可无。 两种方法对比 软件测试方法     操作起来复杂,由于在原代码基础上增加了测试代码,可能会影响到原代码的工作,测试可靠性相对较低。由于使用32位的变量保存systick的计数次数,计时的最大长度可以达到2^32/72M = 59.65 s。 示波器方法     操作简单,在原代码基础上几乎没有增加代码,测试可靠性很高。由于示波器的显示能力有限,超过1s以上的程序段,计时效果不是很理想。但是,通常的单片机程序实时性要求很高,一般不会出现程序段时间超过秒级的情况。       丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 发表了主题帖: PCB设计新人指南

        在开始新设计时,因为将大部分时间都花在了电路设计和元件的选择上,在PCB布局布线阶段往往会因为经验不足,考虑不够周全。     如果没有为PCB布局布线阶段的设计提供充足的时间和精力,可能会导致设计从数字领域转化为物理现实的时候,在制造阶段出现问题,或者在功能方面产生缺陷。      那么设计一个在纸上和物理形式上都真实可靠的电路板的关键是什么?让我们探讨设计一个可制造,功能可靠的PCB时需要了解的前6个PCB设计指南。 1 微调元件布置     PCB布局过程的元件放置阶段既是科学又是艺术,需要对电路板上可用的主要元器件进行战略性考虑。虽然这个过程可能具有挑战性,但你放置电子元件的方式将决定你的电路板的制造难易程度,以及它如何满足你的原始设计要求。 虽然存在元件放置的常规通用顺序,如按顺序依次放置连接器,印刷电路板的安装器件,电源电路,精密电路,关键电路等,但也有一些具体的指导方针需要牢记,包括: ·取向 - 确保将相似的元件定位在相同的方向上,这将有助于实现高效且无差错的焊接过程。 ·布置 - 避免将较小元件放置在较大元件的后面,这样小元件有可能受大元件焊接的影响而产生装贴问题。 ·组织 - 建议将所有表面贴装(SMT)元件放置在电路板的同一侧,并将所有通孔(TH)元件放置在电路板顶部,以尽量减少组装步骤。   最后还要注意的一条PCB设计指南 - 即当使用混合技术元件(通孔和表面贴装元件)时,制造商可能需要额外的工艺来组装电路板,这将增加你的总体成本。 下图,良好的芯片元件方向(左)和不良的芯片元件方向(右)。      下图,良好的元件布置(左)和不良元件布置(右)。   2、合适放置电源,接地和信号走线     放置元件后,接下来可以放置电源,接地和信号走线,以确保你的信号具有干净无故障的通行路径。在布局过程的这个阶段,请记住以下一些准则: 定位电源和接地平面层     始终建议将电源和接地平面层置于电路板内部,同时保持对称和居中。这有助于防止你的电路板弯曲,这也关系到你的元件是否正确定位。     对于给IC供电,建议为每路电源使用公共通道,确保有坚固并且稳定的走线宽度,并且避免元件到元件之间的菊花链式电源连接。 信号线走线连接     接下来,按照原理图中的设计情况连接信号线。建议在元件之间始终采取尽可能短的路径和直接的路径走线。     如果你的元件需要毫无偏差地固定放置在水平方向,那么建议在电路板的元件出线的地方基本上水平走线,而出线之后再进行垂直走线。     这样在焊接的时候随着焊料的迁徙,元件会固定在水平方向。如下图上半部分所示。而下图下半部分的信号走线方式,在焊接的时候随着焊料的流动,有可能会造成元件的偏转。     下图,建议的布线方式 (箭头指示焊料流动方向)。      下图,不建议的布线方式 (箭头指示焊料流动方向) 。   定义网络宽度     你的设计可能需要不同的网络,这些网络将承载各种电流,这将决定所需的网络宽度。考虑到这一基本要求,建议为低电流模拟和数字信号提供0.010’’(10mil)宽度。当你的线路电流超过0.3安培时,它应该进行加宽。这里有一个免费的线路宽度计算器,使这个换算过程变得简单。 3 有效隔离     你可能已经体验到电源电路中的大电压和电流尖峰如何干扰你的低压电流的控制电路。要尽量减少此类干扰问题,请遵循以下准则: ·隔离 - 确保每路电源都保持电源地和控制地分开。如果你必须将它们在PCB中连接在一起,请确保它尽可能地靠近电源路径的末端。 ·布置 - 如果你已在中间层放置了地平面,请确保放置一个小阻抗路径,以降低任何电源电路干扰的风险,并帮助保护你的控制信号。可以遵循相同的准则,以保持你的数字和模拟的分开。 ·耦合 - 为了减少由于放置了大的地平面以及在其上方和下方走线的电容耦合,请尝试仅通过模拟信号线路交叉模拟地。       上图,元件隔离示例(数字和模拟)。 4 解决热量问题     你是否曾因热量问题而导致电路性能的降低甚至电路板损坏?由于没有考虑散热,出现过很多问题困扰许多设计者。这里有一些指导要记住,以帮助解决散热问题: 识别麻烦的元件     第一步是开始考虑哪些元件会耗散电路板上的最多热量。这可以通过首先在元件的数据表中找到“热阻”等级,然后按照建议的指导方针来转移产生的热量来实现。当然,可以添加散热器和冷却风扇以保持元件温度下降,并且还要记住使关键元件远离任何高热源。 添加热风焊盘     添加热风焊盘对于生产可制造的电路板非常有用,它们对于高铜含量元件和多层电路板上的波峰焊接应用至关重要。由于难以保持工艺温度,因此始终建议在通孔元件上使用热风焊盘,以便通过减慢元件管脚处的散热速率,使焊接过程尽可能简单。 作为一般准则,始终对连接到地平面或电源平面的任何通孔或过孔使用热风焊盘方式连接。除了热风焊盘外,你还可以在焊盘连接线的位置添加泪滴,以提供额外的铜箔/金属支撑。这将有助于减少机械应力和热应力。       上图,典型的热风焊盘连接方式。 5 热风焊盘科普     许多工厂内负责制程(Process)或是SMT技术的工程师经常会碰到电路板元件发生空焊(solder empty)、假焊(de-wetting)或冷焊(cold solder)等等这类焊不上锡(non-wetting)的不良问题,不论制程条件怎么改或是回流焊的炉温再怎么调,就是有一定焊不上锡的比率。这究竟是怎么回事?     撇开元件及电路板氧化的问题,究其根因后发现有很大部分这类的焊接不良其实都来自于电路板的布线(layout)设计缺失,而最常见的就是在元件的某几个焊脚上连接到了大面积的铜皮,造成这些元件焊脚经过回流焊后发生焊接不良,有些手焊元件也可能因为相似情形而造成假焊或包焊的问题,有些甚至因为加热过久而把元件给焊坏掉。     一般PCB在电路设计时经常需要铺设大面积的铜箔来当作电源(Vcc、Vdd或Vss)与接地(GND,Ground)之用。这些大面积的铜箔一般会直接连接到一些控制电路(IC)及电子元件的管脚。     不幸的是如果我们想要将这些大面积的铜箔加热到融锡的温度时,比起独立的焊垫通常需要花比较多的时间(就是加热会比较慢),而且散热也比较快。当这样大面积的铜箔布线一端连接在小电阻、小电容这类 小元器件,而另一端不是时,就容易因为融锡及凝固的时间不一致而发生焊接问题;如果回流焊的温度曲线又调得不好,预热时间不足时,这些连接在大片铜箔的元件焊脚就容易因为达不到融锡温度而造成虚焊的问题。     人工焊接(Hand Soldering)时,这些连接在大片铜箔的元件焊脚则会因为散热太快,而无法在规定时间内完成焊接。最常见到的不良现象就是包焊、虚焊,焊锡只有焊在元件的焊脚上而没有连接到电路板的焊盘。从外观看起来,整个焊点会形成一个球状;更甚者,作业员为了要把焊脚焊上电路板而不断调高烙铁的温度,或是加热过久,以致造成元件超过耐热温度而毁损而不自知。如下图所示。     上图,包焊、冷焊或虚焊。   既然知道了问题点就可以有解决的方法,一般我们都会要求采用所谓Thermal Relief pad(热风焊垫)设计来解决这类因为大片铜箔连接元件焊脚所造成的焊接问题。如下图所示,左边的布线没有采用热风焊盘,而右边的布线则已经采用了热风焊盘的连接方式,可以看到焊盘与大片铜箔的接触面积只剩下几条细小的线路,这样就可以大大限制焊垫上温度的流失,达到较佳的焊接效果。       上图,采用Thermal Relief pad(热风焊垫)对比。 6 检查你的工作     当你马不停蹄地哼哧哼哧地将所有的部分组合在一起进行制造时,很容易在设计项目结束时才发现问题,不堪重负。因此,在此阶段对你的设计工作进行双重和三重检查可能意味着制造是成功还是失败。     为了帮助完成质量控制过程,我们始终建议你从电气规则检查(ERC)和设计规则检查(DRC)开始,以验证你的设计是否完全满足所有的规则及约束。使用这两个系统,你可以轻松进行间隙宽度,线宽,常见制造设置,高速要求和短路等等方面的检查。     当你的ERC和DRC产生无差错的结果时,建议你检查每个信号的布线情况,从原理图到PCB,一次检查一条信号线的方式仔细确认你没有遗漏任何信息。另外,使用你的设计工具的探测和屏蔽功能,以确保你的PCB布局材料与你的原理图相匹配。     丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 2021-08-16
  • 发表了主题帖: 0Ω电阻可以过多大电流?

        0Ω电阻到底能过多大电流?这个问题想必每位硬件工程师都查过。而与之相关的还有一个问题,那就是0Ω电阻的阻值到底有多大?     这两个问题本来是很简单的,答案应该也是很明确的,但网上网友却给出了不尽相同的答案。有的人说0Ω电阻是50mΩ,还有的人说其实只有20mΩ;有的人说只能过1A电流,还有的人说可以过1.5A……     那么,到底是多大呢?下面,我们一步一步来看。 0Ω电阻阻值大小       针对这两个问题,我专门查了一下电阻的标准。根据EN60115-2电阻标准文件记载,0Ω电阻的阻值是0Ω,但也会有偏差。0Ω最大电阻偏差有三种可以选择,分别为10mΩ、20mΩ和50mΩ。   也就是说,0Ω电阻偏差可以允许有多种偏差,这主要看电阻厂商做的是哪种了。       我下载了几大品牌的,比如罗姆、国巨、光颉的普通0Ω电阻规格书查看了一下,发现它们标注的0Ω电阻,最大阻值都是50mΩ。     由此可以得出结论:常用的普通0Ω电阻的阻值最大不超过50mΩ。 0Ω电阻的过流能力     网上还有一种观点,认为0Ω电阻的电流是根据功率算出来的,电阻按照50mΩ来算。这样的话,0805的电阻功率一般为1/8W,算出额定电流应该是1.58A。但是,我查看规格书发现,罗姆、国巨、光颉这几大品牌的都是2A,与计算出来的有些出入。     罗姆、国巨、光颉三大厂家的普通0Ω电阻额定电流如下:       从上图可以看出,三大厂家的0Ω电阻的额定电流还是略有差别的。我建议综合各家的、按照最小值来选,这样就不论什么品牌,都不会超出规格设计了。     额定电流综合之后的表格如下:       我们看到,常规的电阻的电流都不大,按照综合后的最小值来选的话,最大的也就2A。如果设计电路时发现,我要用3A或4A的0Ω电阻,那该怎么办呢?其实很简单,可以用2个0Ω电阻并联起来就行了。     说到这里,可能大家会觉得奇怪,怎么有的封装变大了,但过流并没有增加呢?例如,0805和1206都是2A,在这里应该是额定电流虽然没有增加,但瞬间电流应该是能过更大了。如果你打开国巨的电阻规格书,就会发现它写了两个参数,一个是额定电流,另一个是最大电流。额定电流都是2A,但最大电流0805是5A,1206是10A。       注:Jumper就是0Ω电阻(标准文件就是这么写的,如下图所示)。   特殊大额定电流的0Ω电阻       如果是更大的电流,也是电阻可选的。不过,这些电阻就不常规了,比如这个罗姆的超低阻值电阻,最大阻值0.5mΩ,小了100倍,额定电流更是达到了20A+,但是价格比较贵,要好几毛钱,而普通电阻一分钱能买好几个。   巧用0Ω电阻设计PCB板     许多硬件初学者看到PCB板上用到0Ω电阻时,往往就会一脸懵圈,他们经常会问:既然这玩意儿里面啥也没有,干嘛还要用它?     其实,0Ω电阻的用处可大了,如果用好它,可以极大地方便PCB板的设计和调试。下面,我们就来简单说说0Ω电阻的作用。     例如,老板出于成本的考虑,让你设计一个单面板,也就是说,元器件的安装及走线都只能在一面,你最头疼的是有些线实在走不过去,必须跨线连接,打俩孔用跳线?如果在研发的时候,这种方法还是可以的,但有一天你的设计变成了产品,需要大批量生产,机器折腾起跳线来要比放置一个电阻麻烦的多,这时候0Ω电阻就能帮你大忙了!根据你的空间,可以选用0805、0603或0402的电阻。   调试时的前后级隔离     如果你的设计是新的,对PCB板上很多部分的功能以及能够实现的性能还不确定,拿回板子来将会面临一场惊心动魄的调试,debug的一个重要原则就是把问题限定在最小的范围内,因此多块电路之间的隔离就非常重要。     在调试A电路时,你不希望B电路的工作影响到你的调试,那么最好的方式就是断掉它们之间的连接,而0Ω电阻就是一个最好的隔离方式!     调试的时候不焊接,等调试完成确认这部分电路没问题了,就可以将0Ω电阻安装上。当然,在最终的产品中可以彻底去掉。   测试电流用     如果你想测试某一路的电流大小,一种方式是通过电压表测量该通路上某电阻两端的电压(确保电压表的内阻不要影响到测量的精度),通过欧姆定律就可以计算出该路的电流。     另一种方式就是直接将电流表串在该回路上,因此在该电路上可以放置一个0Ω电阻,测量电流的时候用电流表两端代替该电阻,等测量完毕就能将该电阻安装上了。 给自己调试带来灵活性     可以预留各种可能性,根据实际的需要进行选装不同的电阻,它可以替代掉跳线,避免了跳线的钻孔、安装占用比较大的空间,而且跳线也会引起高频干扰。     比如,PCB板上设计有低通滤波器,如果发现最终不需要或者一开始调试的时候没时间调试低通滤波器,但又必须让信号流通过去,可以用0Ω电阻来代替原来设计中的电阻/电感,而不安装电容。在匹配电路参数不确定时,以0Ω电阻代替,实际调试的时候确定参数再以具体的数值的元器件来代替。 用于信号完整性的模拟地和数字地的单点连接     有人说0Ω电阻跟没有一样,干嘛不直接连接上?想象一下,如果你在电路原理图里没有这个0Ω电阻,做PCB Layout的时候就可能忽略这个单点连接的原则,CAD软件也会乱连在一起,达不到你单点连接的初衷。     当然,单点连接的时候也可以用磁珠,但我个人的观点是连接点的位置选择好的话,磁珠除了比电阻贵之外,没有什么好处。在实际的操作中,你可以用比较小的封装的0Ω电阻,比如0402和0201,焊接的时候直接用烙铁将两端搭接在一起就可以,这样连电阻也省了。   增加被逆向工程的难度     如果你在电路上放置多个不同颜色、不同封装、没有阻值标记的0Ω电阻,不影响电路的工作性能,但却可以让抄你板子的人瞬间抓狂。     PCB板上支持不同的配置,有的版本可能有部分电路不安装,可以用它来隔离不安装的电路部分,比如iPhone中有WiFi版本和WiFi+3G版本的,用的实际上是一个设计。      怎么样?这个0Ω电阻的作用很大吧!在以后的项目中大家慢慢体会吧,很多时候灵活应用它,会让你很多头疼的问题都能迎刃而解。       丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 发表了主题帖: 认识电感器的重要作用与特性

    本帖最后由 可乐zzZ 于 2021-8-16 17:38 编辑     电感器俗称电感,本质上是一个线圈,有空心线圈也有实心线圈,实心线圈有铁芯或者其它材料制成的芯,电感的单位是“H”,简称“亨”。此外,更小的单位是mH,uH,换算方式为1H=1000mH=1000000uH。     电感的常见作用          阻交通直             对于直流电,电感是相当于短路的;而对于交流电,电感是对其有阻碍作用的,交流电的频率越高,电感对它的阻碍作用越大。                   变压器             对我们来说最熟悉的电感应用莫过于变压器了,如下图所示为变压器的电路符号。假如左侧线圈匝数为100,右侧匝数为50,如果左侧接220V交流电,那么右侧感应出来的电压为110V,即“匝数比=电压比”而电流却会截然相反;如果左侧流进1A电流,那么右侧会流出2A的电流,即“匝数比=电流的反比”,因为电感只会对电压、电流进行变化,而不能对功率进行变化,如果电压和电流都为正比显然是不合情理的。                   RL低通滤波器             所谓低通滤波器是:低频信号可以通过,而高频信号不能通过,电路原理图如下图。输入信号如果是直流电,那么电感相当于一根导线;现在是短路,信号会经过电感,直接输出,而不经过电阻。如果我们逐渐升高电流的频率,由于电感对交流电有阻碍作用,通过电感的信号会慢慢变小,直到达到某一个频率,当高于这个频率之后的电流再也无法通过,这时候就形成了低通滤波器,这个频率就叫做截止频率,公式为 f=R/(2πL)。                   RL高通滤波器             高通滤波器的道理和低通的类似,只不过电阻和电感的位置变了,如下图。如果是直流电,会经过电感流回去,这时候如果改变频率,当频率逐渐升高,由于电感对交流电的阻碍作用,当频率达到截止频率时,高频信号不经过电感,而直接把我们需要的高频信号输出。截止频率的计算也是 f=R/(2πL)。                       以上列举了一些常用的电感应用,当然电感的作用远远不止这些,以上讲的都是基础,应用的时候考虑的远比以上所说的要多。         十种电感的特性          工字型电感             它的前身是挠线式贴片电感,工字型电感是它们的改良,挡板有效加强储能能力,改变EMI方向和大小,亦可降低RDC。它可以说是讯号通讯电感跟POWER电感的一种妥协。             贴片式的工字型电感主要用于几百kHz至一两MHz的较小型电源切换,如数字相机的LED升压、ADSL等较低频部份的讯号处理或POWER用途。它的Q值有20、30,做为讯号处理颇为适合。RDC比挠线式贴片电感低,作为POWER也是十分好用。当然,很大颗的工字型电感,那肯定是POWER用途了。             工字型电感最大的缺点仍是开磁路,有EMI的问题;另外,噪音的问题比挠线式贴片电感大。         色环电感             色环电感是最简单的棒形电感的加工,主要是用作讯号处理。本身跟棒形电感的特性没有很大的差别,只是多了一些固定物,和加上一些颜色方便分辨感值。因单价算是十分便宜,现时比较不注重体积,以及仍可用插件的电子产品,使用色环电感仍多。         空芯电感             空心电感主要是讯号处理用途,用作共振、接收、发射等。空气可应用在甚高频的产品,故此很多变异要求不太高的产品仍在使用。因为空气不是固定线圈的最佳材料,故此在要求越来越严格的产品趋势上,发展有限。                   环形线圈电感             环形线圈电感,是电感理论中很理想的形状。闭磁路,很少EMI的问题,充分利用磁路,容易计算,几乎理论上的好处,全归环形线圈电感。可是,有一个最大的缺点,就是不好挠线,制程多用人工处理。             环形线圈电感最大量的,是用铁粉芯作材料跟树脂等混在一起,使得Air gap均匀分布在铁粉芯内部。             铁粉芯环形线圈电感的优点是环形,但缺点亦是环形。我前面曾说,使用者最喜欢的形状是方形,故此在妥协下环形线圈电感并不是最具优势。         贴片迭层高频电感             贴片迭层高频电感,其实就是空心电感。特性完全相同,不过因为容易固定,可以小型化。             贴片迭层高频电感跟空心电感比较,因为空气不是好的固定物,但空气的相对导磁率是一,在高频很好用,因此找一些相对导磁率是一,又是很好的固定物,那不是很好。         贴片迭层高频电感跟贴片挠线式高频电感的比较,贴片迭层高频电感的Q值不够高是最大的缺点,。                   磁棒电感             磁棒电感是空心电感的加强,电感值跟导磁率成正比,塞磁性材料进空心线圈,电感值、Q值等都会大为增加。好处,就自己想象了。如果想不通,或者不想思考,要早点改行喔。磁棒电感是最简单、最基本的电感;30年到100年前,电感有什么应用,它就有什么应用,特性亦是如此。         SMD贴片功率电感             SMD贴片功率电感最主要是强调储能能力,以及LOSS要少。         穿心磁珠             穿心磁珠,就是阻抗器啦,电感是低通组件,可让低频通过,阻挡高频。         贴片磁珠             贴片磁珠就是穿心磁珠的下一代。         贴片高频变压器、插件高频变压器             高频变压器嘛,一般用于开关电源。                                       丨 整理文章为传播相关技术,版权归原作者所有丨         丨如有侵权,请联系删除丨                        

  • 2021-08-13
  • 发表了主题帖: 嵌入式开发中的滤波器设计

    什么是滤波器? 各种传感器信号多多少少会携带一些噪声信号,那么通过滤波器就能够更好的降低和去除噪声,还原真实有用信号。 滤波器是一个电路,其去除或“过滤掉”频率分量的特定范围。换句话说,它将信号的频谱分离为将要通过的频率分量和将被阻隔的频率分量。   如果您对频域分析没有太多经验,您可能仍然不确定这些频率成分是什么,以及它们如何在不能同时具有多个电压值的信号中共存。让我们看一个有助于澄清这个概念的简短例子。   假设我们有一个由完美的5kHz正弦波组成的音频信号。我们知道时域中的正弦波是什么样的,在频域中我们只能看到5kHz的频率“尖峰”。现在让我们假设我们激活一个500kHz振荡器,将高频噪声引入音频信号。 在示波器上看到的信号仍然只是一个电压序列,每个时刻有一个值,但信号看起来会有所不同,因为它的时域变化现在必须反映5kHz正弦波和高频噪音波动。    然而,在频域中,正弦波和噪声是在一个信号中同时存在的单独的频率分量。正弦波和噪声占据了信号频域表示的不同部分,这意味着我们可以通过将信号引导通过低频并阻挡高频的电路来滤除噪声。正弦波和噪声信号频域的不同部分分布示意图,如下。   滤波器的类型   滤波器可以放在与滤波器频率响应的一般特征相对应的广泛类别中。如果滤波器通过低频并阻止高频,则称为低通滤波器;如果它阻挡低频并通过高频,它就是一个高通滤波器。还有带通滤波器,其仅通过相对窄的频率范围,以及带阻滤波器,其仅阻挡相对窄的频率范围。各滤波器频域表示,如下图所示。     还可以根据用于实现电路的组件类型对滤波器进行分类。无源滤波器使用电阻器,电容器和电感器,这些组件不具备提供放大的能力,因此无源滤波器只能维持或减小输入信号的幅度。另一方面,有源滤波器既可以滤波信号又可以应用增益,因为它包括有源元件,如晶体管或运算放大器,如下图。       这种有源低通滤波器基于流行的Sallen-Key拓扑结构。 RC低通滤波器   为了创建无源低通滤波器,我们需要将电阻元件与电抗元件组合在一起。换句话说,我们需要一个由电阻器和电容器或电感器组成的电路。从理论上讲,电阻—电感(RL)低通拓扑在滤波能力方面与电阻—电容(RC)低通拓扑相当。但实际上,电阻—电容方案更为常见,因此本文的其余部分将重点介绍RC低通滤波器。RC低通滤波器示意图如下。       如图所示,通过将一个电阻与信号路径串联,并将一个电容与负载并联,可以产生RC低通响应。在图中,负载是单个组件,但在实际电路中,它可能更复杂,例如模数转换器,放大器或示波器的输入级,用于测量滤波器的响应。   如果我们认识到电阻器和电容器形成与频率相关的分压器,就可以直观地分析RC低通拓扑的滤波动作。重新绘制RC低通滤波器,使其看起来像分压器,如下图。          当输入信号的频率低时,电容器的阻抗相对于电阻器的阻抗高;因此,大部分输入电压在电容器上(和负载两端,与电容器并联)下降。当输入频率较高时,电容器的阻抗相对于电阻器的阻抗较低,这意味着电阻器上的电压降低,并且较少的电压传输到负载。因此,低频通过并且高频被阻挡。 RC低通功能的这种定性解释是重要的第一步,但是当我们需要实际设计电路时它并不是很有用,因为术语“高频”和“低频”非常模糊。工程师需要创建通过并阻止特定频率的电路。例如,在上述音频系统中,我们希望保留5kHz信号并抑制500kHz信号。这意味着我们需要一个滤波器,从5kHz到500kHz之间的传递过渡到阻塞。 RC滤波器截止频率 滤波器不会引起显著衰减的频率范围称为通带,滤波器确实导致显着衰减的频率范围称为阻带。模拟滤波器,例如RC低通滤波器,总是从通带逐渐过渡到阻带。这意味着无法识别滤波器停止传递信号并开始阻塞信号的一个频率。然而,工程师需要一种方便,简洁地总结滤波器频率响应的方法,这就是截止频率概念发挥作用的地方。     当您查看RC滤波器的频率响应图时,您会注意到术语“截止频率”不是很准确。信号光谱被“切割”成两半的图像,其中一个被保留而其中一个被丢弃,不适用,因为随着频率从截止点下方移动到截止值以上,衰减逐渐增加。 RC低通滤波器的截止频率实际上是输入信号幅度降低3dB的频率(选择该值是因为幅度降低3dB对应于功率降低50%)。因此,截止频率也称为-3dB频率,实际上该名称更准确且信息量更大。术语带宽是指滤波器通带的宽度,在低通滤波器的情况下,带宽等于-3dB频率,如下图所示。     上图表示RC低通滤波器的频率响应的一般特性,带宽等于-3dB频率。   如上所述,RC滤波器的低通行为是由电阻器的频率无关阻抗与电容器的频率相关阻抗之间的相互作用引起的。为了确定滤波器频率响应的细节,我们需要在数学上分析电阻(R)和电容(C)之间的关系,我们还可以操纵这些值,以设计满足精确规格的滤波器。RC低通滤波器的截止频率(fC)计算如下:       来看一个简单的设计实例。电容值比电阻值更具限制性,因此我们将从常见的电容值(例如10nF)开始,然后我们将使用该公式来确定所需的电阻值。目标是设计一个滤波器,它将保留5kHz音频波形并抑制500kHz噪声波形。我们将尝试100kHz的截止频率,稍后在文章中我们将更仔细地分析此滤波器对两个频率分量的影响,公式如下。    因此,160Ω电阻与10nF电容相结合,将为我们提供一个非常接近所需频率响应的滤波器。 滤波器响应可视化   评估滤波器对信号影响的最方便方法是检查滤波器频率响应的图。这些图形通常称为波德图,在垂直轴上具有幅度(以分贝为单位),在水平轴上具有频率;水平轴通常具有对数标度,使得1Hz和10Hz之间的物理距离与10Hz和100Hz之间,100Hz和1kHz之间的物理距离相同等等。这种配置使我们能够快速准确地评估滤波器在很大频率范围内的行为。如下图,是频率响应图的一个例子。      曲线上的每个点表示如果输入信号的幅度为1V且频率等于水平轴上的相应值,则输出信号将具有的幅度。例如,当输入频率为1MHz时,输出幅度(假设输入幅度为1V)将为0.1V(因为-20dB对应于十倍减少因子)。    当您花费更多时间使用滤波器电路时,此频率响应曲线的一般形状将变得非常熟悉。通带中的曲线几乎完全平坦,然后随着输入频率接近截止频率,它开始下降得更快。最终,衰减的变化率(称为滚降)稳定在20dB/decade-即,输入频率每增加十倍,输出信号的幅度降低20dB。 评估低通滤波器性能   如果我们仔细绘制我们在本文前面设计的滤波器的频率响应,我们将看到5kHz时的幅度响应基本上是0dB(即几乎为零衰减),500kHz时的幅度响应约为-14dB(对应于0.2的增益)。这些值与我们在上一节中执行的计算结果一致。   由于RC滤波器总是从通带到阻带逐渐过渡,并且因为衰减永远不会达到无穷大,我们无法设计出“完美”的滤波器—即对正弦波没有影响并完全消除噪声的滤波器。相反,我们总是需要权衡。如果我们将截止频率移近5kHz,我们将有更多的噪声衰减,但我们想要发送到扬声器的正弦波也会衰减更多。如果我们将截止频率移近500kHz,我们在正弦波频率下的衰减会减少,但噪声频率下的衰减也会减少。   前面我们已经讨论了滤波器修改信号中各种频率分量振幅的方式。然而,除了振幅效应之外,电抗性电路元件总是引入相移。 低通滤波器相移   相位的概念是指周期内特定时刻的周期信号的值。因此,当我们说电路引起相移时,我们的意思是它会在输入信号和输出信号之间产生偏差:输入和输出信号不再在同一时刻开始和结束它们的周期。相移值(例如45°或90°)表示产生的偏差量。   电路中的每个电抗元件都会引入90°的相移,但这种相移不会同时发生。输出信号的相位与输出信号的振幅一样,随着输入频率的增加而逐渐变化。RC低通滤波器中有一个电抗元件(电容器),因而电路最终也会引入90°的相移。   与振幅响应一样,通过检查水平轴表示对数频率的曲线图,可以最容易地评估相位响应。以下描述表示了一般模式,查看下图可以进一步了解详细信息。 ·相移最初为0° ·相移逐渐增加,直到在截止频率处达到45°,在这部分响应期间,变化率逐渐增加 ·在截止频率之后,相移继续增加,但变化率逐渐降低 ·随着相移逐渐接近90°,变化率变得非常小    实线是振幅响应,虚线是相位响应。截止频率为100kHz。注意,截止频率下的相移为45°。 二阶低通滤波器   到目前为止,我们假设RC低通滤波器由一个电阻器和一个电容器组成。这种配置是一阶滤波器。   无源滤波器的“阶数”由电路中电抗元件(即电容器或电感器)的数量决定。高阶滤波器具有更多的无功元件,会产生更多的相移和更陡的滚降,而后者是增加滤波器阶数的主要动机。   向滤波器添加一个电抗元件,例如,从一阶到二阶或二阶到三阶,便可将最大滚降增加20dB/十倍。   二阶滤波器通常围绕由电感器和电容器组成的谐振电路构建,这种拓扑结构称为RLC(Resistor-Inductor-Capacitor)。但是,也可以创建二阶RC滤波器。如下图所示,我们需要做的就是将两个一阶RC滤波器级联起来。     虽然这种拓扑肯定会产生二阶响应,但它没有被广泛使用,其频率响应通常不如二阶有源滤波器或二阶RLC滤波器。 二阶RC滤波器的频率响应   我们可以尝试根据所需的截止频率设计一阶滤波器,然后从中选择两个串联连接来,从而构成二阶RC低通滤波器。此举确实可以使滤波器表示出类似的总频率响应,最大滚降为40dB/decade而不是20dB/decade。   但是,如果我们更仔细地观察响应,我们会发现-3dB频率出现降低。二阶RC滤波器的行为不符合预期,因为两个滤波阶段不是独立的,因此不能简单地将这两个滤波器连接在一起,并将电路分析为一阶低通滤波器叠加一个相同的一阶低通过滤。   此外,即使我们在两级之间插入缓冲器,使得第一阶RC和第二阶RC可以用作独立滤波器,此时原始截止频率处的衰减将是6dB而不是3dB。这恰恰是因为两阶独立工作而导致的。第一个滤波器在截止频率处具有3dB的衰减,而第二个滤波器加上了另外3dB的衰减,如下图。        二阶RC低通滤波器的基本限制是设计人员无法通过调整滤波器的Q因子来微调从通带到阻带的转换;此参数表示频率响应的阻尼程度。如果将两个相同的RC低通滤波器级联,则整体传递函数对应于二阶响应,但Q因子始终为0.5。当Q=0.5时,滤波器处于过阻尼的边界,这会导致频率响应在过渡区域中“下垂”。二阶有源滤波器和二阶谐振滤波器没有这一限制;设计人员可以控制Q因子,从而微调过渡区域的频率响应。 总结   所有电信号都混合了所需频率分量和不需要的频率分量。不需要的频率分量通常由噪声和干扰引起,并且在某些情况下会对系统的性能产生负面影响。    滤波器是以不同方式对信号频谱的不同部分作出反应的电路。低通滤波器旨在让低频分量通过,同时阻止高频分量。   低通滤波器的截止频率表示滤波器从低衰减变为显著衰减的频率区域。   RC低通滤波器的输出电压可以通过将电路视为由(频率无关)电阻和(频率相关)电抗组成的分压器来计算。   振幅(以dB为单位,在垂直轴上)与对数频率(以赫兹为单位,在水平轴上)的曲线图是检查滤波器理论行为的方便有效的方法,还可以使用相位与对数频率的关系图来确定将要应用于输入信号的相移量。   二阶滤波器的滚降更陡峭;当信号不能在所需频率分量和不需要的频率分量之间提供宽带分离时,这种二阶响应比较有用。   可以通过构建两个相同的一阶RC低通滤波器,然后将一个的输出连接到另一个的输入来创建二阶RC低通滤波器,但最终整体的-3dB频率将低于预期。       丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 发表了主题帖: 很神秘的EMC,它是怎么来的

         说起开关电源的难点问题,PCB布板问题不算很大难点,但若是要布出一个精良PCB板一定是开关电源的难点之一(PCB设计不好,可能会导致无论怎么调试参数都调试布出来的情况,这么说并非危言耸听)原因是PCB布板时考虑的因素还是很多的,如:电气性能,工艺路线,安规要求,EMC影响等等;考虑的因素之中电气是最基本的,但是EMC又是最难摸透的,很多项目的进展瓶颈就在于EMC问题;下面就从九个方向给大家分享下PCB布板与EMC。 1、 熟透电路方可从容进行PCB设计之EMI电路     有的产品EMC很难在源头上去处理的,可以采用磁环滤波,当然我这里说的磁环有二个层面的意思,一方面是输入输出端的滤波电感,采用不同材质磁环,不同匝数会有对应的效果,还有一方面意思是直接在输入输出线上套磁环,有时能起到妙用,但不是在所有场合都能用,起码还是能作为判断依据。       上图蓝色和黑色线是输出正负端,上面套了个磁环,解决了输出整流管引起的高频端超出;有些时候端口的干扰在PCB板上加滤波器未必有效果,在输出线上放磁环就有想不到的效果。 2、 PCB走线之关键信号                            注意: ·CS信号(采样信号):从采样电阻R25,R26拉出,注意IC的地线以采样电阻为基准,采样电阻的正负差分走线拉倒IC CS脚以及IC 的GND脚 ·驱动信号从驱动电路拉倒IC驱动引脚,注意不要干扰到CS脚;如图走线三根线并排走,并且将地线走在驱动线和CS线中间起到一定屏蔽作用 ·双面板最好将IC一层铺地屏蔽,铺地的网络一定要从IC GND引出,非关键信号GND可直接打过孔,关键信号地需要单点接地,直接接IC ·FB反馈网络信号注意查分走线并且单点接IC ·RCD吸收网络不要放在主回路 ·VCC的整流滤波地需要接主功率地,二级滤波可接IC 地 ·Y电容走线单独接,不可与主功率混淆,避免干扰 3、 主功率及控制部分地接线示意图       可能很多人看到此图,云里雾里的,大致介绍下: ·PFC的驱动和IC共地接PFC管,更具体点是接采样电阻的地 ·DC-DC部分的驱动地和控制地接DC开关管部分的采样地 ·辅助源部分控制地接辅助源MOS管采样地,MOS管地再接主功率地 ·各自IC的供电地通过辅助源EC滤波接IC地,注意RC滤波靠近IC  总结:注意好各自的单点接地,地线不乱,是走线最重要的地方之一!!! 4、 电磁场屏蔽机理分析         如图对照:输入和输出的电场干扰可以通过电容传输耦合,若增加屏蔽板,则增加了C4的大小,并且C1也会减小,对电场干扰起到衰减的目的。            如图:磁场屏蔽的特点和磁场不一样,需要外壳屏蔽,电场只需要平面屏蔽板,故散热器屏蔽带来的是电场屏蔽,有的采用外壳封闭式电源则起到了一定磁场屏蔽。     磁场屏蔽原理,磁场通过屏蔽罩会改变磁路,导致磁力线向周围扩散,中间磁场干扰达到屏蔽目的。 5、 开关器件与EMC     开关器件哪些参数对EMC有重要影响,我们常说快管,慢管是以什么作为参照的呢?我们都知道快管开通损耗小,为了做高效率都喜欢用,但是为了EMC顺利通过,不得不舍弃效率,降低开关速度来减弱开关辐射。     对于MOS管,开通速度是由驱动电阻与输入结电容决定的;关断速度是由输出结电容与管子内阻决定。         参照以上两图,是不同型号的MOS管,对比下输入结电容和输出结电容,2400PF与6800PF;780PF与2200PF;一看就知道第一个规格是快管,第二个是慢管,这时候决定开关速度还要与驱动电阻匹配;常规情况驱动电阻在10R-150R比较多,选取驱动电阻与结电容有关,针对快板驱动电阻可适当增大,慢管驱动电阻可适当减小。     对于二极管,有肖特基二极管,快回复二极管,普通二极管,还有一种用的比较少的SIC二极管,开关速度SIC二极管几乎为零,等于是没有反向恢复,开关辐射最小,并且损耗也最小,唯一的缺点就是价格昂贵,故很少用;其次就是肖特基二极管,正向压降低,反向恢复时间短,依次是快回复和普通二极管;需要在损耗和EMC之间折中;一般可采取改吸收以及套磁珠等措施整改EMC。 6、 EMC之滤波器      滤波器的架构选择对滤波器的影响很重要,在不同场合,滤波器是根据阻抗匹配来达到滤波效果,大家可根据此图的原则参考选取如何滤波;比如最常用的输出整流桥后采用π型滤波以及输出端采用LC滤波器。                    滤波器的材质对设计滤波电感也是至关重要,采用不同初始磁导率的材质会在不同频率段起作用,选错材质就完全失去应有的效果。 7、 EMC之反激高频等效模型分析       先从最简单的模型理解EMC:     EMC的路径,当然空间辐射是跟环路有关,环路也是路径构造成的;分析出反激高频等效模型,帮助理解EMC形成的机理;我们的测试接收设备会从L,N端接收传导,为了减小接收的干扰,就必须让干扰通过地回路流通而不从L,N端口流向接收设备;这时候我们的EMI电感以及Y电容通过阻抗匹配就可以实现;另外原边的干扰可以通过原副边Y电容,变压器杂散电容以及大地耦合到副边,形成更多的回路;当然一些结电容参数,如MOS管结电容,散热器结电容也能构成流通路径。 8、 辐射的形式以及频率分布       这个图可能有些抽象,不过正好EMC是很难做到具体,需要给到我们一些启示,可知:差模辐射是以环路的形式存在,而共模辐射是以天线的形式发射;因此正好印证前面说我们布板的时候开关环路的布局以及走线的时候不要走锐角,常规走45度,最好是圆弧走线,当然走线效率会比较低。     这些原理基础知识理解得好,对实际处理EMC工作以及布板很有用那个,如果没这种意识,可能毫无用处,因为提供不了直接方法,需要与其他知识想结合。     而且这里提的很多原理东西,在很多EMC资料中是看不到的,而且也没这么集中,需要反复体会!                            如图:一些频率端与开关电源产生部位的关系,这只是一般规律,不要完全相信;既是规律又不能尽信是为什么?规律并不是在所有情况下成立,不同电源的差异也很大,所以原理是帮你分析,而不是按照方法去硬套。 9、 EMC实例                                                   根据传导实例,频率的分布点关键是具体的数据与基频之间的关系,这个测试完后,需要揣测这些数值的规律,可能能发现什么蛛丝马迹;当然对于这些频率如何通过滤波器去解决的手段前面也说过了。     这里是给大家补充一些似乎很神秘的EMC它是怎么来的,感觉不再神秘,而不只是稀里糊涂的采用滤波器解决了问题!       丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨  

  • 2021-08-12
  • 发表了主题帖: 正确使用三极管和MOS管

    三极管与MOS管 三极管是电流控制器件,用基极电流的变化控制集电极电流的变化。有NPN型三极管和PNP型三极管两种,符号如下:       MOS管是电压控制电流器件,用栅极电压的变化控制漏极电流的变化。有P沟道MOS管(简称PMOS)和N沟道MOS管(简称NMOS),符号如下(此处只讨论常用的增强型MOS管):   三极管与MOS管的正确应用 NPN型三极管     适合发射极接GND集电极接负载到VCC的情况。只要基极电压高于射极电压(此处为GND)0.7V,即发射结正偏(VBE为正),NPN型三极管即可开始导通。基极用高电平驱动NPN型三极管导通(低电平时不导通);基极除限流电阻外,更优的设计是,接下拉电阻10-20k到GND。 优点是: ·使基极控制电平由高变低时,基极能够更快被拉低,NPN型三极管能够更快更可靠地截止 ·系统刚上电时,基极是确定的低电平 如下,左图所示。 PNP型三极管     适合发射极接VCC集电极接负载到GND的情况。只要基极电压低于射极电压(此处为VCC)0.7V,即发射结反偏(VBE为负),PNP型三极管即可开始导通。基极用低电平驱动PNP型三极管导通(高电平时不导通);基极除限流电阻外,更优的设计是,接上拉电阻10-20k到VCC。 优点是: ·使基极控制电平由低变高时,基极能够更快被拉高,PNP型三极管能够更快更可靠地截止 ·系统刚上电时,基极是确定的高电平 如下,右图所示。       所以,如上所述:     对NPN三极管来说,最优的设计是,负载R12接在集电极和VCC之间。不够周到的设计是,负载R12接在射极和GND之间。     对PNP三极管来说,最优的设计是,负载R14接在集电极和GND之间。不够周到的设计是,负载R14接在发射极和VCC之间。这样,就可以避免负载的变化被耦合到控制端。从电流的方向可以明显看出。 PMOS     适合源极接VCC漏极接负载到GND的情况。只要栅极电压低于源极电压(此处为VCC)超过Vth(即Vgs超过-Vth),PMOS即可开始导通。栅极用低电平驱动PMOS导通(高电平时不导通);栅极除限流电阻外,更优的设计是,接上拉电阻10-20k到VCC,使栅极控制电平由低变高时,栅极能够更快被拉高,PMOS能够更快更可靠地截止。 NMOS 适合源极接GND漏极接负载到VCC的情况。只要栅极电压高于源极电压(此处为GND)超过Vth(即Vgs超过Vth),NMOS即可开始导通。栅极用高电平驱动NMOS导通(低电平时不导通);栅极除限流电阻外,更优的设计是,接下拉电阻10-20k到GND,使栅极控制电平由高变低时,栅极能够更快被拉低,NMOS能够更快更可靠地截止。   所以,如上所述:     对PMOS来说,最优的设计是,负载R16接在漏极和GND之间。不够周到的设计是,负载R16接在源极和VCC之间。     对NMOS来说,最优的设计是,负载R18接在漏极和VCC之间。不够周到的设计是,负载R18接在源极和GND之间。 总结     为避免负载的变化被耦合到控制端(基极Ib或栅极Vgs)的精密逻辑器件(如MCU)中,负载应接在集电极或漏极。         丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 发表了主题帖: Keil5软件配置与新建STM32工程的步骤

    新建工程文件夹     建立名字为LED的文件夹存放工程文件,其中再建立两个文件夹,Listing文件夹用于存放编译器编译时候产生的C语言、汇编、链接文件,Output文件夹用于存放编译产生的调试信息、hex文件、预览信息、封装库等。     文件夹建好之后,在LED文件夹下存放startup_stm32f10x_hd.s、stm32f10x.h、main.c文件。前两个文件可以在STM32F1xx的固件库中找到,第三个文件是空文件。 在Keil5中新建工程的步骤     如下图所示,Project-New,新建工程,工程名为Led,点击保存。       点击保存之后,弹出如下窗口,选择芯片型号。根据你开发板使用的芯片具体的型号来选择。如果这里没有出现你想要的CPU型号,或者一个型号都没有,那么肯定是你的KEIL5没有添加Device库,关于如何添加请往下看。   安装Device库     下载KEIL MDK5以后是没有安装device的,如果此时创建工程会找不到目标芯片,如下图所示:       此时我们就要安装自己需要的芯片系列,比如STM32F1系列。首先选择Project-Manage-Pack Installer,此时出现下面如下界面:       选择菜单栏中的Packs,点击Check for Updates,此时就会出现最新的支持的CPU系列,更新完毕之后会出现如下界面:       我们选择需要安装的芯片厂商,这里因为要安装STM32F1系列,所以选择ST公司,然后在右侧出现了STM系列的芯片,如上图右侧箭头所示,此时点击需要安装的STM32系列,这里我需要安装的是STM32F1系列,点击安装,此时软件会下载对应的芯片包,如下图所示:       这个下载过程比较慢,耐心等待,安装完毕之后,关闭KEIL5,重新打开KEIL5,此时新建工程,就出现了需要的芯片。     用寄存器控制 STM32 时我们不需要在线添加库文件,如关掉下图窗口。   向工程中添加文件     在新建的工程中添加文件,文件从本地建好的工程文件夹下获取,双击组文件夹就会出现添加文件的路径,然后选择文件即可,如下图所示。   Keil5软件配置 配置魔术棒     如下图所示,Target中选中微库“Use MicroLib”,为了编写串口驱动时可以使用printf函数。       Output 选项卡中把输出文件夹定位到我们工程目录下的 output 文件夹,如果想在编译的过程中生成 hex 文件,那么那 Create HEX File 选项勾上。       点击Listing选项卡中的Select Folder for Listings,把输出文件夹定位到先前创建的Listings文件夹。   配置下载器     在仿真器连接好电脑和开发板且开发板供电正常的情况下,打开KEIL5软件,在魔术棒选项卡里面选择所用仿真器的型号,如下图所示。       在Utilities中勾选Use Debug Driver,如下图所示。       点击Debug中的Settings,选择相应仿真器,勾选SW,Clock选为5MHz,Reset选择Autodetect。           在Flash Download中做如下图所示的配置,勾选Reset and run,程序下载后自动运行,不用先手动复位。   Keil5下载程序     如上,在Keil5中新建了工程,并对软件进行了正确配置之后,就可以点击下图1处的Rebuild按钮编译,再点击2处的LOAD下载到开发板上运行。       丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨    

  • 2021-08-11
  • 发表了主题帖: EMC防护中的滤波电容

       为什么总是在电路里摆两个0.1uF和0.01uF的电容? 旁路和去耦     旁路电容(Bypass Capacitor)和去耦电容(Decoupling Capacitor)这两个概念在电路中是常见的,但是真正理解起来并不容易。     要理解这两个词汇,还得回到英文语境中去。     Bypass在英语中有抄小路的意思,在电路中也是这个意思,如下图所示。      couple在英语中是一对的意思,引申为配对、耦合的意思。如果系统A中的信号引起了系统B中的信号,那么就说A与B系统出现了耦合现象(Coupling),如下图所示。而Decoupling就是减弱这种耦合的意思。 电路中的旁路和去耦     如下图中,直流电源Power给芯片IC供电,在电路中并入了两个电容。   旁路     如果Power受到了干扰,一般是频率比较高的干扰信号,可能使IC不能正常工作。在靠近Power处并联一个电容C1,因为电容对直流开路,对交流呈低阻态。频率较高的干扰信号通过C1回流到地,本来会经过IC的干扰信号通过电容抄近路流到了GND。这里的C1就是旁路电容的作用。 去耦     由于集成电路的工作频率一般比较高,IC启动瞬间或者切换工作频率时,会在供电导线上产生较大的电流波动,这种干扰信号直接反馈到Power会使其产生波动。在靠近IC的VCC供电端口并联一个电容C2,因为电容有储能作用,可以给IC提供瞬时电流,减弱IC电流波动干扰对Power的影响。这里的C2起到了去耦电容的作用。 为什么要用两个电容     回到本文最开始提到的问题,为什么要用0.1uF和0.01uF的两个电容?     电容阻抗和容抗计算公式分别如下:       容抗与频率和电容值成反比,电容越大、频率越高则容抗越小。可以简单理解为电容越大,滤波效果越好。那么有了0.1uF的电容旁路,再加一个0.01uF的电容不是浪费吗?     实际上,对一个特定电容,当信号频率低于其自谐振频率时呈容性,当信号频率高于其自谐振频率时呈感性。当用0.1uF和0.01uF的两个电容并联时,相当于拓宽了滤波频率范围。     丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 发表了主题帖: 小白开始,如何系统学习STM32?

        如何系统地入门学习STM32?     假如你会使用8051 , 会写C语言,那么STM32本身并不需要刻意的学习。     你要考虑的是, 我可以用STM32实现什么?     为什么使用STM32而不是8051?是因为51的频率太低,无法满足计算需求?是51的管脚太少,无法满足众多外设的IO?是51的功耗太大,电池挺不住?是51的功能太弱,而你要使用SPI、I2C、ADC、DMA?是51的内存太小而你要存储的东西太多?     当你需要使用STM32某些功能,而51实现不了的时候, 那STM32自然不需要学习,你会直接去寻找STM32某方面的使用方法。比如要用spi协议的网卡、要使用串口通信、要使用RTOS等等。 从菜鸟到牛人的学习步骤     我们假定大家已经对STM32的书籍或者文档有一定的理解。如不理解,请立即阅读STM32的文档,以获取最基本的知识点。     英文好的同学,请不要以为你很牛,可以只看英文文档。毕竟你是中国人,你最熟悉的,理解最好的还是中文。看英文的速度还是比看中文慢一些,我们要的是最短的时间,而不是追求短时间内记住所有细节。当然,如果是一篇论文,建议看英文原版还是有好处的。     STM32处理器进入国内市场时候,ST官方(或者第三方)的推广工作做的非常好。翻译了大量的英文文档,迎合了国内的很多工程师的思维。     学习的时候,关注两个比较重要的文档:《STM32F103xxx参考手册》,《STM32固件库使用手册》。这是针对有充足的时间、精力的同学,建议去下载需要查阅的文档,以获取更多信息。     阅读《STM32F103xxx参考手册》,一定要注意,不需要全部阅读——没有时间的。建议选读,但是前几章必读。存储器和总线架构、电源控制、备份寄存器、复位和时钟控制,通用和复用功能I/O,中断和时间等等前几章一定要花时间阅读。     后面章节,讲述的是具体的功能模块设计。如果我们用到哪个模块,就可以去阅读哪个模块。比如在使用AD的时候,就需要去阅读第10章ADC。其他不举例。相信每个初学者都有自己的研究方向和判断。     阅读《STM32固件库使用手册》,主要是为了简化编程。STM32给我们提供了一个非常好的固件函数库,我们只要去调用即可。当然,我们也可以不去碰这些固件库——传说使用它会使得代码效率变低,是有道理的。网络上也出现了很多网友自己写的代码,没有使用带固件库函数。如何取舍,在于您的选择。     这里我主要强调的是,阅读《STM32固件库使用手册》的时候,前面几章也是必须阅读的。比如第一章文档和库规范中的命名规则,编码规则,这些都是需要注意的。第二章是最关键的,希望大家熟读。第二章描述了固件库的架构,我们如何去使用固件库的步骤等。有了第二章的基础,我们就可以借助固件库写出自己的代码了。第四章开始之后,就可以根据大家的需要来阅读。实际上,后续的章节,都是描述某个模块有什么什么函数,每个函数如何使用等。     关于后面的章节,建议对GPIO库函数、中断部分库函数、复位和时钟设置的库函数要比较熟悉,因为平时经常会用到。     以上提到的这两个文档,已经足够您看的了,呵呵。希望您能从中获取大量的STM32基础知识。 设定一个不错的两周入门计划 (1)这里所谓的“入门”,指的是能理解并掌握一些常用的STM32外设,真正想掌握一款处理器,两周根本说明不了什么问题。只能说,你已经有所了解了。但是,这对我们初学者来说已经足够了。 (2)这里所谓的“两周”,根据每个人的时间安排不同而不同。 如果您每天有充足的时间学习,那么可以规定自己尽快地能独立地进行简单的STM32开发。     如果您每天只有业余时间来学习STM32,建议根据您的具体情况安排时间。毕竟计划时间如果安排太紧,反而收不到良好的效果,只能进入恶性循环,这是我们要避免的。 但是建议,不管您有无充足的时间,都必须给自己做一个计划! 思路     步骤一,安装完STM32学习的软件,比如J-Link、Keil for ARM(MDK)、ISP(如果需要从串口下载的话)。这些软件安装的详细步骤,可以参考我们推出的相应教程进行。     步骤二,挑选部分例程的HEX,比如LED灯的例程HEX文件,下载到芯达STM32开发板中,观察两个LED灯的闪烁情况。这部分的操作,可以参考我们推出的相应的教程进行。     实际上,以上两个步骤,是为了熟悉要使用的工具软件而已。属于找感觉的阶段。其实我们还没开始STM32的学习呢!     步骤三,准备几个常用的文档,比如《STM32的用户手册》,《STM32固件库使用手册》等文档。用于平时查阅。这些文档,在光盘中的芯片手册目录中均可找到。     步骤四,开始查看例程的编写,看看例程是如何写的,自己可否修改下例程,达到自己想要的效果呢?     步骤五,Ucos-II的移植,是否需要试一下? 恭喜你,至此,你已经可以自如进行独立的开发了。最后一步,给自己一个目标(项目),把它实现出来!     再次强调,以上只是一个学习STM32的思路,供大家参考。     下面列出了前面关键的步骤,希望大家能尽快入门。 第1步:熟悉调试软件     对初学者来说,我们至少需要安装两个软件:J-Link驱动软件、MDK(就是原来的Keil)软件。     这两个软件在安装软件的过程可以查看神舟开发板用户手册,这里不再重复,大家可以参考我们推出的教程《如何安装J-Link驱动软件》以及《如何安装MDK(Keil)软件》。如何验证自己已经熟悉调试软件的操作了呢?很简单,神舟STM32开发板光盘里附带了很多HEX格式的文件,可以选择一些HEX文件,来观察运行结果。     该步骤要达到的目标:熟悉调试软件,如烧写HEX出现问题,可简单判别问题所在,并独立解决。 第2步:GPIO编程     这是第一次接触固件库的编程,一定要硬着头皮去了解固件库。建议大家尽量去用固件库。而不是避开固件库自己写代码——这样只能在学习中才会发生。实际的项目中,代码成百上千个,如何一个一个自己写?调用固件库中的函数来完成,才是王者之道。     GPIO本身的编程实际上很简单:     1、设置GPIO口的引脚为输入或者输出模式。我们在进行点灯代码的时候,一般设置为推挽输出模式。     2、操作寄存器,往寄存器里置1或者清零操作——这个步骤,固件库已经提供了专门的GPIO_SetBits函数和GPIO_ResetBits函数,我们只要去调用即可实现对IO口的置1和清零。     3、实现多种花样的LED闪动,使得自己熟悉GPIO的编程过程。 该步骤要达到的目标:熟悉调试软件,如烧写HEX出现问题,可简单判别问题所在,并独立解决。     第3步:开始全新的STM32深入研究 经过以上调试软件的熟悉和GPIO口的编程调试后,相信您已经对STM32有一定的了解。     至少知道如何利用STM32的固件库去写一个代码。在这个阶段,将要接触到串口编程、TFT液晶屏驱动编程、定时器编程、串行外设接口SPI编程、存储器编程、SD卡与文件系统移植、USB读写、UCOS移植等,有精力还可以研究其他外设。     丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 2021-08-10
  • 发表了主题帖: 嵌入式开发中的防御性C语言编程

        嵌入式产品的可靠性自然与硬件密不可分,但在硬件确定、并且没有第三方测试的前提下,使用防御性编程思想写出的代码,往往具有更高的稳定性。     防御性编程首先需要认清C语言的种种缺陷和陷阱,C语言对于运行时的检查十分弱小,需要程序员谨慎的考虑代码,在必要的时候增加判断;防御性编程的另一个核心思想是假设代码运行在并不可靠的硬件上,外接干扰有可能会打乱程序执行顺序、更改RAM存储数据等等。 1 具有形参的函数,需判断传递来的实参是否合法     程序员可能无意识的传递了错误参数;外界的强干扰可能将传递的参数修改掉,或者使用随机参数意外的调用函数,因此在执行函数主体前,需要先确定实参是否合法。   2 仔细检查函数的返回值     对函数返回的错误码,要进行全面仔细处理,必要时做错误记录。   3 防止指针越界     如果动态计算一个地址时,要保证被计算的地址是合理的并指向某个有意义的地方。特别对于指向一个结构或数组的内部的指针,当指针增加或者改变后仍然指向同一个结构或数组。 4 防止数组越界     数组越界的问题前文已经讲述的很多了,由于C不会对数组进行有效的检测,因此必须在应用中显式的检测数组越界问题。下面的例子可用于中断接收通讯数据。      在使用一些库函数时,同样需要对边界进行检查,比如下面的memset(RecBuf,0,len)函数把RecBuf指指向的内存区的前len个字节用0填充,如果不注意len的长度,就会将数组RecBuf之外的内存区清零:   5 数学算数运算 5.1除法运算,只检测除数为零就可靠吗?     除法运算前,检查除数是否为零几乎已经成为共识,但是仅检查除数是否为零就够了吗?     考虑两个整数相除,对于一个signed long类型变量,它能表示的数值范围为:-2147483648 ~+2147483647,如果让-2147483648/ -1,那么结果应该是+2147483648,但是这个结果已经超出了signedlong所能表示的范围了。所以,在这种情况下,除了要检测除数是否为零外,还要检测除法是否溢出。   #include <limits.h>      signed long sl1,sl2,result;  /*初始化sl1和sl2*/      if((sl2==0)||(sl1==LONG_MIN && sl2==-1))  {      //处理错误      }  else     {      result = sl1 / sl2;  } 5.2检测运算溢出     整数的加减乘运算都有可能发生溢出,在讨论未定义行为时,给出过一个有符号整形加法溢出判断代码,这里再给出一个无符号整形加法溢出判断代码段:  #include <limits.h>      unsigned int a,b,result;  /*初始化a,b*/      if(UINT_MAX-a<b)  {      //处理溢出      }  else     {      result=a+b;  }     嵌入式硬件一般没有浮点处理器,浮点数运算在嵌入式也比较少见并且溢出判断严重依赖C库支持,这里不讨论。 5.3检测移位     在讨论未定义行为时,提到有符号数右移、移位的数量是负值或者大于操作数的位数都是未定义行为,也提到不对有符号数进行位操作,但要检测移位的数量是否大于操作数的位数。下面给出一个无符号整数左移检测代码段:  unsigned int ui1;  unsigned int ui2;  unsigned int uresult;  /*初始化ui1,ui2*/    if(ui2>=sizeof(unsigned int)*CHAR_BIT)  {      //处理错误    }  else    {      uresult=ui1<<ui2;  } 6 如果有硬件看门狗,则使用它     在其它一切措施都失效的情况下,看门狗可能是最后的防线。它的原理特别简单,但却能大大提高设备的可靠性。如果设备有硬件看门狗,一定要为它编写驱动程序。 ·要尽可能早的开启看门狗     这是因为从上电复位结束到开启看门狗的这段时间内,设备有可能被干扰而跳过看门狗初始化程序,导致看门狗失效。尽可能早的开启看门狗,可以降低这种概率; ·不要在中断中喂狗,除非有其他联动措施     在中断程序喂狗,由于干扰的存在,程序可能一直处于中断之中,这样会导致看门狗失效。如果在主程序中设置标志位,中断程序喂狗时与这个标志位联合判断,也是允许的; ·喂狗间隔跟产品需求有关,并非特定的时间     产品的特性决定了喂狗间隔。对于不涉及安全性、实时性的设备,喂狗间隔比较宽松,但间隔时间不宜过长,否则被用户感知到,是影响用户体验的。对于设计安全性、有实时控制类的设备,原则是尽可能快的复位,否则会造成事故。     克莱门汀号在进行第二阶段的任务时,原本预订要从月球飞行到太空深处的Geographos小行星进行探勘,然而这艘太空探测器在飞向小行星时却由于一个软件缺陷而使其中断运作20分钟,不但未能到达小行星,也因为控制喷嘴燃烧了11分钟使电力供应降低,无法再透过远端控制探测器,最终结束这项任务,但也导致了资源与资金的浪费。     “克莱门汀太空任务失败这件事让我感到十分震惊,它其实可以透过硬件中一款简单的看门狗计时器避免掉这项意外,但由于当时的开发时间相当紧缩,程序设计人员没时间编写程序来启动它,”Ganssle说。     遗憾的是,1998年发射的近地号太空船(NEAR)也遇到了相同的问题。由于编程人员并未采纳建议,因此,当推进器减速器系统故障时,29公斤的储备燃料也随之报销──这同样是一个本来可经由看门狗定时器编程而避免的问题,同时也证明要从其他程序设计人员的错误中学习并不容易。 7 关键数据储存多个备份,取数据采用“表决法”     RAM中的数据在受到干扰情况下有可能被改变,对于系统关键数据应该进行保护。关键数据包括全局变量、静态变量以及需要保护的数据区域。备份数据与原数据不应该处于相邻位置,因此不应由编译器默认分配备份数据位置,而应该由程序员指定区域存储。     可以将RAM分为3个区域,第一个区域保存原码,第二个区域保存反码,第三个区域保存异或码,区域之间预留一定量的“空白”RAM作为隔离。可以使用编译器的“分散加载”机制将变量分别存储在这些区域。需要进行读取时,同时读出3份数据并进行表决,取至少有两个相同的那个值。     假如设备的RAM从0x1000_0000开始,我需要在RAM的0x1000_0000~0x10007FFF内存储原码,在0x1000_9000~0x10009FFF内存储反码,在0x1000_B000~0x1000BFFF内存储0xAA的异或码,编译器的分散加载可以设置为:  LR_IROM1 0x00000000 0x00080000  {    ; load region size_region    ER_IROM1 0x00000000 0x00080000  {  ; load address = execution address     *.o (RESET, +First)     *(InRoot$$Sections)     .ANY (+RO)    }    RW_IRAM1 0x10000000 0x00008000  {  ;保存原码     .ANY (+RW +ZI )    }    RW_IRAM3 0x10009000 0x00001000{    ;保存反码     .ANY (MY_BK1)    }    RW_IRAM2 0x1000B000 0x00001000  {  ;保存异或码     .ANY (MY_BK2)    }  } 如果一个关键变量需要多处备份,可以按照下面方式定义变量,将三个变量分别指定到三个不连续的RAM区中,并在定义时按照原码、反码、0xAA的异或码进行初始化。    uint32  plc_pc=0;                                                       //原码    __attribute__((section("MY_BK1"))) uint32 plc_pc_not=~0x0;              //反码    __attribute__((section("MY_BK2"))) uint32 plc_pc_xor=0x0^0xAAAAAAAA;    //异或码       当需要写这个变量时,这三个位置都要更新;读取变量时,读取三个值做判断,取至少有两个相同的那个值。     为什么选取异或码而不是补码?这是因为MDK的整数是按照补码存储的,正数的补码与原码相同,在这种情况下,原码和补码是一致的,不但起不到冗余作用,反而对可靠性有害。比如存储的一个非零整数区因为干扰,RAM都被清零,由于原码和补码一致,按照3取2的“表决法”,会将干扰值0当做正确的数据。 8 对非易失性存储器进行备份存储     非易失性存储器包括但不限于Flash、EEPROM、铁电。仅仅将写入非易失性存储器中的数据再读出校验是不够的。强干扰情况下可能导致非易失性存储器内的数据错误,在写非易失性存储器的期间系统掉电将导致数据丢失,因干扰导致程序跑飞到写非易失性存储器函数中,将导致数据存储紊乱。     一种可靠的办法是将非易失性存储器分成多个区,每个数据都将按照不同的形式写入到这些分区中,需要进行读取时,同时读出多份数据并进行表决,取相同数目较多的那个值。 9 软件锁     对于初始化序列或者有一定先后顺序的函数调用,为了保证调用顺序或者确保每个函数都被调用,我们可以使用环环相扣,实质上这也是一种软件锁。此外对于一些安全关键代码语句(是语句,而不是函数),可以给它们设置软件锁,只有持有特定钥匙的,才可以访问这些关键代码。也可以通俗的理解为,关键安全代码不能按照单一条件执行,要额外的多设置一个标志。     比如,向Flash写一个数据,我们会判断数据是否合法、写入的地址是否合法,计算要写入的扇区。之后调用写Flash子程序,在这个子程序中,判断扇区地址是否合法、数据长度是否合法,之后就要将数据写入Flash。     由于写Flash语句是安全关键代码,所以程序给这些语句上锁:必须具有正确的钥匙才可以写Flash。这样即使是程序跑飞到写Flash子程序,也能大大降低误写的风险。    /***************************************************************  * 名称:RamToFlash()  * 功能:复制RAM的数据到FLASH,命令代码51。  * 入口参数:dst        目标地址,即FLASH起始地址。以512字节为分界  *           src        源地址,即RAM地址。地址必须字对齐  *           no         复制字节个数,为512/1024/4096/8192  *           ProgStart  软件锁标志      * 出口参数:IAP返回值(paramout缓冲区) CMD_SUCCESS,SRC_ADDR_ERROR,DST_ADDR_ERROR,  SRC_ADDR_NOT_MAPPED,DST_ADDR_NOT_MAPPED,COUNT_ERROR,BUSY,未选择扇区  ****************************************************************/    void  RamToFlash(uint32 dst, uint32 src, uint32 no,uint8 ProgStart)    {      PLC_ASSERT("Sector number",(dst>=0x00040000)&&(dst<=0x0007FFFF));      PLC_ASSERT("Copy bytes number is 512",(no==512));      PLC_ASSERT("ProgStart==0xA5",(ProgStart==0xA5));      paramin[0] = IAP_RAMTOFLASH;       // 设置命令字        paramin[1] = dst;                  // 设置参数        paramin[2] = src;      paramin[3] = no;      paramin[4] = Fcclk/1000;      if(ProgStart==0xA5)                //只有软件锁标志正确时,才执行关键代码        {          iap_entry(paramin, paramout);  // 调用IAP服务程序                           ProgStart=0;      }      else        {          paramout[0]=PROG_UNSTART;      }  }     该程序段是编程lpc1778内部Flash,其中调用IAP程序的函数iap_entry(paramin, paramout)是关键安全代码,所以在执行该代码前,先判断一个特定设置的安全锁标志ProgStart,只有这个标志符合设定值,才会执行编程Flash操作。如果因为意外程序跑飞到该函数,由于ProgStart标志不正确,是不会对Flash进行编程的。 10 通信     通讯线上的数据误码相对严重,通讯线越长,所处的环境越恶劣,误码会越严重。抛开硬件和环境的作用,我们的软件应能识别错误的通讯数据。对此有一些应用措施: ·制定协议时,限制每帧的字节数;     每帧字节数越多,发生误码的可能性就越大,无效的数据也会越多。对此以太网规定每帧数据不大于1500字节,高可靠性的CAN收发器规定每帧数据不得多于8字节,对于RS485,基于RS485链路应用最广泛的Modbus协议一帧数据规定不超过256字节。因此,建议制定内部通讯协议时,使用RS485时规定每帧数据不超过256字节; ·使用多种校验     编写程序时应使能奇偶校验,每帧超过16字节的应用,建议至少编写CRC16校验程序。 ·增加额外判断     1)增加缓冲区溢出判断。这是因为数据接收多是在中断中完成,编译器检测不出缓冲区是否溢出,需要手动检查,在上文介绍数据溢出一节中已经详细说明。     2)增加超时判断。当一帧数据接收到一半,长时间接收不到剩余数据,则认为这帧数据无效,重新开始接收。可选,跟不同的协议有关,但缓冲区溢出判断必须实现。这是因为对于需要帧头判断的协议,上位机可能发送完帧头后突然断电,重启后上位机是从新的帧开始发送的,但是下位机已经接收到了上次未发送完的帧头,所以上位机的这次帧头会被下位机当成正常数据接收。这有可能造成数据长度字段为一个很大的值,填满该长度的缓冲区需要相当多的数据(比如一帧可能1000字节),影响响应时间;另一方面,如果程序没有缓冲区溢出判断,那么缓冲区很可能溢出,后果是灾难性的。 ·重传机制     如果检测到通讯数据发生了错误,则要有重传机制重新发送出错的帧。 11 开关量输入的检测、确认     开关量容易受到尖脉冲干扰,如果不进行滤除,可能会造成误动作。一般情况下,需要对开关量输入信号进行多次采样,并进行逻辑判断直到确认信号无误为止。 12 开关量输出     开关信号简单的一次输出是不安全的,干扰信号可能会翻转开关量输出的状态。采取重复刷新输出可以有效防止电平的翻转。 13 初始化信息的保存和恢复     微处理器的寄存器值也可能会因外界干扰而改变,外设初始化值需要在寄存器中长期保存,最容易被破坏。由于Flash中的数据相对不易被破坏,可以将初始化信息预先写入Flash,待程序空闲时比较与初始化相关的寄存器值是否被更改,如果发现非法更改则使用Flash中的值进行恢复。     公司目前使用的4.3寸LCD显示屏抗干扰能力一般。如果显示屏与控制器之间的排线距离过长或者对使用该显示屏的设备打静电或者脉冲群,显示屏有可能会花屏或者白屏。     对此,我们可以将初始化显示屏的数据保存在Flash中,程序运行后,每隔一段时间从显示屏的寄存器读出当前值和Flash存储的值相比较,如果发现两者不同,则重新初始化显示屏。下面给出校验源码,仅供参考。     定义数据结构:       定义const修饰的结构体变量,存储LCD部分寄存器的初始值,这个初始值跟具体的应用初始化有关,不一定是表中的数据,通常情况下,这个结构体变量被存储到Flash中。    /*LCD部分寄存器设置值列表*/    lcd_redu_list_struct const lcd_redu_list_str[]=  {    {SSD1963_Get_Address_Mode,{0x20}                                   ,1}, /*1*/    {SSD1963_Get_Pll_Mn      ,{0x3b,0x02,0x04}                         ,3}, /*2*/    {SSD1963_Get_Pll_Status  ,{0x04}                                   ,1}, /*3*/    {SSD1963_Get_Lcd_Mode    ,{0x24,0x20,0x01,0xdf,0x01,0x0f,0x00}     ,7}, /*4*/    {SSD1963_Get_Hori_Period ,{0x02,0x0c,0x00,0x2a,0x07,0x00,0x00,0x00},8}, /*5*/    {SSD1963_Get_Vert_Period ,{0x01,0x1d,0x00,0x0b,0x09,0x00,0x00}     ,7}, /*6*/    {SSD1963_Get_Power_Mode  ,{0x1c}                                   ,1}, /*7*/    {SSD1963_Get_Display_Mode,{0x03}                                   ,1}, /*8*/    {SSD1963_Get_Gpio_Conf   ,{0x0F,0x01}                              ,2}, /*9*/    {SSD1963_Get_Lshift_Freq ,{0x00,0xb8}                              ,2}, /*10*/  };     实现函数如下所示,函数会遍历结构体变量中的每一个命令,以及每一个命令下的初始值,如果有一个不正确,则跳出循环,执行重新初始化和恢复措施。这个函数中的MY_DEBUGF宏是我自己的调试函数,使用串口打印调试信息,在接下来的第五部分将详细叙述。     通过这个函数,我可以长时间监控显示屏的哪些命令、哪些位容易被干扰。程序里使用了一个被妖魔化的关键字:goto。大多数C语言书籍对goto关键字谈之色变,但你应该有自己的判断。在函数内部跳出多重循环,除了goto关键字,又有哪种方法能如此简洁高效!    /**  * lcd 显示冗余  * 每隔一段时间调用该程序一次  */    void lcd_redu(void)    {      uint8_t  tmp[8];      uint32_t i,j;      uint32_t lcd_init_flag;      lcd_init_flag =0;      for(i=0;i<sizeof(lcd_redu_list_str)/sizeof(lcd_redu_list_str[0]);i+)      {          LCD_SendCommand(lcd_redu_list_str.lcd_command);          uyDelay(10);          for(j=0;j<lcd_redu_list_str.lcd_value_num;j++)          {              tmp[j]=LCD_ReadData();              if(tmp[j]!=lcd_redu_list_str.lcd_get_value[j])              {                  lcd_init_flag=0x55;                  MY_DEBUGF(MENU_DEBUG,("读lcd寄存器值与预期不符,命令为:0x%x,第%d个参数,              该参数正确值为:0x%x,实际读出值为:0x%x\n",lcd_redu_list_str.lcd_command,j+1,              lcd_redu_list_str.lcd_get_value[j],tmp[j]));                  goto handle_lcd_init;              }          }      }      handle_lcd_init:      if(lcd_init_flag==0x55)      {          //重新初始化LCD            //一些必要的恢复措施        }  } 14 陷阱     对于8051内核单片机,由于没有相应的硬件支持,可以用纯软件设置软件陷阱,用来拦截一些程序跑飞。对于ARM7或者Cortex-M系列单片机,硬件已经内建了多种异常,软件需要根据硬件异常来编写陷阱程序,用来快速定位甚至恢复错误。 15 阻塞处理     有时候程序员会使用while(!flag);语句阻塞在此等待标志flag改变,比如串口发送时用来等待一字节数据发送完成。这样的代码时存在风险的,如果因为某些原因标志位一直不改变则会造成系统死机。     一个良好冗余的程序是设置一个超时定时器,超过一定时间后,强制程序退出while循环。     2003年8月11日发生的W32.Blaster.Worm蠕虫事件导致全球经济损失高达5亿美元,这个漏洞是利用了Windows分布式组件对象模型的远程过程调用接口中的一个逻辑缺陷:在调用GetMachineName()函数时,循环只设置了一个不充分的结束条件。     原代码简化如下所示:       微软发布的安全补丁MS03-026解决了这个问题,为GetMachineName()函数设置了充分终止条件。一个解决代码简化如下所示(并非微软补丁代码): HRESULT GetMachineName( WCHAR *pwszPath,    WCHARwszMachineName[MAX_COMPUTTERNAME_LENGTH_FQDN+1])  {         WCHAR *pwszServerName = wszMachineName;         WCHAR *pwszTemp = pwszPath + 2;         WCHAR *end_addr = pwszServerName +MAX_COMPUTTERNAME_LENGTH_FQDN;         while ((*pwszTemp != L’\\’ ) && (*pwszTemp != L’\0’)&& (pwszServerName<end_addr))  /*充分终止条件*/                 *pwszServerName++= *pwszTemp++;         /*… */    }     丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 发表了主题帖: 学习STM32单片机,绕不开的串口

        刚开始学单片机的你,是不是会因用程序把LED点亮而感到高兴,会因用程序把数码管点亮而感到高兴。这是好事,这也是想继续学习下去的动力。     但是数据相关的实验是学习单片机和STM32的一道坎,此时就需要用好本文要说的串口这个调试工具。 串口通信介绍       串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式......这种太过理论了,看似懂了,但又不懂。还是用我笔者自己的话来说吧。     串口通信就是可以把程序在单片机或者STM32芯片中运行的结果发送到电脑的一种通信方式。       如何使用串口通讯,你需要知道的几个重要的知识点: 波特率,数据传输的速度,如上图设置为9600,那么程序中也要设置为9600 硬件连接,接收、发送交叉连接,如上图TxD->RxD,RxD->TxD 停止位 奇偶校验 硬件数据流 其中,后3项一般不需要改变。 学会串口通信能做什么     学过C语言的人都知道,程序开发需要不断调试不断验证。很多的语言编程软件都有很完整的程序调试功能。使用起来很方便。而我们的开发虽然也是用C语言,但我们的程序最终运行的环境不是在我们的开平台而是在真正的硬件系统中运行。这时想要查看程序的运行过程或者结果就不像编程软件那么方便了。     想要解决这个问题,我们这时就可以借助串口通信来把我们需要知道的结果又或者是程序运行的关键步骤发送到电脑上,我们就知道程序在硬件系统中运行是否出现问题。51单片机可以用串口来调试,STM32可以用串口来调试,Linux开发板也是使用串口来调试。     当你学会串口通信时,你可以开始玩WIFI模块、GSM模块、蓝牙模块、GPS模块、以及各种使用串口通信的传感器等等。有能力你还可以编写上位机软件通过串口通信来控制设备。 串口通信需要什么     如果你只有STM32核心板,那么你还需要一个串口转USB模块和一个串口数据接收软件还有几根杜邦线就可以了。     如果你的是比较完整的一款开发板的话,一般都已经带有串口转USB模块,这样使用起来就更简单了。聪明的你是不是发现还缺少了点什么,对。没错因为还缺少了最重要的程序。想要使用串口通信当然还需要写串口通信的程序。     下文就教你如何去用,而不是写。 串口实验     在做一个实验时,最好把这个实验分割成几个关键的步骤,这样做的好处就是可以清晰的知道自己需要做什么,以及做完了哪些。还有哪些还没做。     下面把串口实验分成几个关键的步骤: 1)串口通信使用到的GPIO引脚配置     STM32F103系列的芯片一般都有三个串口以上,用来调试使用的串口一般都是使用USART1。其他的串口配置都是一样的。     下面这段就是串口配置的程序:   GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //使能USART1,GPIOA时钟 //USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化GPIOA.9 //USART1_RX GPIOA.10初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  //PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure);  //初始化GPIOA.10     串口使用的的GPIO口是PA9和PA10,所以只需配置这两个IO口的输入输出模式就可以了。 2)串口主要参数设置(直接看程序)   USART_InitTypeDef USART_InitStructure; //USART 初始化设置 USART_InitStructure.USART_BaudRate = bound; //串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据格式,8位 USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口接受中断     串口参数配置无法就是配置串口的波特率、数据格式、停止位、奇偶校验、硬件流、收发模式。除了波特率需要改变其他的参数都不需要管。直接复制拿来用。 3)串口中断配置     串口如果使用中断接收,那么就需要配置串口的中断参数,配置项无法就是配置那个的中断源和中断的优先级。   NVIC_InitTypeDef NVIC_InitStructure; //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;  //抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //IRQ通道使能 NVIC_Init(&NVIC_InitStructure);   //根据指定的参数初始化VIC寄存器 串口使能     就是你需要什么时候开始使用串口功能,就是一句原有的函数。 USART_Cmd(USART1, ENABLE);  //使能串口1 编写串口中断处理函数     使用库函数开发,所有的中断函数都是已经存在的,只是中断函数里面没有处理任何事情而已。中断函数如下:       完整的串口中断函数:   void USART1_IRQHandler(void) { int Res=0;  //定义一个变量用来接收串口数据集 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)   {   Res =USART_ReceiveData(USART1);  //读取接收到的数据   USART_SendData(USART1,Res );     //把接收到的数据通过串口1发送出去   } }     串口数据的接收和发送的函数都是库函数提供的,想用时只需找到它直接拿来用就可以了。 6)实验现象     把程序编译烧写到STM32然后用串口转USB模块连接到电脑,在串口调试工具设置好波特率,打开串口。正常的话,那发送什么到STM32单片机,串口工具上就会收到什么。 总结     以上就完成了一个最简单的串口实验。     本文章主要是说明串口的重要性,用来调试程序很方便。 丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

  • 2021-08-09
  • 发表了主题帖: 详解PCB走线与信号完整性问题

    高速信号的PCB走线     现在但凡打开SoC原厂的PCB Layout Guide,都会提及到高速信号的走线的拐角角度问题,都会说高速信号不要以直角走线,要以45度角走线,并且会说走圆弧会比45度拐角更好。     事实是不是这样?PCB走线角度该怎样设置,是走45度好还是走圆弧好?90度直角走线到底行不行?       大家开始纠结于PCB走线的拐角角度,也就是近十几二十年的事情。上世纪九十年代初,PC界的霸主Intel主导定制了PCI总线技术。     似乎从PCI接口开始,我们开始进入了一个“高速”系统设计的时代。     电子设计和芯片制造技术按照摩尔定律往前发展,由于IC制程的工艺不断提高,IC的晶体管开关速度也越来越快,各种总线的时钟频率也越来越快,信号完整性问题也在不断的引起大家的研究和重视。     早期PCB拉线菌应该还是比较单纯,把线路拉通、撸顺,整洁、美观即可,不用去关注各种信号完整性问题。比如下图所示的HP经典的HP3456A万用表的电路板,大量的90°角走线,几乎是故意走的直角,绝大多数地方没有铺铜。       上面PCB板的右上角,不仅走直角不止,拐弯后,线宽还变小了,会造成信号反射问题,影响信号完整性。     本文跟大家探讨一下关于高频/高速信号的走线拐角角度问题。我们从锐角到直角、钝角、圆弧一直到任意角度走线,看看各种走线拐角角度的优缺点。 为什么PCB不能以锐角走线?     PCB能不能以锐角走线,答案是否定的。先不管以锐角走线会不会对高速信号传输线造成负面影响,单从PCB DFM方面,就应该避免出现锐角走线的情形。     因为在PCB导线相交形成锐角处,会造成一种叫酸角“acid traps”的问题。在PCB制板过程中,在PCB线路蚀刻环节,在“acid traps”处会造成PCB线路腐蚀过度,带来PCB线路虚断的问题。     虽然,我们可以借助CAM 350 进行DFF Audit自动检测出“acid traps”潜在问题,避免在PCB在制造产生时产生加工瓶颈。如果pcb板厂工艺人员检测到有酸角(acid trap)存在,他们将简单地贴一块铜到这个缝隙中。     很多板厂的工程人员他们其实并不懂Layout的,他们只是从PCB工程加工的角度修复酸角(acid trap)的问题,但这种修复是否能带来进一步的信号完整性问题便不得而知了,所以我们在Layout时就应该从源头去尽量避免产生酸角(acid trap)。     怎样避免拉线时出现锐角,造成acid trap DFM 问题?     现代的EDA设计软件(如Cadence Allegro、Altium Designer等)都带有了完善的Layout走线选项,我们在Layout走线时,灵活运用这些辅助选项,可以极大的避免我们在Layout时产生产生“acid trap”现象。     焊盘的出线角度设置,避免导线与焊盘形成锐角角度的夹角,如下图示例。      利用 Cadence Allegro 的 Enhanced Pad Entry 功能能够让我们在Layout时尽可能的避免导线与焊盘在出线时形成夹角,避免造成“acid traps”DFM问题。      避免两条导线交叉形成锐角夹角。     灵活应用 Cadence Allegro 布线时切换 ” toggle “ 选项,可以避免导线拉出T型分支时形成锐角夹角,避免造成“acid traps”DFM问题。   PCB Layout能不能以90°走线     高频高速信号传输线应避免以90°的拐角走线,是各种PCB Design Guide中极力要求的,因为高频高速信号传输线需要保持特性阻抗一致,而采用90°拐角走线,在传输线拐角处,会改变线宽,90°拐角处线宽约为正常线宽的 1.414倍,由于线宽改变了,就会造成信号的反射。     同时,拐角处的额外寄生电容也会对信号的传输造成时延影响。     当然,当信号沿着均匀互连线传播时,不会产生反射和传输信号的失真。如果均匀互连线上有一个90°拐角,则会在拐角处造成PCB传输线宽的变化,根据相关电磁理论计算得出,这肯定会带来信号的反射影响。     直角走线的对信号的影响就是主要体现在三个方面: ·拐角可以等效为传输线上的容性负载,减缓上升时间 ·90°拐角处线宽约为正常线宽的 1.414倍,引起阻抗不连续,进而造成信号的反射 ·直角尖端产生的EMI,尖端容易发射或接收电磁波,产生EMI     传输线的直角带来的寄生电容可以由下面这个经验公式来计算:   C=61W(Er)1/2/ZO       在上式中,C就是指拐角的等效电容(单位pF),W指走线的宽度(单位inch),Er指介质的介电常数,ZO就是传输线的特征阻抗。       对于高速数字信号来说,90°拐角对高速信号传输线会造成一定的影响,对于我们现在高密高速pcb来说,一般走线宽度为4-5mil,一个90°拐角的电容量大约为10fF,经测算,此电容引起的时延累加大约为0.25ps,所以,5mil线宽的导线上的90°拐角并不会对现在的高速数字信号(100-psec上升沿时间)造成很大影响。     而对于高频信号传输线来说,为了避免集肤效应(Skin effect)造成的信号损坏,通常会采用宽一点的信号传输线,例如50Ω阻抗,100mil线宽,这90°拐角处的线宽约为141mil,寄生电容造成的信号延时大约为25ps,此时,90°拐角将会造成非常严重的影响。     同时,微波传输线总是希望能尽量降低信号的损耗,90°拐角处的阻抗不连续和而外的寄生电容会引起高频信号的相位和振幅误差、输入与输出的失配,以及可能存在的寄生耦合,进而导致电路性能的恶化,影响 PCB 电路信号的传输特性。 关于90°信号走线,老wu自己的观点是,尽量避免以90°走线 45度外斜切线     除了射频信号和其他有特殊要求的信号,我们PCB上的走线应该优选以45°走线。要注意一点的是,45°角走线绕等长时,拐角处的走线长度要至少为1.5倍线宽,绕等长的线与线之间的间距要至少4倍线宽的距离。     由于高速信号线总是沿着阻抗的路径传输,如果绕等长的线间距太近,由于线间的寄生电容,高速信号走了捷径,就会出现等长不准的情况。现代的EDA软件的绕线规则都可以很方便的设置相关的绕线规则。     以arc弧形走线     如果不是技术规范明确要求要以弧形走线,或者是RF微波传输线,个人觉得,没有必要去走弧形线,因为高速高密度PCB的Layout,大量的弧形线后期修线非常麻烦,而且大量的弧形走线也比较费空间。     对于类似USB3.1或HDMI2.0这样的高速差分信号,个人认为还是可以走圆弧线的。       当然,对于RF微波信号传输线,还是优先走圆弧线,甚至是要走“采用 45° 外斜切”线走线。 总结     随着4G/5G无线通讯技术的发展和电子产品的不断升级换代,目前PCB数据接口传输速率已高达10Gbps或25Gbps以上,且信号传输速率还在不断的朝着高速化方向发展。随着信号传输的高速化、高频化发展,对PCB阻抗控制和信号完整性提出了更高的要求。     对于PCB板上传输的数字信号来说,电子工业界应用的包括FR4在内的许多电介质材料,在低速低频传输时一直被认为是均匀的。     但当系统总线上电子信号速率达到Gbps级别时,这种均匀性假设不再成立,此时交织在环氧树脂基材中的玻璃纤维束之间的间隙引起的介质层相对介电常数的局部变化将不可忽视,介电常数的局部扰动将使线路的时延和特征阻抗与空间相关,从而影响高速信号的传输。     基于FR4测试基板的测试数据表明,由于微带线与玻纤束相对位置差异,导致测量所得的传输线有效介电常数波动较大,值之差可以达到△εr=0.4。尽管这些空间扰动看上去较小,它会严重影响数据速度为5-10Gbps的差分传输线。     在一些高速设计项目中,为了应对玻纤效应对高速信号的影响,我们可以采用zig-zag routing布线技术以减缓玻纤效应的影响。     Cadence Allegro PCB Editor 16.6-2015 及后续版本带来了对zig-zag布线模式的支持。     在Cadence Allegro PCB Editor 16.6-2015 菜单中选择”Route -> Unsupported Prototype -> Fiber Weave Effect” 打开zig-zag routing功能。     二十年前我们PCB Layout不用关注是否要走弧形线,不用担心PCB板材玻璃纤维对高速信号的影响。     不存在一成不变的PCB Layout规则,随着PCB制造工艺的提升和数据传输速率的提高,有可能现在正确的规则在将来将变得不再适用。     丨 整理文章为传播相关技术,版权归原作者所有丨 丨如有侵权,请联系删除丨

统计信息

已有20人来访过

  • 芯积分:170
  • 好友:1
  • 主题:117
  • 回复:2
  • 课时:--
  • 资源:--

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言