拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于ADS1278 EKIT的8通道同步数据采集:时序、代码与验证

简介这是围绕 TI ADS1278 高精度 24 位 Σ-Δ ADC 在 TI DSP 平台上的参考工程代码包面向数据采集、传感器接口与信号调理等嵌入式开发者帮助快速掌握芯片驱动与系统集成方法。资源共 44 个文件压缩包约 445KB包含 C/C 源码、头文件、CCS 工程文件、链接命令脚本、GEL 初始化脚本及编译批处理同时提供编译输出的 .out/.map/.obj 等调试文件目录划分了 Debug 与 Release便于直接对照构建。已有 586 人学习浏览。代码覆盖 ADS1278 的关键开发环节如 SPI/I2C 接口时序、Σ-Δ 输出数字滤波、误差校准、低功耗切换及异常处理通过阅读 main.c、t1278_ob.c 等模块还能体会 TI DSP 实时处理 ADC 数据流的优化思路。对需要基于 ADS1278 快速完成原型验证的工程师而言是一份可直接复用的基础范例。1. ADS1278 EKIT 代码要解决的是 8 路同步数据采集机器振动监测、电力系统录波、医疗脑电采集有一个共同要求多个通道必须在同一时刻采样否则相位一偏后续做互相关、功率谱就全错了。TI 的 ADS1278 是 8 通道、24 位、同步采样 Δ-Σ ADCEKIT 是配套评估板CODE 则是你真正要写的驱动、数据解析和验证代码。这套组合的价值在于采样率、通道数和分辨率都处在工业采集的关键区间评估板又把模拟前端、参考电压和电源问题先解决好开发重心可以全部放在数字接口上。下面按“先解释时序再给最小代码最后讲验证手段”的顺序把从拿到 EKIT 到连续采出 8 路波形这条路走通适合做工业数据采集的嵌入式工程师也适合刚接手多通道 ADC 的硬件工程师。2. ADS1278 的工作模式与 SPI 读出时序改代码前先看懂这两个表2.1 ADS1278 的 Δ-Σ 架构与同步采样能力ADS1278 与逐次逼近型 ADC 的最大差异在量化噪声整形Δ-Σ 调制器用远高于奈奎斯特频率的过采样率工作把低频段量化噪声推到高频段再由片上数字滤波器在抽取时消掉。代价是转换需要固定周期不能像 SAR ADC 那样随时出结果好处是 8 个通道共享同一时钟源和数字滤波器天然保证采样时刻一致。EKIT 代码里的启动流程一般就做三件事确认 CLKIN 信号到位给 SYNC 一个复位脉冲然后等待 DRDY。这三件事在硬件上的顺序固定软件侧先把 SPI 外设初始化好DRDY 一到就立即搬数据尽量减少 MCU 从检测到中断到 SCLK 打出第一个时钟的延迟。通道间失真的主要来源不是 ADC 本身而是 MCU 侧轮询引入的软件偏差这个偏差在 kHz 级采样率下可以忽略。2.2 模式选择从 MODE 引脚到寄存器配置ADS1278 的运行模式由 MODE[2:0] 引脚或内部寄存器决定EKIT 板卡上通常用跳线把 MODE 拉成固定电平所以拿到板子先看丝印和原理图别急着改代码。不同模式体现在最大数据速率与功耗的取舍上模式典型最大 fDATA功耗相对值适合场景High-Speed约 144 kSPS高振动分析、瞬态记录High-Resolution约 52 kSPS中三相反馈、称重、通用采集Low-Power约 52 kSPS低电池供电、长时间记录Low-Speed约 10 kSPS最低温度、缓变信号采样率与输入时钟的关系是 fDATA 与 fCLKIN、OSR 之间存在固定折算具体公式常数以数据手册的 fDATA 计算表为准。同一个 CLKIN 下提高 OSR 必然降低输出速率但分辨率更好。写代码时不建议硬编码目标采样率而应从 CLKIN 频率反推有效位开销我一般先确定信号最高频率再反推需要的 fDATA最后选择模式宁可留 20% 余量别让数字滤波器的抽取率正好卡在信号带宽上。代码里我习惯先用一个枚举把模式名固定下来方便在驱动层判断typedef enum { ADS1278_MODE_HS 0, /* High-Speed */ ADS1278_MODE_HR 1, /* High-Resolution */ ADS1278_MODE_LP 2, /* Low-Power */ ADS1278_MODE_LS 3 /* Low-Speed */ } ads1278_mode_t;别把这个枚举值当成 MODE 引脚电平直接往 GPIO 写。它只是代码里的抽象层真正决定模式的还是跳线和寄存器。寄存器地址与位定义在 TI 数据手册的 Register Map 里有明确偏移量不同批次板载版本可能有小差异代码里应该用宏隔离这些地址换板子时只改一个头文件。MODE[2] 这一位决定输出接口是 SPI/TDM 还是帧同步EKIT 默认多半是 SPI/TDM这也是 CODE 部分最需要关注的内容。2.3 SPI/TDM 读出时序与 192 位数据帧ADS1278 在 SPI/TDM 模式下DRDY 引脚拉低表示当前一组 8 通道数据已经准备好。一次完整读出是 8 通道 × 24 位等于 192 位DOUT 在 SCLK 驱动下按通道顺序逐位输出高位在前。MCU 侧通常把 SPI 传输长度配成 8 位字节连续进行 24 次字节读写再把每 3 字节拼成一个 24 位有符号字。DRDY 是异步信号代码里要用外部中断或轮询引脚处理不要试图用定时器推算数据就绪时刻。温度变化会让分频误差累积最终表现为丢帧或半帧错位。数据手册时序图给出 DRDY 下降沿到 SCLK 第一个有效边沿的最小间隔这个参数决定了中断服务函数里是否要禁止嵌套中断、是否需要先做 Cache 操作。SPI 极性/相位组合不是唯一的常见 CPOL0、CPHA1 或 CPOL0、CPHA0 都能工作关键在采样边沿落在数据稳定的窗口内。如果拼出来的数据低位乱跳先换一组 SPI 模式。FSYNC 可以当作帧同步信号控制每次读取EKIT 上没把 FSYNC 引到 MCU 时让 CS 常低也无妨因为 192 位的帧边界可以从 DRDY 周期推出来。真正的帧边界风险在于单片机 SPI 硬件只保证字节内移位不保证字节之间是否对齐 24 位边界所以代码里必须以 DRDY 为起始点从第 0 字节计数。2.4 EKIT 默认硬件的几个注意点EKIT 上的模拟输入接口通常是 SMA 或排针参考电压由板载基准产生。拿到板子先确认 VREF 电压值后面换算物理量时直接用。板上开关电源纹波偏大时参考电压会被耦合干扰而 Δ-Σ ADC 对参考电压的高频噪声几乎没有抑制能力。我用 EKIT 测小信号时习惯在板载基准输出处再并一个 0.1 μF 陶瓷电容和一个 10 μF 钽电容效果比换电源方案明显。电源顺序先 AVDD/DVDD再 IOVDD等 CLKIN 稳定后再释放 SYNC。这个顺序落到代码里就是GPIO 初始化要在 SPI 外设时钟使能之后SYNC 复位脉冲放在 main 函数进入主循环之前不要放在中断服务函数里否则数字滤波器建立期的首帧数据会被业务逻辑拿走。3. 在 EKIT 上跑通 ADS1278 最小采集代码初始化、读 8 通道、拼字节3.1 硬件连接把 EKIT 的 SPI 排针接到 MCUEKIT 数字接口一般在板边排针引出最少接 6 根线SCLK、DIN、DOUT、DRDY、SYNC、GND。DIN 是 SPI 输入用于写寄存器或发命令DOUT 是串行数据输出。选 MCU 时注意 IOVDD 电平一致性若板卡 IOVDD 是 5 VMCU 引脚必须容忍 5 V 输入多数 3.3 V MCU 的 SPI 引脚并非 5 V 容忍需要加电平转换。接入顺序建议先接 GND再接 DOUT、DRDY最后接 SCLK 和 DIN避免上电瞬间 CLK 线上毛刺被当成移位时钟。引脚映射如下EKIT 排针信号方向接到 MCUSCLK输入SPI 时钟引脚DIN输入SPI MOSIDOUT输出SPI MISODRDY输出外部中断引脚SYNC输入GPIO 输出GND地与 MCU 共地3.2 初始化代码GPIO、SPI、工作模式和软复位下面这段 C 代码用伪平台层封装spi_write_read对应 MCU 的 SPI 字节交换gpio_pin_write抽象引脚操作在 STM32、ESP32 或 Zynq 裸机工程里可以直接平移#define SPI_CS_ACTIVE() do{ gpio_pin_write(CS_PIN, 0); }while(0) #define SPI_CS_RELEASE() do{ gpio_pin_write(CS_PIN, 1); }while(0) void ads1278_init(void) { /* 1) 先配置引脚再开 SPI 外设时钟 */ gpio_pin_init(DRDY_PIN, GPIO_INPUT); gpio_pin_init(SCLK_PIN, GPIO_OUTPUT); gpio_pin_init(DOUT_PIN, GPIO_OUTPUT); gpio_pin_init(CS_PIN, GPIO_OUTPUT); gpio_pin_init(SYNC_PIN, GPIO_OUTPUT); gpio_pin_write(SYNC_PIN, 0); /* 2) SPI 配成主模式8 位字节时钟先保守 */ spi_master_init(SPI_CLK_21MHZ, SPI_MODE_1); /* 3) 软复位SYNC 低电平保持几个时钟周期 */ gpio_pin_write(SYNC_PIN, 0); delay_us(1); gpio_pin_write(SYNC_PIN, 1); }SPI_MODE_1对应 CPOL0、CPHA1如果后续数据错位优先修改 spi_master_init 的第二参数。SCLK 用 21 MHz 是保守值EKIT 走线较长时不超过 20 MHz 更稳真正上限以手册时序特性表为准。SYNC 低电平时间来自手册的最小脉宽要求这里用delay_us(1)占位实际项目用示波器量过再定。初始化不做寄存器写入因为 EKIT 默认模式由跳线决定需要改模式时单独写一个ads1278_write_reg(addr, val)函数不要在初始化函数里塞魔法字节。3.3 数据读取循环等 DRDY、搬 24 字节、组装 8 个 24 位样本每次 DRDY 下降沿到来发起一次 192 位读操作。读过程中 SCLK 由 MCU 产生DIN 持续发 0DOUT 上按“通道 1 高字节、通道 1 中字节、通道 1 低字节……通道 8 低字节”的顺序移出数据typedef struct { int32_t ch[8]; /* 有符号 24 位扩展为 int32 */ } ads1278_frame_t; volatile bool frame_ready false; void drdy_isr(void) { static uint8_t buf[24]; for (int i 0; i 24; i) { buf[i] spi_write_read(0x00); } ads1278_frame_t *f get_current_frame_buffer(); /* 双缓冲切换 */ for (int c 0; c 8; c) { uint32_t raw ((uint32_t)buf[c*3] 16) | ((uint32_t)buf[c*31] 8) | (uint32_t)buf[c*32]; if (raw 0x800000u) { raw | 0xFF000000u; /* 24 位负数扩展为 32 位 */ } f-ch[c] (int32_t)raw; } frame_ready true; }中断里不要做滤波、缩放、打印只做拼字和置标志。缓冲区必须双缓冲否则主循环还没消费完上一帧下一次 DRDY 就把数据覆盖了。spi_write_read返回的就是 DOUT 在采样边沿读到的数据字节顺序要与手册 MSB first 设置一致若发现通道 1 和通道 2 对调把 buf 的字节索引按逆序重排即可。符号扩展的临界点在 bit230x7FFFFF 是最大正数0x800000 是最小负数不能把 24 位原码直接放进 uint32 当 int32 用否则负半周全变成大正数。3.4 EKIT 代码调试时最容易出问题的四个参数第一SCLK 空闲电平和采样边沿多数错位问题换 SPI 模式就能解决。第二CS 是否真的拉低有的复用引脚初始化时默认推挽输出高代码里没执行SPI_CS_ACTIVE()就永远读不到数据。第三DRDY 中断优先级要与 SPI/DMA 通道匹配用 DMA 搬运时让 DRDY 触发 DMA 请求轮询模式会被主循环调度延迟放大。第四SYNC 之后的第一次 DRDY 要去掉因为数字滤波器还处在建立期。处理办法是初始化后连续读 8 帧再正式进入业务或者丢弃第一帧后把frame_ready清掉。4. ADS1278 原始码流换算电压从 24 位二进制补码到物理量4.1 输出格式与满量程关系LSB 怎么算ADS1278 输出对应差分输入的二进制补码满量程输入范围是 ±VREF。按 24 位量化LSB 大小为 2 × VREF / 2^24即 VREF / 2^23。VREF2.5 V 时每个 LSB 约为 0.298 μV但这是理想值实际有效位数受噪声影响远低于 24 位。换算公式为电压 raw × VREF / (1 23)raw 是上一节做符号扩展后的 int32。切忌把每次 raw 都转成 float 再参与业务累加工程上一般保留原始码字只有显示和标定才做浮点运算否则长时间采集时浮点舍入会掩盖 ADC 本身的非线性。4.2 用 Python 批量验证 EKIT 采集结果裸机上看波形效率低常见做法是把原始 24 字节帧通过串口或文件导出在 PC 上分析。下面 Python 片段从二进制文件读 1000 帧并换算电压import numpy as np vref 2.5 raw np.fromfile(ads1278_log.bin, dtypenp.uint8) # 字节流 raw raw.reshape(-1, 24) # 每帧 24 字节 data np.zeros((len(raw), 8), dtypenp.float64) for c in range(8): hi raw[:, c*3].astype(np.int32) mi raw[:, c*31].astype(np.int32) lo raw[:, c*32].astype(np.int32) code (hi 16) | (mi 8) | lo code np.where((code 0x800000) ! 0, code | 0xFF000000, code) data[:, c] code.astype(np.float64) * vref / (1 23)np.where条件里的!优先级低于按位与括号不能省。文件长度不是 24 的整数倍时说明 MCU 侧丢帧或串口传输超时应在固件里给帧加序列号而不是在 PC 端强行对齐。处理完先打印通道 1 的均值、峰峰值和标准差均值接近零、峰峰值在手册 ENOB 对应的码值范围内说明链路基本正常。4.3 三个必调参数VREF、平均次数、时钟频率参数影响调整建议VREF决定满量程范围和 LSB 数值改板载电阻或基准芯片时同步修改代码中的宏平均次数降低输出噪声但压缩带宽缓变信号用 8 点平均快变信号不平均CLKIN 频率决定 fDATA 和数字滤波器陷波点工频测量场景由 50 Hz 整数倍分频得到 CLKINΔ-Σ ADC 已经做过数字滤波再做移动平均是在等信号带宽而不是增加信息量对缓变信号取 8 点平均能把噪声峰峰值压掉约 2/3对振动这类快变信号则不要平均改用整周期同步采样。VREF 改动会影响模拟输入范围但不影响数字码流所以代码里用宏集中管理不要把 2.5 散落在各处。4.4 数据错位与符号扩展的坑错位的典型表现是只接一路信号但 8 个通道里有两个出现相同波形且相距一个通道位置。原因是 SPI 字节对齐错误192 位数据流滑动了一个或多个字节。解决办法除了重排索引还要检查 DRDY 到来时 SCLK 是否已经开始翻转。若 DRDY 中断响应太慢比如被高优先级中断卡住 20 μs第一个采样字节会混入上一帧的尾部位。硬实时做法是让 SPI 的 DMA 请求直接由 DRDY 边沿触发不让 CPU 碰第一个字节。另一个典型错误是把 raw 当无符号数乘以 vref / 0x7FFFFF。ADS1278 的 0x800000 表示 -VREF0x7FFFFF 表示 VREF查表前必须先判符号。若写成无符号转换负半周信号会全部折叠到正半周波形看着像全波整流输出很多人会误判为模拟前端故障。5. 用逻辑分析仪验证 ADS1278 数据链路和上电细节5.1 三线抓取DRDY、SCLK、DOUT把 DRDY、SCLK、DOUT 三根线接到逻辑分析仪采样率设 50 MHz 以上触发条件选 DRDY 下降沿。观察三点第一DRDY 拉低后到 SCLK 第一个有效边沿之间是否留出手册要求的最小间隔。第二一帧内 SCLK 边沿数是否稳定等于 192 或刚好多一个字节数量忽多忽少说明 SPI 主设备配置有问题常见是硬件 NSS 自动翻转割裂了帧。第三DOUT 在采样边沿处是否建立稳定毛刺多时在 DOUT 线上串一个 22 Ω 电阻能明显改善。若波形单靠肉眼看不出问题把异常帧的 CSV 导出发给 TI FAE比口头描述“数据不对”有效得多。5.2 上电顺序与 SYNC/PWDN 操作的验证EKIT 上电顺序是模拟电源、数字电源、IOVDDMCU 侧初始化顺序是引脚模式、SPI 外设、SYNC 释放。如果板卡有 PWDN 引脚复位时先拉低 PWDN等电源稳定后再释放。SYNC 脉冲不能在 SPI 传送中途发送否则会截断正在输出的这帧数据。验证方法是把 PWDN、SYNC、DRDY、DOUT 四根线接到同一逻辑分析仪确认 SYNC 上升沿之后超过一个数据周期才出现第一个 DRDY。这个稳定时间从手册的数字滤波器建立周期估算再上浮 20% 写入工程注释后续改采样率时不会忘记重新计算。5.3 零输入自检技巧短接输入端看噪声分布在 EKIT 模拟输入插头上把每个通道的正负极短接连续采集 10000 帧统计每个通道的标准差和最大值与最小值之差单位记成 LSB。这套数值就是后续代码修改的回归基线改动 VREF、模式、SPI 速率后各重跑一遍结果变差说明改动引入了额外噪声。注意对比基线时时钟和模式必须相同否则只有采样率不同结果没有可比性。如果某通道标准差明显大于其它通道优先查该通道输入插座附近的去耦电容是否虚焊再看它与数字接口走线的距离。全套验证跑完后把基线采集逻辑做成固件里的自检命令设备每次上电执行一次比只用万用表量电压更能发现早期失效。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门