编写用于模数转换器的软件驱动程序
换完成的时间可以用来捣弄数字或刷新显示器。重要的事情是,固件用以下方式恰当地以流水线方式传送数据:数据在有效之前不被使用。不过,这超出了本文的范围,因此,在本文的余下部分,我们将集中探讨不依靠中断的固件。
组合 ADC 与微控制器
与 I2C 外部设备通信的步骤视器件的不同而有所改变,这里存在很多陷阱。该数据表显示事件序列,我们需要这些事件来确认转换完成、为下一次转换写配置、读数据和启动下一次转换。用诸如图 1 中所示的数码作为"伪代码",并直接转换成 C 语言。
图 1:你可以非常容易地将一个数据表数据序列转换成可用代码
在执行该代码的过程中,您期望读回构成ADC转换结果的4个数据字节。请注意,全零不构成 LTC2499 的有效输出,因此一个零返回码可以用来指示转换正在进行中。一个适合捣弄数字的地方就是立即在从 read_LTC2499 读一个有效结果之后。这是因为对最后一个数据字节的读操作触发下一次转换,ADC 将忙于执行为时 145ms 的下一次转换。
在尝试中断已经被读回的字节之前,用模拟示波器 (而不是用逻辑分析仪) 看数字 SDA 和 SCL 信号是个好主意。尽管这些是"数字" 信号,但是很大一部分错误实际上是模拟的。即使你复核过,处理器引脚是正确配置的,仍然要确认两个信号始终没有拉低。检查一下,保证安装了正确的上拉电阻,常见的是 5k 或 10k,不过最佳值取决于总线电容和其它因素。图 2 中上面的曲线显示 50k 上拉电阻的结果 (上升时间过长,下降时间尚可),下面的曲线显示 100Ω 电阻的结果 (上升时间和下降时间都很短,但是低电平太高;甚至可能损坏处理器和/或外部设备引脚。)
图 2:上面的曲线是过大的 (50k) 上拉电阻的结果,下面的曲线是太小的 (100Ω) 上拉电阻的结果。
SDA 和 SCL 是两个单独的单端信号 (不是一个差分对)。图 3 显示如果数据线非常长且相邻很近时 (在这种情况下,是 120cm 的 CAT-5 双绞线和 5k 上拉电阻) 会发生什么变化。上面的曲线应该是在恒定的高电平上,然而却显示出与下面的曲线在上升沿和下降沿上的过度耦合。图 4 显示由短的走线和 5k 上拉电阻所产生的可接受波形。
图 3:这些曲线显示,在相邻很近、很长的 (120cm) 传输线上,信号会发生什么变化。
图 4:一个可接受的 I2C 波形
物理接口工作正常以后,要将注意力转向实际的转换数据。使用 ADC 的良好开端是,加上一个已知输入,寻找预期输出。首先,将 ADC 设置成在 Channel 0 - 1 上差动转换,发送之前定义的配置字节,然后读出转换结果。
在使用 LTC2499 的情况下,将 CH1 引脚连接到地,CH0 引脚连接到 5V,应该产生正的过量程代码 0xC0000000。以相反方式连接,应该产生一个输出代码 0x3FFFFFFF。而将两个输入都接地 (零差分输入) 应该产生一个接近0x80000000的代码。
到这个阶段以后,一种非常省心的方法是,编写一个函数,将 ADC 代码转换成可读的电压。该器件的数据格式是偏移二进制;即:当输入为零时,输出为 231。(之所以是 31,原因是LTC2499 除了输出 24 个数据位和一个符号位之外,还输出了子 LSB (最低有效位))。采用带符号整数算法将该偏移从 ADC 转换结果中减去,将产生一个具 +/-230 范围的二进制补码字 (当输入电压从负全标度变至正全标度时)。因此:
输入电压 = 基准电压 x (ADC 代码 - 231) / 231
以伏特为单位显示 ADC 的输出,你就可以在"真实的模拟世界"中比较转换结果和数字电压表输出。请注意,基准电压为 5V 时,LTC2449 的输入范围是 –Vref/2 至 +Vref/2,或 +/-2.5V。
扫描通道
用多通道 ADC 完成的一个常见的任务是,重复扫描一个预先确定的通道序列。完成这个任务的一个方便方法是,设置大量通道地址以及一个阵列来存储接收的数据,用 1 偏移 (请记住:你正在从上一次转换读出数据,并为下一次转换写通道配置)。图 5 中的电路给各个差分通道施加了一个电压"阶梯"。这使你能够非常方便地证实,你正在选择正确的通道,并正在向正确的单元存储数值。
图 5:一个"阶梯电路"为你提供一串级联的电压,以测试固件的可读性。
表 2 显示的内容包括:Channel Array 常数、来自结果表的 16 进制数值以及利用上面所写的输入电压等式将这些数值转换成的电压值:
result = read_LTC2499(0xA0, EXT_1X_50_60HZ);
while(result==0){ //Loop until conversion done
result = read_LTC2499(0xA0, EXT_1X_50_60HZ);
}
for(i=0; i<8; ++i)
{
result = read_LTC2499(Channel_Array(i), EXT_1X_50_60HZ);
while(result==0){ //Loop until conversion done
result = read_LTC2499(Channel_Array(i), EXT_1X_50_60HZ);
}
Result_table(i) = result;
}
- 基于AD73360和TMS320F2812的数据采集系统设计(12-06)
- 基于 LT6015 / LT6016 / LT6017 的运放精准型正压和负压限幅器(10-07)
- 如何用运算放大器构成最精确的限幅器(09-23)
- 仿真ADC的前端(08-21)
- 模数转换器的工作原理与分类特点详解(05-06)
- ADC模数转换器如何选型?ADC模数转换器分类详解(05-06)