一、19个常用的5V转3.3V技巧

01 使用LDO稳压器

    标准三端线性稳压器的压差通常是 2.0-3.0V。要把 5V 可靠地转换为 3.3V,就不能使用它们。压差为几百个毫伏的低压降 (Low Dropout, LDO)稳压器,是此类应用的理想选择。图 1-1 是基本LDO 系统的框图,标注了相应的电流。

    从图中可以看出, LDO 由四个主要部分组成:

  • 导通晶体管
  • 带隙参考源
  • 运算放大器
  • 反馈电阻分压器

    在选择 LDO 时,重要的是要知道如何区分各种LDO。器件的静态电流、封装大小和型号是重要的器件参数。根据具体应用来确定各种参数,将会得到最优的设计。

嵌入式分享合集124_比较器

LDO的静态电流IQ是器件空载工作时器件的接地电流 IGND。IGND 是 LDO 用来进行稳压的电流。当IOUT>>IQ 时, LDO 的效率可用输出电压除以输入电压来近似地得到。然而,轻载时,必须将 IQ 计入效率计算中。具有较低 IQ 的 LDO 其轻载效率较高。轻载效率的提高对于 LDO 性能有负面影响。静态电流较高的 LDO 对于线路和负载的突然变化有更快的响应。

02 采用齐纳二极管的低成本方案

    这里详细说明了一个采用齐纳二极管的低成本稳压器方案。

嵌入式分享合集124_比较器_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 个整流二极管的更低成本稳压器方案。

嵌入式分享合集124_运放_03

我们也可以把几个常规开关二极管串联起来,用其正向压降来降低进入的 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 在这两种状态期间时,通过平衡电感的电压- 时间,可以建立输入和输出电压之间的关系。

嵌入式分享合集124_运放_04

    在选择输出电容值时,好的初值是:使 LC 滤波器特性阻抗等于负载电阻。这样在满载工作期间如果突然卸掉负载,电压过冲能处于可接受范围之内。 

嵌入式分享合集124_嵌入式硬件_05

   在连接两个工作电压不同的器件时,必须要知道其各自的输出、输入阈值。知道阈值之后,可根据应用的其他需求选择器件的连接方法。表 4-1 是本文档所使用的输出、输入阈值。在设计连接时,请务必参考制造商的数据手册以获得实际的阈值电平。 

嵌入式分享合集124_引脚_06

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 输入的输入容抗以及电路板上任何的杂散电容。输入开关速度可通过下式计算:

 

嵌入式分享合集124_嵌入式硬件_07

07 使用二极管补偿

    表 7-1 列出了 5V CMOS 的输入电压阈值、 3.3VLVTTL 和 LVCMOS 的输出驱动电压。

嵌入式分享合集124_比较器_08

     从上表看出, 5V CMOS 输入的高、低输入电压阈值均比 3.3V 输出的阈值高约一伏。因此,即使来自 3.3V 系统的输出能够被补偿,留给噪声或元件容差的余地也很小或者没有。我们需要的是能够补偿输出并加大高低输出电压差的电路。

嵌入式分享合集124_比较器_09

输出电压规范确定后,就已经假定:高输出驱动的是输出和地之间的负载,而低输出驱动的是 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 所示。

嵌入式分享合集124_引脚_10

嵌入式分享合集124_引脚_11

    若 R2 取值为 1K,则 R1 为 1.8K。

    经过适当连接后的运算放大器可以用作比较器,以将 3.3V 输入信号转换为 5V 输出信号。这是利用了比较器的特性,即:根据 “反相”输入与 “同相”输入之间的压差幅值,比较器迫使输出为高(VDD)或低 (Vss)电平。

    注:要使运算放大器在 5V 供电下正常工作,输出必须具有轨到轨驱动能力。

嵌入式分享合集124_引脚_12

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 伏电压。

嵌入式分享合集124_引脚_13

  如果 3.3V CMOS 输入不能耐受 5 伏电压,则将出现问题,因为超出了输入的最大电压规范。

10 使用二极管钳位

    很多厂商都使用钳位二极管来保护器件的 I/O 引脚,防止引脚上的电压超过最大允许电压规范。钳位二极管使引脚上的电压不会低于 Vss 超过一个二极管压降,也不会高于 VDD 超过一个二极管压降。要使用钳位二极管来保护输入,仍然要关注流经钳位二极管的电流。流经钳位二极管的电流应该始终比较小 (在微安数量级上)。

    如果流经钳位二极管的电流过大,就存在部件闭锁的危险。由于5V 输出的源电阻通常在 10Ω 左右,因此仍需串联一个电阻,限制流经钳位二极管的电流,如图 10-1所示。使用串联电阻的后果是降低了输入开关的速度,因为引脚 (CL)上构成了 RC 时间常数。

