自己的原文哦~            https://blog.51cto.com/whaosoft/14157096

一、可控硅控制电路实例

可控硅是可控硅整流器的简称。可控硅有单向、双向、可关断和光控几种类型。它具有体积小、重量轻、效率高、寿命长、控制方便等优点,被广泛用于可控整流、调压、逆变以及无触点开关等各种自动控制和大功率的电能转换的场合。

    单向可控硅是一种可控整流电子元件,能在外部控制信号作用下由关断变为导通,但一旦导通,外部信号就无法使其关断,只能靠去除负载或降低其两端电压使其关断。单向可控硅是由三个PN结PNPN组成的四层三端半导体器件与具有一个PN结的二极管相比,单向可控硅正向导通受控制极电流控制;与具有两个PN结的三极管相比,差别在于可控硅对控制极电流没有放大作用。

    可控硅导通条件:

    一是可控硅阳极与阴极间必须加正向电压,二是控制极也要加正向电压。以上两个条件必须同时具备,可控硅才会处于导通状态。另外,可控硅一旦导通后,即使降低控制极电压或去掉控制极电压,可控硅仍然导通。可控硅关断条件:降低或去掉加在可控硅阳极至阴极之间的正向电压,使阳极电流小于最小维持电流以下。

简易单向可控硅12V触摸开关电路

    触摸一下金属片开,SCR1导通,负载得电工作。触摸一下金属片关,SCR2导通,继电器J得电工作,K断开,负载失电,SCR2关断后,电容对继电器J放电,维持继电器吸合约4秒钟,故电路动作较为准确。如果将负载换为继电器,即可控制大电流工作的负载。

可控硅是一种新型的半导体器件,它具有体积小、重量轻、效率高、寿命长、动作快以及使用方便等优点,活动导入以可控硅实际应用案例的展示,以激发学生的活动兴趣。

    下文是可控硅控制电路的制作13例。

1:可调电压插座

电路如图,可用于调温(电烙铁)、调光(灯)、调速(电机),使用时只要把用电器的插头插入插座即可,十分方便。

    V1为双向二极管2CTS,V2为3CTSI双向可控硅,调节RP可使插座上的电压发生变化。

2:简易混合调光器

根据电学原理可知,电容器接入正弦交流电路中,电压与电流的最大值在相位上相差90°。根据这一原理,把C1和C2串联联接,并从中间取出该差为我所用,这比电阻与电容串联更稳定。电路中,D1和D2分别对电源的正半波及负半波进行整流,并加到A触发和C1或C2充电。进一步用W来改变触发时间进行移相,只要调整W的阻值,就可达到改变输出电压的目的。D1和D2还起限制触发极的反相电压保护双向可控硅的作用。

3:可调速吸尘器

    这种吸尘器使用可控硅元件构成调速电路,能根据需要控制电机转速,以发迹管道吸力的大小。下图所示的调速电路比较成熟,普遍使用在高档大功率吸尘器中。 

4:光控电子开关

    光控电子开关,它的“开”和“关”是靠可控硅的导通和阻断来实现的,而可控硅的导通和阻断又是受自然光的亮度(或人为亮度)的大小所控制的。该装置适合作为街道、宿舍走廊或其它公共场所照明灯,起到日熄夜亮的控制作用,以节约用电。 

工作原理:电路如上图所示,220V交流电通过灯泡H及整流全桥后,变成直流脉动电压,作为正向偏压,加在可控硅VS及R支路上。白天,亮度大于一定程度时,光敏二极管D呈现底阻状态≤1KΩ,使三极管V截止,其发射极无电流输出,单向可控硅VS因无触发电流而阻断。此时流过灯泡H的电流≤2.2mA,灯泡H不能发光。电阻R1和稳压二极管DW使三极管V偏压不超过6.8V,对三极管起保护作用。夜晚,亮度小于一定程度时,光敏二极管D呈现高阻状态≥100KΩ,使三极管V正向导通,发射极约有0.8V的电压,使可控硅VS触发导通,灯泡H发光。RP是清晨或傍晚实现开关转换的亮度选择元件。

    安装与调试:安装时,将装焊好的印制板放入透明塑料盒内并固定好,将它与受控电灯H串联,并让它正对着天幕或房子采光窗前较明亮的空间,避免3米以内夜间灯光的直接照射。调试宜傍晚时进行,调节RP阻值的大小,使受控电灯H在适当的亮度下始点亮。

5:自动延时照明开关

    夜晚离开房间,总要先关掉照明灯。可如果灯开关不在门口,那么关上灯再摸黑走到门口,十分不方便。

    本文介绍的一种开关仅用9个元件,可方便地加在原来的开关上,使您的灯在关掉后延时几十秒钟,让您有充足的时间离开房间,免受摸黑之苦。

    工作原理:电路原理如下图所示。A、B分别接在原开关两端。合上开关S时,交流电的正半周经D6、R2、R1、D1和可控硅控制极,触发可控硅导通;交流电的负半周经D4、R2、R1、D1和可控硅控制极,触发可控硅导通。可控硅导通后,相当于短路C、D两点,因而A、B两点也经过二极管和导通的可控硅闭合起来。此时照明灯亮。

 断开开关S后,由于电容C1经R1、D1和可控硅控制极放电,使可控硅仍有触发电流维持导通。放电电流逐渐减小,一段时间后,可控硅截止,灯灭。此电路延时时间约为40~50秒。

    元件选择:可控硅选最大电流1A、耐压400V的。D1、D3~D6可用1N4004。C1用耐压630V、35μF的彩电电容。如果合上开关S灯不亮,可适当减小R1的阻值。

6:声控音乐彩灯

    彩灯控制器的电路如下图,R1、R2、D和C组成电阻降压半波整波电路,输出约3V的直流电供SCR的控制回路用。压电陶瓷片HTD担任声-电换能器,平时调W使BG集电极输出低电平,SCR关断,彩灯不亮。当HTD接收到声波信号后,BG集电极电平升高,SCR即开通,所以彩灯能随室内收录机播出的音乐节奏而闪烁发光。

W可用来调节声控灵敏度,W由大调小时,声控灵敏度愈高,但W过小时,电灯常亮,这时就失去声控作用,使用调试时,将W由大逐渐调小至某一阻值时,电灯即点亮,再将W退回少许(即稍微调大),电灯就熄灭,这时声控灵敏度最高,离HTD二三米远处普通谈话声就能使彩灯闪烁。如嫌灵敏度太高,只要将W调大些即可,电灯长亮不熄,表示BG的放大倍数β值过小,应更换β大些的三极管。电阻均为1/8W碳膜电阻。

7:简易延时照明灯

    本文介绍的这种延时照明灯非常简单,安装也十分方便,将它直接连接于普通开关的两端即可。使用时,打开开关电灯点亮,关灯后由于延时电路的作用使电灯仍亮几秒钟后自动熄灭。本电路安全可靠,适合初学者自制。

    电路原理:该延时照明灯的电路如附图所示。延时电路如虚线框内所示。图中K为拉线开关或墙壁开关,当K闭合后,该延时电路不工作,电灯处于正常的发光状态。当K被关断后,该电压一方面经R1向电容C充电,由于在C的充电期间没有电流流过R2,则三极管V一直处于截止状态;另一方面,该电压经R3、R4向可控硅SCR提供触发电压,使可控硅处于导通状态,因此在关灯后电灯亮一段时间。当电容C被充足电后,使三极管V由截止转为导通状态,将可控硅SCR关断,电灯也就熄灭了。

本电路关灯延时期间,延时时间由R1、C的取值来确定,读者也可根据各自需要自行确定。本电路中的可控硅,笔者选用的为单向可控硅,在关灯延时期间电灯的亮度约为开灯时亮度的一半,以适合人们的视觉上的需要,同时又可节能。

    电路制作:图中单向可控硅SCR选用MCR100-8,耐压须为600V以上。灯泡的功率不大于100W为宜。二极管VD为1N4007,V为C1815。电阻均为1/8W碳膜电阻。

    制作时,用一小块电路板将图中虚线框内各元器件焊装上。最好将本电路装在拉线开关底部凹槽内,用胶水粘牢并将引线接至开关两接线端即可。

8:单键自锁开关 

单键自锁开关说明:

1、上电不动作。

2、按钮按下后再释放,继电器吸合。

3、按钮长按时,继电器释放,松开后继电器吸合。

4、按钮点按时:继电器释放 ←→ 吸合循环动作。

5、因为47Ω电阻有压降,继电器可以用DC9V的。

9:简单的停电自锁开关

电网供电正常时,它象普通开关一样使用。按一下K1,220V交流电经R1和R2分压给双向可控硅提供一触发电压,使双向可控硅导通。可控硅导通后,在电源电压正半周期间,少量电流经R4、D向C充电,同时经R3、R2分压触发可控硅;在负半周期间,C向R3和R2放电并触发双向可控硅,这样使双向可控硅继续导通,保证负载正常工作。一旦电网突然停电,C上的电荷经R3和R2放电。在电网恢复供电后,由于K1常开,C上又无电压,不能使双向可控硅触发导通,电路呈断开自锁状态,因此没有电流流过负载。只有重按一下K1,负载才能正常工作,从而有效地防止了因断电后恢复供电造成的浪费和事故。常闭按钮K2用于正常供电情况下关断电路。

10:双色彩灯

    本彩灯是以多谐振荡器为控制信号,灯光交替闪耀,可给节日晚上(尤其是舞会)增加不少光彩和欢快气氛。

    工作原理如下图所示。交流220V电源经C1、VD1、VD2及VD3降压、整流、滤波后,在VD3两端得到3V的稳定电压。多谐振荡器中的VT1、VT2轮流导通,其集电极电流控制双向晶闸管VS1和VS2工作,彩灯将交替闪烁着光彩。

元器件选择:电容C1为0.47μ/400V(涤纶电容)、C2为220μ/6V,C3、C4为50μ/16V。电阻R1为1M/1W,R2、R3为20K/1/4W。二极管VD1、VD2

    选1N4004。稳压二极管VD3选3V/1W。发光二极管VD4、VD5为FG114001。双向晶闸管VS1、VS2为TLC3A/400V。三极管VT1、VT2为3CK9D,60≤β≤120。

    使用方法:

(1)如彩灯不亮,将3V稳压管换成4.5V稳压管。

(2)为防止流过发光二极管VD4、VD5的电流过大,最好在其回路中分别串入一个300Ω的限流电阻。

(3)调整时,改变R1、R2或C1、C2的大小,则可直接控制彩灯相互变化的快慢节奏。

(4)如双向晶闸管VS1、VS2用3A/400V,最好负载功率在300W以下,切忌不可超过最高限额500W。如想增大功率,可选用电流大于3A的晶闸管,但C1的容量还需增加。如原用0.47μ/400V可换成0.68~1μ/400V即可。

(5)本装置采用塑料作外壳,以避免市电源对人的触电,这样更为安全。

11:可控硅交流调压器

    交流调压器采用可控硅调压器。电路简单、装置容易、控制方便的可控硅交流调压器,这可用作家用电器的调压装置,进行照明灯调光,电风扇调速、电熨斗调温等控制。本活动调压器的输出功率达100W,一般家用电器都能使用。

    电路原理,电路图如下:

可控硅交流调压器由可控整流电路和触发电路两部分组成,从图中可知,二极管D1—D4组成桥式整流电路,双基极二极管T1构成张弛振荡器作为可控硅的同步触发电路。当调压器接上220V交流电通过负载电阻RL经二极管D1—D4整流,在可控硅SCR的A、K两端形成一个脉动直流电压,该电压由电阻R1降压后作为触发电路的直流电源。在交流电的正半周时,整流电压通过R4、W1对电容C充电。当充电电压Uc达到T1管的峰值电压Up时,T1管由截止变为导通,于是电容C通过T1管的e、b1结和R2迅速放电,结果在R2上获得一个尖脉冲。这个脉冲作为控制信号送到可控硅SCR的控制极, 使可控硅导通。可控硅导通后的管压降很低,一般小于1V,所以张弛振荡器停止工作。当交流电通过零点时,可控硅自关断。当交流电在负半周时,电容C又从新充电……如此周而复始,便可调整负载RL上的功率了。

    元器件选择:

    调压器的调节电位器选用阻值为470KΩ的WH114-1型合成碳膜电位器,这种电位器可以直接焊在电路板上,电阻除R1要用功率为1W的金属膜电阻外,其佘的都用功率为1/8W的碳膜电阻。D1—D4选用反向击穿电压大于300V、最大整流电流大于0.3A的硅整流二极管,如2CZ21B、2CZ83E、2DP3B等。SCR选用正向与反向电压大于300V、额定平均电流大于1A的可控硅整流器件,如国产3CT

12:电热毯温控器

    市售电热毯一般有高、低两个温度档。使用时,拨在高温档,入睡后总被热醒;拨在低温档,有时醒来会觉得热度不够。为此,笔者制作了这种电热毯温控器,它可以把电热毯的温度控制在一个适宜的范围内。

    工作原理:电路如下图所示。图中IC为NE555时基电路;RP3为温度调节电位器,其滑动臂电位决定IC的触发电位V2和阈电位Vf,且V5=Vf=2Vz。220V交流电压经C1、R1限流降压,D1、D2整流,C2滤波,DW稳压后,获得9V左右的电压供IC用。室温下接通电源,因已调V2《Vz、V6《Vf,IC③脚为高电位,BCR被触发导通,电热丝通电发热,温度逐渐升高。热敏传感器BG1随温度的升高,其穿透电流Iceo增大,V2、V6升高。当V2》Vz,V6≥Vf时,IC翻转,③脚变为低电位,BCR截止邮电局热丝停止发热,温度开始逐渐下降,BG1的Iceo随之逐渐减小,V2、V6降低。当V6《Vf,V2≤Vz时,IC③脚回到高电位,BCR又被触发导通,电热丝又开始发热。实践证明,调节RP2使V2=1/2V6时,温差为零;而V2=V6时最大。

