一、传感器的数据处理算法
在传感器使用中,我们常常需要对传感器数据进行各种整理,让应用获得更好的效果,以下介绍几种常用的简单处理方法:
- 加权平滑:平滑和均衡传感器数据,减小偶然数据突变的影响。
- 抽取突变:去除静态和缓慢变化的数据背景,强调瞬间变化。
- 简单移动平均线:保留数据流最近的K个数据,取平均值。
下面,具体介绍一下这3种处理方法。
加权平滑
使用算法如下:
(新值) = (旧值)*(1 - a) + X * a其中a为设置的权值,X为最新数据,程序实现如下:
float ALPHA = 0.1f;
public void onSensorChanged(SensorEvent event){
x = event.values[0];
y = event.values[1];
z = event.values[2];
mLowPassX = lowPass(x,mLowPassX);
mLowPassY = lowPass(x,mLowPassY);
mLowPassZ = lowPass(x,mLowPassZ);
}
private float lowPass(float current,float last){
return last * (1.0f - ALPHA) + current * ALPHA;
}
抽取突变
此算法采用上面加权平滑的逆算法,实现代码如下:
public void onSensorChanged(SensorEvent event){
final float ALPHA = 0.8;gravity[0] = ALPHA * gravity[0] + (1-ALPHA) * event.values[0];
gravity[1] = ALPHA * gravity[1] + (1-ALPHA) * event.values[1];
gravity[2] = ALPHA * gravity[2] + (1-ALPHA) * event.values[2];filteredValues[0] = event.values[0] - gravity[0];
filteredValues[1] = event.values[1] - gravity[1];
filteredValues[2] = event.values[2] - gravity[2];
}
简单移动平均线
这个算法,保留传感器数据流中最近的K个数据,返回它们的平均值。k表示平均“窗口”的大小,实现代码如下:
public class MovingAverage{
private float circularBuffer[]; //保存传感器最近的K个数据
private float avg; //返回到传感器平均值
private float sum; //数值中传感器数据的和
private float circularIndex; //传感器数据数组节点位置
private int count;public MovingAverage(int k){
circularBuffer = new float[k];
count= 0;
circularIndex = 0;
avg = 0;
sum = 0;
}
public float getValue(){
return arg;
}
public long getCount(){
return count;
}
private void primeBuffer(float val){
for(int i=0;i<circularbuffer.length;++i){circularBuffer[i] = val;
sum += val;
}
}
private int nextIndex(int curIndex){
if(curIndex + 1 >= circularBuffer.length){
return 0;
}
return curIndex + 1;
}
public void pushValue(float x){
if(0 == count++){
primeBuffer(x);
}
float lastValue = circularBuffer[circularIndex];
circularBuffer[circularIndex] = x; //更新窗口中传感器数据
sum -= lastValue; //更新窗口中传感器数据和
sum += x;
avg = sum / circularBuffer.length; //计算得传感器平均值
circularIndex = nextIndex(circularIndex);
}
}
二、STM32的启动模式配置与应用
三种BOOT模式
所谓启动,一般来说就是指我们下好程序后,重启芯片时,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存。用户可以通过设置BOOT1和BOOT0引脚的状态,来选择在复位后的启动模式
- Main Flash memory
是STM32内置的Flash,一般我们使用JTAG或者SWD模式下载程序时,就是下载到这个里面,重启后也直接从这启动程序。 - System memory
从系统存储器启动,这种模式启动的程序功能是由厂家设置的。一般来说,这种启动方式用的比较少。系统存储器是芯片内部一块特定的区域,STM32在出厂时,由ST在这个区域内部预置了一段BootLoader, 也就是我们常说的ISP程序, 这是一块ROM,
出厂后无法修改。一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的BootLoader中,提供了串口下载程序的固件,可以通过这个BootLoader将程序下载到系统的Flash中。但是这个下载方式需要以下步骤:
Step1:将BOOT0设置为1,BOOT1设置为0,然后按下复位键,这样才能从系统存储器启动BootLoader
Step2:最后在BootLoader的帮助下,通过串口下载程序到Flash中
Step3:程序下载完成后,又有需要将BOOT0设置为GND,手动复位,这样,STM32才可以从Flash中启动可以看到, 利用串口下载程序还是比较的麻烦, 需要跳帽跳来跳去的,非常的不注重用户体验。 - Embedded Memory
内置SRAM,既然是SRAM,自然也就没有程序存储的能力了,这个模式一般用于程序调试。假如我只修改了代码中一个小小的地方,然后就需要重新擦除整个Flash,比较的费时,可以考虑从这个模式启动代码(也就是STM32的内存中),用于快速的程序调试,等程序调试完成后,在将程序下载到SRAM中。
开发BOOT模式选择
通常使用程序代码存储在主闪存存储器,配置方式:
BOOT0=0,BOOT1=X
Flash锁死解决办法
开发调试过程中,由于某种原因导致内部Flash锁死,无法连接SWD以及Jtag调试,无法读到设备,可以通过修改BOOT模式重新刷写代码。
修改为BOOT0=1,BOOT1=0即可从系统存储器启动,ST出厂时自带Bootloader程序,SWD以及JTAG调试接口都是专用的。重新烧写程序后,可将BOOT模式重新更换到BOOT0=0,BOOT1=X即可正常使用。
.
三、两种USB接口电路图解析
1 USB接口电路的原理图中,R3是上拉电阻器,它可使USB口的D+端上拉到DS2490S的VB端,表示USB主机系统是高速设备,同时这个上拉电阻器告诉主机有USB设备插入。该上拉电阻器的设置对适配器的影响很大,它的负载值和1-Wire网络的总长决定1-Wire总线电压上升到5 V的速度。经过实验测试选择R3的阻值为27 Ω±lO%。R1、R2为USB数据线保护电阻器。L、L2具有禁止高频干扰并且减弱EMI辐射的功能。LF33CV为3.3 V电压稳压器,与周围元件C1、C2组成强上拉部分,给EEPROM或温度传感器等器件提供额外的电源。
2 采用PDIUSBD12芯片,这是一种价格便宜、功能完善的并行接口芯片,它支持多路复用、非多路复用和 DMA并行传输。PDIUSBD12接口芯片遵从协议USB1.1,适合于不同用途的传输类型。PDIUSBD12需要外接微控制器(MCU)来进行协议处理和数据交换,它对MCU没有特殊要求,而且接口方便灵活,因此设计师可以选用自己熟悉的MCU对芯片进行控制,也可利用Philips公司的固件 (firmware)结构来缩短开发时间、降低风险、减小投资。
PDIUSBD12除了具有USB设备的一般特性外,还具有如下特点:
(1)是一种高性能的USB接口芯片,其内部集成有 SIE(Serial Interface Engine)、320字节的FIFO、收发器和电压调节器。
(2)适用于大部分设备类规范。可与任何外部微控制器/微处理器实现高速并行接口,其速度可高达2Mbit/s。
(3)可进行完全独立的DMA操作。
(4)主端点配置有双缓冲,因而可提高数据的吞吐量、减小数据传输时间,轻松实现数据的实时传输。
(5)当采用同步传输方式时,数据的传输速度为1Mbit/s;而采用批量传输方式的速度为1Mbyte/s。在使用上述方式进行数据传输时,可方便地使用多种中断方式。
(6)带有可编程的时钟输出,与USB总线的连接可通过软件来控制(Soft Connect TM)。
(7)有两种工作电压可供选择:分别为3.3±0.3V和3.6~5.5V。
(8)输出和数据传输状态可通过USB连接指示灯来监控。
.
四、简易大功率变压器电路图
本文介绍的电子变压器克服了传统硅钢片变压器体积、重量大、效率低、价格高的缺点,电路成熟,性能稳定。
本电子变压器工作原理与开关电源相似,电路原理图见图1,由VD1-VD4将市电整流为直流,再把直流变成几十千赫兹的 高频电流,然后用铁氧休变压器对高频、高压脉冲降压。图中R2、C1、VD5为启动触发电路。C2、C3、L1、L2、L3、VT1、VT2构成高频振荡部分。
元器件选择与制作
L1、L2、L3分别绕在H7&TImes;4&TImes;2mm3的磁环上,L1、L2绕6匝;L2绕1匝。L4、L5绕在H31&TImes;18&TImes;7mm3的磁环上,L4绕用Φ=0.1mm的高强度线绕340匝;L5用Φ=1.45mm的高强度线绕20匝。VT1、VT2选用耐压BVceo≥350V大功率硅管。其它元件无特殊要求。
电路正常工作时,A点工作电压约为215V,B点约为108V,C点约为10V,D点约为25V。如果不振荡,检查VT1、VT2及L1、L2、L3的相位是否正常(交换L3的两根接线即刻)。改变L5的匝数可改变输出电压。
500W大功率变压器电路
如图为500W大功率变压器电路原理。电路采用TL494为振荡器,VT1~VT6为激励级,是输出为500W的大功率逆变电路。TL494在该逆变器中的应用方法如下:
1、2脚构成稳压取样、误差放大电路f逆变器次级绕组整流输出的15V直流电压作为取样电压,经R1、R3分压,使1脚在逆变器正常工作时有近4.7~5.6V的取样电压。2脚输入5V的基准电压(由14脚输出)。当输出电压降低时,1脚电压降低,误差放大器输出低电平,通过TL494内部电路使输出电压升高。
四款电子变压器电路图
电路一
我们经过反复实验这种电子变压器的电流反应速度很快!已经超过了普通的工频变压器,该电路完全可以代替功放的电源。电子变压器AC/DC有过电流限制保护功能适合电动自行车的电瓶充电。如果将几个AC/DC并联可以做成大功率的充电机。由于该电路的适应电流变化能力很强采用并联可以代替数KW的火牛,应用在音响电源。
电路二
自激式电子变压器电路图
电路三
该电子变压器工作原理与开关电源相似,由VD1~VD4把市电整成直流,再把直流整成几十千赫兹的高频电流,然后用铁氧体变压器对高频、高压脉冲降压(如图所示)。图中R2、C1、VD5为启动触发电路。C2、C3、L1、L2、L3、VT1、VT2构成高频振荡部分。
电路四
五、电源口的防雷电路设计
电源口防雷电路的设计要素
1、防雷电路的设计应满足规定的防护等级要求,且防雷电路的残压水平应能够保护后级电路免受损坏。
2、在遇到雷电暂态过电压作用时,保护装置应具有足够快的动作响应速度,即能尽早的动作限压和旁路泄流。
3、防雷电路加在馈电线路上,不应影响设备的正常馈电。例如,采用串联式电源防雷电路时,防雷电路应可通过设备满负荷工作时的电流并有一定的裕量。
4、防护电路在系统的最高工作电压时不应动作。通常在交流回路中,防护电路的动作电压是交流工作电压有效值的2.2~2.5倍,在直流回路中,防护电路的动作电压是直流额定工作电压的1.8~2倍。
5、防雷电路加在馈电线路上,不应给设备的安全运行带来隐患。例如,应避免由于电路设计不当而使防雷电路存在着火等安全隐患。
6、在整个馈电通路上存在多级防雷电路时,应注意各级防雷电路间有良好的配合关系,不应出现后级防雷电路遭到雷击损坏而前级防雷电路完好的情况。
7、防雷电路应具有损坏告警、遥信、热容和过流保护功能,并具有可替换性。
下面分别给出交流电源口和直流电源口的防雷电路设计指导。
交流电源口防雷电路设计
交流电源口防雷电路
上图是一个两级的交流电源口防护电路:
1、G1和G2为气体放电管
2、Rvz1~Rvz6为压敏电阻
3、F1和F2为空气开关
4、F3和F4为保险
5、L1和L2是退耦电感。
简述电路原理
第1级防雷电路为具有共模和差模保护的电路,差模保护采用的压敏电阻。共模保护采用压敏电阻和气体放电管串联。第1级防雷电路的通流能力较高,通常在几十kA(8/20us)。第1级防雷电路宜选用空气开关做短路过流故障的保护器件。
第2级防雷电路的形式与第1级相同,合理设计第1级电路和第2级电路间的电感值,可以使大部分的雷电流通过第1级防雷电路泄放,第2级电路只泄放少部分雷电流,这样就可以通过第2级电路将防雷器的输出残压进一步降低以达到保护后级设备的目的。第2级防雷电路应选用保险作保护器件。
防护电路中各保护器件的通流量的选择应达到设计指标的要求并有一定裕量;差模压敏电阻的压敏电压取值可按压敏电阻章节给出的方法选择;压敏电阻和气体放电管串联的共模防护电路中,压敏电阻、空气放电管的取值仍可按压敏、放电管单独并接在线路中时的相x关章节给出的计算方法来选取。
交流电源口防雷电路变型
变型电路1
如上图变型电路1,将原电路中的电感换成了一定长度的馈电线。规定长度的馈电线所具有的电感量与原电路中电感的感值是基本相同的。
将电感换成馈电线的优点是:在设备的工作电流很大的情况下,合理的选择馈电线线径就可以满足给设备供电的需求,克服了在设备供电电流很大时,空心电感的体积过大而无法在电路上实现的问题。第1级的防护电路和第2级的防护电路可以分别放置在两个不同的设备中实现,例如:将第1级防护电路设计为一个独立的防雷箱,将第2级防雷电路内置于通信设备中。
由于去掉了电感,变型电路1可以看作为两个并联式的防雷电路。当这两级防雷电路做成两个单独的防雷器时,需要注意防雷器的安装问题。
变型电路2
如上图变型电路2,是交流防雷电路的简化设计:只保留防雷电路中的第1级防雷电路或者第2级防雷电路,其它设计要点同交流电源口防雷电路。
电路a在后级电路抗浪涌过电压能力较强时采用,电路b在外部具有一级保护措施时采用,一般设计在电源模块内部。变形电路2降低了电路的复杂性,并且由于去掉了电感,不需要考虑满足通过设备正常工作电流的需要,方案更容易实现。由于该电路去掉了电感,它由一个串联式防雷电路变成了一个并联式防雷电路。当这个电路做成一个独立的防雷器时,需要注意防雷器的安装问题。
直流电源口防雷电路设计
上图是一个具有串联式2级差模防护的电路,可以做到标称放电电流5kA,电路原理简述如下:
第1级采用两个压敏电阻并联的差模保护,两个气体放电管并联进行共模保护(注:这里选用两个器件并联的目的是降低残压和增大通流能力,在使用单个器件满足要求的情况下可以只使用一个器件),可以达到标称放电电流5kA的设计指标,第2级采用压敏电阻和TVS管保护,将残压降低到后级电路能够承受的水平,其中TVS管T1推荐采用双向TVS管,可以防反接,也可以采用单向的TVS管,但具有不防反接的缺点。共模保护采用两个气体放电管并联构成的1级防护电路。该电路的优点是具有较低的输出残压,适用于后级电路抗过电压水平很低的情况。防雷电路中各保护元件通流量、压敏电压、反向击穿电压的选择、电感的取值可参照相x关章节给出的方法进行。两级防雷电路都应选用保险做保护器件。
该防护电路的应用场合是后级电路的抗浪涌过电压的能力较弱,一级防雷电路不足以保护后级的设备,需要通过第2级的防雷电路将残压进一步降低。
直流电源口防雷电路变型
变型电路1
变型电路1将图6-4直流电源口防雷电路中的电感换成了一定长度的馈电线。规定长度的馈电线所具有的电感量与原电路中电感的感值是基本相同的。将电感换成馈电线的优点是:在设备的工作电流很大的情况下,合理的选择馈电线线径就可以满足给设备供电需求,克服了在设备供电电流很大时,空心电感的体积过大而无法在电路上实现的问题。第1级的防护电路和第2级的防护电路可以分别放置在两个不同的设备中实现,例如:将第1级防护电路设计到直流高阻柜中,将第2级防雷电路内置于通信设备中。
由于去掉了电感,变型电路1可以看作为两个并联式的防雷电路。当这两级防雷电路做成两个单独的防雷器时,需要注意防雷器的安装问题。
变型电路2
变型电路2是直流电源口防雷电路的简化设计:保留防雷电路中的第1级防雷电路(注:这里选用两个器件并联的目的是降低残压和增大通流能力,在使用单个器件满足要求的情况下可以只使用一个器件),去掉电感及第2级防雷电路。其它设计要点同直流电源口防雷电路。
变型电路2的应用场合是在后级电路抗浪涌过电压能力较强时采用,这个方案可以降低电路的复杂性。同时由于去掉了电感,不需要考虑满足通过设备正常工作电流的需要,方案更容易实现。由于变型电路2去掉了电感,它由一个串联式防雷电路变成了一个并联式防雷电路。当这个电路做成一个独立的防雷器时,需要注意防雷器的安装问题。
.
六、手机充电器电路分析
充电器简单原理分析:
分析一个电源,往往从输入开始着手。220V交流输入,一端经过一个IN4007半波整流,另一端经过一个10欧的电阻后,由10uF电容滤波。这个10欧的电阻用来做保护的,如果后面出现故障等导致过流,那么这个电阻将被烧断,从而避免引起更大的故障。右边的4007、4700pF电容、82KΩ电阻,构成一个高压吸收电路,当开关管13003关断时,负责吸收线圈上的感应电压,从而防止高压加到开关管13003上而导致击穿。13003为开关管(完整的名应该是MJE13003),耐压400V,集电极最大电流1.5A,最大集电极功耗为14W,用来控制原边绕组与电源之间的通、断。当原边绕组不停的通断时,就会在开关变压器中形成变化的磁场,从而在次级绕组中产生感应电压。由于图中没有标明绕组的同名端,只能推断输出段没有续流管和储能电感推断出为反激电路。
左端的510KΩ为启动电阻,给开关管提供启动用的基极电流。13003下方的10Ω电阻为电流取样电阻,电流经取样后变成电压(其值为10*I),这电压经二极管4148后,加至三极管C945的基极上。当取样电压大约大于1.4V,即开关管电流大于0.14A时,三极管C945导通,从而将开关管13003的基极电压拉低,从而集电极电流减小,这样就限制了开关的电流,防止电流过大而烧毁(其实这是一个恒流结构,将开关管的最大电流限制在140mA左右)。
变压器左下方的绕组(取样绕组)的感应电压经整流二极管4148整流,22uF电容滤波后形成取样电压。为了分析方便,我们取三极管C945发射极一端为地。那么这取样电压就是负的(-4V左右),并且输出电压越高时,采样电压越负。取样电压经过6.2V稳压二极管后,加至开关管13003的基极。前面说了,当输出电压越高时,那么取样电压就越负,当负到一定程度后,6.2V稳压二极管被击穿,从而将开关13003的基极电位拉低,这将导致开关管断开或者推迟开关的导通,从而控制了能量输入到变压器中,也就控制了输出电压的升高,实现了稳压输出的功能。
而下方的1KΩ电阻跟串联的2700pF电容,则是正反馈支路,从取样绕组中取出感应电压,加到开关管的基极上,以维持振荡。右边的次级绕组就没有太多好说的了,经二极管RF93整流,220uF电容滤波后输出6V的电压。没找到二极管RF93的资料,估计是一个快速回复管,例如肖特基二极管等,因为开关电源的工作频率较高,所以需要工作频率的二极管。这里可以用常见的1N5816、1N5817等肖特基二极管代替。 whaosoft aiot http://143ai.com
同样因为频率高的原因,变压器也必须使用高频开关变压器,铁心一般为高频铁氧体磁芯,具有高的电阻率,以减小涡流。
.
七、C语言弱符号和弱引用
__attribute__
是一个编译器指令,其实是 GNU C
的一种机制,本质是一个编译器的指令,在声明的时候可以提供一些属性,在编译阶段起作用,来做多样化的错误检查和高级优化。
用于在 C
,C++
,Objective-C
中修饰变量、函数、参数、方法、类等。
合理使用 __attribute__
有什么好处?
- 给编译器提供上下文,帮助编译器做优化,合理使用可以收到显著的优化效果。
- 编译器会根据
__attribute__
产生一些编译警告,使代码更规范。 - 给代码阅读者提供必要的注解,助其理解代码意图。
总之,__attribute__
起到了给编译器提供上下文的作用,如果错误的使用 __attribute__
指令,因为给编译器提供了错误的上下文,由此引起的错误通常很难被发现。
强符号和弱符号
在同一作用域下不能定义同一个变量或函数,很多C语言学习者都理所当然地这么认为。
这个其实是是有所偏颇的,GNU C对标准C语言进行了扩展,在GCC中,对于符号(在编译时,变量和函数都被抽象成符号)而言,存在着强符号和弱符号之分。
是的,是否支持这个特性是由不同的C语言标准决定的。
对于C/C++而言,编译器默认函数和已初始化的全局变量为强符号,而未初始化的全局变量为弱符号。
在编程者没有显示指定时,编译器对强弱符号的定义会有一些默认行为,同时开发者也可以对符号进行指定,使用"attribute((weak))"来声明一个符号为弱符号。
定义一个相同的变量,当两者不全是强符号时,gcc在编译时并不会报错,而是遵循一定的规则进行取舍:
- 当两者都为强符号时,重复定义的报错:
redefinition of 'xxx'
- 当两者为一强一弱时,选取强符号的值
- 当两者同时为弱时,选择其中占用空间较大的符号,这个其实很好理解,编译器不知道编程者的用意,选择占用空间大的符号至少不会造成诸如溢出、越界等严重后果。
在默认的符号类型情况下,强符号和弱符号是可以共存的,类似于这样:
int x;
int x = 1;
编译不会报错,在编译时x的取值将会是1。
注意,这里可以使用__attribute__((weak))
将强符号转换为弱符号,却不能与一个强符号共存,类似于这样:
int __attribute__((weak)) x = 0;
int x = 1;
编译器将报重复定义错误。
强引用和弱引用
除了强符号和弱符号的区别之外,GNUC还有一个特性就是强引用和弱引用。
我们知道的是,编译器在编译阶段只负责将源文件编译成目标文件(即二进制文件),然后由链接器对所有二进制文件进行链接操作。
编译器默认所有的变量和函数为强引用,同时编程者可以使用__attribute__((weakref))
来声明一个函数。
注意这里是声明而不是定义,既然是引用,那么就是使用其他模块中定义的实体,对于函数而言,我们可以使用这样的写法:
__attribute__((weakref)) void func(void);
然后在函数中调用func()
,如果func()
没有被定义,则func
的值为0,如果func
被定义,则调用相应func,在《程序员的自我修养》这本书中有介绍,它是这样写的:
__attribute__((weakref)) void func(void);
void main(void)
{if(func) {func();}
}
但是在现代的编译系统中,这种写法却是错误的,编译虽然通过(有警告信息),但是却不正确:
warning: ‘weakref’ attribute should be accompanied with an ‘alias’ attribute [-Wattributes]
警告显示:weakref需要伴随着一个别名才能正常使用。
强/弱符号和强/弱引用的作用
这种弱符号、弱引用的扩展机制在库的实现中非常有用。
我们在库中可以使用弱符号和弱引用机制,这样对于一个弱符号函数而言,用户可以自定义扩展功能的函数来覆盖这个弱符号函数。
同时我们可以将某些扩展功能函数定义为弱引用,当用户需要使用扩展功能时,就对其进行定义,链接到程序当中。
如果用户不进行定义,则链接也不会报错,这使得库的功能可以很方便地进行裁剪和组合。
注意:C标准里根本没有提到强、弱符号。这只是GCC这个实现定义的特性,在MS C编译器里是不存在这个概念的。
.
八、MOS管驱动电路设计
一般认为MOSFET是电压驱动的,不需要驱动电流。然而,在MOS的G S两级之间有结电容存在,这个电容会让驱动MOS变的不那么简单。
如果不考虑纹波和EMI等要求的话,MOS管开关速度越快越好,因为开关时间越短,开关损耗越小,而在开关电源中开关损耗占总损耗的很大一部分,因此MOS管驱动电路的好坏直接决定了电源的效率。
对于一个MOS管,如果把GS之间的电压从0拉到管子的开启电压所用的时间越短,那么MOS管开启的速度就会越快。与此类似,如果把MOS管的GS电压从开启电压降到0V的时间越短,那么MOS管关断的速度也就越快。
由此我们可以知道,如果想在更短的时间内把GS电压拉高或者拉低,就要给MOS管栅极更大的瞬间驱动电流。
大家常用的PWM芯片输出直接驱动MOS或者用三极管放大后再驱动MOS的方法,其实在瞬间驱动电流这块是有很大缺陷的。
比较好的方法是使用专用的MOSFET驱动芯片如TC4420来驱动MOS管,这类的芯片一般有很大的瞬间输出电流,而且还兼容TTL电平输入,MOSFET驱动芯片的内部结构如下:
MOS驱动电路设计需要注意的地方:
因为驱动线路走线会有寄生电感,而寄生电感和MOS管的结电容会组成一个LC振荡电路,如果直接把驱动芯片的输出端接到MOS管栅极的话,在PWM波的上升下降沿会产生很大的震荡,导致MOS管急剧发热甚至爆炸,一般的解决方法是在栅极串联10欧左右的电阻,降低LC振荡电路的Q值,使震荡迅速衰减掉。
因为MOS管栅极高输入阻抗的特性,一点点静电或者干扰都可能导致MOS管误导通,所以建议在MOS管G S之间并联一个10K的电阻以降低输入阻抗。
如果担心附近功率线路上的干扰耦合过来产生瞬间高压击穿MOS管的话,可以在GS之间再并联一个18V左右的TVS瞬态抑制二极管。
TVS可以认为是一个反应速度很快的稳压管,其瞬间可以承受的功率高达几百至上千瓦,可以用来吸收瞬间的干扰脉冲。
MOS管驱动电路参考:
MOS管驱动电路的布线设计
MOS管驱动线路的环路面积要尽可能小,否则可能会引入外来的电磁干扰。
驱动芯片的旁路电容要尽量靠近驱动芯片的VCC和GND引脚,否则走线的电感会很大程度上影响芯片的瞬间输出电流。
常见的MOS管驱动波形,如下图。
如果出现了这样圆不溜秋的波形就等着核爆吧。有很大一部分时间管子都工作在线性区,损耗极其巨大。
一般这种情况是布线太长电感太大,栅极电阻都救不了你,只能重新画板子。
高频振铃严重的毁容方波。
在上升下降沿震荡严重,这种情况管子一般瞬间死掉,跟上一个情况差不多,进线性区。
原因也类似,主要是布线的问题。又胖又圆的肥猪波。
上升下降沿极其缓慢,这是因为阻抗不匹配导致的。
芯片驱动能力太差或者栅极电阻太大。
果断换大电流的驱动芯片,栅极电阻往小调调就OK了。
打肿脸充正弦的生于方波他们家的三角波。
驱动电路阻抗超大发了。此乃管子必杀波。解决方法同上。
大众脸型,人见人爱的方波。
高低电平分明,电平这时候可以叫电平了,因为它平。边沿陡峭,开关速度快,损耗很小,略有震荡,可以接受,管子进不了线性区,强迫症的话可以适当调大栅极电阻。
方方正正的帅哥波,无振铃无尖峰无线性损耗的三无产品,这就是最完美的波形了。
.
九、单片机接口电路设计中的电流倒灌和电平转换
接口电路的设计在电单片机应用场合中还是很重要的,因为如果接口电路没有设计好,严重就会烧芯片,或者烧芯片IO口,轻者就会导致工作紊乱,工作不正常。
有时候这种问题自己在设计调试的时候根本发现不了,在批量生产或者用户在使用的时候才出现芯片被烧掉,或者IO口被烧掉。如果我们在设计的时候能考虑到接口的一些问题就可以减少,提高产品的可靠性。
下面我们就从电流倒灌问题和电平匹配问题进行叙述。
电流倒灌
1 概念
倒灌就是电流流进IC内部,电流总是流入电势低的地方。比如说电压源,一般都是输出电流,但是如果有另一个电源同时存在,并且电势高于这个电源,电流就会流入这个电源,称为倒灌。
2 危害
1. 电流太大会将使IO口上的钳位二极管迅速过载并使其损坏。
2. 会使单片机复位不成功。
3. 会使可编程器件程序紊乱。
4.会出现闩锁效应。
3 原因
如上图,STM32的IO口框图。
当两个单片机进行串口通信,如果其中一个单片机断电,另一个单片机继续供电,正常运行。那么没有断电的单片机的IO口给断电的单片机的IO口供电,并同通过上拉保护二极管向断电的单片机进行供电。或者说两个单片机供电电压不一样,电流就会从供电高的一方流向供电低的一方。
4 解决办法
如上图,加一个小电阻,可以防止过流损坏二极管D1。还可以进行阻抗匹配,因为信号源的阻抗很低,跟信号线之间阻抗不匹配,串上一个电阻后,可改善匹配情况,以减少反射,避免振荡等。也可以减少信号边沿的陡峭程度,从而减少高频噪声以及过冲等。但不能解决灌流在Vcc上建立电压。一般情况下就会选择串电阻,取值范围是几欧到1K欧,根据实际情况而定,小编我喜欢取330欧。
如上图,在信号线上加二极管D3及上拉电阻R1,D3用于阻断灌流通路,R1解决前级输出高电平时使G1的输入保持高电平。
此方法既可解决灌流损坏二极管D1的问题,又可解决灌流在Vcc上建立电压。缺点只适用于速率不快的电路上。如果单片机IO口比较脆弱,或者两边电压不也一样需要低成本进行电平转换,且是但一方向,速率比较低(比如串口)的时候就可以选择该方案。二极管要选择肖特基二极管才比较好
电平转换
在电路设计过程中,会碰到处理器MCU的I/O电平与模块的I/O电平不相同的问题,为了保证两者的正常通信,需要进行电平转换。如果两边的电平不一样就直接连接进行通信,像TTL电平就会出现上一节将的那样电流倒灌现象。
设计电平转换电路需要几个问题:
(1)VOH>VIH;VOL<vil
各种电平的电压范围,如上图。
(2)对于多电源系统,某些器件不允许输入电平超过电源电压,针对有类似要求的器件,电路上应适当做些保护。
(3)电平转换电路会影响通信速度,所以使用时应当注意通信速率上的要求。
1 NPN三极管电平转换
这个电平转换就是两级三极管电路组成。三极管只能单向进行转换,而且元器件比较多。
2 NMOS电平转换
该电路可实现双向传输,使用条件是VCC2>VCC1+0.7V,这个电路也是小编我常用的电路。
其工作过程是:
Port1向Port2传输:
(1)Port1高电平时,NMOS的Ugs=0V截止,Port2端的电压为VCC2高电平。
(2)Port1低电平时,NMOS的Ugs=3.3V导通,Port2端的电压为Port1端的电压低电平。
Port2向Port1传输:
(1)Port2高电平时,NMOS的Ugs=0V截止,Port1端的电压为VCC1--高电平。
(2)Port2低电平时,NMOS的体二极管导通,使得Vs的电压为0.7V左右,那么Ugs=VCC1-0.7V,只要选择的开启电压小于Ugs电压就可以让MOS管导通,Port1端的电压为Port2端的电压--低电平。
3 使用专用电平芯片转换电平
使用专用的电平转换芯片,分别给输入和输出信号提供不同的电压,转换由芯片内部完成,例如PCA9306DCTR等电平转换芯片。专用芯片是最可靠的电平转换方案。
优势:
1) 驱动能力强:专用芯片的输出一般都使用了CMOS工艺,输出驱动10mA不在话下。
2) 漏电流几乎为0:内部是一些列的放大、比较器,输入阻抗非常高,一般都达到数百K。漏电流基本都是nA级别的。
3) 路数较多:专用芯片针对不同的应用,从2路到数十路都有,十分适合对面积要求高的场合。
4) 速率高:专用芯片由于集成度较高,工艺较高,,速率从数百K到数百M的频率都可以做。
劣势:
1) 成本:专用芯片集众多优势于一身,就是成本是最大的劣势,一个普通的数百K速率的4通道电平转换芯片,价格至少要1元人民币以上,如果使用三极管做,成本2毛钱都不到。
4 使用电阻分压转换电平
优势:
1) 便宜:便宜是最大的优点,2个电阻一分钱不到;
2) 容易实现:电阻采购容易,占用面积小。
劣势:
1) 速度:分压法为了降低功耗,使用K级别以上的电阻,加上电路和器件的分布和寄生电容,速率很难上去,一般只能应用于100K以内的频率。
2) 驱动能力:由于使用了大阻值的电阻,驱动能力被严格控制,并不适合需要高驱动能力的场合,例如LED灯等
3) 漏电:漏电是该方案最大的缺点,由于通过电阻直连,左右两端的电压会流动,从而互相影响。例如,RS232接口采用该方案,上电瞬间外设就给主芯片提供2.8V的电平,轻则影响时序导致主芯片无法启动,重则导致主芯片闩锁效应,烧毁芯片。
5 使用电阻限流转换电平
优势:
1) 便宜:便宜是最大的优点,只需要一个电阻就解决。
2) 容易实现。
劣势:
1) 电阻选值不是很容易选择,需要对芯片内部很熟悉。
6 使用二极管转换电平
优势:
1) 漏电流小:由于二极管的漏电流非常小(uA级),可以单向防止电源倒灌,防止电流倒灌。
2) 容易实现。
劣势:
1) 电平误差大:主要是二极管的正向压降较大,容易超出芯片的工作电压范围。
2) 单向防倒灌:只能单向防止倒灌,不能双向防止倒灌。
3) 速度和驱动能力不理想:由于电阻限流,驱动速度和能力均不理想,只能应用在100K以内的频率。
.
十、用三极管来配合单片机IO口驱动负载
驱动继电器的时候,通常我们会采用三极管来配合单片机IO口。至于为什么不直接用单片机IO口驱动,非得加个三极管,在上一篇推文中我们已经做过计算了。至于为什么采用三极管,更大的原因是因为三极管属于流控型器件,也就是说三极管的这个电子开关的闭合与断开是通过电流开控制的,并且所需要的电流非常小。三极管基极驱动电压只要高于Ube(一般是0.7V)就能导通。
现在的大家都讲究低功耗,供电电压也越来越低,一般单片机供电为3.3V,所以它的I/O最高电压也就是3.3V。
3.3V电压肯定是大于Ube的,所以直接在基极串联一个合适的电阻,让三极管工作在饱和区就可以了。Ib=(VO-0.7V)/R2。根据公式计算,上图中Ib的电流应该等于(5-0.7)/(4.7x1000),大于是0.918mA,实际仿真测试结果为0.628mA,基本符合实际值,三极管能正常开启和闭合实现控制,可以正常的实现控制负载(此处为LED灯)。
到这可能会有硬件基础好的小伙伴要说了,MOS管也可以啊,为什么非得用三极管呢?
其原因在于,MOS管是电压控制型,驱动电压必须高于阈值电压Vgs(TH)才能正常导通,不同MOS管的阈值电压是不一样的,一般为3-5V左右,饱和驱动电压可在6-8V。
前面说过现在单片机的供电基本都是3.3V,IO口最高电压也是3.3V,大部分的MOS管的饱和电压>3.3V,如果用3.3V来驱动的话,很可能MOS管根本就打不开,或者处于半导通状态。在半导通状态下,管子的内阻很大,驱动小电流负载可以这么用。但是大电流负载就不行了,内阻大,管子的功耗大,MOS管很容易就烧坏了。所以,一般选择三极管来配合单片机IO口驱动。
当然,MOS管得驱动电流很大,在更多的需要大功率的驱动电路中,通过会采用但机关配合MOS一起来实现大电流的驱动运用场景,比如下面这个电路图就是。
I/O口驱动三极管后再驱动MOS管
当I/O为高电平时,三极管导通,MOS管栅极被拉低,负载RL不工作。
当I/O为低电平时,三极管不导通,MOS管通过电阻R3,R4分压,为栅极提供合适的阈值电压,MOS管导通,负载RL正常工作。
结合以上的分析,相比大家应该都清除了,通常情况下大家习惯用三极管来连接单片机IO口实现驱动,是因为三极管是流控型器件,但是三极管的驱动能力比较弱。在需要大功率驱动的地方,通常会采用三极管再去控制MOS管实现最终的控制。
直接用MOS管来连接单片机的IO实现驱动也是可以的,但这样的MOS管型号不好找。小编在立创商城上所搜了一下,也有这样的器件,控制电压最低可以到1V,驱动电流峰值2.3A,持续1.6A;相同封装的三极管8050,驱动的Ic电流只能到600mA。
可见MOS管的驱动能力是三极管3-4倍,所以对负载电流有要求的都使用MOS管。大的驱动能力,带来的会是成本的增加,搜索结果中MOS管的价格几乎是三极管的10倍。
所以,在要求不高,成本低的应用场合,一般使用三极管作为开关管。
.
十一、STM32CubeMX-实时时钟(RTC)
RTC简介
实时时钟 (RTC) 是一个独立的 BCD 定时器/计数器。RTC 提供具有可编程闹钟中断功能的日历时钟 /日历。RTC 还包含具有中断功能的周期性可编程唤醒标志。系统可以自动将月份的天数补偿为 28、29(闰年)、30 和 31 天。只要芯片的备用电源一直供电,RTC上的时间会一直走。
新建工程
本程序在串口printf工程的基础上修改,复制串口printf的工程,修改文件夹名。点击STM32F746I.ioc打开STM32cubeMX的工程文件重新配置。RTC选择内部唤醒(Internal WakeUp)开启RTC。开启外部低速晶振,PC14,PC15配置。
RTC时钟选择为外部低速晶振(LSE),频率为32.768。
在RTC配置中,设置时间和日期,其他为默认设置。此处设置时间为2016/04/16 16:25:49。
生成报告以及代码,编译程序。
添加应用程序
在rtc.c文件中可以看到ADC初始化函数。在stm32f7xx_hal_rtc.h头文件中可以看到rtc时间和日期读写操作函数。
从操作函数中可以看到,时间和日期是以结构体的形式读写的。所以在main.c文件前面申明两个结构体变量存储读取的时间和日期数据。
/* USER CODE BEGIN PV */
/* Private variables --------*/
RTC_DateTypeDef sdatestructure;
RTC_TimeTypeDef stimestructure;
/* USER CODE END PV */
在stm32f7xx_hal_rtc.h头文件中,可以找到RTC_TimeTypeDef,RTC_DateTypeDef这两个结构体的成员变量。
在while循环中添加应用程序,读取当前的时间和日期,并通过串口发送到电脑上显示。
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 *//* Get the RTC current Time ,must get time first*/HAL_RTC_GetTime(&hrtc, &stimestructure, RTC_FORMAT_BIN);/* Get the RTC current Date */HAL_RTC_GetDate(&hrtc, &sdatestructure, RTC_FORMAT_BIN);/* Display date Format : yy/mm/dd */printf("%02d/%02d/%02d\r\n",2000 + sdatestructure.Year, sdatestructure.Month, sdatestructure.Date);/* Display time Format : hh:mm:ss */printf("%02d:%02d:%02d\r\n",stimestructure.Hours, stimestructure.Minutes, stimestructure.Seconds);printf("\r\n");HAL_Delay(1000);
}
/* USER CODE END 3 */
程序中使用HAL_RTC_GetTime(),HAL_RTC_GetDate()读取时间和日期,并保存到结构体变量中,然后通过串口输出读取的时间和日期。注意:要先读取时间再读取日期,如果先读取日期在读取时间会导致读取的时间不准确,一直都是原来设置的时间。
实验效果
编译程序并下载到开发板。打开串口调试助手。设置波特率为115200。串口助手上会显示RTC的时间日期。
.
十二、三种LED驱动电源电路
1 开关恒流源
采用变压器将高压变为低压,并进行整流滤波,以便输出稳定的低压直流电。开关恒流源又分隔离式电源和非隔离式电源,隔离是指输出高低电压隔离,安全性非常高,所以对外壳绝缘性要求不高。非隔离安全性稍差,但成本也相对低,传统节能灯就是采用非隔离电源,采用绝缘塑料外壳防护。RGB电源的安全性相对较高(一般是输出低压),性能稳定,缺点是电路复杂、价格较高。开关电源技术成熟,性能稳定,是目前LED照明的主流电源。
上图,开关恒流隔离式日光灯管电源。
上图,开关恒流隔离电源原理图。
上图,开关恒流源电源。
上图,开关恒流非隔离电源原理图。
2 线性IC电源
采用一个IC或多个IC来分配电压,电子元器件种类少,功率因数、电源效率非常高,不需要电解电容,寿命长,成本低。缺点是输出高压非隔离,有频闪,要求外壳做好防触电隔离保护。市面上宣称无(去)电解电容,超长寿命的,均是采用线性IC电源。RGB电源IC驱电源具有高可靠性,高效率低成本优势,是未来理想的LED驱动电源。
上图,线性IC电源。
上图,线性IC电源原理图。
3 阻容降压电源
采用一个电容通过其充放电来提供驱动电流,电路简单,成本低,但性能差,稳定性差,在电网电压波动时及容易烧坏LED,同时输出高压非隔离,要求绝缘防护外壳。功率因数低,寿命短,一般只适于经济型小功率产品(5W以内)。RGB电源功率高的产品,输出电流大,电容不能提供大电流,否则容易烧坏,另外国家对高功率灯具的功率因数有要求,即7W以上的功率因数要求大于0.7,但是阻容降压电源远远达不到(一般在0.2-0.3之间),所以高功率产品不宜采用阻容降压电源。市场上,要求不高的低端型的产品,几乎全部是采用阻容降压电源,另外,一些高功率的便宜的低端产品,也是采用阻容降压电源。
上图,阻容降压电源。
上图,阻容降压电源原理图。
三种电源成本性能比较
以3W小球泡和16W日光灯管为例,各种电源成本比较:
可见,不同类别的电源,其成本差异是非常大的,其中过认证的开关隔离源最贵,阻容降压电源最便宜。
各类电源性能比较:
在中高端市场,开关恒流非隔离电源仍是市场的主流电源,厂家一般会在结构设计上进行防高压隔离。而在低端市场,大部份厂家是采用阻容降压电源,也有部分厂家采用线性IC电源,这要求厂家有一定的设计能力。
采用不同的电源,产品的性能及价格是不一样的,我们应该根据不同的市场选用不同的产品。
.
十三、19个常用的5V转3.3V技巧
01 使用LDO稳压器
标准三端线性稳压器的压差通常是 2.0-3.0V。要把 5V 可靠地转换为 3.3V,就不能使用它们。压差为几百个毫伏的低压降 (Low Dropout, LDO)稳压器,是此类应用的理想选择。图 1-1 是基本LDO 系统的框图,标注了相应的电流。
从图中可以看出, LDO 由四个主要部分组成:
- 导通晶体管
- 带隙参考源
- 运算放大器
- 反馈电阻分压器
在选择 LDO 时,重要的是要知道如何区分各种LDO。器件的静态电流、封装大小和型号是重要的器件参数。根据具体应用来确定各种参数,将会得到最优的设计。
LDO的静态电流IQ是器件空载工作时器件的接地电流 IGND。IGND 是 LDO 用来进行稳压的电流。当IOUT>>IQ 时, LDO 的效率可用输出电压除以输入电压来近似地得到。然而,轻载时,必须将 IQ 计入效率计算中。具有较低 IQ 的 LDO 其轻载效率较高。轻载效率的提高对于 LDO 性能有负面影响。静态电流较高的 LDO 对于线路和负载的突然变化有更快的响应。
02 采用齐纳二极管的低成本方案
这里详细说明了一个采用齐纳二极管的低成本稳压器方案。
可以用齐纳二极管和电阻做成简单的低成本 3.3V稳压器,如图 2-1 所示。在很多应用中,该电路可以替代 LDO 稳压器并具成本效益。但是,这种稳压器对负载敏感的程度要高于 LDO 稳压器。另外,它的能效较低,因为 R1 和 D1 始终有功耗。R1 限制流入D1 和 PICmicro MCU的电流,从而使VDD 保持在允许范围内。由于流经齐纳二极管的电流变化时,二极管的反向电压也将发生改变,所以需要仔细考虑 R1 的值。
R1 的选择依据是:在最大负载时——通常是在PICmicro MCU 运行且驱动其输出为高电平时——R1上的电压降要足够低从而使PICmicro MCU有足以维持工作所需的电压。同时,在最小负载时——通常是 PICmicro MCU 复位时——VDD 不超过齐纳二极管的额定功率,也不超过 PICmicro MCU的最大 VDD。
03 采用3个整流二极管的更低成本方案
图 3-1 详细说明了一个采用 3 个整流二极管的更低成本稳压器方案。
我们也可以把几个常规开关二极管串联起来,用其正向压降来降低进入的 PICmicro MCU 的电压。这甚至比齐纳二极管稳压器的成本还要低。这种设计的电流消耗通常要比使用齐纳二极管的电路低。
所需二极管的数量根据所选用二极管的正向电压而变化。二极管 D1-D3 的电压降是流经这些二极管的电流的函数。连接 R1 是为了避免在负载最小时——通常是 PICmicro MCU 处于复位或休眠状态时——PICmicro MCU VDD 引脚上的电压超过PICmicro MCU 的最大 VDD 值。根据其他连接至VDD 的电路,可以提高R1 的阻值,甚至也可能完全不需要 R1。二极管 D1-D3 的选择依据是:在最大负载时——通常是 PICmicro MCU 运行且驱动其输出为高电平时——D1-D3 上的电压降要足够低从而能够满足 PICmicro MCU 的最低 VDD 要求。
04 使用开关稳压器
如图 4-1 所示,降压开关稳压器是一种基于电感的转换器,用来把输入电压源降低至幅值较低的输出电压。输出稳压是通过控制 MOSFET Q1 的导通(ON)时间来实现的。由于 MOSFET 要么处于低阻状态,要么处于高阻状态(分别为 ON 和OFF),因此高输入源电压能够高效率地转换成较低的输出电压。
当 Q1 在这两种状态期间时,通过平衡电感的电压- 时间,可以建立输入和输出电压之间的关系。
在选择输出电容值时,好的初值是:使 LC 滤波器特性阻抗等于负载电阻。这样在满载工作期间如果突然卸掉负载,电压过冲能处于可接受范围之内。
在连接两个工作电压不同的器件时,必须要知道其各自的输出、输入阈值。知道阈值之后,可根据应用的其他需求选择器件的连接方法。表 4-1 是本文档所使用的输出、输入阈值。在设计连接时,请务必参考制造商的数据手册以获得实际的阈值电平。
05 3.3V→5V直接连接
将 3.3V 输出连接到 5V 输入最简单的方法是直接连接,但直接连接需要满足以下 2 点要求:
- 3.3V输出的 VOH 大于 5V 输入的 VIH
- 3.3V输出的 VOL 小于 5V 输入的 VIL
能够使用这种方法的例子之一是将 3.3V LVCMOS输出连接到 5V TTL 输入。从表 4-1 中所给出的值可以清楚地看到上述要求均满足。
- 3.3V LVCMOS 的 VOH (3.0V)大于5V TTL 的VIH (2.0V)
- 3.3V LVCMOS 的 VOL (0.5V)小于 5V TTL 的VIL (0.8V)
如果这两个要求得不到满足,连接两个部分时就需要额外的电路。可能的解决方案请参阅技巧 6、7、 8 和 13。
06 使用MOSFET转换器
如果 5V 输入的 VIH 比 3.3V CMOS 器件的 VOH 要高,则驱动任何这样的 5V 输入就需要额外的电路。图 6-1 所示为低成本的双元件解决方案。
在选择 R1 的阻值时,需要考虑两个参数,即:输入的开关速度和 R1 上的电流消耗。当把输入从 0切换到 1 时,需要计入因 R1 形成的 RC 时间常数而导致的输入上升时间、 5V 输入的输入容抗以及电路板上任何的杂散电容。输入开关速度可通过下式计算:
07 使用二极管补偿
表 7-1 列出了 5V CMOS 的输入电压阈值、 3.3VLVTTL 和 LVCMOS 的输出驱动电压。
从上表看出, 5V CMOS 输入的高、低输入电压阈值均比 3.3V 输出的阈值高约一伏。因此,即使来自 3.3V 系统的输出能够被补偿,留给噪声或元件容差的余地也很小或者没有。我们需要的是能够补偿输出并加大高低输出电压差的电路。
输出电压规范确定后,就已经假定:高输出驱动的是输出和地之间的负载,而低输出驱动的是 3.3V和输出之间的负载。如果高电压阈值的负载实际上是在输出和 3.3V 之间的话,那么输出电压实际上要高得多,因为拉高输出的机制是负载电阻,而不是输出三极管。
如果我们设计一个二极管补偿电路 (见图 7-1),二极管 D1 的正向电压 (典型值 0.7V)将会使输出低电压上升,在 5V CMOS 输入得到 1.1V 至1.2V 的低电压。它安全地处于 5V CMOS 输入的低输入电压阈值之下。输出高电压由上拉电阻和连至3.3V 电源的二极管 D2 确定。这使得输出高电压大约比 3.3V 电源高 0.7V,也就是 4.0 到 4.1V,很安全地在 5V CMOS 输入阈值 (3.5V)之上。
注:为了使电路工作正常,上拉电阻必须显著小于 5V CMOS 输入的输入电阻,从而避免由于输入端电阻分压器效应而导致的输出电压下降。上拉电阻还必须足够大,从而确保加载在 3.3V 输出上的电流在器件规范之内。
08 使用电压比较器
比较器的基本工作如下:
- 反相 (-)输入电压大于同相 (+)输入电压时,比较器输出切换到 Vss。
- 同相 (+)输入端电压大于反相 (-)输入电压时,比较器输出为高电平。
为了保持 3.3V 输出的极性, 3.3V 输出必须连接到比较器的同相输入端。比较器的反相输入连接到由 R1 和 R2 确定的参考电压处,如图 8-1 所示。
若 R2 取值为 1K,则 R1 为 1.8K。
经过适当连接后的运算放大器可以用作比较器,以将 3.3V 输入信号转换为 5V 输出信号。这是利用了比较器的特性,即:根据 “反相”输入与 “同相”输入之间的压差幅值,比较器迫使输出为高(VDD)或低 (Vss)电平。
注:要使运算放大器在 5V 供电下正常工作,输出必须具有轨到轨驱动能力。
09 直接连接
通常 5V 输出的 VOH 为 4.7 伏, VOL 为 0.4 伏;而通常 3.3V LVCMOS 输入的 VIH 为 0.7 x VDD, VIL为 0.2 x VDD。
当 5V 输出驱动为低时,不会有问题,因为 0.4 伏的输出小于 0.8 伏的输入阈值。当 5V 输出为高时, 4.7 伏的 VOH 大于 2.1 伏 VIH,所以,我们可以直接把两个引脚相连,不会有冲突,前提是3.3V CMOS 输出能够耐受 5 伏电压。
如果 3.3V CMOS 输入不能耐受 5 伏电压,则将出现问题,因为超出了输入的最大电压规范。
10 使用二极管钳位
很多厂商都使用钳位二极管来保护器件的 I/O 引脚,防止引脚上的电压超过最大允许电压规范。钳位二极管使引脚上的电压不会低于 Vss 超过一个二极管压降,也不会高于 VDD 超过一个二极管压降。要使用钳位二极管来保护输入,仍然要关注流经钳位二极管的电流。流经钳位二极管的电流应该始终比较小 (在微安数量级上)。
如果流经钳位二极管的电流过大,就存在部件闭锁的危险。由于5V 输出的源电阻通常在 10Ω 左右,因此仍需串联一个电阻,限制流经钳位二极管的电流,如图 10-1所示。使用串联电阻的后果是降低了输入开关的速度,因为引脚 (CL)上构成了 RC 时间常数。
如果没有钳位二极管,可以在电流中添加一个外部二极管,如图 10-2 所示。
11 5V→3.3V有源钳位
使用二极管钳位有一个问题,即它将向 3.3V 电源注入电流。在具有高电流 5V 输出且轻载 3.3V 电源轨的设计中,这种电流注入可能会使 3.3V 电源电压超过 3.3V。
为了避免这个问题,可以用一个三极管来替代,三极管使过量的输出驱动电流流向地,而不是 3.3V 电源。设计的电路如图 11-1 所示。
Q1的基极-发射极结所起的作用与二极管钳位电路中的二极管相同。区别在于,发射极电流只有百分之几流出基极进入 3.3V 轨,绝大部分电流都流向集电极,再从集电极无害地流入地。基极电流与集电极电流之比,由晶体管的电流增益决定,通常为10-400,取决于所使用的晶体管。
12 电阻分压器
可以使用简单的电阻分压器将 5V 器件的输出降低到适用于 3.3V 器件输入的电平。这种接口的等效电路如图 12-1 所示。
通常,源电阻 RS 非常小 (小于 10Ω),如果选择的 R1 远大于RS 的话,那么可以忽略 RS 对 R1 的影响。在接收端,负载电阻 RL 非常大 (大于500 kΩ),如果选择的R2远小于RL的话,那么可以忽略 RL 对 R2 的影响。
在功耗和瞬态时间之间存在取舍权衡。为了使接口电流的功耗需求最小,串联电阻 R1 和 R2 应尽可能大。但是,负载电容 (由杂散电容 CS 和 3.3V 器件的输入电容 CL 合成)可能会对输入信号的上升和下降时间产生不利影响。如果 R1 和 R2 过大,上升和下降时间可能会过长而无法接受。
如果忽略 RS 和 RL 的影响,则确定 R1 和 R2 的式子由下面的公式 12-1 给出。
公式 12-2 给出了确定上升和下降时间的公式。为便于电路分析,使用戴维宁等效计算来确定外加电压 VA 和串联电阻R。戴维宁等效计算定义为开路电压除以短路电流。根据公式 12-2 所施加的限制,对于图 12-1 所示电路,确定的戴维宁等效电阻 R 应为 0.66*R1,戴维宁等效电压 VA 应为0.66*VS。
例如,假设有下列条件存在:
- 杂散电容 = 30 pF
- 负载电容 = 5 pF
- 从 0.3V 至 3V 的最大上升时间 ≤ 1 μs
- 外加源电压 Vs = 5V
确定最大电阻的计算如公式 12-3 所示。
13 电平转换器
尽管电平转换可以分立地进行,但通常使用集成解决方案较受欢迎。电平转换器的使用范围比较广泛:有单向和双向配置、不同的电压转换和不同的速度,供用户选择最佳的解决方案。
器件之间的板级通讯 (例如, MCU 至外设)通过 SPI 或 I2C™ 来进行,这是最常见的。对于SPI,使用单向电平转换器比较合适;对于 I2C,就需要使用双向解决方案。下面的图 13-1 显示了这两种解决方案。
3.3V 至 5V 接口的最后一项挑战是如何转换模拟信号,使之跨越电源障碍。低电平信号可能不需要外部电路,但在 3.3V 与 5V 之间传送信号的系统则会受到电源变化的影响。例如,在 3.3V 系统中,ADC转换1V峰值的模拟信号,其分辨率要比5V系统中 ADC 转换的高,这是因为在 3.3V ADC 中,ADC 量程中更多的部分用于转换。但另一方面,3.3V 系统中相对较高的信号幅值,与系统较低的共模电压限制可能会发生冲突。
因此,为了补偿上述差异,可能需要某种接口电路。本节将讨论接口电路,以帮助缓和信号在不同电源之间转换的问题。
14 模拟增益模块
从 3.3V 电源连接至 5V 时,需要提升模拟电压。33 kΩ 和 17kΩ 电阻设定了运放的增益,从而在两端均使用满量程。11 kΩ 电阻限制了流回 3.3V 电路的电流。
15 模拟补偿模块
该模块用于补偿 3.3V 转换到 5V 的模拟电压。下面是将 3.3V 电源供电的模拟电压转换为由 5V电源供电。右上方的 147 kΩ、 30.1 kΩ 电阻以及+5V 电源,等效于串联了 25 kΩ 电阻的 0.85V 电压源。
这个等效的 25 kΩ 电阻、三个 25 kΩ 电阻以及运放构成了增益为 1 V/V 的差动放大器。0.85V等效电压源将出现在输入端的任何信号向上平移相同的幅度;以 3.3V/2 = 1.65V 为中心的信号将同时以 5.0V/2 = 2.50V 为中心。左上方的电阻限制了来自 5V 电路的电流。
16 有源模拟衰减器
此技巧使用运算放大器衰减从 5V 至 3.3V 系统的信号幅值。
要将 5V 模拟信号转换为 3.3V 模拟信号,最简单的方法是使用 R1:R2 比值为 1.7:3.3 的电阻分压器。
然而,这种方法存在一些问题:
- 1)衰减器可能会接至容性负载,构成不期望得到的低通滤波器。
- 2)衰减器电路可能需要从高阻抗源驱动低阻抗负载。
无论是哪种情形,都需要运算放大器用以缓冲信号。所需的运放电路是单位增益跟随器 (见图 16-1)。
电路输出电压与加在输入的电压相同。
为了把 5V 信号转换为较低的 3V 信号,我们只要加上电阻衰减器即可。
如果电阻分压器位于单位增益跟随器之前,那么将为 3.3V 电路提供最低的阻抗。此外,运放可以从3.3V 供电,这将节省一些功耗。如果选择的 X 非常大的话, 5V 侧的功耗可以最大限度地减小。
如果衰减器位于单位增益跟随器之后,那么对 5V源而言就有最高的阻抗。运放必须从 5V 供电,3V 侧的阻抗将取决于 R1||R2 的值。
17 模拟限幅器
在将 5V 信号传送给 3.3V 系统时,有时可以将衰减用作增益。如果期望的信号小于 5V,那么把信号直接送入 3.3V ADC 将产生较大的转换值。当信号接近 5V 时就会出现危险。所以,需要控制电压越限的方法,同时不影响正常范围中的电压。
这里将讨论三种实现方法:
- 使用二极管,钳位过电压至 3.3V 供电系统。
- 使用齐纳二极管,把电压钳位至任何期望的电压限。
- 使用带二极管的运算放大器,进行精确钳位。
进行过电压钳位的最简单的方法,与将 5V 数字信号连接至 3.3V 数字信号的简单方法完全相同。使用电阻和二极管,使过量电流流入 3.3V 电源。选用的电阻值必须能够保护二极管和 3.3V 电源,同时还不会对模拟性能造成负面影响。如果 3.3V 电源的阻抗太低,那么这种类型的钳位可能致使3.3V 电源电压上升。即使 3.3V 电源有很好的低阻抗,当二极管导通时,以及在频率足够高的情况下,当二极管没有导通时 (由于有跨越二极管的寄生电容),此类钳位都将使输入信号向 3.3V 电源施加噪声。
为了防止输入信号对电源造成影响,或者为了使输入应对较大的瞬态电流时更为从容,对前述方法稍加变化,改用齐纳二极管。齐纳二极管的速度通常要比第一个电路中所使用的快速信号二极管慢。不过,齐纳钳位一般来说更为结实,钳位时不依赖于电源的特性参数。钳位的大小取决于流经二极管的电流。这由 R1 的值决定。如果 VIN 源的输出阻抗足够大的话,也可不需要 R1。
如果需要不依赖于电源的更为精确的过电压钳位,可以使用运放来得到精密二极管。电路如图 17-3所示。运放补偿了二极管的正向压降,使得电压正好被钳位在运放的同相输入端电源电压上。如果运放是轨到轨的话,可以用 3.3V 供电。
由于钳位是通过运放来进行的,不会影响到电源。
运放不能改善低电压电路中出现的阻抗,阻抗仍为R1 加上源电路阻抗。
18 驱动双极型晶体管
在驱动双极型晶体管时,基极 “驱动”电流和正向电流增益 (Β/hFE)将决定晶体管将吸纳多少电流。如果晶体管被单片机 I/O 端口驱动,使用端口电压和端口电流上限 (典型值 20 mA)来计算基极驱动电流。如果使用的是 3.3V 技术,应改用阻值较小的基极电流限流电阻,以确保有足够的基极驱动电流使晶体管饱和。
RBASE的值取决于单片机电源电压。公式18-1 说明了如何计算 RBASE。
如果将双极型晶体管用作开关,开启或关闭由单片机 I/O 端口引脚控制的负载,应使用最小的 hFE规范和裕度,以确保器件完全饱和。
对于这两个示例,提高基极电流留出裕度是不错的做法。将 1mA 的基极电流驱动至 2 mA 能确保饱和,但代价是提高了输入功耗。
19 驱动N沟道MOSFET晶体管
在选择与 3.3V 单片机配合使用的外部 N 沟道MOSFET 时,一定要小心。MOSFET 栅极阈值电压表明了器件完全饱和的能力。
对于 3.3V 应用,所选 MOSFET 的额定导通电阻应针对 3V 或更小的栅极驱动电压。例如,对于具有 3.3V 驱动的100 mA负载,额定漏极电流为250 μA的FET在栅极 - 源极施加 1V 电压时,不一定能提供满意的结果。在从 5V 转换到 3V 技术时,应仔细检查栅极- 源极阈值和导通电阻特性参数,如图 19-1所示。稍微减少栅极驱动电压,可以显著减小漏电流。
对于 MOSFET,低阈值器件较为常见,其漏-源电压额定值低于 30V。漏-源额定电压大于 30V的 MOSFET,通常具有更高的阈值电压 (VT)。
如表 19-1 所示,此 30V N 沟道 MOSFET 开关的阈值电压是 0.6V。栅极施加 2.8V 的电压时,此MOSFET 的额定电阻是 35 mΩ,因此,它非常适用于 3.3V 应用。
对于 IRF7201 数据手册中的规范,栅极阈值电压最小值规定为 1.0V。这并不意味着器件可以用来在1.0V 栅 - 源电压时开关电流,因为对于低于 4.5V 的VGS (th),没有说明规范。对于需要低开关电阻的 3.3V 驱动的应用,不建议使用 IRF7201,但它可以用于 5V 驱动应用。
.
十四、总结3.7V升压5V电路
3.7V输出5V1A
同步整流升压PS7516。
特点:效率极高普遍90%及以上,外围器件少,可过EMI。
3.3V~4.2V升压输出5V1A
异步升压芯片PL2628。
特点:效率普遍80%左右,需要整流肖特基二极管。
3V、3.3V、3.7V升压输出5V2.4A
PS7526超高效率的同步整流升压方案,现实应用足2.4A 。
2.4V~4.5V升压输出5V3A
FP6277超高效率的同步整流升压方案,现实应用足3A 。
0.8V升压输出3.0V、3.3V、3.6V、4.0V、5V
低纹波,低噪声只需四个外围元件,0.8V低压启动,升压固定输出3.0V、3.3V、3.6V、4.0V、5V。
低起动电压:0.8V(1mA)
输出精度:优于±2.5%
最高效率:89%
输出电流:大于300mA(Vin=2.5V,Vout=3.3V)
2.7V~4.5V升压输出4.94V
无电感升压5V200MA,外围只需3个10uf的贴片电容即可。
最简单的升压电路了,抗干扰强,可用于收音机类产品。
2.7V~4.5V升压输出4.94V
无电感升压5V200MA,外围只需3个10uf的贴片电容即可。
最简单的升压电路了,抗干扰强,可用于收音机类产品。
十五、STM32之SD卡
一、SD卡概述
1、定义
SD卡(安全数码卡),是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(外语缩写PDA)和多媒体播放器等。
2、容量等级
3、SD卡框图
引脚说明:
4、SD卡与TF卡的区别
TF卡又名micro SD卡,个头是比SD卡的1/4还小,可以通过“TF转SD卡套”转换成SD卡。
二、 SD卡内部结构
(摘自SanDisk Secure Digital Card Product Manual Version 1.9)
1、 SD卡内部结构简图
由SD卡控制器和存储阵列组成,SD卡与外界的通讯接口是SD Bus或者SPI Bus。
2、 存储阵列结构图
Block:
读写时的单元(数据传输单元),它的单位是“字节”。
Sector:
如果CSD寄存器ERASE_BLK_EN = 0时,Sector是最小的擦除单元,它的单位是“块”。Sector的值等于CSD寄存器中的SECTOR_SIZE的值+1。
WP Group:
最小的写保护单元,它的单位是“扇区”。
3、Buffer
SD Card的Buffer最大容量定义在CSD寄存器的READ_BL_LEN和WRITE_BL_LEN。它们的值是一样的,而且有可能超过512字节,尽管这样Block还是要设置成512字节,因为512字节是数据边界(这句话不是太理解)。也就是SD卡上有数据传输缓冲器Buffer,不同的产品可能不一样,但是在使用时要将Buffer设置成512字节。
4、“存储阵列Block”--最小的存储单元
资料上的Block通通指的是数据传输时的最小单元,定义这个数值是为了数据传输、CRC校验等。
存储阵列通常采用NandFlash的结构,显然不能按字节存取,而这里讨论的“存储阵列Block”就是指这个概念。可惜的是目前,我还没有找到资料讨论这个问题,所以这一章节是笔者自己的推测。
据我推测存储阵列Block应该是512Byes,因为众多的数据都围绕着512Bytes在转。比如说最小的擦除单元是512Byes,最小的读写单位应该被设置成512Bytes,那么有理由推测是这个数值。
5、SD卡特殊功能寄存器
- CID: 宽度128位,卡标识号
- RCA: 宽度16位,卡相对地址,在初始化的时候确定
- CSD: 宽度128位,卡描述数据:卡操作条件的信息
- SCR: 宽度64位,SD卡配置寄存器:SD卡特定信息数据
- OCR: 宽度32位,操作条件寄存
三、SDIO接口
四、SD卡协议之数据读、写、擦除
1、SD卡写数据块
执行写数据块命令(CMD24-27) 时,主机把一个或多个数据块从主机传送到卡中,同时在每个数据块的末尾传送一个CRC码。主机传送数据,SD卡接收数据并将数据保存在Buffer中,累计接收数据达到Block长度的时候,SD卡把接下来的数据当做CRC校验码,并且开始数据校验。如果CRC校验错误,卡通过SDIO_D 线指示错误,传送的数据被丢弃而不被写入,所有后续(在多块写模式下)传送的数据块将被忽略。
如果主机传送部分数据而累计的数据长度未与数据块对齐,当不允许块错位( 未设置CSD的参数WRITE_BLK_MISALIGN),卡将在第一个错位的块之前检测到块错位错误( 设置状态寄存器中的ADDRESS_ERROR 错误位) 。当主机试图写一个写保护区域时,写操作也会被中止,此时卡会设置WP_VIOLATION位。
数据块Block的最大长度定义在CSD中的WRITE_BL_LEN,但是在数据传输时应该用CMD16指令将其设置为512Byets,不去在意WRITE_BL_LEN是1024或者2048Bytes。
另外需要注意的是,Block的长度设置还要参考CSD寄存器的WRITE_BL_PARTIAL。当WRITE_BL_PARTIAL为0时,那么么办法Block只能设置为512Bytes;如果WRITE_BL_PARTIAL=1,那么允许将Block设置成更小的块,比如说一个字节。协议是这样规定的,但是据我分析如果这样的话SD卡的制作会非常复杂(写入的单位可以是字节),价格也会很高。笔者测试了自己的SD卡,WRITE_BL_PARTIAL 等于0,也就是不支持“块部分写”功能。
2、SD卡读数据块
在读数据块模式下,数据传输的基本单元是数据块Block。为保证数据传输的正确,传输一个数据块Blcok后都有一个CRC校验码。笔者认为主机在累计接收到Block长度数据后,软件可以把接下来的数据当做CRC校验码,并且进行校验。
Block的最大值在CSD中(READ_BL_LEN) 给出了定义,但是在数据传输时应该用CMD16指令将其设置为512Byets,不去在意READ_BL_LEN是1024或者2048Bytes。
如果CSD寄存器中的READ_BL_PARTIAL等于1,可以传送的较小数据块,较小数据块是指开始和结束地址完全包含在一个物理块中。事实上,协议规定READ_BL_PARTIAL永远等于1,也就说在任何SD卡上都允许“读部分块”,读的块的最小字节是1Bytes。使用这种功能,可以通过CMD16命令设置更小的Block(比如说等于128)。读取的这128字节必须在512Bytes边界内,不能跨越边界(其实因为存储阵列是以512Bytes为单位的,读取“部分块”只能在一个块内,不允许跨块读)。
3、擦除SD卡
CSD寄存器ERASE_BLK_EN决定了SD卡的最小擦除单位。
当ERASE_BLK_EN等于0的时候,主机擦除的最小单位是扇区。比如一个Sector包含32个Block,擦除时的起始地址是5,而结束地址是40,那么实际擦除的块是从0到63。
当ERASE_BLK_EN等于1的时候,主机擦除的最小单位是512 Byetes。比如擦除时的起始地址是5,而结束地址是40,那么实际擦除的块就是从5到40。
五、SD卡物理层协议
SD卡的协议相对于SPI、I2C等协议的存储器来说相对复杂,包含SD卡物理层(机械封装、管脚、芯片结构、命令集等)、SD卡接口(SDIO)、SD主机控制器,甚至是软件设计的流程,都进行了详细的规定。
1、接口
① SDIO接口
参考《Simplified_SDIO_Card_Spec.pdf》
<1> CLK 时钟同步线
<2> CMD 命令信号线,主机发出的命令以及从机对命令的响应都是通过这条线进行传输
<3> DAT[3:0] 表示4条数据线,主机和从机的数据都是从这四条数据线上传输
② SPI接口
2、命令格式
3、响应格式
以R1为例
4、SD卡的工作状态
5、SD卡的两种状态信息
① Card Status
执行命令过程中的状态信息,比如地址不对齐错误、块长度错误、卡锁、ECC校验错误等等
blog.csdn.net/g_salamander
② SD Status
SD卡的专有特征,编程中不经常涉及。这个状态值有512位,不是通过命令线传送给主机,而是通过数据线。
六、STM32与SD卡相配的外设--SDIO适配器
1、SDIO adapter 结构图
2、命令状态机(CPSM)
当发送命令和接收响应时,启动CPSM状态机。
3、数据通道状态机
当传输数据时,启动数据通道状态机。
4、FIFO
数据FIFO(先进先出)子单元是一个具有发送和接收单元的数据缓冲区。
FIFO包含一个每字32位宽、共32个字的数据缓冲区,和发送与接收电路。因为数据FIFO工作在AHB 时钟区域(HCLK/2),所有与SDIO时钟区域(SDIOCLK)连接的信号都进行了重新同步。依据TXACT和RXACT标志,可以关闭FIFO、使能发送或使能接收。TXACT和RXACT 由数据通道子单元设置而且是互斥的:
─ 当 TXACT 有效时,发送 FIFO 代表发送电路和数据缓冲区
─ 当 RXACT 有效时,接收 FIFO 代表接收电路和数据缓冲区
5、SDIO的特殊功能寄存器
- SDIO电源控制寄存器(SDIO_POWER)
- SDIO时钟控制寄存器(SDIO_CLKCR) : 时钟选择、分频
- SDIO参数寄存器(SDIO_ARG)
- SDIO命令寄存器(SDIO_CMD):控制发送命令
- SDIO命令响应寄存器(SDIO_RESPCMD):包含响应命令中的命令索引
- SDIO响应1..4寄存器(SDIO_RESPx):包含响应命令中的卡状态信息
- SDIO数据定时器寄存器(SDIO_DTIMER)
- SDIO数据长度寄存器(SDIO_DLEN):读或者写的长度,通常是是512的倍数
- SDIO数据控制寄存器(SDIO_DCTRL):控制数据的读写方向、使能传输等信息
- SDIO数据计数器寄存器(SDIO_DCOUNT):当DPSM状态机从Idle state切换到Wait_R或者Wait_S状态时,SDIO_LEN的数值加载到该寄存器中
- SDIO状态寄存器(SDIO_STA)
- SDIO清除中断寄存器(SDIO_ICR)
- SDIO中断屏蔽寄存器(SDIO_MASK)
- SDIO FIFO计数器寄存器(SDIO_FIFOCNT):当SDIO_DCTRL中的DTEN使能,并且DPSM处于Idle state时,SDIO_LEN/4的数值加载到该寄存器中
- SDIO数据FIFO寄存器(SDIO_FIFO):读写数据缓冲FIFO
七、SD卡编程
SD卡的编程在STM32官方固件库中就有例程,而且野火开发板对该例程进行了中文注释,不必再把源码贴入。这里着重讲一下SD卡编程流程,主要包含SD卡初始化、SD卡读、SD卡写、SD卡擦除。
1、SD卡编程的内容
SD卡主要就是用来存储数据的,所以核心就是读写。为了实现这个目标,必须实现响应的驱动。
配置过程中,不仅要设置好SD控制器,还需要将SD卡设置到合适的状态。在读取状态的时候,不仅涉及到SD控制器的状态,还涉及到SD卡的状态。
2、SD卡初始化
① STM32外设SDIO初始化
- 端口配置、端口时钟、SDIO时钟、DMA2时钟使能
- SDIO寄存器复位
- 设置时钟SDIO_CK为400KHz以下,设置数据线宽度,开启时钟、开启SDIO电源
② SD卡上电初始化
上电初始化流程如上图所示,笔者认为官方库提供的例程没有完全按照这个流程图的指示去做。事实上,官方库的程序只做了如上图红色方框内的流程,之外的没涉及。
CMD0命令复位所有的卡。
SD协议规定:在初始化的时候,使用ACMD41之前,必须先使用CMD8命令。而且ACMD41命令属于应用命令,在使用之前需要先发送命令CMD55。
CMD8命令是为了核查电源是否匹配。ACMD41命令不断询问SD卡是否支持主机提供的电压,并且询问SD卡是否上电完成进入准备状态。ACMD41命令还能询问SD卡的类型(SDSC、SDHC)。
③卡进一步核查、获取卡信息
发送命令CMD2,以获取CID信息。
发送命令CMD3,以获取RCA相对地址,可以通过多次发送CMD3获取不同的RCA值,但是只有最后一次的才是有效的RCA地址。
发送命令CMD9,以获取CSD寄存器。
④ 设置SDIO工作在数据传输模式
设置SDIO的时钟为24MHz、数据线宽度为4位。
通过SD_GetCardInfo函数将之前得到CID、CSD处理成卡的信息。
通过CMD7命令选择匹配地址的卡,而取消选择其他的卡。
至此,初始化完成。
3、读SD卡的一个块
- 数据控制寄存器(SDIO_DCTRL)清零
- 发送命令CMD16,设置SD卡的Block大小
- 调用函数SDIO_DataConfig设置SDIO数据传输方式
- 发送命令CMD17,读单个块
- SDIO数据传输结束中断使能
- SDIO的DMA传输功能使能
- DMA设置,并使能
4、写SD卡的一个块
- 数据控制寄存器(SDIO_DCTRL)清零
- 发送命令CMD16,设置SD卡的Block大小
- 发送命令CMD24,写单个块
- 调用函数SDIO_DataConfig设置SDIO数据传输方式
- SDIO数据传输结束中断使能
- DMA设置,并使能
- 使能SDIO的DMA传输功能
八、SD卡疑惑
1、SD卡擦除后,其中的内容是0,还是1 ?
The data at the card after an erase operation is either '0' or '1', depends on the card vendor.The SCR register bit DATA_STAT_AFTER_ERASE (bit 55) defines whether it is '0' or '1'.(摘自《SD Specifications_Part_1_Physical_Layer_Specification_Ver3.00_Final_090416.pdf》)
也就是说这是芯片厂商生产工艺决定的,可以通过SCR寄存器的 DATA_STAT_AFTER_ERASE位得知。
2、在SDIO_DCTRL中设置传输Block的要求
Block大小决定了主机在发送数据时,发送到什么程度时开始发送CRC校验码;而在接收数据时,在接收到什么程度时开始把SD卡的数据作为CRC校验码并进行校验。Block还可能影响着其他的时序。在STM32的SDIO寄存器组中,SDIO_DCTRL中的位段DBLOCKSIZE决定主机Block大小。
在摘自《Simplified_SD_Host_Controller_Spec.pdf》的引文中,提到这样的配置要求:主机的Block一定要与SD卡设置的Block一样大小,这显然是必要的。我们经常设置SD卡的Block大小是512Bytes,所以设置DBLOCKSIZE为9(2^9 = 512)。
3、STM32固件库“stm32_eval_sdio_sd.c version v4.5.0”偶遇BUG
参考网页:http://www.cprogramdevelop.com/3742318/
4、SD卡写Block是怎样进行的?
写SD卡的单位是Block(512Bytes),再写之前要先整块擦除,然后才能写。
在多块写操作中,可以在发送多块写命令CMD25之前,有选择性的先发送命令ACMD23设置预擦除。怎样理解呢?
既然是有选择性的,也可以不发送ACMD23命令。在多块写的过程中,由于SD卡事先不知道你要写入几个块(CMD25命令只告诉SD卡要写入的起始地址),所以写入的过程是:根据需要判断要写一个块时,先擦除然后再写,再判断是否要写入下一个块,如果是就再擦除再写。
倘若发送ACMD23命令就不一样了,ADM23命令会在写命令CMD25生效之前,告诉SD卡准备写入的块数N。这样当CMD25命令生效的时候,SD卡会一次性先将这N个块都擦除,然后再一个块一个块写。由于擦除操作比较集中,所以整个多块写操作更节省时间。
九、SD卡参数测试
使用野火开发板配套例程做测试,笔者测试用的SD卡是金士顿的2G内存块,打印SD卡的参数信息如下:
Card Type is :1
ManufacturerID is :2
Card device size is :3795
Card Block Size is :1024
Card device size multiplier is :7
Card Capacity is :1990197248
the maximum read date block length is :1024
partial blocks for write allowed is :0
the maximum write date block length is :1024
erase single block enable is :1
erase sector size is :127
write protect group size is :0
RCA is :4660
Card Type:1 SDSC卡版本2.0
Card device size: C_SIZE(CSD),为3795
Card Block Size: max read data block length(READ_BL_LEN(CSD)) ,为1024 Bytes
Card device size multiplier is: C_SIZE_MULT(CSD),为7
Card Capacity: 1990197248 Bytes
计算方法(摘自《Simplified_Physical_Layer_Spec.pdf》):
memory capacity = BLOCKNR * BLOCK_LEN
BLOCKNR = (C_SIZE+1) * MULT (C_SIZE <= 4096)
MULT = 2^(C_SIZE_MULT+2) (C_SIZE_MULT < 8)
BLOCK_LEN = 2^READ_BL_LEN, (READ_BL_LEN < 12)注意:SDSC最大为2GB。
the maximum read date block length:READ_BL_LEN(CSD) ,为1024 Bytes
partial blocks for write allowed:WRITE_BL_PARTIAL(CSD),为不支持
the maximum write date block length:WRITE_BL_LEN(CSD) ,为1024 Bytes
erase single block enable:ERASE_BLK_EN(CSD),为1,支持单块擦除
erase sector size:SECTOR_SIZE(CSD),实际扇区擦除的block数为(SECTOR_SIZE+1),为128 Blocks
write protect group size:WP_GRP_SIZE(CSD),实际保护的扇区数为(WP_GRP_SIZE+1),为1 Sector
RCA: SD卡相对地址为4660
.
十六、示波器接地良好,反而容易炸机?
用错电源线导致炸机
这天隔壁桌同事王工正在用示波器测试板子,板子上电之后,示波器的探头炸了!
原来他正在用示波器探头测量市电整流后的310V电压,电源线是3芯带接地的电源线,而实验室的插座都是已经良好接地的。
示波器本来用的是2芯(去掉接地插片)的电源线。
普通国标插头的最上面一个插片是接地线,是接大地的,而市电的零线实际上在发电厂端也是接大地的。可以认为3芯插头最上面的接地插片是和零线等同的,实际可能会根据不同负荷有3-10几伏的电压差。
原理分析
下图简单画了个同事用示波器测量板子的示意图。
那么示波器按图中接入待测电路的后,发生了什么呢?
因为3芯电源线最上面的插片是接零线的,当探头接入待测电路后,交流电的正半周时,电流流向如下图:
上图,交流电正半周时,电流流向无异常,市电通过示波器的接地探头回流到零线,接下来再看看,交流电的负半周时电流流向,如下图:
因为3芯电源线最上面的插片是同零线等电位的,可以据此画出上图的交流电负半周的电流流向,可以看出,市电火零线被短路了,火零线之间只有一个二极管的阻抗。再加上王工的这块板子上的保险管被焊锡丝给短接了,所以出现了上面说的炸机现象。
如何避免
为了避免这个问题,我们可以用隔离变压器供电,或者将电源线的接地线给拔掉,但这样做可能会有以下问题,示波器的金属部分一般都是和3芯线接地线相连的,当你把3芯线的接地插片给断开后,如下图:
因为接地的断开,两个Y电容的中点会带有110V的电压,因此当人触摸到示波器的金属部分会有瞬间被放电的感觉。
最好的方法是使用高压差分探头,前提是不差钱。而且上电测量前,如果不了解电路的话,最好用万用表测量下待测电路的地和示波器探头的地之间有没有电压差,如果测量结果不为零,则不能用示波器的地线直接夹在待测电路板上的地。
而且如果这样做的话,触摸到示波器的金属部分会有触电风险,因为示波器的地线夹和示波器的金属部分是相连的,一旦地线夹夹在待测电路板上的热地,示波器的金属部分同样会带电。
总结
交流电源的零线是在变电所接地的,示波器探头的GND是通过大地连接到远端变电所的零线。此时被测设备如果没有用隔离变压器隔离,那么电流会通过示波器探头GND流向大地,造成板子或者示波器的损坏。
最简单的方法大概就是2芯电源线,这样就不会烧板子或者示波器了。