嵌入式分享合集124_引脚_14

 如果没有钳位二极管,可以在电流中添加一个外部二极管,如图 10-2 所示。

嵌入式分享合集124_运放_15

 11 5V→3.3V有源钳位

    使用二极管钳位有一个问题,即它将向 3.3V 电源注入电流。在具有高电流 5V 输出且轻载 3.3V 电源轨的设计中,这种电流注入可能会使 3.3V 电源电压超过 3.3V。

    为了避免这个问题,可以用一个三极管来替代,三极管使过量的输出驱动电流流向地,而不是 3.3V 电源。设计的电路如图 11-1 所示。

嵌入式分享合集124_引脚_16

 Q1的基极-发射极结所起的作用与二极管钳位电路中的二极管相同。区别在于,发射极电流只有百分之几流出基极进入 3.3V 轨,绝大部分电流都流向集电极,再从集电极无害地流入地。基极电流与集电极电流之比,由晶体管的电流增益决定,通常为10-400,取决于所使用的晶体管。

12 电阻分压器

    可以使用简单的电阻分压器将 5V 器件的输出降低到适用于 3.3V 器件输入的电平。这种接口的等效电路如图 12-1 所示。

嵌入式分享合集124_嵌入式硬件_17

 通常,源电阻 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 给出。

嵌入式分享合集124_比较器_18

 公式 12-2 给出了确定上升和下降时间的公式。为便于电路分析,使用戴维宁等效计算来确定外加电压 VA 和串联电阻R。戴维宁等效计算定义为开路电压除以短路电流。根据公式 12-2 所施加的限制,对于图 12-1 所示电路,确定的戴维宁等效电阻 R 应为 0.66*R1,戴维宁等效电压 VA 应为0.66*VS。 

嵌入式分享合集124_比较器_19

例如,假设有下列条件存在:

  • 杂散电容 = 30 pF
  • 负载电容 = 5 pF
  • 从 0.3V 至 3V 的最大上升时间 ≤ 1 μs
  • 外加源电压 Vs = 5V

    确定最大电阻的计算如公式 12-3 所示。

嵌入式分享合集124_运放_20

13 电平转换器

    尽管电平转换可以分立地进行,但通常使用集成解决方案较受欢迎。电平转换器的使用范围比较广泛:有单向和双向配置、不同的电压转换和不同的速度,供用户选择最佳的解决方案。

    器件之间的板级通讯 (例如, MCU 至外设)通过 SPI 或 I2C™ 来进行,这是最常见的。对于SPI,使用单向电平转换器比较合适;对于 I2C,就需要使用双向解决方案。下面的图 13-1 显示了这两种解决方案。

嵌入式分享合集124_嵌入式硬件_21

   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 电路的电流。

 

嵌入式分享合集124_引脚_22

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 电路的电流。

 

嵌入式分享合集124_比较器_23

16 有源模拟衰减器

    此技巧使用运算放大器衰减从 5V 至 3.3V 系统的信号幅值。

    要将 5V 模拟信号转换为 3.3V 模拟信号,最简单的方法是使用 R1:R2 比值为 1.7:3.3 的电阻分压器。

    然而,这种方法存在一些问题:

  • 1)衰减器可能会接至容性负载,构成不期望得到的低通滤波器。
  • 2)衰减器电路可能需要从高阻抗源驱动低阻抗负载。

    无论是哪种情形,都需要运算放大器用以缓冲信号。所需的运放电路是单位增益跟随器 (见图 16-1)。

嵌入式分享合集124_比较器_24

电路输出电压与加在输入的电压相同。

为了把 5V 信号转换为较低的 3V 信号,我们只要加上电阻衰减器即可。

嵌入式分享合集124_比较器_25

 如果电阻分压器位于单位增益跟随器之前,那么将为 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 电源施加噪声。

嵌入式分享合集124_嵌入式硬件_26

   为了防止输入信号对电源造成影响,或者为了使输入应对较大的瞬态电流时更为从容,对前述方法稍加变化,改用齐纳二极管。齐纳二极管的速度通常要比第一个电路中所使用的快速信号二极管慢。不过,齐纳钳位一般来说更为结实,钳位时不依赖于电源的特性参数。钳位的大小取决于流经二极管的电流。这由 R1 的值决定。如果 VIN 源的输出阻抗足够大的话,也可不需要 R1。

嵌入式分享合集124_嵌入式硬件_27

   如果需要不依赖于电源的更为精确的过电压钳位,可以使用运放来得到精密二极管。电路如图 17-3所示。运放补偿了二极管的正向压降,使得电压正好被钳位在运放的同相输入端电源电压上。如果运放是轨到轨的话,可以用 3.3V 供电。 