元件选择:BG1可选用3AX、3AG等PNP型锗管;BCR用400V以上小型塑封双向可控硅,其它元件可按图标选用。

    制作要点:热敏传感器BG1可用耐温的细软线引出,并将其连同管脚接头装入一电容器铝壳内,注入导热硅脂,制成温度探头。使用时,把该探头放在适当部位即可。

13:安全省电的按键式床头灯

    一盏延时式床头灯,对于许多读者在夜晚使用是很方便的。本文介绍的按键式床头灯能安全和方便的要求,电路原理如下图所示。

该床头灯由节电型单稳态电路和亮度可控照明灯两部分组成。两部分靠光电耦合器耦合,电气部分完全独立,使用十分安全。当K1断开时,VT1截止,其集电极电压为0V,VT2截止,NE555第①脚接地端开路而不工作,此时,电路的耗电仅为VT1、VT2的穿透电流,约3~5μA,四节电池能使用一年半以上。按下K1后,VT1饱和导通,R3两端电压接近电源电压,VT2饱和导通,NE555工作,此时,NE555第②脚由高电平变为低电平,而且低于1/3的电源电压,NE555翻转,第③脚输出高电平,其一路能过R7驱动光电耦合器4N25,使双向可控硅VS导通,床头灯H点亮;另一路通过二极管VD1、电阻R6向VT2提供足够大的偏流,维持VT2饱和导通,此时,即使K1断开,VT2的工作状态也不变,即NE555的暂稳状态不变。在此期间,电源经R5为C1充电,使C1两端电压不断升高,当C1两端电压大于2/3电源电压时,通过NE555的放电端第⑦脚放电,NE555的暂稳态结束,第三③脚由高电平变为低电平,VT2截止,进入另一个稳定状态,只有在K1再次接通时,NE555才再次进入暂稳态,床头灯再次点亮。

    该床头灯所用元件型号及数据如附图所示,无特殊要求。整个床头灯安装容易,调试简单,只要安装无误,就能正常使用。若延时时间太短,可加大R5的阻值或C1的容量,反之亦然。安装时将按键部分外置,其余元件装入塑料盒内,以确保使用安全。

 .

二、三极管滤波

❤如图1是无刷电机霍尔信号的滤波电路,为了保证波形质量,简单的阻容滤波并不能完全解决实际复杂的工作环境所带来的波形异常,量产的无刷驱动模块也有该电路。

❤为了保证滤波质量,在RC滤波后面加一个NPN三极管,利用三极管自身的响应速度达到高质量滤波目的

❤三极管响应速度有个最小宽度要求,通常是几十个纳秒到几百纳秒,信号大于最小脉宽要求才能保证正常输出而不失真

图1:无刷电机霍尔信号滤波

❤通常在做驱动的时候,会遇到霍尔信号或编码器信号的处理,该信号是脉冲(方波)信号,在滤波之前的波形如图1左边所示,实际上毛刺会更多更杂。

❤毛刺宽度一般只有几十个纳秒,在RC滤波后面加上一个三极管后可根本滤除毛刺,让输出更干净,质量更高,如图1右边所示。

图2、图3、图4是实测无刷电机霍尔信号滤波前后的波形对比,红色波形代表霍尔信号滤波前的;蓝色波形代表霍尔信号滤波后的。滤波前的毛刺异常恐怖。

图2:滤波前后对比

 图3:滤波前后对比(放大) 

图4:滤波前后对比(再放大)

图5是实测无刷电机霍尔信号经过RC滤波后和三级管后滤波的波形对比,红色波形代表霍尔信号经过RC滤波后的,蓝色波形代表霍尔信号经过RC滤波再经过三极管滤波后的;

注:两个波形没有反相,是因为上面那个红色波形一直在左右晃动,随机抓取的。

图5:RC滤波和三级管滤波对比

要点:

①该类信号属于OC输出,所以需要加上拉电阻(R4);

②阻容滤波(R2、C1)是低通滤波,信号频率应低于fc=1/2πRC;

③三极管导通时必须工作在饱和状态,通常基极电流Ib>1mA能保证三极管工作在饱和状态;

④三极管输出波形与输入波形反相,这点在程序里可以做取反处理。

 .

三、看电路图

昨天说了电烙铁,有的同学分享了自己第一次学习使用电烙铁的艰辛,也有同学说目前正在学习电烙铁使用,还有同学说刚学会电烙铁,现在准备研读线路图,想要知道电路图容不容易读懂,要怎么看懂电路图。

        其实电路图第一眼看上去感觉很复杂,但是它都是由各个元器件图形符号和文字符号组成的,比如我们常见的电阻、电容、电感、晶体管、集成电路等等。

        我们如果想要看懂电路图,那么我们首先要了解图中使用了哪些电子元器件,这些元器件的结构、功能、特征是什么,这些元器件结合所组成的模块作用是什么,如果其中某个元器件损坏了,那么会导致什么样的结果。

        我们知道,电阻在电路中主要起到阻碍作用,利用这个特性,我们可以将电阻做成分压电路、限流电路、降压电路等等,电容具有通交隔直、储能的特性,我们可以将其用于滤除交流杂波、存储能量等方面,除去这两个最常用的元器件,我们电路图中最重要和最常见的应该是晶体管和集成电路,因此要了解晶体管的输入、输出特性及其工作在放大区、截止区和饱和区的条件,集成电路芯片的引脚及功能等是十分重要的。

        我们拿到一张电子电路图时,能够首先要明白电路不管有多么复杂,它都可以分解成若干个单元电路,如果是模拟电路,一般可以分为输入电路、主电路、输出电路、电源电路、附属电路、保护电路等等,而这些模块电路就是由若干个元器件组成的,我刚接触电路时采用过一个方法来记住这些电路的联系,那就是画框法,简单说就是将每一个电路模块用框来表示,然后找出它们之间的联系,搞清楚每个模块的元器件有哪些,它们的作用是什么,这样你就可以弄清楚每个单元电路的功能,从而弄明白这些模块之间有什么关系,久而久之你就能对整个电路了如指掌,对于模块我们要从较为简单的局部电路开始分析,然后再进行整体电路分析,在识图过程中要注意综合知识的运用,逐步深入分析,对基本电路理解的越深,掌握的越牢,就会化难为易,看懂复杂的电路图。然后通过反复的训练和实践,取得一定经验,识图能力一定会逐步提高。

    我们在分析电路时,要注意我们的电路都是有静态和动态两种情况,比如电路中的晶体管和集成电路,它们在工作中需要建立静态工作点,才能实现对交流信号的放大作用,为了识图方便,我经常在分析时采用直流等效法和交流等效电路法对电路的静态和动态进行分析。

       直流等效法就是在输出信号为零时,各级放大器在直流电源作用下的工作状态,简单来说就是找出电路的直流通路,就像我们前面说的,电容具有通交隔直的特性,而电感与之相反,所以在直流通路中,电容可以看做是导线,电感可以看为断线,找出直流通路后,我们就可以确定各级电路在静态时的偏置电流和电压,交流等效电路法就是在输入信号不为零的情况下,确定电路中的交流信号通路及工作状态。

.

四、不用串口,如何打印STM32单片机log

本文主要介绍在嵌入式开发中用来输出log的方法。

    最常用的是通过串口输出uart log,这种方法实现简单,大部分嵌入式芯片都有串口功能。但是这样简单的功能有时候却不是那么好用,比如:

  • 一款新拿到的芯片,没有串口驱动时如何打印log
  • 某些应用下对时序要求比较高,串口输出log占用时间太长怎么办?比如USB枚举。
  •  某些bug正常运行时会出现,当打开串口log时又不再复现怎么办
  • 一些封装中没有串口,或者串口已经被用作其他用途,要如何输出log 

    下文来讨论这些问题。

1 输出log信息到SRAM

    准确来说这里并不是输出log,而是以一种方式不使用串口就可以看到log。在芯片开发阶段都可以连接仿真器调试,可以使用打断点的方法调试,但是有些操作如果不能被打断就没法使用断点调试了。

    这时候可以考虑将log打印到SRAM中,整个操作结束后再通过仿真器查看SRAM中的log buffer,这样就实现了间接的log输出。

    本文使用的测试平台是STM32F407 discovery,基于usb host实验代码,对于其他嵌入式平台原理也是通用的。首先定义一个结构体用于打印log,如下:

  定义一段SRAM空间作为log buffer:

static u8 log_buffer[LOG_MAX_LEN];

    log buffer是环形缓冲区,在小的buffer就可以无限打印log,缺点也很明显,如果log没有及时输出就会被新的覆盖。Buffer大小根据SRAM大小分配,这里使用1kB。为了方便输出参数,使用printf函数来格式化输出,需要做如下配置(Keil):

并包含头文件#include <stdio.h>, 在代码中实现函数fputc(): 

写入数据到SRAM: 

为了方便控制log打印格式,在头文件中再添加自定义的打印函数。 

在需要打印log的地方直接调用DEBUG()即可,最终效果如下,从Memory窗口可以看到打印的log: 

2 通过SWO输出log

    通过打印log到SRAM的方式可以看到log,但是数据量多的时候可能来不及查看就被覆盖了。为了解决这个问题,可以使用St-link的SWO输出log,这样就不用担心log被覆盖。查看原理图f407 discovery的SWO已经连接了,否则需要自己飞线连接:

在log结构体中添加SWO的操作函数集:

typedef struct
{
    u8 (*init)(void* arg);
    u8 (*print)(u8 ch);
    u8 (*print_dma)(u8* buffer, u32 len);
}log_func;
typedef struct
{
volatile u8     type;
    u8*             buffer;
volatile u32    write_idx;
volatile u32    read_idx;
//SWO
    log_func*       swo_log_func;
}log_dev;

    SWO只需要print操作函数,实现如下:

u8 swo_print_ch(u8 ch)
{
    ITM_SendChar(ch);
return 0;
}

    使用SWO输出log同样先输出到log buffer,然后在系统空闲时再输出,当然也可以直接输出。log延迟输出会影响log的实时性,而直接输出会影响到对时间敏感的代码运行,所以如何取舍取决于需要输出log的情形。

    在while循环中调用output_ch()函数,就可以实现在系统空闲时输出log。

/*output log buffer to I/O*/
void output_ch(void)
{   
    u8 ch;
    volatile u32 tmp_write,tmp_read;
    tmp_write = log_dev_ptr->write_idx;
    tmp_read = log_dev_ptr->read_idx;
if(tmp_write != tmp_read)
    {
        ch = log_dev_ptr->buffer[tmp_read++];
//swo
if(log_dev_ptr->swo_log_func)
            log_dev_ptr->swo_log_func->print(ch);
if(tmp_read >= LOG_MAX_LEN)
        {
            log_dev_ptr->read_idx = 0;
        }
else
        {
            log_dev_ptr->read_idx = tmp_read;
        }
    }
}

2.1 通过IDE输出

    使用IDE中SWO输出功能需要做如下配置(Keil):

在窗口可以看到输出的log:

2.2 通过STM32 ST-LINK Utility输出

    使用STM32 ST-LINK Utility不需要做特别的设置,直接打开ST-LINK菜单下的Printf via SWO viewer,然后按start:

3 通过串口输出log

    以上都是在串口log暂时无法使用,或者只是临时用一下的方法,而适合长期使用的还是需要通过串口输出log,毕竟大部分时候没法连接仿真器。添加串口输出log只需要添加串口的操作函数集即可:

typedef struct
{
volatile u8     type;
    u8*             buffer;
volatile u32    write_idx;
volatile u32    read_idx;
volatile u32    dma_read_idx;
//uart
    log_func*       uart_log_func;
//SWO
    log_func*       swo_log_func;
}log_dev;

    实现串口驱动函数:

 添加串口输出log与通过SWO过程类似,不再多叙述。而下面要讨论的问题是,串口的速率较低,输出数据需要较长时间,严重影响系统运行。

虽然可以通过先打印到SRAM再延时输出的办法来减轻影响,但是如果系统中断频繁,或者需要做耗时运算,则可能会丢失log。要解决这个问题,就是要解决CPU与输出数据到串口同时进行的问题,嵌入式工程师立马可以想到DMA正是好的解决途径。

    使用DMA搬运log数据到串口输出,同时又不影响CPU运行,这样就可以解决输出串口log耗时影响系统的问题。串口及DMA初始化函数如下:

u8 uart_log_init(void* arg)
{
    DMA_InitTypeDef DMA_InitStructure;
    u32* bound = (u32*)arg;
//GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟
//串口2对应引脚复用映射
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);
//USART2端口配置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //速度50MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
    GPIO_Init(GPIOA,&GPIO_InitStructure);
//USART2初始化设置
    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_Tx; //收发模式
    USART_Init(USART2, &USART_InitStructure); //初始化串口1
#ifdef LOG_UART_DMA_EN  
    USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);
#endif
    USART_Cmd(USART2, ENABLE);  //使能串口1 
    USART_ClearFlag(USART2, USART_FLAG_TC);
while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
#ifdef LOG_UART_DMA_EN
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
//Config DMA channel, uart2 TX usb DMA1 Stream6 Channel
    DMA_DeInit(DMA1_Stream6);
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; 
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA1_Stream6, &DMA_InitStructure);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
#endif
return 0;
}

    DMA输出到串口的函数如下:

这里为了方便直接使用了查询DMA状态寄存器,有需要可以修改为DMA中断方式,查Datasheet可以找到串口2使用DMA1 channel4的stream6: 

