1、 使用一个 I/0 口 实现 A/D 转 换 输 入1使用一个 I/O 口实现 A/D 转换输入文件编码:HA0128S简介在某些特定的场合,主要是在数字电子应用方面,需要一个模拟信号输入来做一些基本的模拟量的测量或者是提供可控的方式使用外部电位器。当然,像这样的需求,由一个内置A/D 转换的 MCU 就能极好地实现,但是也可以使用一些经济的外部器件,由一个标准的数字 I/O 口来实现一个简单的模数转换功能。此篇应用将以 HOLTEK 系列 MCU 为对象,介绍如何使用标准的施密特输入口或 CMOS IO 口做为基本的 A/D 转换口使用,为对 A/D转换精度要求不高的应用提供一种超低成本的
2、A/D 转换实用方案。 功能说明这种模数转换的原理就是通过对某一电容充电达到某个固定的电压值,然后以恒定电流进行放电,我们可以通过测量放电时间来获得当前输入信号的强弱。通过设置 I/O 口为输出高电平可以迅速对电容进行充电,在输出口与电容之间建议串接一个 100 欧姆的小电阻来限流,防止大电流损坏。电容充电的表达公式如下:Vc = Vo (1-e-t/RC)此处 Vc 是电容电压, Vo 是 IO 口输出电压(与 MCU 实际工作电压有关) ,将输出口置高开始对电容充电后仅需仅短时间的延时,充电电压即可达到 Vo 的 98%,此案中需要的时间大约为 39s。完成充电过程后即可将控制口设置为输入
3、状态,因为其输入状态为高阻态,此时电容就只能通过三极管的发射极对地以恒定的电流放电,电流大小与发射极上串拉的电阻有关。改变放电电流的大小即会改变放电斜率。使用一个 I/0 口 实现 A/D 转 换 输 入2电流大小与电容电量之间的关系式如下:I = C dtV此处 C 是元件的电容,单位是法拉。dV/dt 是电容上电压变化率,单位是伏特/每秒。I 是流过电容的电流,单位为安培。如下图所示,如果流经电容的电流是恒定的,那么充电时电容电压上升的速率也是恒定的,实际上也就是说对电容的充放电斜坡的斜率是由电容参数值和充放电电流值决定的,电压的变化率 等于 。dtVCICLR PAC.0SET PAC.
4、0VcTimePA.0Mode TimeI/O Input SwitchingThresholdSlope Proprtional toDischarge CuretTimer OnCapcitor ChargedQuikly Vi Outpt Line0VTimer Of0V5VOutpt ModeInput Mode在放电时,如果电容与与一个 CMOS 输入端相连接,随着电容电压幅度的减小,当其幅度降低到 CMOS 输入的开关极限值,CMOS 输入端将从高电平变为低电平。使用内部定时 /计数器从放电周期开始对输入端进行监测。当输入端出现下降沿时,如果定时计数器停止计数,定时器寄存器的剩余值
5、是与放电电流成比例的,放电电流大小是由发射极的两个电阻决定的,其中一个电阻是电位器。使用一个 I/0 口 实现 A/D 转 换 输 入3硬件部分硬件电路很简单,由极少的标准元器件组成。用一个红色的 LED 提供一个大约 1.8V 的参考电压,它还具有上电指示的功能。当然,不同颜色的 LED 或串联几个低功耗的二极管,如 IN4148,也可以作为选择。这个 LED 的正向电压,与 Q1 基极到射极之间的电压相减,便得出串联电阻 R2 和 R3 上的电压,从而在 Q1 的发射极产生一个恒流源。这将在三极管的集电极产生一个恒定的电流,该电流即为放电电流。三极管的集电极电流同基极电流的关系,是由三极管
6、的 hfe 值决定的,与外部电路的精确度无关。几乎所有的 NPN 型三极管都可以应用到该电路中。一个 I/O 引脚经一个 100 欧姆的电阻与电容连接,当充电时,这个电阻对电容具有限流保护作用。在放电期间,I/O 口具有高输入阻抗,所以不会影响A/D 转换的精确度。R2 的作用是当 R3 电位计在最小值时,确保三极管工作在非饱和区,并维持电流源工作。如果选择 R2 为 1.2K,提供的电流源的值大约为 1mA,选取较小的电阻值以便于计算。选取 R3 为 10K 是有作用的,当其在较大值时可减少功耗,并且可以防止外界干扰。该例使用 HT48F06E Flash I/O 型单片机,事实上任何一款带
7、有施密特触发,CMOS I/O 结构的 Holtek 单片机都可以使用。注意,NMOS 型 I/O 引脚不适合于该应用。如果电容放电电压的下降沿下降相对比较缓慢,非施密特型的 CMOS 输入也不适用于该应用,因为缓慢的下降沿输入在电压降到门限电压时不能产生一个明确的逻辑转换。使用一个 I/0 口 实现 A/D 转 换 输 入4检查电路将会发现,电容电压从 Vdd 开始放电到输入引脚的门限电压之间的时间可由电压的变化量/电压的变化率求得,方程式如下: IVth)C(dTimeVth 是输入引脚的门限电压值,C 是电容值,I 是恒定的放电电流值。但 I 可由发射极的电压/(R2 + R3) 得出,
8、代入上面方程式,可得出: VeR3)Cth)(2(dTimeVe 是发射极电压值,它可由 LED 的正向电压减去三极管的 Vbe 得出。使用一个 I/0 口 实现 A/D 转 换 输 入5软件部分模数转化编码很简单,它是由连续地对电容充放电来实现的。对电容充电是通过设置 I/O为输出,并设置一个较长的固定时间周期以确保对电容满充。一个 100 nF 的电容和一个100 欧姆的电阻可以达到 10us 的固定时间周期,它可以作为一个计算合适充电时间的标准。推荐对电容充电的合适时间应不小于 10 倍的 RC 充电时间常数。当 I/O 口由低输出变为高输入状态,放电过程即可开始,同时定时计数器也开始计
9、时。该系统使用 3.58MHz 的晶体振荡,如果设置定时器预分频器的值为 16,将得到一个约 4.47us 的时钟周期。此时TMR 寄存器的溢出周期为(2554.47us)1.14ms。当该溢出周期远小于电容由满充到输入门限电压值的放电时间,模数转换值将会是大于 8 位二进制的数据。如果增加预分频器值到 64,将会得到一个足够长的时钟周期,允许模数转换值在 8 位以内即 255 以内。NClear TimerSetup I/O as utpt -CacitorChrgesDelay for CapcitorhginSetup I/O as Input -CacitorDichrgesStar
10、TimerInput Pin High ?Stop TimerTransfer Timer Value toRgistY使用一个 I/0 口 实现 A/D 转 换 输 入6结果如下示波器图形为电容电压,可以清楚地看到电容充电整个过程的指数上升曲线。可见上升时间比预计值长,这可能是由于单片机 CMOS 输出口的电压驱动能力没有理想中的好。这一点在充电周期起始阶段,当充电电流值比较大时,表现得尤为明显。注意,电流源将不断地从 CMOS 输出口吸收电流,这对上升时间产生一些影响。这些问题通过在电容充电时加一个较长延时便可解决。这条曲线表明,在这个范例中,允许电容充电时间的编程值明显长于所必需的时间,
11、并且可以缩短整个模数转换的时间。至于比较重要的放电斜率,尽管没有测量,但看起来线性度非常好。施密特触发 I/O 输入口的转换也很明显,而且没有检测到干扰信号。在该例中,曲线表明,由高到低变化的门限电压值为 1.62V,当然,这个值依赖于处理过程,而且随着选择的芯片不同而有所不同,对模数转换值有着重要的影响。使用一个 I/0 口 实现 A/D 转 换 输 入7误差由于该应用范例只是提供一个模数转换的基本形式,并不适用于做精确的测量,但是适用于转换精度有限的领域。绝对误差的主要来源存在于所使用电容的实际值和输入电压的门限值。尽管使用的电容为 0.1uF,但它的容限可能会大。如果采用软件进行校准,对
12、绝对误差进行补偿,那么将获得一个合理的精确度。另外,还存在一些小误差,如其中一个就是由于电容放电时,三极管 Vce 电压值不断变化引起放电电流的微弱变化。其它误差可能是由不很理想的电源电压引入的。确保没有上拉电阻与 I/O 引脚相连,否则将会产生误差,因为这将影响放电斜率的线性度,尤其在放电电流较小的情况下。结论该应用范例已说明了如何用一个标准逻辑 I/O 引脚与内部定时/计数器,和一些低成本的器件来实现 A/D 转换功能。虽然不是针对高精度的 A/D 转换应用,但这个构思实际上可以实施于低分辨率,低成本的 A/D 转换功能。在示波器曲线上随意测量放电斜率,虽然测量方式比较粗糙,但可以看到很好的线性。目前的应用范例只使用了一个 I/O 引脚,但很容易适用于多通道模拟输入。该应用范例使用一个电位计提供模拟信号输入,但可以用一个固定电阻来代替,并使用一个缓冲电压源与晶体管的基极连接,从而来提供模拟信号的输入。虽然这个电压源可以用来控制放电电流,但是对三极管保持导通并工作在线性区域的输入电压范围加强了限制。使用外部中断作为模拟测量输入脚可以实现更高效率的程序规划,即在模数转化过程中,程序可以继续执行其他的任务。