嵌入式分享合集124_运放_28

    由于钳位是通过运放来进行的,不会影响到电源。

    运放不能改善低电压电路中出现的阻抗,阻抗仍为R1 加上源电路阻抗。

18 驱动双极型晶体管

    在驱动双极型晶体管时,基极 “驱动”电流和正向电流增益 (Β/hFE)将决定晶体管将吸纳多少电流。如果晶体管被单片机 I/O 端口驱动,使用端口电压和端口电流上限 (典型值 20 mA)来计算基极驱动电流。如果使用的是 3.3V 技术,应改用阻值较小的基极电流限流电阻,以确保有足够的基极驱动电流使晶体管饱和。

嵌入式分享合集124_比较器_29

  RBASE的值取决于单片机电源电压。公式18-1 说明了如何计算 RBASE。

嵌入式分享合集124_引脚_30

    如果将双极型晶体管用作开关,开启或关闭由单片机 I/O 端口引脚控制的负载,应使用最小的 hFE规范和裕度,以确保器件完全饱和。 

嵌入式分享合集124_运放_31

  对于这两个示例,提高基极电流留出裕度是不错的做法。将 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所示。稍微减少栅极驱动电压,可以显著减小漏电流。

嵌入式分享合集124_嵌入式硬件_32

  对于 MOSFET,低阈值器件较为常见,其漏-源电压额定值低于 30V。漏-源额定电压大于 30V的 MOSFET,通常具有更高的阈值电压 (VT)。

嵌入式分享合集124_嵌入式硬件_33

    如表 19-1 所示,此 30V N 沟道 MOSFET 开关的阈值电压是 0.6V。栅极施加 2.8V 的电压时,此MOSFET 的额定电阻是 35 mΩ,因此,它非常适用于 3.3V 应用。

嵌入式分享合集124_引脚_34

  对于 IRF7201 数据手册中的规范,栅极阈值电压最小值规定为 1.0V。这并不意味着器件可以用来在1.0V 栅 - 源电压时开关电流,因为对于低于 4.5V 的VGS (th),没有说明规范。对于需要低开关电阻的 3.3V 驱动的应用,不建议使用 IRF7201,但它可以用于 5V 驱动应用。

二、总结3.7V升压5V电路

3.7V输出5V1A

    同步整流升压PS7516。

    特点:效率极高普遍90%及以上,外围器件少,可过EMI。

嵌入式分享合集124_运放_35

3.3V~4.2V升压输出5V1A

    异步升压芯片PL2628。

    特点:效率普遍80%左右,需要整流肖特基二极管。

嵌入式分享合集124_比较器_36

3V、3.3V、3.7V升压输出5V2.4A 

     PS7526超高效率的同步整流升压方案,现实应用足2.4A 。

嵌入式分享合集124_嵌入式硬件_37

2.4V~4.5V升压输出5V3A

    FP6277超高效率的同步整流升压方案,现实应用足3A 。

嵌入式分享合集124_运放_38

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的贴片电容即可。

    最简单的升压电路了,抗干扰强,可用于收音机类产品。

嵌入式分享合集124_比较器_39

2.7V~4.5V升压输出4.94V

    无电感升压5V200MA,外围只需3个10uf的贴片电容即可。

    最简单的升压电路了,抗干扰强,可用于收音机类产品。

 

嵌入式分享合集124_引脚_40

三、STM32之SD卡

一、SD卡概述

1、定义

  SD卡(安全数码卡),是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(外语缩写PDA)和多媒体播放器等。

2、容量等级

嵌入式分享合集124_运放_41

3、SD卡框图

嵌入式分享合集124_引脚_42

引脚说明: 

 

嵌入式分享合集124_引脚_43

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。

嵌入式分享合集124_比较器_44

2、 存储阵列结构图

嵌入式分享合集124_嵌入式硬件_45

 

Block:      

  读写时的单元(数据传输单元),它的单位是“字节”。

Sector:     

  如果CSD寄存器ERASE_BLK_EN = 0时,Sector是最小的擦除单元,它的单位是“块”。Sector的值等于CSD寄存器中的SECTOR_SIZE的值+1。

WP Group:   

  最小的写保护单元,它的单位是“扇区”。

3、Buffer

嵌入式分享合集124_比较器_46

  SD Card的Buffer最大容量定义在CSD寄存器的READ_BL_LEN和WRITE_BL_LEN。它们的值是一样的,而且有可能超过512字节,尽管这样Block还是要设置成512字节,因为512字节是数据边界(这句话不是太理解)。也就是SD卡上有数据传输缓冲器Buffer,不同的产品可能不一样,但是在使用时要将Buffer设置成512字节。

嵌入式分享合集124_运放_47

 

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接口

嵌入式分享合集124_引脚_48

四、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。