最后在PC端串口助手可以看到log输出: 

使用DMA搬运log buffer中数据到串口,同时CPU可以处理其他事情,这种方式对系统影响最小,并且输出log及时,是实际使用中用的最多的方式。并且不仅可以用串口,其他可以用DMA操作的接口(如SPI、USB)都可以使用这种方法来打印log。

4 使用IO口模拟串口输出log

    最后要讨论的是在一些封装中没有串口,或者串口已经被用作其他用途时如何输出log,这时可以找一个空闲的普通IO,模拟UART协议输出log到上位机的串口工具。常用的UART协议如下:

 只要在确定的时间在IO上输出高低电平就可以模拟出波形,这个确定的时间就是串口波特率。为了得到精确延时,这里使用TIM4定时器产生1us的延时。注意:定时器不能重复用,在测试工程中TIM2、3都被用了,如果重复用就错乱了。初始化函数如下:

u8 simu_log_init(void* arg)
{
    TIM_TimeBaseInitTypeDef TIM_InitStructure;  
    u32* bound = (u32*)arg;
//GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //速度50MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    GPIO_SetBits(GPIOA, GPIO_Pin_2);
//Config TIM
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //使能TIM4时钟
    TIM_DeInit(TIM4);
    TIM_InitStructure.TIM_Prescaler = 1;        //2分频
    TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_InitStructure.TIM_Period = 41;          //1us timer
    TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(TIM4, &TIM_InitStructure);
    TIM_ClearFlag(TIM4, TIM_FLAG_Update);
    baud_delay = 1000000/(*bound);          //根据波特率计算每个bit延时
return 0;
}

    使用定时器的delay函数为:

    最后是模拟输出函数,注意:输出前必须要关闭中断,一个byte输出完再打开,否则会出现乱码:

u8 simu_print_ch(u8 ch)
{
volatile u8 i=8;
    __asm("cpsid i");
//start bit
    GPIO_ResetBits(GPIOA, GPIO_Pin_2);
    simu_delay(baud_delay);
while(i--)
    {
if(ch & 0x01)
        GPIO_SetBits(GPIOA, GPIO_Pin_2);
else
        GPIO_ResetBits(GPIOA, GPIO_Pin_2);
        ch >>= 1;
        simu_delay(baud_delay);
    }
//stop bit
    GPIO_SetBits(GPIOA, GPIO_Pin_2);
    simu_delay(baud_delay);
    simu_delay(baud_delay);
    __asm("cpsie i");
return 0;
}

    使用IO模拟可以达到与真实串口类似的效果,并且只需要一个普通IO,在小封装芯片上比较使用。   .

           

五、画PCB板时阻抗设计的重要性

什么是阻抗

    在电学中,常把对电路中电流所起的阻碍作用叫做阻抗。阻抗单位为欧姆,常用Z表示,是一个复数:

Z= R+i( ωL–1/(ωC))

    具体说来阻抗可分为两个部分,电阻(实部)和电抗(虚部)。

    其中电抗又包括容抗和感抗,由电容引起的电流阻碍称为容抗,由电感引起的电流阻碍称为感抗。

阻抗匹配的理想模型

    射频工程师大都遇到过匹配阻抗的问题,通俗的讲,阻抗匹配的目的是确保能实现信号或能量从“信号源”到“负载”的有效传送。

    其最最理想模型当然是希望Source端的输出阻抗为50欧姆,传输线的阻抗为50欧姆,Load端的输入阻抗也是50欧姆,一路50欧姆下去,这是最理想的。

 然而实际情况是:源端阻抗不会是50ohm,负载端阻抗也不会是50ohm,这个时候就需要若干个阻抗匹配电路。

    而匹配电路就是由电感和电容所构成,这个时候我们就需要使用电容和电感来进行阻抗匹配电路调试,以达到RF性能最优。

阻抗匹配的方法

    阻抗匹配的方法主要有两个,一是改变阻抗力,二是调整传输线。

    改变阻抗力就是通过电容、电感与负载的串并联调整负载阻抗值,以达到源和负载阻抗匹配。

调整传输线是加长源和负载间的距离,配合电容和电感把阻抗力调整为零。

    此时信号不会发生发射,能量都能被负载吸收。

    高速PCB布线中,一般把数字信号的走线阻抗设计为50欧姆。一般规定同轴电缆基带50欧姆,频带75欧姆,对绞线(差分)为85-100欧姆。

阻抗匹配应用举例——振铃现象

    曾经做一个项目,在电信号测量时,遇到过振铃这种问题,。

    由于任何传输线都不可避免地存在着引线电阻、引线电感和杂散电容,因此,一个标准的脉冲信号在经过较长的传输线后,极易产生上冲和振铃现象。大量的实验表明,引线电阻可使脉冲的平均振幅减小;而杂散电容和引线电感的存在,则是产生上冲和振铃的根本原因。在脉冲前沿上升时间相同的条件下,引线电感越大,上冲及振铃现象就越严重;杂散电容越大,则是波形的上升时间越长;而引线电阻的增加,将使脉冲振幅减小。

    如果信号传输过程中感受到阻抗的变化,就会发生信号的反射。这个信号可能是驱动端发出的信号,也可能是远端反射回来的反射信号。根据反射系数的公式,当信号感受到阻抗变小,就会发生负反射,反射的负电压会使信号产生下冲。信号在驱动端和远端负载之间多次反射,其结果就是信号振铃。大多数芯片的输出阻抗都很低,如果输出阻抗小于PCB走线的特性阻抗,那么在没有源端端接的情况下,必然产生信号振铃。

在实际电路中,采用下列几种方法来来减小和抑制上冲及振铃。

    (1)串联电阻。利用具有较大电阻的传输线或是人为地串入适当的阻尼电阻,可以减小脉冲的振幅,从而达到减小上冲和振铃程度的目的。但当传入电阻的数值过大时,不仅脉冲幅度减小过多,而且使脉冲的前沿产生延迟。因此,串入的阻尼电阻值应适当,并且应选用无感电阻,电阻的连接位置应靠近接收端。

    (2)减小引线电感。设法减小线路及传输线的引线电感是最基本的方法,总的原则是:

  • 尽量缩短引线长度
  • 加粗导线和印制铜箔的宽度
  • 减小信号的传输距离
  • 采用引线电感小的元器件,尤其是传输前沿很陡的脉冲信号时更应注意这些问题

    (3)由于负载电路的等效电感和等效电容同样可以影响发送端,使之脉冲波形产生上冲和振铃,因此,应尽量减小负载电路的等效电感和电容。尤其是负载电路的接地线过长时,形成的地线电感和杂散电容相当可观,其影响不容忽视。

    (4)逻辑数字电路中的信号线可增加上拉电阻和交流终端负载,如图6所示。上拉电阻(可取)的接入,可将信号的逻辑高电平上拉到5V。交流终端负载电路的接入不影响支流驱动能力,也不会增加信号线的负载,而高频振铃现象却可得到有效的抑制。

    上述振铃除了与电路条件有关外,还与脉冲前沿的上升时间密切相关。即使电路条件相同,当脉冲前沿上升时间很短时,上冲的峰值将大大增加。一般对于前沿上升时间在1以下的脉冲,均考虑产生上冲及振铃的可能。因此,在脉冲信号频率的选择问题上,应考虑在满足系统速度要求的前提下,能选用较低频率的信号绝不选用高频信号;如无必要,也不应过分要求脉冲的前沿非常陡峭。这对从根本上消除上冲和振铃视听有利的。

Smith圆图在RF匹配电路调试中的应用

    Smith圆图上可以反映出如下信息: 阻抗参数Z,导纳参数Y,品质因子Q,反射系数,驻波系数,噪声系数,增益,稳定因子,功率,效率,频率信息等抗等参数。

是不是一脸懵,我们还是来看阻抗圆图吧: 

阻抗圆图的构图原理是利用输入阻抗与电压反射系数之间的一一对应关系,将归一化输入阻抗表示在反射系数极坐标系中,其特点归纳如下:

  • 上半圆阻抗为感抗,下半圆阻抗为容抗
  • 实轴为纯电阻,单位圆为纯电抗
  • 实轴的右半轴皆为电压波腹点(除开路点),左半轴皆为电压波节点(除短路点)
  • 匹配点(1,0),开路点(∞,∞)和短路点(0,0)
  • 两个特殊圆:最大的为纯电抗圆,与虚轴相切的为匹配圆
  • 两个旋转方向:逆时针转为向负载移动,顺时针转为向波源移动

    导纳圆图与阻抗圆图互为中心对称,同一张圆图,即可以当作阻抗圆图来用,也可以当作导纳圆图来用,但是在进行每一次操作时,若作为阻抗圆图用则不能作为导纳圆图。

    Smith圆图中,能表示出一些很有意思的特征:

    在负载之前串联或并联一个可变电感/电容,电路图如下图左侧4个图所示,将得到Smith圆图上右侧的几条曲线。

    对应Smith阻抗圆及导纳圆,其运动轨迹如下:

  • 使用Smith阻抗圆时,串联电感顺时针转,串联电容逆时针转
  • 使用Smith导纳圆时,并联电感,逆时针转,并联电容顺时针转

.

六、总结10种复杂电路分析方法

电路问题计算的先决条件是正确识别电路,搞清楚各部分之间的连接关系。对较复杂的电路应先将原电路简化为等效电路,以便分析和计算。识别电路的方法很多,现结合具体实例介绍十种方法。

一、特征识别法

    串并联电路的特征是;串联电路中电流不分叉,各点电势逐次降低,并联电路中电流分叉,各支路两端分别是等电势,两端之间等电压。根据串并联电路的特征识别电路是简化电路的一种最基本的方法。

    例1.试画出图1所示的等效电路。

   解:设电流由A端流入,在a点分叉,b点汇合,由B端流出。支路a—R1—b和a—R2—R3(R4)—b各点电势逐次降低,两条支路的a、b两点之间电压相等,故知R3和R4并联后与R2串联,再与R1并联,等效电路如图2所示。

二、伸缩翻转法

    在实验室接电路时常常可以这样操作,无阻导线可以延长或缩短,也可以翻过来转过去,或将一支路翻到别处,翻转时支路的两端保持不动;导线也可以从其所在节点上沿其它导线滑动,但不能越过元件。这样就提供了简化电路的一种方法,我们把这种方法称为伸缩翻转法。

    例2.画出图3的等效电路。

 解:先将连接a、c节点的导线缩短,并把连接b、d节点的导线伸长翻转到R3—C—R4支路外边去,如图4。

    再把连接a、C节点的导线缩成一点,把连接b、d节点的导线也缩成一点,并把R5连到节点d的导线伸长线上(图5)。由此可看出R2、R3与R4并联,再与R1和R5串联,接到电源上。

三、电流走向法

    我们一直寻找的,却是自己原本早已拥有的;我们总是东张西望,唯独漏了自己想要的,这就是我们至今难以如愿以偿的原因。

    电流是分析电路的核心。从电源正极出发(无源电路可假设电流由一端流入另一端流出)顺着电流的走向,经各电阻绕外电路巡行一周至电源的负极,凡是电流无分叉地依次流过的电阻均为串联,凡是电流有分叉地分别流过的电阻均为并联。

    例3.试画出图6所示的等效电路。

    解:电流从电源正极流出过A点分为三路(AB导线可缩为一点),经外电路巡行一周,由D点流入电源负极。第一路经R1直达D点,第二路经R2到达C点,第三路经R3也到达C点,显然R2和R3接联在AC两点之间为并联。二、三络电流同汇于c点经R4到达D点,可知R2、R3并联后与R4串联,再与R1并联,如图7所示。

四、等电势法

    在较复杂的电路中往往能找到电势相等的点,把所有电势相等的点归结为一点,或画在一条线段上。当两等势点之间有非电源元件时,可将之去掉不考虑;当某条支路既无电源又无电流时,可取消这一支路。我们将这种简比电路的方法称为等电势法。

    例4.如图8所示,已知 R1 = R2 = R3 = R4 = 2Ω ,求A、B两点间的总电阻。

  解:设想把A、B两点分别接到电源的正负极上进行分析,A、D两点电势相等,B、C两点电势也相等,分别画成两条线段。电阻R1接在A、C两点,也即接在A、B两点;R2接在C、D两点,也即接在B、A两点;R3接在D、B两点,也即接在A、B两点,R4也接在A、B两点,可见四个电阻都接在A、B两点之间均为并联(图9)。所以,PAB=3Ω。  

五、支路节点法

    节点就是电路中几条支路的汇合点。所谓支路节点法就是将各节点编号(约定;电源正极为第1节点,从电源正极到负极,按先后次序经过的节点分别为1、2、3……),从第1节点开始的支路,向电源负极画。可能有多条支路(规定:不同支路不能重复通过同一电阻)能达到电源负极,画的原则是先画节点数少的支路,再画节点数多的支路。然后照此原则,画出第2节点开始的支路。余次类推,最后将剩余的电阻按其两端的位置补画出来。

    例5.画出图10所示的等效电路。

 解:图10中有1、2、3、4、5五个节点,按照支路节点法原则,从电源正极(第1节点)出来,节点数少的支路有两条:R1、R2、R5支路和R1、R5、R4支路。取其中一条R1、R2、R5支路,画出如图11。

    再由第2节点开始,有两条支路可达负极,一条是R5、R4,节点数是3,另一条是R5、R3、R5,节点数是4,且已有R6重复不可取。所以应再画出R5、R4支路,最后把剩余电阻R3画出,如图12所示。

