从LTC1867.rar到16位ADC驱动:SPI时序与多通道采集实战解析
发布时间:2026/10/2 8:54:27来源:尧图网络
简介LTC1867是凌特公司推出的一款16位低噪声高速逐次逼近SAR型模数转换器在工业自动化、医疗仪器、精密测量等需要高精度高速模数转换的场合应用广泛。面向嵌入式系统开发和电子设计学习者压缩包提供了一套基于C51单片机的LTC1867驱动代码围绕“如何让C51正确配置并读取LTC1867”这一问题给出了初始化、工作模式选择、转换启动、数据读取等环节的函数实现与配套说明。包内共2个文件C源码文件集中了所有驱动逻辑可直接加入Keil C51工程中编译调用TXT文本则记录了引脚连接、关键寄存器设置、通信时序要点以及调试注意事项源码与笔记配合使用能够大大降低上手门槛。整个压缩包大小仅950B内容精简但完整目前已有170人学习浏览在同类小型驱动资源中具有一定参考性。借助包内驱动方案开发者不仅能快速掌握LTC1867的软件控制流程还能将代码灵活移植到自己的数据采集、仪表显示或工业控制项目中同时规避常见的时序与配置错误从而提升开发效率是一份适合快速验证和课程设计的轻量参考。1. LTC1867.rar一个压缩包背后是完整的16位ADC落地路径拿到一个名为“LTC1867.rar”的压缩包很多人的第一反应是解压看看里面有什么。但真正做过数据采集项目的工程师会明白这个文件名指向的是一颗16位、8通道、200ksps的SAR ADC而rar里装的往往是数据手册、应用笔记、示例代码和封装库。对硬件工程师来说它决定的是传感器前端怎么设计、参考电压怎么布、SPI时序怎么对对驱动开发来说它决定了配置字节怎么发、数据怎么拼接、代码里该踩哪些坑才不翻车。这篇文章就顺着这个压缩包的典型内容把从解压、读懂时序、写驱动到调通整条链路的实战路径拆开讲清楚适合正在做多通道模拟量采集、工业控制或仪器仪表的开发者。2. 拆开LTC1867.rar解压工具、密码移除与资料清单的识别姿势2.1 解压工具选择与加密包处理流程从网上下载的LTC1867.rar不少是带密码的可能因为上传者加密了原始资料。最常见的需求就是“rar密码移除”或者“课程资料.rar忘记解压密码”这类场景。我一般先用7-Zip或WinRAR直接尝试打开如果弹密码框先用常见的默认密码试一遍比如芯片型号小写、www开头、123456这类。很多技术资料包的上传者图省事密码就是板子型号或日期。如果常规密码不对再考虑用Advanced RAR Password Recovery这类工具跑字典或暴力破解。但我得先说一句这类工具只能用于你本人有合法访问权的文件比如自己加密后忘了密码或者公司内部明确授权的归档。别拿它去试别人的压缩包这在多数情况下是不合适的。实际操作时跑暴力破解前先去设置里把字符集锁死在“字母数字”上把密码长度上限先设为6位能省掉大量无效计算。跑出来的速度取决于文件大小和CPU通常纯8位小写字母不超过1小时就能出结果超过8位且带特殊符号的话不如找原始来源重新下载更快。我习惯在用工具前先确认压缩包是否真的加密右键看属性里的“已加密”标记不一定靠谱更保险的是在命令行下执行7z l LTC1867.rar如果列出文件时每个文件名后面有一行“Encrypted ”那就是真加密了。有些rar其实只压缩没加密只是文件名带个.rar让你误以为要密码。这种情况下直接解压就行别浪费时间跑恢复工具。2.2 从压缩包内部文件结构判断资料完整度解压成功后第一步不是急着打开PDF而是先把文件列表看一遍判断手里的资料到底全不全。一份正常的LTC1867资料包通常包含几类东西官方数据手册一般是LTC1867.pdf或1867fa.pdf、应用笔记AN开头的PDF、参考代码C或Verilog的示例、以及可能的SPICE模型或封装库文件。我第一次处理这类压缩包时犯过傻直接打开数据手册从头读结果发现应用笔记里才有寄存器时序图害得我多花两个小时翻文档。我建议先按文件类型分个类PDF归PDF源码归源码库文件归库文件。接着重点看三样数据手册里有没有“Differential Input”那几页、应用笔记里有没有“Software Controlled Calibration”相关内容、示例代码是针对STM32还是8051。这个判断方式很实用因为LTC1867的官方资料有多个版本早期的PDF只讲基本SPI后期才补了多字节读取的时序图。如果你下载到的包里有ltc1867.c这样的文件说明代码可以绕开不少读时序的细节如果只有一个PDF那后面第4章的驱动代码就需要自己手写了。另外留意压缩包里是否包含PCB封装库常见有.lib或.bsch文件。LTC1867是16脚SSOP封装如果包里没有封装库去芯片官网搜索“LTC1867 SSOP footprint”能很快找到现成的。我在Altium里直接导入过官方给的封装省掉了自己画焊盘的误差。但注意有些流传的数据库文件是旧的丝印层和真实引脚不匹配画板前一定要对照数据手册第1页的引脚图核对一遍。3. LTC1867为什么值得深挖8通道16位ADC的时序与配置字节拆解3.1 单端/差分输入与通道选择编码LTC1867的8个输入通道可以配置成8路单端或4路差分具体模式靠写入的配置字节决定。常见的配置字节只有8位SGL/DIFF位最高位为1时表示单端模式为0时表示差分模式然后是ODD/SIGN位用于选择通道。很多人在这里栽过跟头因为单端和差分模式下通道编号的映射是不一样的。单端模式下通道选择是二进制编码000对应CH0001对应CH1以此类推到111对应CH7。差分模式下就复杂一点ODD/SIGN位和地址位组合起来选的是INx和INy-的配对关系。比如ODD0, A20, A10, A00对应IN0与IN1-而ODD1, A20, A10, A00对应IN1与IN0-。如果你只照着数据手册的表抄不画一张输入对映射图很容易在PCB布局时把信号接到反相输入端上。我自己的习惯是先在Excel里列一个表把配置字节、模式、实际正负输入管脚对应关系写清楚画原理图时对照着拉网络标号。这个字节的另一个关键位是UNI/BIP它决定输出是单极性还是双极性。LTC1867默认是单极性也就是输入0V到Vref对应输出0到65535。如果你要用它采集正负10V的工业信号前置电路得把负电压抬到0V以上或者把UNI/BIP设为双极性模式。注意双极性模式下输出编码是偏移二进制-Vref对应00V对应32768Vref对应65535。这个编码方式很容易让人在换算电压时多除一次或少乘一次。3.2 采样时钟与SPI时序的匹配关系LTC1867的采样转换过程由SCLK脉冲驱动而不是靠外部CONVST引脚。这意味着你要通过SPI主控器发时钟来触发转换同时也要在同一个时钟序列里读取数据。官方时序里有一个关键参数一次完整转换需要至少16个时钟周期前8个时钟用于写入配置字节并触发采样保持后8个时钟用于移出转换结果。但很多主控的SPI是8位一帧16位一帧的模式不一定支持所以常见的做法是连续发两个8位帧第一帧写配置第二帧读数据。这里有个容易忽略的细节在发出配置字节的最后一个SCLK下降沿之后芯片开始转换转换时间tCONV最长是4.4us。如果你紧接着就发读帧必须等足够的延时否则读回来的是上一次转换的残留或者全0。我一般在写配置和读数据之间加至少5us的延时稳妥的做法是延迟10us因为200ksps的转换周期本身是5us所以这个延时不会影响吞吐率。实际项目中我会在SPI片上使能后先用GPIO方式验证一下读回的电压值是否随输入变化再切换到DMA模式。另一个和时序相关的参数是SCLK最大频率。LTC1867手册给出SCLK最快可以是16MHz但这是理论值。我在实际STM32上跑到10MHz以上就偶尔出现错位问题最后降到4MHz才稳定。原因是SPI主控的片选信号和时钟之间的延迟、PCB走线电容都会影响边沿对齐。如果你不需要极致的采样率把SCLK设在2MHz到4MHz之间最舒服既保证时序余量又能轻松实现200ksps的满速采样。4. 用LTC1867资料跑通SPI驱动从寄存器到电压值的完整代码4.1 最小MCU驱动代码配置字节、忙检测与数据读取假设你用的是STM32的HAL库SPI已经初始化为主模式单线接收模式时钟极性和相位都配成模式0CPOL0CPHA0。下面这段代码是我反复用的最小驱动可以从LTC1867的通道0读到单端电压值#include stm32f1xx_hal.h extern SPI_HandleTypeDef hspi1; // 配置字节单端模式通道0单极性 #define LTC1867_CONFIG_CH0_SINGLE ((0x80) | (0x00 4) | (0x00 1) | 0x00) uint16_t LTC1867_ReadChannel(uint8_t config_byte) { uint8_t tx_data[2] {0}; uint8_t rx_data[2] {0}; uint16_t raw 0; // 第一帧发送配置字节触发采样保持 tx_data[0] config_byte; // 第二帧发送任意字节0xFF同时移出转换结果 tx_data[1] 0xFF; HAL_GPIO_WritePin(ADC_CS_GPIO_Port, ADC_CS_Pin, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(hspi1, tx_data, rx_data, 2, 10); // 转换期间等待 // LTC1867的转换时间最长4.4us这里延时5us以上 DelayMicros(10); // 注意第二帧读回的数据在rx_data[1]中 raw ((uint16_t)rx_data[0] 8) | rx_data[1]; HAL_GPIO_WritePin(ADC_CS_GPIO_Port, ADC_CS_Pin, GPIO_PIN_SET); return raw; }这段代码的逻辑是把片选拉低后连续发两个字节。第一个字节写入配置借由SCLK的上升沿芯片在内部将配置锁存并进入采样。第二个字节期间芯片把上一次转换出的16位结果从DOUT引脚移出。HAL_SPI_TransmitReceive在这里是全双工操作所以rx_data会收到两个字节其中rx_data[0]是配置字节被芯片回显后的值rx_data[1]才是有效数据的高8位但我们需要把两个拼接起来。实际使用时要留意由于在第二帧发送之前DelayMicros(10)已经让芯片完成转换所以第二帧读到的就是当前配置对应的电压。如果你不延时读到的就是上一次通道的旧数据。另外tcsh和th这两个时间参数控制CS拉低到第一个SCLK的时间HAL库在片选后立即发时钟可能不满足手册要求的1us建立时间我在MCU时钟跑得快的时候会在拉低CS后也加一点延时稳妥起见再加上1us。4.2 数据拼接与电压换算别把符号位和极性弄混拼接高8位和低8位时有个坑如果你把rx_data[0]当作高字节在收到配置字节回显后那些位根本不对。正确理解是在16个SCLK周期中前8个时钟期间DOUT引脚保持高阻或输出前一次结果的最高位后8个时钟才逐位移出当前结果。在HAL库收满两字节后rx_data[0]里存的是前8个SCLK采到的位rx_data[1]存的是后8个SCLK采到的位。如果我们把rx_data[0]左移8位再与rx_data[1]相或得到的是一个组合结果但需要验证最高位是否正确。我在调试时做过一个实验给CH0加1.25V参考电压LTC1867单极性模式下输出应接近32768。用上面的拼接方式如果出来的是0xFFFF或0x0000说明配置字节没有被正确写入或者时序相位反了。更可靠的验证方法是先用逻辑分析仪抓SPI三根线对照数据手册的时序图看DOUT是否在第一帧后的第16个SCLK下降沿后输出有效数据。我自己的经验是把raw打印到串口后旋转输入电压的旋钮观察数据是否线性变化。如果数据跳变但整体偏移多半是参考电压引脚接触不良或内部偏移未校准。电压换算公式很简单voltage raw * (Vref / 65535)这里Vref是参考电压引脚上的实际电压而不是你理论上给的值。我用万用表实测过很多板子上的参考电压芯片标称2.5V实际是2.498V不修正的话满量程误差接近10mV。另外单极性模式下输出是16位无符号数但如果你读到的raw大于32768说明输入电压超过了Vref的一半别把负电压和正电压搞混。双极性模式下raw的最高位是符号位需要先把它变成有符号数再做除法。// 电压换算Vref是实测值 float LTC1867_ToVoltage(uint16_t raw_value, float vref) { // 单极性模式0V映射到0Vref映射到65535 return ((float)raw_value * vref) / 65535.0f; }5. LTC1867落地避坑配置字、参考源与布局的5个血泪经验5.1 通道切换后第一笔数据是脏的现象在单端模式下从通道0切换到通道1后读到的第一笔数据明显偏移甚至跳到满量程。第二次读就恢复正常了。原因LTC1867的输入采样电容在前一次转换中存储了上一个通道的电压残量。切换通道的瞬间采样电容需要重新充电到新通道的信号电压。虽然手册提到芯片有自动清零功能但切换后首次转换的精度并不会完全达到16位。解决软件上每次通道切换后丢弃第一次转换结果连续读取两次第二次数据作为有效值。我一般在通道切换函数里这样写uint16_t LTC1867_ReadStable(uint8_t config_byte) { uint16_t discard LTC1867_ReadChannel(config_byte); // 丢弃 return LTC1867_ReadChannel(config_byte); // 有效 }如果采样率不够用还可以考虑在PCB上让每个模拟输入通道接入一个0.1uF的电容对地这样能加快采样电容的充电速度减少通道间串扰。5.2 参考电压引脚上的去耦电容不是越大越好现象参考电压用的是2.5V基准源引脚旁边加了10uF电解电容并联0.1uF陶瓷电容结果实测出来的噪声反而比只在引脚旁放一个1uF陶瓷电容时更大。原因LTC1867的数据手册里对参考输入有一个动态阻抗要求。参考引脚在采样脉冲到来时会有瞬间的电流抽取如果去耦电容太大且ESR很低会形成一个LC振荡回路与基准源内部放大器产生谐振导致参考电压出现振铃直接叠加到ADC的转换结果上。解决参考输入端的去耦电容并非越大越好。我测试下来在引脚旁边放置一个1uF的X7R陶瓷电容距离引脚不超过3mm这样效果最好。基准源输出到ADC参考引脚之间加一个几欧姆的小电阻例如4.7Ω可以抑制振荡。如果你用的是精密基准源如LT1019在它的输出端再放一个2.2uF电容后经过电阻再进ADC引脚抗噪效果会更好。5.3 SPI时钟极性与相位错了读回来的全是0x7FFF现象SPI配置成模式1CPOL0CPHA1后读回的原始数据稳定在0x7FFF附近改变输入电压数据只在小范围波动。原因LTC1867要求数据在SCLK上升沿被驱动下降沿被接收。如果主控在错误的边沿采样就会采到数据线上的毛刺或处于跳变过程中的值。0x7FFF这个模式特别典型——它意味着所有高12位都正确最低几位不稳定其实是时钟相位与芯片输出时序错了一个边沿。解决把SPI配置成模式0CPOL0CPHA0或者模式2CPOL1CPHA0都行。我用逻辑分析仪对比过LTC1867的数据手册时序图更接近CPOL0CPHA0。如果你用的主控不能直接改相位可以先用软件模拟SPI验证时序再把bitbang版本翻译成硬件SPI。我的经验是先检查SPI输出数据时DOUT引脚是否在SCLK上升沿后约20ns内稳定如果稳定时间不够可能是主控IO口驱动能力或上拉电阻没接对。5.4 差分模式下的共模电压范围限制现象配置成差分模式给差分对的负端施加一个稳定的2.5V共模电压正端在2.5V附近小幅波动结果输出数据不是预期的16位正弦波而是严重失真。原因LTC1867的差分输入要求每个输入引脚相对于地有一个共模电压范围虽然它内部有共模抑制能力但每个引脚对地的绝对电压必须在-0.05V到Vref0.05V之间。如果你的传感器输出是浮地的共模电压可能超出这个范围。解决在差分输入各引脚对地接一个电阻分压网络把共模电压抬到Vref/2。比如Vref2.5V那就在每个引脚上接一个100kΩ电阻到2.5V再接一个100kΩ到地使得没有输入信号时引脚电压为1.25V。这样既保证共模电平合适又不会过多加载信号源。如果是高速信号还需要在电阻两端并联一个小电容用于补偿源阻抗。注意输入信号的内阻不能过大手册建议源阻抗不超过几百欧姆否则从引脚看进去的RC时间常数会影响充放电时间导致采样值不准确。5.5 忘记给VREF引脚并联一个足够低阻抗的旁路电容现象板子只给VREF引脚焊了一个4.7uF钽电容结果ADC在采样率200ksps时输出数据的末两位一直在跳。接上0.1uF陶瓷电容后跳变明显减少。原因SAR ADC在转换完成前的采样阶段会从参考源抽取一个短暂的大电流脉冲频率等于采样率。如果参考引脚旁路阻抗过高参考电压会在每个转换周期里出现微小凹陷这个凹陷被量化进结果表现为低位的随机噪声。解决在VREF引脚上同时放置0.1uF陶瓷电容和1uF陶瓷电容两者并联尽可能靠近引脚。不要在它们之间加过孔要保持一条连续的铜皮回地。另外参考源芯片的输出端也要放一个10uF左右的电容来储存能量否则脉冲电流会让参考源芯片本身产生压降。我在这块上吃过亏之前为了省空间只放了一个1uF电容结果后端信号链的ENOB从13位掉到11位。6. 把LTC1867用出上限多通道扫描、均值滤波与现场校准6.1 多通道扫描的时序安排与数据重组如果需要连续采集8个单端通道我通常会禁止SPI的自动CS模式改由软件控制CS。扫描一圈的流程是针对每个通道先发配置字节等转换再读数据。一个简单可靠的轮询顺序是void LTC1867_ScanAllChannels(uint16_t *results, float vref) { const uint8_t configs[8] { 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0 }; for (int ch 0; ch 8; ch) { LTC1867_ReadStable(configs[ch]); // 切换通道后丢弃第一笔 results[ch] LTC1867_ReadChannel(configs[ch]); } }这段代码里configs数组的高位的排列方式对应单端模式CH0-CH7。注意在循环里先读一次丢弃再读一次取有效值。这样一圈8个通道总耗时大约是8乘以两倍的转换时间也就是约80us可以支持接近12ksps的通道轮询速率。如果实际系统采样循环里还有别的任务这个速率够了。若是想加快可以把丢弃和读取合并成一次首次读到数据后延迟一段时间再读同一通道但那样代码就复杂了收益不大。多通道扫描时还要留意每个通道的输入源阻抗可能不同。如果你用分压电阻给通道2提供信号它会比直接来自运放的通道0更容易受采样电容充放电影响。在这种情况下我在每个通道输入端统一放一个RC滤波截止频率设在几十kHz能显著降低通道间串扰。6.2 利用内部校准模式验证线性度LTC1867数据手册里提到内部有校准脉冲可以用于自校准偏移和增益误差。很多工程师拿到资料包后只在做演示时用这个功能实际项目里却不管它。我在批量生产中会做个简单校准流程在板子上预留一路精确的0V和一路精确的Vref/2信号用继电器切换到ADC输入端分别采集原始码然后算出增益系数和偏移量写入EEPROM里。这样即使参考电压有微小偏差MCU每次上电后都可以做软件修正。这个方法比依赖芯片手册里的绝对精度更可靠因为LTC1867的增益误差典型值为±8LSB偏移误差±2LSB。如果你用软件校准可以轻松把这两个误差压到1LSB以内。具体校准方程是float LTC1867_CalibratedVoltage(uint16_t raw, float vref) { // 假设校准后 gain 1.00036, offset -1.25 LSB // 从EEPROM读取校准参数 float corrected (float)raw * gain offset; if (corrected 0.0f) corrected 0.0f; if (corrected 65535.0f) corrected 65535.0f; return (corrected * vref) / 65535.0f; }实际校准读取时不要用单次采样值而是每次采1000点取平均。校准完成后我还习惯在调试串口里把每个通道的原始码与实测万用表电压值打印出来计算一下R2是否达到0.9999以上。如果某个通道偏离线性先检查前端运放是否进入了饱和而不是怀疑ADC。这个习惯救了我很多次也让我在量产过程中能快速区分是焊接问题还是软件问题。最后说一个我自己的教训刚用LTC1867时总想着把采样率顶到200ksps结果换一个输入源就出现奇怪的谐波。后来养成先确认源阻抗和电容匹配度再逐步调采样率的习惯。所有驱动代码都要先在低速时钟、单通道模式下跑通再上多通道和轮询。把参考电压实测值写死在程序里不如做一次上电自校准来得省心。希望这篇从rar到驱动的拆解能帮你在碰到LTC1867.rar时少走几步弯路。本文还有配套的精品资源点击获取
网站建设高端定制企业官网