嵌入式分享合集124_引脚_49

             当ERASE_BLK_EN等于1的时候,主机擦除的最小单位是512 Byetes。比如擦除时的起始地址是5,而结束地址是40,那么实际擦除的块就是从5到40。 

嵌入式分享合集124_引脚_50

 五、SD卡物理层协议

  SD卡的协议相对于SPI、I2C等协议的存储器来说相对复杂,包含SD卡物理层(机械封装、管脚、芯片结构、命令集等)、SD卡接口(SDIO)、SD主机控制器,甚至是软件设计的流程,都进行了详细的规定。

1、接口

① SDIO接口

  参考《Simplified_SDIO_Card_Spec.pdf》

 

嵌入式分享合集124_比较器_51

<1> CLK 时钟同步线

<2> CMD 命令信号线,主机发出的命令以及从机对命令的响应都是通过这条线进行传输

<3> DAT[3:0] 表示4条数据线,主机和从机的数据都是从这四条数据线上传输

② SPI接口

 

嵌入式分享合集124_比较器_52

2、命令格式

嵌入式分享合集124_运放_53

 

3、响应格式

  以R1为例

嵌入式分享合集124_嵌入式硬件_54

4、SD卡的工作状态

嵌入式分享合集124_引脚_55

 

5、SD卡的两种状态信息

① Card Status

  执行命令过程中的状态信息,比如地址不对齐错误、块长度错误、卡锁、ECC校验错误等等

blog.csdn.net/g_salamander

② SD Status

  SD卡的专有特征,编程中不经常涉及。这个状态值有512位,不是通过命令线传送给主机,而是通过数据线。

六、STM32与SD卡相配的外设--SDIO适配器

 1、SDIO adapter 结构图

 

嵌入式分享合集124_比较器_56

2、命令状态机(CPSM)

  当发送命令和接收响应时,启动CPSM状态机。

 

嵌入式分享合集124_嵌入式硬件_57

 3、数据通道状态机

  当传输数据时,启动数据通道状态机。

 

嵌入式分享合集124_嵌入式硬件_58

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初始化

  1. 端口配置、端口时钟、SDIO时钟、DMA2时钟使能
  2. SDIO寄存器复位
  3. 设置时钟SDIO_CK为400KHz以下,设置数据线宽度,开启时钟、开启SDIO电源

② SD卡上电初始化

嵌入式分享合集124_运放_59


 

上电初始化流程如上图所示,笔者认为官方库提供的例程没有完全按照这个流程图的指示去做。事实上,官方库的程序只做了如上图红色方框内的流程,之外的没涉及。

  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
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

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几伏的电压差。

原理分析

    下图简单画了个同事用示波器测量板子的示意图。

嵌入式分享合集124_运放_60

   

    那么示波器按图中接入待测电路的后,发生了什么呢?

    因为3芯电源线最上面的插片是接零线的,当探头接入待测电路后,交流电的正半周时,电流流向如下图:

嵌入式分享合集124_比较器_61

 上图,交流电正半周时,电流流向无异常,市电通过示波器的接地探头回流到零线,接下来再看看,交流电的负半周时电流流向,如下图:

嵌入式分享合集124_比较器_62

 

  因为3芯电源线最上面的插片是同零线等电位的,可以据此画出上图的交流电负半周的电流流向,可以看出,市电火零线被短路了,火零线之间只有一个二极管的阻抗。再加上王工的这块板子上的保险管被焊锡丝给短接了,所以出现了上面说的炸机现象。

如何避免

    为了避免这个问题,我们可以用隔离变压器供电,或者将电源线的接地线给拔掉,但这样做可能会有以下问题,示波器的金属部分一般都是和3芯线接地线相连的,当你把3芯线的接地插片给断开后,如下图:

嵌入式分享合集124_引脚_63

 因为接地的断开,两个Y电容的中点会带有110V的电压,因此当人触摸到示波器的金属部分会有瞬间被放电的感觉。

    最好的方法是使用高压差分探头,前提是不差钱。而且上电测量前,如果不了解电路的话,最好用万用表测量下待测电路的地和示波器探头的地之间有没有电压差,如果测量结果不为零,则不能用示波器的地线直接夹在待测电路板上的地。

    而且如果这样做的话,触摸到示波器的金属部分会有触电风险,因为示波器的地线夹和示波器的金属部分是相连的,一旦地线夹夹在待测电路板上的热地,示波器的金属部分同样会带电。

 

嵌入式分享合集124_运放_64

嵌入式分享合集124_比较器_65

 

总结

    交流电源的零线是在变电所接地的,示波器探头的GND是通过大地连接到远端变电所的零线。此时被测设备如果没有用隔离变压器隔离,那么电流会通过示波器探头GND流向大地,造成板子或者示波器的损坏。

    最简单的方法大概就是2芯电源线,这样就不会烧板子或者示波器了。