六、几何变形法

    几何变形法就是根据电路中的导线可以任意伸长、缩短、旋转或平移等特点,将给定的电路进行几何变形,进一步确定电路元件的连接关系,画出等效电路图。

    例6.画出图13的等效电路。

    解:使ac支路的导线缩短,电路进行几何变形可得图14,再使ac缩为一点,bd也缩为一点,明显地看出R1、R2和R5三者为并联,再与R4串联(图15)。

七、撤去电阻法

    根据串并联电路特点知,在串联电路中,撤去任何一个电阻,其它电阻无电流通过,则这些电阻是串联连接;在并联电路中,撤去任何一个电阻,其它电阻仍有电流通过,则这些电阻是并联连接。

仍以图13为例,设电流由A端流入,B端流出,先撤去R2,由图16可知R1、R3有电流通过。再撤去电阻R1,由图17可知R2、R3仍有电流通过。同理撤去电阻R3时,R1、R2也有电流通过由并联电路的特点可知,R1、R2和R3并联,再与R4串联。

八、独立支路法

    让电流从电源正极流出,在不重复经过同一元件的原则下,看其中有几条路流回电源的负极,则有几条独立支路。未包含在独立支路内的剩余电阻按其两端的位置补上。应用这种方法时,选取独立支路要将导线包含进去。

    例7.画出图18的等效电路。

    方案一:选取A—R2—R3—C—B为一条独立支路,A—R1—R5—B为另一条独立支路,剩余电阻R4接在D、C之间,如图19所示。

  方案二:选取A—R1—D—R4—C—B为一条独立支路,再分别安排R2、R3和R5,的位置,构成等效电路图20。

    方案三:选取A—R2—R3—C—R4—D—R5—B为一条独立支路,再把R1接到AD之间,导线接在C、B之间,如图21所示,结果仍无法直观判断电阻的串并联关系,所以选取独立支路时一定要将无阻导线包含进去。

九、节点跨接法

    将已知电路中各节点编号,按电势由高到低的顺序依次用1、2、3……数码标出来(接于电源正极的节点电势最高,接于电源负极的节点电势最低,等电势的节点用同一数码,并合并为一点)。然后按电势的高低将各节点重新排布,再将各元件跨接到相对应的两节点之间,即可画出等效电路。

    例8.画出图22所示的等效电路。

 解:节点编号:如图22中所示。

    节点排列:将1、23节点依次间隔地排列在一条直线上,如图23。

    元件归位:对照图22,将R1、R2、R3、R4分别跨接在排列好的1、2得等效电路如图24。

十、电表摘补法

    若复杂的电路接有电表,在不计电流表A和电压表V的内阻影响时,由于电流表内阻为零,可摘去用一根无阻导线代替;由于电压表内阻极大,可摘去视为开路。用上述方法画出等效电 搞清连接关系后,再把电表补到电路对应的位置上。

   例9.如图25的电路中,电表内阻的影响忽略不计,试画出它的等效电路。

    解:先将电流去,用一根导线代摘替,再摘去电压表视为开路,得图26。然后根据图25把电流表和电压表补接到电路中的对应位置上,如图27所示。

 .

七、dB,dB, dBm, dBi

dB应该是无线通信中最基本、最习以为常的一个概念了。我们常说“传播损耗是xx dB”、“发射功率是xx dBm”、“天线增益是xx dBi”……有时,这些长得很像的dBx们可能被弄混,甚至造成计算失误。它们究竟有什么区别呢?  

这事不得不先从dB说起。

而说到dB,最常见的就是3dB啦!

3dB在功率图或误码率图中经常出现。其实,没什么神秘的,下降3dB就是指功率下降一半,3 dB点指的就是半功率点。

+3dB表示增大为两倍,-3dB表示下降为1/2。这是怎么来的呢

dB在缺省情况下总是定义功率单位,以10lg 为计。当然某些情况下可以用信号强度(Amplitude)来描述功和功率,这时候就用20lg 为计。不管是控制领域还是信号处理领域都是这样。比如有时候大家可以看到dBmV 的表达。

注意基本概念

在dB,dBm计算中,要注意基本概念。比如前面说的0dBw = 10lg1W = 10lg1000mw = 30dBm;又比如,用一个dBm 减另外一个dBm时,得到的结果是dB。如:30dBm - 0dBm = 30dB。

dB和dB之间只有加减

一般来讲,在工程中,dB和dB之间只有加减,没有乘除。而用得最多的是减法:dBm减dBm 实际上是两个功率相除,信号功率和噪声功率相除就是信噪比(SNR)。dBm 加dBm 实际上是两个功率相乘,这个已经不多见(我只知道在功率谱卷积计算中有这样的应用)。dBm 乘dBm 是什么,1mW的1mW 次方?除了同学们老给我写这样几乎可以和歌德巴赫猜想并驾齐驱的表达式外,我活了这么多年也没见过哪个工程领域玩这个。

dB是功率增益的单位

dB,表示一个相对值。当计算A的功率相比于B大或小多少个dB时,可按公式10 lg A/B计算。例如:A功率比B功率大一倍,那么10 lg A/B = 10 lg 2 = 3dB。也就是说,A的功率比B的功率大3dB;如果A的功率为46dBm,B的功率为40dBm,则可以说,A比B大6dB;如果A天线为12dBd,B天线为14dBd,可以说A比B小2dB。

dBm是一个表示功率绝对值的单位,计算公式为:10lg功率值/1mW。例如:如果发射功率为1mW,按dBm单位进行折算后的值应为:10 lg 1mW/1mW = 0dBm;对于40W的功率,则10 lg(40W/1mW)=46dBm。

1、dBm

dBm是一个考征功率绝对值的值,计算公式为:10lg(功率值/1mw)。

[例1] 如果发射功率P为1mw,折算为dBm后为0dBm。

[例2] 对于40W的功率,按dBm单位进行折算后的值应为:

10lg(40W/1mw)=10lg(40000)=10lg(4*10^4)=40+10*lg4=46dBm。

2、dBi 和dBd

dBi和dBd是考征增益的值(功率增益),两者都是一个相对值,但参考基准不一样。dBi的参考基准为全方向性天线,dBd的参考基准为偶极子,所以两者略有不同。一般认为,表示同一个增益,用dBi表示出来比用dBd表示出来要大2. 15。

[例3] 对于一面增益为16dBd的天线,其增益折算成单位为dBi时,则为18.15dBi (一般忽略小数位,为18dBi)。

[例4] 0dBd=2.15dBi。

[例5] GSM900天线增益可以为13dBd(15dBi),GSM1800天线增益可以为15dBd(17dBi)。

3、dB

dB是一个表征相对值的值,当考虑甲的功率相比于乙功率大或小多少个dB时,按下面计算公式:10lg(甲功率/乙功率)

[例6] 甲功率比乙功率大一倍,那么10lg(甲功率/乙功率)=10lg2=3dB。

也就是说,甲的功率比乙的功率大3 dB。

[例7] 7/8 英寸GSM900馈线的100米传输损耗约为3.9dB。

[例8] 如果甲的功率为46dBm,乙的功率为40dBm,则可以说,甲比乙大6 dB。

[例9] 如果甲天线为12dBd,乙天线为14dBd,可以说甲比乙小2 dB。

4、dBc

有时也会看到dBc,它也是一个表示功率相对值的单位,与dB的计算方法完全一样。一般来说,dBc 是相对于载波(Carrier)功率而言,在许多情况下,用来度量与载波功率的相对值,如用来度量干扰(同频干扰、互调干扰、交调干扰、带外干扰等)以及耦合、杂散等的相对量值。在采用dBc的地方,原则上也可以使用dB替代。

搞无线和通信经常要碰到的dBm, dBi, dBd, dB, dBc

经验算法:

有个简便公式:0dBm=0.001W 左边加10=右边乘10

所以0+10dBm=0.001*10W 即10dBm=0.01W

故得20dBm=0.1W 30dBm=1W 40dBm=10W

还有左边加3=右边乘2,如40+3dBm=10*2W,即43dBm=20W,这些是经验公式,蛮好用的。

所以-50dBm=0dBm-10-10-10-10-10=1mW/10/10/10/10/10=0.00001mW。

-----------------------------------------------------------------------------------------------------

dBm的计算方法:(dBm与mW)

一般坊间贩售的802.11x无线网路AP上头,常会有规格说明,里头总会有一项说明到这个AP(或是无线网路卡),它的传输功率(transmission POWER)有20dBm,或者有些产品,是以mW(milliWatts)为单位,例如很有名的神脑长距离网卡,就说他们的网卡具有高达100mW的发射功率。

这些单位是怎么回事呢?

dBm是dB-milliWatt,即是这个读数是在与一个milliWatt作比较而得出的数字。在仪器中如果显示着0dBm的意思即表示这个讯号与1mW的讯号没有分别,也就是说这个讯号的强度就是1mW了。至于Watt(瓦特)是功率的单位我想大家都知道,就不赘述了。

所以我们必须先从dB讲起,dB到底是什么呢?dB的全写是decibel,英文(其实是拉丁语文)中deci即十分一的的意思。这个单位原本是bel 。但因为要达到一个bel的数值比较所需之能量差通常都较为大而在电路学上并不常用,故此才比较常用十分之一bel,亦即decibel这个单位了。

那么decibel(或者bel)又指什么呢?

其实它是指当你遇上有两个能量(讯号)的时候,dB就是我们用来表示这两个能量之间的差别的一种表示单位。它本身并不是一个独立的(如伏特Volt、安培Ampere等)绝对单位,dB这个单位一出现即意味着是有两个同样性质的能量(或讯号)正在被比较之中而获得的单位。

至此或许大家会有疑问:「既然dB只是表示两个讯号间的能量差别的话,为何不干脆用”倍数”来做表示呢?是否为了要故作深奥而造出这个单位来呢?」

当然不是啦!不过这个问题倒也问得相当好。不是吗?干脆用”倍数”不是来得简单易懂而不致于有这么多的人搞错了观念吗?某程度上林教官也相当同意这个说法。譬如当你制作一部高频线性放大器(LINEAR Amp.)时,它的输入所需功率是10Watts而输出则可达40Watts的话,为何不干脆说有四倍的增益而要说成是6dB的增益呢?在这个例子之中,其实的确是用”四倍”这个说法来得干脆俐落,但试看一看另一个同类例子……

今天我们试想像一套发射设备由初级振荡的能量以至最后级的输出功率之间的增益…,假设在初级振荡时的功率是0.5mW(注意是假设,真的当然会远低于此数)而在最后的LINEAR Amp.输出是2kW。现在试算一算它们之间的倍数差别……,2kW就是2000Watts亦即2,000,000mW用2,000,000mW除以0.5mW便得出倍数,即4,000,000倍了。试想一想,我已假设了振荡级是0.5mW那么大都还得出了四百万倍这个如此惊人的数字,一旦用上真实的数字的话那倍数势必比四百万来得更大更多位数了。至此大家或许已经明白在各类电子及无线电电路中(尤其是接收方面)这类倍数之差别比比皆是(即如一部厂制的发射机的抗干扰能力是优于一百万倍就标示成better than 60dB)。如果每次都要在各个层面(例如说明书,规格表)内都标示出数百万以至千万甚至亿倍的数字将会是何等的不方便啊!

那么dB又是如何运算出来的呢?

bel = lg ( P2 / P1 )

上面公式里头,P1就是第一个被比较的能量(讯号),P2就是第二个作比较的能量(讯号),P1与P2的单位要大家相同。

dB = 10 * bel = 10 * lg ( P2 / P1 )

例:第一个讯号功率是4Watts,第二个讯号功率是24Watts,那增益就是:

10 * lg ( 24 / 4 ) = 10 * lg6 = 7.78 dB

OK,我们回到dBm来看,因此换算dBm与mW的公式就应该是长成这样:

dBm = 10 * lg(mW)或mW = 10^( dBm / 10 )

所以底下这些例子大家可以验算一下:

0 dBm = 1 mW

10 dBm = 10 mW

14 dBm = 25 mW

15 dBm = 32 mW

16 dBm = 40 mW

17 dBm = 50 mW

20 dBm = 100 mW

30 dBm = 1000 mW = 1W

如果大家都很聪明,一定可以从log的基本性质中,发现到底下的rule:

dB增加3dB = mW乘2倍;dB减少3dB = mW变成1/2 ;增加10dB =乘10倍

这样一来,你便可以用你的脑袋直接进行快速运算来求得概略值:

+3dBm= *2
+6dBm= *4 (2*2)
+7dBm= *5 (+10dB-3dB = 10/2)
+4dBm= *2.5 (+10dB-6dB = 10/4)
+1dBm= *1.25 (+4dB-3dB=2.5/2)
+2dBm=*1.6(+6dBm-4dBm=4/2.5=1.6)

举个例子,假设你已经知道0dBm = 1mW,那么3dBm当然就等于2mW啰。那么,47dBm呢?40dBm →10^4mW,再多7dBm →5 * 10^4mW = 50W。

dBc

有时也会看到dBc,它也是一个表示功率相对值的单位,与dB的计算方法完全一样。一般来说,dBc 是相对于载波(Carrier)功率而言,在许多情况下,用来度量与载波功率的相对值,如用来度量干扰(同频干扰、互调干扰、交调干扰、带外干扰等)以及耦合、杂散等的相对量值。在采用dBc的地方,原则上也可以使用dB替代。

dBuV

根据功率与电平之间的基本公式V^2=P*R,可知dBuV=90+dBm+10*log(R),R为电阻值。在PHS系统中正确应该是dBm=dBuv-107,因为其天馈阻抗为50欧。

dBuVemf 和dBuV

emf:electromotive force(电动势)

对于一个信号源来讲,dBuVemf是指开路时的端口电压,dBuV是接匹配负载时的端口电压。

问:请问dBi、dBd、dB、dBm、dBc之间的区别。

答:它们都是功率增益的单位,不同之处如下:

dBi和dBd是功率增益的单位,两者都是相对值,但参考基准不一样。dBi的参考基准为全方向性天线;dBd的参考基准为偶极子。一般认为dBi和dBd表示同一个增益,用dBi表示的值比用dBd表示的要大2.15 dBi。例如:对于一增益为16 dBd的天线,其增益折算成单位为dBi时,则为18.15dBi,一般忽略小数位,为18dBi。

dB也是功率增益的单位,表示一个相对值。当计算A的功率相比于B大或小多少个dB时,可按公式10 lg A/B计算。例如:A功率比B功率大一倍,那么10 lg A/B = 10 lg 2 = 3dB。也就是说,A的功率比B的功率大3dB;如果A的功率为46dBm,B的功率为40dBm,则可以说,A比B大6dB;如果A天线为12dBd,B天线为14dBd,可以说A比B小2dB。

dBm是一个表示功率绝对值的单位,计算公式为:10lg功率值/1mW。例如:如果发射功率为1mW,按dBm单位进行折算后的值应为:10 lg 1mW/1mW = 0dBm;对于40W的功率,则10 lg(40W/1mW)=46dBm。

dBc也是一个表示功率相对值的单位,与dB的计算方法完全一样。一般来说,dBc相对于载波(Carrier)功率而言。在许多情况下,用来度量载波功率的相对值,如度量干扰(同频干扰、互调干扰、交调干扰、带外干扰等)以及耦合、杂散等的相对量值。在采用dBc的地方,原则上也可以使用dB替代。

实用资料——关于天线增益及其考量

在无线通讯的实际应用中,为有效提高通讯效果,减少天线输入功率,天线会做成各种带有辐射方向性的结构以集中辐射功率,由此就引申出“天线增益”的概念。简单说,天线增益就是指一个天线把输入的射频功率集中辐射的程度,显然,天线的增益与其方向图的关系很大,主瓣越窄、副瓣越小的天线其增益就越高,而不同结构的天线,其方向图的差别是很大的。

在通讯技术领域,与其它考量功率、电平等参数的量值同样,天线增益也采用相对比较并取对数的简化法来表示,具体计算方法为:在某一方向向某一位置产生相同辐射场强的时,对无损耗理想基准天线的输入功率与待考量天线的输入功率的比值取对数后乘以10 (G=10lg(基准Pin/考量Pin)),即称为该天线在该点方向的增益。常用衡量天线增益的单位是dBi和dBd。对于dBi,其基准为理想的点源天线,即一个真正意义上的“点”来作天线增益的对比基准。理想点源天线的辐射是全向的,其方向图是个理想的球,同一球面上所有点的电磁波辐射强度均相同;对于dBd,其基准则为理想的偶极子天线。因偶极子天线是带有方向性的,故二者有个固定的恒差2.15即0dBd="2".15dBi。

需要说明的是,通常所说的“全向天线”不是严格的说法,全向天线应指在三维立体空间的全向,但工程界也往往把某个平面内方向图为圆周的天线称为全向天线,如鞭状天线,它在径向的主瓣是圆,但仍有轴向的副瓣。

常见天线的增益:鞭状天线6-9dBi,GSM基站用八木天线15-17dBi,抛物面定向天线则很容易做到24dBi。

无线电发射机输出的射频信号,通过馈线(电缆)输送到天线,由天线以电磁波形式辐射出去。电磁波到达接收地点后,由天线接收下来(仅仅接收很小很小一部分功率),并通过馈线送到无线电接收机。因此在无线网络的工程中,计算发射装置的发射功率与天线的辐射能力非常重要。

Tx是发射(Transmits )的简称。无线电波的发射功率是指在给定频段范围内的能量,通常有两种衡量或测量标准:

1、功率(W ): 相对1 瓦(Watts )的线性水准。例如,WiFi 无线网卡的发射功率通常为0.036W ,或者说36mW 。

2、增益(dBm ):相对1 毫瓦(milliwatt )的比例水准。例如WiFi 无线网卡的发射 增益 为15.56dBm 。

两种表达方式可以互相转换:

1、dBm = 10 x log[ 功率mW]

2、mW = 10[ 增益dBm / 10 dBm]

在无线系统中,天线被用来把电流波转换成电磁波,在转换过程中还可以对发射和接收的信号进行“放大”,这种能量放大的度量成为 “增益(Gain)”。天线增益的度量单位为“dBi ”。由于无线系统中的电磁波能量是由发射设备的发射能量和天线的放大叠加作用产生,因此度量发射能量最好同一度量-增益(dB ),例如,发射设备的功率为100mW ,或20dBm;天线的增益为10dBi ,则:

发射总能量=发射功率(dBm )+天线增益(dBi )
                =20dBm +10dBi
                =30dBm
      或者:  =1000mW
                =1W

在“小功率”系统中(例如无线局域网络设备)每个dB 都非常重要,特别要记住“3 dB 法则”。每增加或降低3 dB ,意味着增加一倍或降低一半的功率:

-3 dB = 1/2 功率

-6 dB = 1/4 功率

+3 dB = 2x 功率

+6 dB = 4x 功率

例如,100mW 的无线发射功率为20dBm ,而50mW 的无线发射功率为17dBm ,而200mW 的发射功率为23dBm 。

功率/电平(dBm):放大器的输出能力,一般单位为W、mW、dBm。dBm是取1mW作基准值,以分贝表示的绝对功率电平。

换算公式:

电平(dBm)=10lgW

5W  →10lg5000  = 37dBm

10W →10lg10000 = 40dBm

20W →10lg20000 = 43dBm

从上不难看出,功率每增加一倍,电平值增加3dBm

.

八、Wi-Fi HaLow

Wi-Fi HaLow很快就会出现在我们日常生活中的智慧门锁、安保摄影机、可穿戴设备和无线传感器网络上。什么是Wi-Fi HaLow?与传统的Wi-Fi(4/5/6)有何不同?究竟是什么让Wi-Fi HaLow成为物联网的理想协议?

Wi-Fi就像是在互联世界的氧气,为当今最普遍的无线网络协议,承载了超过一半的因特网流量。「Wi-Fi」是一个通用术语,指的是经过二十多年发展而成的802.11协议家族。Wi-Fi联盟是推动Wi-Fi应用和发展的组织,该组织用数字命名法,简化了常用的几代Wi-Fi名称,例如Wi-Fi 4 = 802.11n、Wi-Fi 5 = 802.11ac、Wi-Fi 6 = 802.11ax。您正在家中或工作场所使用的,很有可能就是这些类型的Wi-Fi。

尽管Wi-Fi 4/5/6无处不在,但物联网(IoT)的快速发展迫使人们重新思考传统的Wi-Fi协议,并揭示了技术上的差异,以及重新定义802.11协议于当今无线连接世界的超低功耗物联网设备上应扮演的角色。由于物联网和机器对机器(Machine-to-Machine, M2M)的应用对远程连接和低功耗性能的要求更高,更需要另一种优化的Wi-Fi技术来满足物联网的需求。

Wi-Fi HaLow协议经由提供超低功耗无线解决方案来满足这些需求。相较于传统Wi-Fi,此解决方案能在更远距离以更低功率来连接大量的物联网设备。该协议于2016年获得IEEE 802.11ah专业工作组的批准,并由Wi-Fi联盟冠名为Wi-Fi HaLow。

Wi-Fi HaLow协议标准具有出色的能源效率、远程连接、低延迟、高清视讯质量的数据速率、安全功能和支持本地IP的独特组合,使其成为无线连接、电池供电物联网设备的理想选择。本文将详细分析Wi-Fi HaLow和传统Wi-Fi的主要区别,以及为何802.11ah协议非常适合且能满足物联网应用的连接要求。

表一 Wi-Fi和Wi-Fi HaLow的差异

Wi-Fi和Wi-Fi HaLow的差异

功能

Wi-Fi 4/5/6

(IEEE 802.11n/ac/ax)

Wi-Fi HaLow

(IEEE 802.11ah)

工作频段

2.4 GHz,5 GHz,6 GHz

Sub-1-GHz

(美国902-982 MHz)

频道宽度选择

20,40,80,160 MHz

1,2,4,8(16可选)MHz

每个接入点的最大可寻址站数

2007

8191

单流MCS数据速率范围

6.5 Mbps-150 Mbps

(802.11n, Wi-Fi 4)

150 Kbps-86.7 Mbps

标准范围

100公尺

一公里以上10X 更长距离100X

更大区域1000X更大空间

(相较于20 MHz 802.11n)

链路预算改善(1-MHz频道)

-

15-24 dBm

适用于电池供电的协议

Wi-Fi HaLow为功率敏感的物联网设备提供卓越的能源效率。IEEE 802.11ah规范各种复杂的睡眠模式,使HaLow设备能够长时间保持在非常低的功耗状态,节省电池能量。

目标唤醒时间(Target Wake Time;TWT):

允许站点(STA)和存取点(access point;AP)预先安排时间唤醒睡眠中的STA,以接听信标。

限制存取窗口(Restricted Access Window;RAW):

限制存取窗口(Restricted Access Window;RAW):

延长最大基本服务集(basic service set;BSS)的闲置期:

允许STA闲置期延长至五年。

分层的流量指示图(Traffic Indication Mapping;TIM)

群组对TIM进行更有效的编码,可以节省信标传播时间。

媒体访问控制(Medium Access Control;MAC)标头较短:

可以减少标头消耗、传播时间和功耗,并释出频谱。

无数据物理层(PHY)协议数据单元(Null data PHY protocol data;NPD):

将类似MAC的ACK/NAK嵌入到PHY层以减少时间和功率。

短信标:

完整信标发送频率较低时,短(有限制性)信标可频繁发送以同步STA。

BSS着色:

当STA可忽略其他颜色时,颜色配置会指定BSS群组给特定的AP。

双向TXOP(BDT)(昔称为速度帧):

当STA醒来,发现要传输的上行链路和下行链路帧存在时,可减少媒体存取的次数。BDT利用物理层协议数据单元 (physical-layer protocol data unit;PPDU) 讯号(SIG)字段中的响应指示,增加TXOP保护期间,免于受第三方STA传输的干扰。

该协议的高效睡眠和电源管理模式,可支持物联网设备以电池供电多年,并具有广泛且灵活的电源和电池尺寸选项,应用可从钮扣电池上运行的短距离物联网设备到更高功率、更大电池、超过1公里以上的范围。与2.4和5 GHz频段的Wi-Fi协议相比,该协议的1GHz以下窄频讯号可传送得更远且能耗更低,每单位能量可传输更多位数。

低能耗

Wi-Fi HaLow芯片所需功率远远低于传统Wi-Fi芯片。虽然传统Wi-Fi高数据速率能够使用2.4 GHz、5 GHz和6 GHz 频段的宽带,快速传输高清视讯内容并大量下载档,但这些Wi-Fi连接的有效距离很短,并且会很快耗尽电池,需要经常充电、更换电池或要求理想的主电源连接。有鉴于此,由于这些设备需要到达更远的距离并仰赖电池供电运行多年,同时仍须提供每秒数兆位的数据传输量,对受制于电能的物联网设备而言,Wi-Fi HaLow是更好的选择。

更长覆盖范围

与传统Wi-Fi最窄的20 MHz频道相比,Wi-Fi HaLow的1GHz以下讯号使用1 MHz(含)以上更窄的频道。由于频道中的热噪声较低,这相差20倍的带宽因子可转化为13dB链路预算的改善。与传统的2.4 GHz Wi-Fi相比,频率在750 MHz–950 MHz之间的射频仅额外增加8-9 dB的链路预算,节省自由空间的传播损耗。此外,Wi-Fi HaLow协定添加了范围优化的调制和编码设计(MCS10),可额外提供3dB链路预算的改善。

 图一 : 传统的Wi-Fi 4/5/6协议使用更高的频率和更宽的带宽来达到最大吞吐量。Wi-Fi HaLow的1 GHz以下协议优化了穿透率、覆盖范围、功率和容量。

能为终端使用者提供覆盖数百米的无线物联网解决方案,且无需额外的中继设备或昂贵的蜂巢电讯数据规划,此为802.11ah协议的关键竞争优势。凭借其远程覆盖能力,Wi-Fi HaLow的优势扩展了智能家庭和智能城市网络的范围,让用户能够控制1公里以外的物联网设备,远远超出传统Wi-Fi协议的覆盖范围。

 图二 : 802.11n/ac(左)和802.11ah(右)的吞吐量与范围。

更好的讯号穿透力

与传统Wi-Fi相比,1GHz以下Wi-Fi HaLow讯号可以更轻松穿过墙壁和其他障碍物。与2.4GHz和5GHz频段中的Wi-Fi协议相比,住宅和商业大楼的建筑材料和平面布局的差异对1GHz以下HaLow讯号的影响较小。传统Wi-Fi产品有时会出现用户遇到问题而致电客服求助,甚至要求退货的困扰,而Wi-Fi HaLow能穿透墙壁和建筑物的卓越覆盖范围,有助于减少此类问题。

无论产品使用时位于室内还是室外,或者位于家中的地下室还是阁楼,设备制造商都可以确保与存取点(AP)建立可靠的HaLow连接。

可大幅扩展的解决方案

一个Wi-Fi HaLow AP的设备寻址能力最多可达到8,191台,是传统Wi-Fi AP设备数量的4倍之多。在可预见的未来,这足以连接每个LED灯泡、电灯开关、智慧门锁、电动窗帘、恒温器、烟雾探测器、太阳能电池板、安保摄影机或任何可想象的智慧家庭设备。典型的家用Wi-Fi路由器一般可支持数十台设备。

当宽带服务厂商在家中部署一组Wi-Fi HaLow AP时,即可成为一个可扩展的平台,额外提供安全装置及管理水电设备和服务。

具备抗噪能力的免许可频谱

与2.4GHz、5GHz和6GHz频段的传统Wi-Fi一样,Wi-Fi HaLow 终端使用者能够拥有自己的设备并使用从750MHz到950MHz的免许可1GHz以下无线电频谱。

在ISM频段内运行的Wi-Fi HaLow可以使用多种带宽的通道:1MHz、2MHz、4MHz、8MHz和16MHz。带宽越窄,讯号可以传播的越远。数据以数据包形式使用OFDM传输跨越多个亚通道时,可在深具挑战性的RF环境中提高性能,尤其是受到其他无线电设备的强烈干扰时。前向纠错(Forward error correction;FEC)编码还为数据包的复原提供额外的保护,确保连接的稳健性。

安全且具备互操作性

Wi-Fi HaLow与其他IEEE 802.11 Wi-Fi版本一样,是一种原生的无线安全协议,支持最新的Wi-Fi身份验证要求(WPA3)和空中无线(over-the-air;OTA)传输的AES加密,其数据速率可实现安全的OTA韧体升级。
与其他类型的Wi-Fi一样,HaLow是全球公认的标准(IEEE 802.11ah),定义连接设备如何执行身份验证和通讯安全。使用Wi-Fi HaLow的设备厂商可以确保他们的产品和网络能够遵照Wi-Fi联盟的发展指南进行互操作。由于它是 IEEE 802.11标准的一部分,Wi-Fi HaLow网络还可以与Wi-Fi 4、Wi-Fi 5和Wi-Fi 6网络共存,不会影响他们的射频性能。

利用IP实现本地化

所有物联网网络都需要因特网协议(Internet protocol;IP)支持来执行云端连接。因为Wi-Fi HaLow是802.11 Wi-Fi标准,所以可提供本地TCP/IP支持。这种内置的IP功能意味着物联网连接不再需要专有网关或网桥。所有连接支持Wi-Fi HaLow路由器的客户端设备,都可以使用IPv4/IPv6传输协议直接存取因特网,以实现基于云端的物联网数据服务和管理。

延伸覆盖范围,扩大物联网的可能性

传统Wi-Fi的网络拥堵、范围限制和较高的功耗,以及可连接到单个AP的设备数量有限,在当今物联网设备的世界中已不再可行。这些限制阻碍了各行业内以物联网为中心的新商业模式,这些模式需要更远的距离、更大的容量、更灵活的电池和电源选项,同时最大限度地降低部署成本。

作为一种远程协议,Wi-Fi HaLow支持那些2.4GHz和5GHz Wi-Fi无法达到的室内外物联网应用,例如远程安保摄影机、门禁网络甚至无人机。其他潜在使用案例包括大型公共场所,如体育场馆、购物中心和会议中心,在这些场所,单个Wi-Fi HaLow存取点可以替代大量的存取点,无需复杂的网状网络,简化了安装,降低了总体拥有成本。

工业物联网、过程控制传感器、楼宇自动化、仓库和零售店等众多应用,也将受益于这种远程、低功耗协议,让无数设备能够在日益自动化的世界中保持连接。事实上,Wi-Fi-HaLow 在传统的802.11协议中因其覆盖范围、能效、容量和多功能性而胜出。

 .

九、CAN FD协议及其与CAN2.0的异同

1. CANFD的来历

我们知道了, CAN2.0数据段只有8byte,最高速率为 1Mbit/s,通常使用的是 500k,随着功能的逐渐增多,各 ECU 之间的信息交互也越多,导致总线负载持续走高;CAN 报文中只有约 40~50%的带宽用于实际数据传输;响应机制受车内布线的物理特性限制,例如 CAN 控制器中的 ACK 生成延迟;收发器传播延迟;导线延迟等,然而随着汽车功能越来越多,CAN总线的局限性也逐渐暴露:

为了解决上诉CAN总线的局限性,对其进行升级时必不可少的,从而有了CAN FD,其全称为CAN with Flexible Data rate。2011年,开始CAN FD协议的开发,2015年ISO11898-1进行了修订,将CAN FD加入其中。

CAN与CAN-FD性能对比:

 2.  CANFD与CAN的协议异同

在完全理解了CAN协议后,我们只需要对比CANFD与其的不同就可以比较简单的熟悉CANFD协议,那相对于CAN,CAN FD有什么不同呢?

1)传输速率不同。

CAN FD的速率可变,从控制场中的BRS位到ACK场之前(含CRC分界符)为可变速率,最高速率可达到8Mbps(下图的蓝色部分)。其他部分与CAN相同。

(2)数据长度不同。

CAN FD支持的最大数据长度为64byte。

(3)帧格式不同。

CanFD新增了FDF、BRS、ESI位:

FDF:表示 CAN 报文还是 CAN-FD 报文;BRS:表示位速率转换,该位隐性时,速率可变(即 BSR 到 CRC 使用转换速率传输),该位为显性时,以正常的 CAN-FD 总线速率传输(恒定速率);ESI:表示发送节点状态。

(4)ID长度不同。

CAN FD标准帧ID长度可扩展至12bit,CAN的标准帧ID为11bit。

3. CANFD帧结构解析

CAN FD节点可以正常收发CAN报文,但CAN节点不能正确收发CAN FD报文,因为其帧格式不一致。

CAN FD的帧结构是什么呢?

与CAN一样,CAN FD一共具有,帧起始SOF,仲裁段,控制段,数据域,CRC域,ACK域,帧结束,共七个部分组成。

 3.1 帧起始

CAN与CANFD使用相同的SOF标志位来标志报文的起始。帧起始由1个显性位构成,标志着报文的开始,并在总线上起着同步作用。

3.2.仲裁域

与CAN不同,CAN FD取消了对远程帧的支持,用RRS位替换了RTR位,为常显性。IDE用于区分标准帧和扩展帧。

3.3 控制域

CANFD与CAN有着相同的IDE,res,DLC位。同时增加了FDF、BRS、ESI三个bit位。FDF为隐性时,表示为CAN FD报文;

BRS为为速率转换开发,当其隐性时,速率可变,当其显性时,以正常的CAN-FD总线速率传输(恒定速率);

ESI用于表示错误状态,主动错误发送显性位,被动错误发送隐性位。

3.4 数据域

CAN FD兼容CAN的数据格式,同时最大还能支持12, 16, 20, 24, 32, 48, 64byte。

 3.5 CRC

CAN FD对CRC算法进行了改进,CRC对填充位也加入了计算。在校验和部分为避免有连续位超过6个,就确定在第一位以及以后每4位添加一个填充位加以分割,这个填充位的值是上一位的反码,作为格式检查,如果填充位不是上一位的反码,就作出错处理。CAN FD的CRC场扩展到了21位。

3.6 ACK

ACK紧跟着CRC结束标识位。不同的是,CAN FD支持2bits的ACK的识别。

3.7 帧结尾

与CAN一样,CAN FD的帧结尾也为连续7位的隐性位。

.

十、弱电控制强电:继电器的使用方法
  1. 继电器的基本含义;
  2. 继电器的基本参数;
  3. 继电器如何驱动;
  4. 继电器如何实现节能;
  5. 固态继电器的基本知识;

讨论继电器的基本知识、使用方法和典型应用电路。

1.继电器的基本含义

继电器是常用的开关型电控器件,根据工作原理、结构和功能的不同,可以分为电磁继电器、固态继电器、时间继电器、温度继电器、光继电器等。本文中主要介绍电磁继电器。

电磁继电器主要由线圈、衔铁和触点构成,其中线圈是继电器的输入部分,触点是继电器的输出部分,当线圈有合适的电流流过时,根据电磁效应,会产生磁场吸附衔铁,从而使触点动作。电磁继电器经常用于控制回路中,实现小电流控制大电流的目的。电磁继电器的内部结构如图1所示。.

继电器的结构组成

2.继电器的基本参数

在继电器选型时,需要了解其基本的参数,这些参数包括:线圈电压、触点容量、触点接触电阻,释放电压等。

线圈电压就是继电器正常工作时加在线圈两端的电压,在购买继电器时,被经常问道:你要几伏的继电器,这里就是指继电器的线圈电压。

触点容量是指继电器带负载的能力,如2A/30VDC,20A/220VAC;

释放电压,是指随着线圈两端的电压下降,触点复位时所对应的电压。

电器实物图

继电器的触点,一般有常开、常闭、常开/常闭组合类型。

3.继电器如何驱动

学过单片机的朋友都知道,在单片机开发板上继电器基本是标配,通过控制继电器来学习单片机的IO口如何配置为输出。对于小功率的继电器,可以通过三极管来驱动,使用NPN三极管和PNP三极管驱动继电器的电路图如下。

NPN三极管驱动继电器

用NPN三极管驱动继电器的时候需要将继电器接在三极管的集电极上,并在线圈上并联一个反向二极管,典型原理图如图3所示。

NPN三极管驱动继电器

上图中,基极上的电阻为限流电阻,防止基极电流过大将三极管烧坏;基极和发射极之间的电阻叫做下拉电阻,单片机的IO口在初始化的时候,电平可能是不确定的状态,下拉电阻将基极下拉到低电平使三极管截止,从而防止了继电器的误动作。

当基极的信号是高电平时,三极管导通,继电器线圈得电,继电器触点动作;

当基极的信号是低电平时,三极管截止,继电器线圈失电,继电器触点复位;

PNP三极管驱动继电器

用PNP三极管驱动继电器的时候需要将继电器接在三极管的集电极上,并在线圈上并联一个反向二极管,典型原理图如图4所示。

 PNP三极管驱动继电器

上图中,基极上的电阻为限流电阻,防止基极电流过大将三极管烧坏;基极和发射极之间的电阻叫做上拉电阻,单片机的IO口在初始化的时候,电平可能是不确定的状态,上拉电阻将基极拉到高电平使三极管截止,从而防止了继电器的误动作。

当基极的信号是低电平时,三极管导通,继电器线圈得电,继电器触点动作;

当基极的信号是高电平时,三极管截止,继电器线圈失电,继电器触点复位;

续流二极管的作用

上面两种驱动方式,都在线圈上方向并联了一个二极管,该二极管叫做续流二极管。由于继电器的线圈呈现感性特性,在断电时流过线圈的电流不会发生突变,会感应出反向电动势,该反向电压可能会超过三极管的耐压值将三极管损坏,为避免这种情况。加了一个反向的续流二极管,在断电瞬间给反向电动势提供了一条泄放通道,从而保护了三极管。

4.继电器如何节能

现在用户对功耗比较敏感,要求功耗尽可能的小,而性能不打折扣。对于继电器而言这一点非常明显,有些继电器的线圈电阻非常小,在启动、工作时所需要的电流非常大。继电器在动作的瞬间需要较大的电流,而在动作以后只需要较小的维持电流就可以让继电器保持动作状态。所以只需要在继电器动作后,降低线圈流过的电流即可实现继电器驱动的节能。

5-继电器节能

节能方式有两种,介绍如下:

降压的方式实现节能

继电器在启动时加在线圈两端的电压为额定电压,当继电器动作稳定大约100-500ms之后,将线圈两端的电压降至释放电压以上,这样加在线圈两端的电压小了,流过线圈的电流就小了。如图5左侧所示。

PWM方式实现节能

这最常用的节能方式,用PWM来驱动三极管或者MOS管的控制端,以降低线圈两端的平均电压,从而实现线圈的节能。

以上两种方式的大致波形如图6所示。

电器节能

5.固态继电器的基本知识

电磁继电器的触点是机械式的,在大电流分断的时候,容易产生电弧,触点长久工作在电弧的环境中会被腐蚀,从而失效,所以电磁继电器的触点都是具有工作寿命的。而固态继电器是完全电子式的继电器,其触点是由MOS管或者可控硅来实现的,电子式的触点不存在电弧问题,所以固态继电器的触点没有寿命的限制,且动作响应非常快不存在抖动问题,噪音较小。

固态继电器的主要构成

固态继电器分为交流固态继电器和直流固态继电器。交流固态继电器主要由光耦和可控硅构成;而直流固态继电器主要由光耦和MOSFET构成。

固态继电器的过零检测

固态继电器可以分为带过零检测和不带过零检测的。交流负载中,不带过零检测的情况下,只要输入端有触发信号,触点就动作;而带过零检测的,在输入端有触发信号后,触点等到负载端出现一次过零后才动作。

态继电器

固态继电器的触点是电子式的,过大电流时需要带大面积的散热片,相比电磁继电器而言,价格比较贵。

电磁继电器和固态继电器各有优缺点。

.

十一、智能灯光控制系统(基于stm32)

带你走进物联网的世界说一个整天方案哦 这次是基于stm32的 当然你可以用esp

“智能光照灯”使用STM32作为系统的MCU,由于单片机IO口驱动电流过小,搭配三极管放大电流,从而满足光照强度需求,且将单片机IO配置成PWM输出,以便于调节不同的光强度,也就是一档、二档、三档。在此基础上增加WiFi模块搭配手机APP可实现在手机端控制灯光、使用su-03t语音识别模块可实现语音控制灯光等,其他额外功能在下文介绍。所需材料如表1所示。

表1 材料清单

序号

名称

数量

1

STM32核心板

1

2

三极管

3

3

LED灯板

2

4

WiFi模块

1

5

Su-03t芯片

1

6

oled屏幕

1

7

超声波模块

1

8

dht11

1

9

按键

4

10

蜂鸣器

1

项目整体展示如图1:

需要的模块

01 STM32核心板

STM32是“意法半导体”生产的基于“ARM公司Cortex-M3内核”的32位MCU,其性能强大,资源丰富,被广泛应用于嵌入式系统的开发,也是高校学生接触嵌入式的敲门砖。最小系统板如图2所示,其由处理器、电源、复位、晶振电路等组成,可独立的完成相应的控制任务,在本次工程中核心知识就是PWM输出,I/O口引脚电平判断。

图2  STM32最小系统板 

02 三极管

三极管的放大作用就是:集电极电流受基极电流的控制(假设电源能够提供给集电极足够大的电流的话),并且基极电流很小的变化,会引起集电极电流很大的变化,且变化满足一定的比例关系:集电极电流的变化量是基极电流变化量的β倍,即电流变化被放大了β倍。至于三极管的控制,如图3所示及其简单,在图片中所标的A引脚初,输出高电平就能导通三极管,上方VCC的电源就能流过三极管。

03 WiFi模块

本项目所使用的WiFi模块是ESP-01S,是ESP8266系列的一种,其可以连接环境中的WiFi,从而使设备上网。本项目主要使用了该模块串口功能,通过串口与stm32单片机连接,WiFi模块通过周围环境中的WiFi信号连接云平台,如此将WiFi模块作为中介,可以实现单片机与云平台的信息交互。WiFi模块与单片机连接引脚如图4:

图4  WiFi模块连接图 

04 su-03t语音识别模块

su-03t是一款低成本、低功耗、小体积的离线语音识别的模组,无需编程,使用刷词条的方式进行开发,可谓是不爱编程的福音啊。本项目使用该模块的串口功能,通俗一点讲就是模块识别到相应的语音命令后,通过串口输出一个数据。关于该模块的配置,本文再次不过多阐述。该模块引脚如图5所示:

图5  SU-03T引脚展示图 

05 超声波模块

超声波模块为HC-SR04如图6所示,该超声波测距模块可提供约2cm~400厘米的非接触式距离感测功能,测距精度可达高到3毫米,该模块由发射装置与接受装置组成,发射装置发射超声波,接受装置接受超声波并将电平做出相应转变。

图6 超声波模块

06 OLED屏 

OLED显示屏是利用有机电自发光二极管制成的显示屏。由于同时具备自发光有机电激发光二极管,不需背光源、对比度高、厚度薄、视角广、反应速度快、比LCD屏幕显示效果更好一些,但由于现有技术限制,目前OLED屏幕无法做的很大。本项目主要使用OLED屏幕显示台灯的当前状态、温湿度信息、以及万年历时钟灯,相关显示如图7所示。

制作

01 先让灯亮起来

灯带是通过三极管驱动的,单片机的IO口连接三极管基极,可以将其看成控制信号,当该引脚输出高电平时,可以认为三极管导通,电流由发射极提供,由集电极输出,本设计中发射极连接VCC,也就是用电源给等待供电,这个电流远大于IO口直接输出的电流,足以满足等待的需求。

02 调节灯光亮度

刚刚已经介绍过如何使用三极管点亮灯带。那么又该如何控制灯的亮度哪?也就是如何控制电流呢?这就需要常说的PWM输出了,可以将三极管看成一个“水龙头”,PWM可以理解为我们拧水龙头的力气,通过调节不同的占空比,使得三极管“打开不同的口子”,控制逻辑如下:

PWM占空比大→“打开的口子大”→输出的电流大→灯带更亮

PWM占空比小→“打开的口子小”→输出的电流小→灯带更暗

在程序中首先将IO口配置为PWM输出,本设计选用的定时器4的通道3与通道4产生PWM(两个灯,一个冷光一个暖光,需要两路PWM输出)具体程序见程序1:

程序1:

void Motor_PWM_Init(u16 arr,u16 psc)
{ 
      GPIO_InitTypeDef GPIO_InitStructure;
      TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
      TIM_OCInitTypeDef  TIM_OCInitStructure;
     
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);      //使能定时器4时钟
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB  | RCC_APB2Periph_AFIO, ENABLE);  //使能GPIO外设和AFIO复用功能模块时钟
     
       
   /*****输出TIM4_CH3和TIM4_CH4和的PWM脉冲波形*****/
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //TIM_CH3和TIM_CH4
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
   /********************初始化TIM3*******************/
      TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
      TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
      TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
      TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
     
      /*******初始化TIM4 Channel3、TIM4 Channel4 PWM模式********/       
      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
       TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高
      TIM_OC3Init(TIM4, &TIM_OCInitStructure);  //初始化外设TIM4 OC3
      TIM_OC4Init(TIM4, &TIM_OCInitStructure);  //初始化外设TIM4 OC4
   /*******使能预装载寄存器********/
      TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); 
      TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); 
      TIM_Cmd(TIM4, ENABLE);  //使能TIM4
     
}

如此PWM的输出就已经配置好了,下面就在主循环中调用修改PWM占空比函数即可,具体程序见程序2,该程序修改了三个不同的占空比,以对应灯光的一档、二档、三档。

程序2:

/********两端都使能 1档**********/
TIM_SetCompare3(TIM4,800);                             
TIM_SetCompare4(TIM4,800);     
/********两端都使能 2档**********/
TIM_SetCompare3(TIM4,2000);     
TIM_SetCompare4(TIM4,2000);     
/********两端都使能 3档**********/
TIM_SetCompare3(TIM4,5000);     
TIM_SetCompare4(TIM4,5000);

03 远程控制功能

正如上文所说,远程控制功能实现的原理是,手机app开发时连接上云平台,手机APP相应按键触发时,将相应的控制指令上传至云平台,esp-01s通过周围的WiFi信号连接云平台,获取云平台上的数据,并通过串口将该数据传输给STM32单片机,单片机解析数据并完成相应的驱动。接下来就分布实现开发,分为手机端app的制作,手机连接云平台、设备连接云平台。

(1) 手机端app的制作

自行开发哦

(2) 手机端连接云平台

也很简单弄个阿里云 搭建个工程或直接弄个mqtt也都行

(3) 设备(单片机)连接云平台

esp-01s也是一个MCU,通过编程开发,本设计通过arduino平台开发相关的功能,值得注意的是esp-01s通过wifi信号连接云平台,所以环境中必须要有WiFi,由于此处程序过多,仅展示重要的地方。

①云平台定义及主题相关定义见程序3:

程序3:

#include
#include
//巴法云服务器地址
#define TCP_SERVER_ADDR "bemfa.com"
//服务器端口,tcp创客云端口8344
#define TCP_SERVER_PORT "8344"
//********************需要修改的部分*******************//
#define DEFAULT_STASSID  "HUAWEI P30 Pro+"     //WIFI名称,区分大小写,不要写错
#define DEFAULT_STAPSW   "18253858772"        //WIFI密码
String UID = "23f9a5f2d3584dc8516409db14b4827c";  //用户私钥,可在控制台获取,修改为自己的UID
String TOPIC1 ="TD00light";         //主题名字,可在控制台新建
String TOPIC2 = "TD00temp";       //用户私钥,可在控制台获取,修改为自己的UID
const int LED_Pin = 0;              //单片机LED引脚值,GPIO0引脚
int pinDHT11 = 2;
//**************************************************//

②接下来是连接服务器,向服务器发送指令cmd=1&uid="+UID+"&topic="+

TOPIC1+"\r\n,其中的UID与TOPIC1就是程序3中相关的定义具体程序见程序4。

程序4:

void startTCPClient(){
if(TCPclient.connect(TCP_SERVER_ADDR,atoi(TCP_SERVER_PORT))){         Serial.print("\nConnected to server:");
Serial.printf("%s:%d\r\n",TCP_SERVER_ADDR,atoi(TCP_SERVER_POR      T));
    String tcpTemp="";  //初始化字符串
    tcpTemp = "cmd=1&uid="+UID+"&topic="+TOPIC1+"\r\n"; //构建订阅指令
    sendtoTCPServer(tcpTemp); //发送订阅指令
    tcpTemp="";//清空
   
    preTCPConnected = true;
    preHeartTick = millis();
    TCPclient.setNoDelay(true);
  }
  else{
    Serial.print("Failed connected to server:");
    Serial.println(TCP_SERVER_ADDR);
    TCPclient.stop();
    preTCPConnected = false;
  }
  preTCPStartTick = millis();
}

③获取云平台传来的数据,并通过串口传输给STM32,具体程序见程序5:

程序5:

if (TCPclient.available()) //若有数据传来
{
   char c =TCPclient.read();
   TcpClient_Buff +=c;        //数据存储
   TcpClient_BuffIndex++;
   TcpClient_preTick = millis();
   if(TcpClient_BuffIndex>=MAX_PACKETSIZE - 1)
   {
      TcpClient_BuffIndex = MAX_PACKETSIZE-2;
      TcpClient_preTick = TcpClient_preTick - 200;
    }
    preHeartTick = millis();
 }
if((TcpClient_Buff.length() >= 1) && (millis() - TcpClient_preTick>=200))
{
   TCPclient.flush();
   Serial.println(TcpClient_Buff);    //串口传输
   if((TcpClient_Buff.indexOf("&msg=11") > 0))
{
      turnOnLed();
    }else if((TcpClient_Buff.indexOf("&msg=10") > 0))
{
      turnOffLed();
    }
   TcpClient_Buff="";
   TcpClient_BuffIndex = 0;
  }

如此就可以将云平台中的控制指令传输给STM32,STM32进行解析并完成相应的控制,由于本设计还添加了语音识别功能,所以相关控制的实现等讲解完语音识别后在进行讲解。

04 语音识别功能

语音识别功能主要采用了SU-03T离线语音识别模块,这个模块不需要编程,使用厂家提供的云平台开发,正如前文所说本设计主要用了该模块的串口功能,该模块的串口与STM32单片机的另一个串口连接,当识别到相应的语音时,串口输出相应的控制指令给STM32。该模块相关配置如图10所示。

图10 su-03t平台配置

05 STM32解析指令并完成相关驱动

正如前文所说,WiFi模块与su-03t都是使用串口与STM32单片机建立联系的,所以我们首先需要完成串口的相关配置,在此以WiFi模块对应的usart3为例,配置串口,具体程序见程序5:     

程序5: 

void usart3_init(u32 bound)
{ 
NVIC_InitTypeDef NVIC_InitStructure;
      GPIO_InitTypeDef GPIO_InitStructure;
      USART_InitTypeDef USART_InitStructure;
/***********使能时钟************/
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);            RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
       USART_DeInit(USART3);  //复位串口3
/*******配置输出引脚*******/
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;      //复用推挽输出
   GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10
  
   /*******配置输入引脚*******/
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
   GPIO_Init(GPIOB, &GPIO_InitStructure);  //初始化PB11
     
/********串口相关配置********/
      USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
      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_HardwareFl
owControl_None;//无硬件数据流控制
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
      USART_Init(USART3, &USART_InitStructure); //初始化串口3
      USART_Cmd(USART3, ENABLE);                    //使能串口
   USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断  
     
      /*******设置中断优先级********/
      NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;            //子优先级3
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;      //IRQ通道使能
      NVIC_Init(&NVIC_InitStructure);      //根据指定的参数初始化VIC寄存器
     
      TIM3_Int_Init(1000-1,7200-1);            //10ms中断
      USART3_RX_STA=0;                   //清零
      TIM_Cmd(TIM3,DISABLE);                  //关闭定时器7
}

至此WiFi模块对应的串口就配置完成,su-0t对应的串口配置与该串口相似,WiFi模块传输来的数据是需要解析的,而su-03t直接传输的十六进制,不需要解析,所以接下来就是解析WiFi模块通过串口传来的数据,具体程序见程序6。

程序6:

if(USART3_RX_STA&0X8000)            //接收到一次数据了
{
      rlen=USART3_RX_STA&0X7FFF;      //得到本次接收到的数据长度
      USART3_RX_BUF[rlen]=0;            //添加结束符
      //数据提取
      if(strncmp(USART3_RX_BUF,"cmd=2",5)==0)
      {
            for(i=0;i<strlen(usart3_rx_buf)+1;i++)< span=""></strlen(usart3_rx_buf)+1;i++)<>
            {
                  data_tiqu[s]=USART3_RX_BUF[i];
                  s++;
            }
            printf("%s",data_tiqu);
            for(i=0;i<strlen(data_tiqu);i++)< span=""></strlen(data_tiqu);i++)<>
            {
                  if(data_tiqu[i]==cmd[0])
                  {
                        k=i;
                        k++;
                        for(j=1;j<strlen(cmd);j++)< span=""></strlen(cmd);j++)<>
                        {
                              if(data_tiqu[k]==cmd[j])
                              {
                                    k++;
                                    flag=1;
                              }
                              else
                              {
                                    flag=0;
                              }
                        }
                  }                 
            }
            s=0;
            //数据提取结束
            printf("\r\n\r\n");
            if(flag==1)
            {
                  for(i=k+1;i<strlen(data_tiqu)+1;i++) 此时="" i为传输接受数据的索引<="" span="">
                  {
                        data[s]=data_tiqu[i];
                        s++;
                  }
                  printf("%s",data);
                  printf("zaici");     //作用:程序定位
                  printf("\r\n");
            }
      }
      if(strncmp(USART3_RX_BUF,"cmd=0&res=1",11)==0)
      {
            printf("%s",USART3_RX_BUF);
      }
      USART3_RX_STA=0;
}

解析好的数据就存放在data这个数组中,接下来就在主循环中判断data数组中存放的数据以及su-03t通过串口直接传来的十六进制指令即可,根据相应的指令完成相关外设的驱动,具体程序见程序7。

程序7:

/******************驱动控制**************************/
//判断APP控制开关灯
if((data[0]=='1'&&data[1]=='1') || (temp == 0x11))
{
      GPIO_SetBits(LED0_PORT,LED0_PIN);   //开LED0
      GPIO_ResetBits(LED1_PORT,LED1_PIN); //关LED1
      TIM_SetCompare3(TIM4,800);                              //两端都使能 1档
      TIM_SetCompare4(TIM4,800);     
     
      temp=0;
      state_flag_temp=11;
      state_flag[0]=1;  //冷亮
      state_flag[2]=1;  //一档
      display_on[5] = 24;    //已为您打开灯(oled显示的汉字在数组中的索引)
      display_on[6] = 0;      //已为您打开灯(oled显示的汉字在数组中的索引)
}
if((data[0]=='1'&&data[1]=='0') || (temp == 0x10))
{
      GPIO_ResetBits(LED0_PORT,LED0_PIN); //关LED0
      GPIO_ResetBits(LED1_PORT,LED1_PIN); //关LED1
      temp=0;
      state_flag_temp=10;
      state_flag[0]=0;  
      state_flag[1]=0;
      state_flag[2]=0; 
      display_off[5] = 24;
      display_off[6] = 0;
}
//判断APP控制冷暖光调节
if((data[0]=='2'&&data[1]=='1') || (temp == 0x21)) //冷亮暖灭
{
      GPIO_SetBits(LED0_PORT,LED0_PIN);       //IN1—开冷光LED0
      GPIO_ResetBits(LED1_PORT,LED1_PIN); //IN3—关暖光LED1
      temp=0;
      state_flag_temp=21;
      state_flag[0]=1;  //冷亮
      state_flag[1]=0;  //暖灭
      display_on[5] = 26;            
      display_on[6] = 25;            
}
if((data[0]=='2'&&data[1]=='2') || (temp == 0x22))  //冷灭暖亮
{
      GPIO_ResetBits(LED0_PORT,LED0_PIN);       //IN1—关冷光LED0
      GPIO_SetBits(LED1_PORT,LED1_PIN);             //IN3—开暖光LED1
      temp=0;
      state_flag_temp=22;
      state_flag[0]=0;  //冷灭
      state_flag[1]=1;  //暖亮
      display_on[5] = 27;         
      display_on[6] = 25;
}     
                 
//判断APP控制1、2、3档位
if((data[0]=='3'&&data[1]=='1')|| (temp == 0x31))                    //1档
{
      TIM_SetCompare3(TIM4,800);                              //两端都使能 1档
      TIM_SetCompare4(TIM4,800);     
      temp=0;
      state_flag_temp=31;
      state_flag[2]=1;     //一档
      display_now[5] = 37;             
}
if((data[0]=='3'&&data[1]=='2')|| (temp == 0x32))                    //2档
{
      TIM_SetCompare3(TIM4,2000);                              //两端都使能 2档
      TIM_SetCompare4(TIM4,2000);     
      temp=0;
      state_flag_temp=32;
      state_flag[2]=2;              //二档
      display_now[5] = 38;
}
if((data[0]=='3'&&data[1]=='3')|| (temp == 0x33))                     //3档
{
      TIM_SetCompare3(TIM4,5000);                              //两端都使能 3档
      TIM_SetCompare4(TIM4,5000);     
      temp=0;
      state_flag_temp=33;
      state_flag[2]=3;        //三档
      display_now[5] = 39;     
}

至此台灯的控制功能已经全部开发完毕,已经实现了APP远程控制、语音控制功能。

06 超声波识别坐姿

还记得在第二章节所介绍的超声波模块HC-SR04,该模块主要是用于把该系统做成台灯时使用,用于检测坐姿规范的,若是开发家里的照明灯,可不加该模块。该模块实现测距的主要原理是:发射装置发射超声波,同时打开定时器,超声波遇到障碍物反弹,被接收装置接受,此时获取定时器的时间,然后根据速度计算距离。其坐姿判断逻辑如下:

HC-SR04测距低于阈值→坐姿不对,距离桌面过近→蜂鸣器报警

HC-SR04测距高于阈值→坐姿正确,距离桌面适宜→蜂鸣器正常

具体程序见程序8:

程序8:

//一次获取超声波测距数据 两次测距之间需要相隔一段时间,隔断回响信号
//为了消除余震的影响,取五次数据的平均值进行加权滤波。
float Hcsr04GetLength(void )
{
      u32 t = 0;
      int i = 0;
      float lengthTemp = 0;
      float sum = 0;
      while(i!=5)
      {
            TRIG_Send = 1;      //发送口高电平输出
            Delay_Us(20);
            TRIG_Send = 0;
            while(ECHO_Reci == 0);      //等待接收口高电平输出
            OpenTimerForHc();        //打开定时器
            i = i + 1;
            while(ECHO_Reci == 1);
            CloseTimerForHc();        //关闭定时器
            t = GetEchoTimer();        //获取时间,分辨率为1US
            lengthTemp = ((float)t/58.0);//cm
            sum = lengthTemp + sum ;
      }
      lengthTemp = sum/5.0;
      return lengthTemp;
}
Hcsr_num++;
if(Hcsr_num == 5)
{
      Hcsr_num = 0;
      length_C = Hcsr04GetLength();                 //测距离
      printf("距离为:%.3f\r\n",length_C);
      if(length_C < 20)
      {
            state_flag[3] =1;
            BEEP =~ BEEP;
            delay_ms(300);
      }
      else
      {
            state_flag[3] =0;
            BEEP = 0;
      }
      if(Hcsr_flag != state_flag[3])
      {
            Hcsr_flag = state_flag[3];
            display_all_flag=1;
      }
}

07 OLED屏显示状态

这部分实现的原理是,在上方介绍相关控制功能时会更改相应的标志位,然后在主程序中检查该标志位的状态,当标志位发生改变时,修改OLED屏幕的显示,具体程序见程序9。

程序9:

switch(Dis_mode)
{
      case 0:                                                                //在显示控制状态界面
            switch(state_flag_temp)     //定时显示界面
            {
                  case 11:control_part_display(2,6,display_1,display_on);break;      //显示“以为您打开灯”
                  case 10:control_part_display(2,6,display_1,display_off);break;     //显示“以为您关闭灯”
                  case 21:control_part_display(1,7,display_1,display_on);break;      //显示“以为您打开冷灯”
                  case 22:control_part_display(1,7,display_1,display_on);break;      //显示“以为您打开暖灯”
                  case 31:control_part_display(1,7,display_1,display_now);break;     //显示“当前亮度为一档”
                  case 32:control_part_display(1,7,display_1,display_now);break;     //显示“当前亮度为二档”
                  case 33:control_part_display(1,7,display_1,display_now);break;     //显示“当前亮度为三档”
            }
            data[0]='0';               //清空控制指令
            data[1]='0';
            state_flag_temp=0;
            if(display_all_flag)       //状态整体显示界面
            {
                  display_all_flag=0;
                  control_all_display(state_flag);
                  TIM_Cmd(TIM2,DISABLE);                          //关闭TIM2定时器
            }
      break;
      case 1:                                                       //在始终显示界面
            RTC_Display();                                           //显示时钟
      break;

      至此,智能灯光系统的相关功能已全部开发完毕,给电路板接上电源后,可使用APP控制、语音控制两种方式,实现灯光的开关、一档二档三档的的调节、冷暖光的调节、以及姿势纠正等功能。

.

十二、单片机中用二极管实现不同电压的输出

利用二极管的单向导电性可以设计出好玩、实用的电路。

    分享本文,分析限幅电路和钳位电路,是如何用二极管来实现的。

限幅电路

    如下图所示,当在正半周期,并且VIN大于等于0.7V,二极管正向导通。此时,

VOUT会被钳位在0.7V上。

    而当VIN小于0.7V时二极管是截止状态,在负半周期时相当于电流反向,二极管也是截至状态,此时VOUT=VIN,VOUT波形跟随VIN变化。

限辐电路示意图

根据上面限辐电路的原理,可以设计如下双向限辐电路。

双向限辐电路示意图

然而有时候0.7V电压不能满足要求,那么,怎么产生不同大小的限幅电压?

    在电路中加入偏置电压VBIAS,只有当VIN大于等于VBIAS时二极管才能导通。此时VOUT被钳位,其值是0.7V+VBIAS,如下图所示。

偏压限幅电路示意图

钳位电路

    下面是二极管结合电容实现的钳位电路。分析中不考虑二极管的导通压降,假设RC时间常数足够大,从而使输出波形不会失真。

钳位电路原理

    当输入Vin在负半周期为负时,电流如下图中红色箭头所示。二极管导通,电容逐渐充电至V,在此过程中Vout=0。

    当输入Vin在正半周为正时,电流如蓝色箭头所示。二极管截止,Vout等于电容上电压加上正半周电压V,此时Vout=2V。

钳位电路原理

偏压钳位电路

    跟限幅电路类似的,为了获得所需要的钳位值,要在电路中加入偏置电压,如下图所示。

偏压钳位电路

    当所加的偏压与二极管导通方向一致,钳位值会提高V1,Vout=2V+V1。

双向二极管钳位电路应用举例

    在某些电路中会利用两个二极管的钳位作用进行保护,如下图所示,假设0.7V为D1和D2的导通电压。

  • Vin大于等于Vmax,D1导通,Vout会被钳位在Vmax
  • Vin小于等于Vmin时,Vout被钳位在Vmin

二极管钳位保护电路 

.

十三、入门级电路

半波整流

    电路是一种利用二极管的单向导通特性来进行整流的常见电路,除去半周、剩下半周的整流方法,叫半波整流。作用是将交流电转换为直流电,也就是整流。

全波整流

    是指能够把交流转换成单一方向电流的电路,最少由两个整流器合并而成,一个负责正方向,一个负责反方向,最典型的全波整流电路是由四个二极管组成的整流桥,一般用于电源的整流。也可由MOS管搭建。

点亮一个LED灯

    使用一个开关,控三极管的基极,当开关按下的时候,三极管被导通,LED灯被点亮,当开关松开的时候,三极管被关闭,LED灯被关闭。

稳压电路

    左边变压器,输入降压后的交流电,经过半波整流,使用稳压管,是最简单的稳压电路,只要改变稳压管的参数,就可以获得不同的电压输出。

功率放大器

    功率放大器(英文名称:power amplifier),简称“功放”,是指在给定失真率条件下,能产生最大功率输出以驱动某一负载(例如扬声器)的放大器。功率放大器在整个音响系统中起到了“组织、协调”的枢纽作用,在某种程度上主宰着整个系统能否提供良好的音质输出。

LC 振荡器

    是指用电感L、电容C组成选频网络的振荡电路,用于产生高频正弦波信号,常见的LC正弦波振荡电路有变压器反馈式LC振荡电路、电感三点式LC振荡电路和电容三点式LC振荡电路。LC振荡电路的辐射功率是和振荡频率的四次方成正比的,要让LC振荡电路向外辐射足够强的电磁波,必须提高振荡频率,并且使电路具有开放的形式。

.

十四、串口的使用

串口通信介绍

    串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式......这种太过理论了,看似懂了,但又不懂。还是用我笔者自己的话来说吧。

    串口通信就是可以把程序在单片机或者STM32芯片中运行的结果发送到电脑的一种通信方式。

如何使用串口通讯,你需要知道的几个重要的知识点:

  • 波特率,数据传输的速度,如上图设置为9600,那么程序中也要设置为9600
  • 硬件连接,接收、发送交叉连接,如上图TxD->RxD,RxD->TxD
  • 停止位
  • 奇偶校验
  • 硬件数据流

    其中,后3项一般不需要改变。

学会串口通信能做什么

    学过C语言的人都知道,程序开发需要不断调试不断验证。很多的语言编程软件都有很完整的程序调试功能。使用起来很方便。而我们的开发虽然也是用C语言,但我们的程序最终运行的环境不是在我们的开平台而是在真正的硬件系统中运行。这时想要查看程序的运行过程或者结果就不像编程软件那么方便了。

    想要解决这个问题,我们这时就可以借助串口通信来把我们需要知道的结果又或者是程序运行的关键步骤发送到电脑上,我们就知道程序在硬件系统中运行是否出现问题。51单片机可以用串口来调试,STM32可以用串口来调试,Linux开发板也是使用串口来调试。

    当你学会串口通信时,你可以开始玩WIFI模块、GSM模块、蓝牙模块、GPS模块、以及各种使用串口通信的传感器等等。有能力你还可以编写上位机软件通过串口通信来控制设备。

串口通信需要什么

    如果你只有STM32核心板,那么你还需要一个串口转USB模块和一个串口数据接收软件还有几根杜邦线就可以了。

    如果你的是比较完整的一款开发板的话,一般都已经带有串口转USB模块,这样使用起来就更简单了。聪明的你是不是发现还缺少了点什么,对。没错因为还缺少了最重要的程序。想要使用串口通信当然还需要写串口通信的程序。

    下文就教你如何去用,而不是写。

串口实验

    而下文中的实验基于标准库实现的,与HAL相比思路是一样的。

    在做一个实验时,最好把这个实验分割成几个关键的步骤,这样做的好处就是可以清晰的知道自己需要做什么,以及做完了哪些。还有哪些还没做。

    下面把串口实验分成几个关键的步骤:
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寄存器

4)串口使能
    就是你需要什么时候开始使用串口功能,就是一句原有的函数。

USART_Cmd(USART1, ENABLE);  //使能串口1

5)编写串口中断处理函数
    使用库函数开发,所有的中断函数都是已经存在的,只是中断函数里面没有处理任何事情而已。中断函数如下:

 完整的串口中断函数:

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单片机,串口工具上就会收到什么。

总结

    以上就完成了一个最简单的串口实验。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