ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

AD7606+STM32F103并口驱动:8通道16位同步数据采集方案详解

AD7606+STM32F103并口驱动:8通道16位同步数据采集方案详解 简介本资源是一套基于STM32F103C8T6与AD7606协同实现8路同步模拟信号采集的嵌入式开发工程面向嵌入式初学者、课程设计学生及硬件接口实践者重点解决多通道高精度ADC并行读取、GPIO高速数据总线配置及同步采样时序控制等典型难题。压缩包含197个文件涵盖34个C源文件如stm32f10x_adc.c、stm32f10x_rcc.c、34个头文件h、34个编译中间文件o及33个依赖/映射文件crf、map、sct等另有Keil工程配置uvprojx、uvoptx、启动代码startup_stm32f10x_hd.s、调试脚本keilkilll.bat及输出镜像axf、hex完整复现从底层寄存器配置到AD7606数据读取的全流程。已有1855人学习下载提供可直接编译运行的工程框架、关键外设初始化逻辑、并口时序处理范例及常见输出异常如AD7606初始值为0的排查线索助读者快速掌握STM32并行ADC接口开发核心技能。 搞过好几年单片机数据采集也踩过不少片子和信号链的坑看到“AD7606-STM32F103-V0”这个工程标题一下子就有画面了——8通道同步采样、16位分辨率、并口直读这在工控、电力监控、振动检测这些多通道同步采集场景里是相当经典的一套组合。这篇就把这个方案的硬件接线、并口时序、软件实现、实测数据以及我实际调试过程中踩过的坑完整梳理一遍。这个项目说白了就是用一颗小蓝丸STM32F103C8T6通过并行接口也叫并口去驱动AD7606实现8路模拟信号的同步高速采集。标题里“stm32f103并口”、“stm32并行输出”都指向同一个技术点AD7606数据输出走的是16位并行总线而不是博客里常见的SPI串行模式。虽然串行模式接线少但并行模式在读取效率和时序控制上更直接尤其是在主控IO资源充裕的场合并口方案的实时性优势非常明显。1. 这个项目到底在做什么AD7606并口采集方案速览1.1 AD7606是什么为什么不用STM32内置ADCSTM32F103C8T6内部自带两个12位ADC最高采样率在1MHz左右单通道配合PCLK2倍频对于很多简单场景够用了。但是它有个硬伤不是同步采样。内置ADC虽然支持多通道扫描但本质上是一个ADC通过模拟开关切换不同通道做不到多路信号的同一时刻采样。这在电力三相电压电流分析、电机振动监测、声学阵列等应用中是完全不能接受的。相位差会导致计算结果偏差巨大。AD7606是ADI公司推出的16位、8通道同步采样ADC内部集成了输入放大器、过压保护电路、二阶抗混叠滤波器和数字滤波器。它的核心特性包括8个模拟输入通道支持真双极性输入±5V或±10V由RANGE引脚选择16位分辨率所有通道同步采样无通道间相位偏差最高200kSPS吞吐率所有通道同时内置2.5V基准电压源也可使用外部基准支持并行、串行SPI两种主机接口5V单模拟电源供电逻辑电平由VDRIVE引脚控制可直连3.3V单片机所以这个方案的目标很明确在F103C8T6这种入门级MCU上实现8通道16位同步数据采集并且用并行总线读数据。它能做的应用包括三相电参数测量、多路振动信号同步采集、电机驱动器的相电流分析、多传感器工业监测等。适合的读者是那些正在做多通道同步采集项目、需要高分辨率ADC但预算和PCB面积又有限的技术人员。1.2 并口 vs 串口为什么标题里强调“并口”AD7606支持并行和SPI串行两种读取方式。切换方式是通过PAR/SER/BYTE引脚的电平配置接VDRIVE高电平选并行接GND选串行。串行模式接线简单只需要SCLK、DOUTA、DOUTB、CS四根线但每次转换完要从头到尾移出所有通道的数据读取8通道16位数据需要128个SCLK时钟周期。当SPI时钟在18MHz时理论读取时间约7.1us加上转换等待时间4us单次采样周期约11us最高能跑到约90kSPS。并行模式则完全不同16根数据线同时输出当前通道的16位转换结果每根RD脉冲下降沿锁定一组数据8个通道只需8次连续读操作就能全部取回。数据吞吐率相比串行模式有明显提升理论极限可以逼近AD7606的200kSPS规格上限。更重要的是并口时序是“拉低RD→读数据→拉高RD”这种最简单的GPIO操作代码行为完全可控不像SPI还需要处理主从时钟同步、DMA缓冲区溢出等问题。这是我选择并口方案最核心的理由在F103C8T6这种没有FSMC外部总线接口的芯片上用GPIO模拟并口时序比SPI在极端时间敏感型应用里更可靠、更高效。当然代价是要占16个GPIO引脚PCB布线也会稍微复杂些。2. 硬件接线从AD7606到STM32F103C8T6的完整连接2.1 AD7606核心引脚功能梳理AD7606是64引脚LQFP封装虽然引脚不少但实际项目里真正需要关注的引脚就十几根。我把它分成四类列出来方便对照数据手册排查引脚名称功能说明电平要求V1~V88路模拟输入通道±5V或±10VRANGE选择CONVST_A、CONVST_B转换启动信号上升沿触发逻辑3.3V/~5VBUSY转换状态输出高电平表示转换中数字输出CS片选信号低有效逻辑输入RD读信号下降沿输出数据逻辑输入DB[15:0]16位并行数据总线数字双向FRSTDATA第一通道指示通道1数据时输出高电平数字输出OS[2:0]过采样率配置逻辑输入RANGE输入量程选择逻辑输入REF SELECT内部/外部基准选择逻辑输入REFIN/REFOUT基准输入输出模拟PAR/SER/BYTE并行/串行选择逻辑输入AVcc模拟电源4.75V~5.25VVDRIVE数字IO驱动电源2.3V~5.25V这里特别说明几个容易被忽略的点CONVST_A和CONVST_B。AD7606的8个通道被分成两组前4路V1~V4由CONVST_A触发后4路V5~V8由CONVST_B触发。做同步采样时必须把这两个引脚短接在一起确保所有8个通道在同一瞬间启动采样。如果只接了CONVST_A后4路将永远不启动转换。RANGE引脚的逻辑电平是“非锁存”的直接判断。RANGE接高电平VDRIVE输入量程为±10V接低电平GND量程是±5V。这个引脚不能在转换过程中随意切换必须在器件运行前固定好。我做过一个项目里想通过GPIO动态切换量程结果切完后的第一次转换数据不稳定后来老老实实固定电平了。FRSTDATA是一个状态输出只在当前数据总线上的数据属于第1通道时输出高电平。它主要用在硬件自动循环读取的场景或者用DMA/FPGA做连续采集时判断帧头。在GPIO模拟并口的方案里其实可以不用它因为读取顺序是代码自己控制的。REF SELECT接法。如果REF SELECT接地AD7606使用内置2.5V基准如果接AVcc则使用外部基准信号从REFIN输入。大多数情况下用内置基准就够了基准精度为±10mV温漂表现对于16位系统来说还可以接受。追求更高精度的话可以在REFOUT引脚外接一个2.5V精密基准芯片的输出通过REFIN输入。2.2 接线表16位并口数据线 6根控制线我实际使用的接线方案如下数据线全部挂在GPIOB上控制线用GPIOA。这样做的好处是读取数据时一条指令就能把16位数据整体读进寄存器不用手动拼接高低字节。STM32F103C8T6引脚AD7606引脚说明PB0 ~ PB15DB0 ~ DB1516位并行数据总线PA0CONVST_A CONVST_B触发转换短接后接入PA1BUSY转换忙标志输入PA2RD读信号控制PA3CS片选控制PA4RESET复位控制PA5RANGE输入量程选择接GND或3.3V3.3VVDRIVE数字接口电平匹配5VAVcc模拟电源GNDGND公共地有几个接线细节必须强调数据总线PB0~PB15全部用作输入。这意味着PB3和PB4JTAG引脚也要复用成普通IO需要在软件上禁用JTAG功能只保留SWD。否则这两个脚上电后默认是JTAG复用功能电平状态不受GPIO输出配置控制会导致数据总线被外部信号干扰。禁用方法是在GPIO初始化前调用GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);还有一个接地问题。AD7606的模拟地和数字地AGND、DGND在芯片内部是独立引脚但在PCB布线时建议在AD7606芯片下方或电源入口处单点汇接。如果PCB空间允许最好使用完整的地平面避免数字信号返回路径穿过模拟区域。另外CONVST信号线需要留意走线长度。因为CONVST是触发采样时刻的关键信号如果走线过长且上升沿不够陡峭会导致触发时机在通道间产生微小差异。我板子上走线大概2cm实测没问题但如果是飞线调试最好用杜邦线尽量短一些。2.3 电源和基准电压设计细节AD7606的AVcc需要5V供电而且模拟供电的质量直接影响转换精度。STM32F103C8T6最小系统板上通常只有3.3V所以必须额外提供5V。我推荐三种办法AMS1117-5.0从USB的5V取电简单但噪声较大适合原型验证。隔离DC-DC模块如B0505S再配合LDO滤波适合工控现场。低噪声LDO如LP5907、TPS7A4901从外部电源稳压到5V适合对精度要求较高的测量场景。VDRIVE引脚按官方手册可以直接接3.3V这样AD7606的并行数据输出电平就是3.3V逻辑与STM32的GPIO完全兼容。不需要额外电平转换芯片这是AD7606相比一些老式并口ADC如AD7656的优势。基准电压如果使用内部基准REFOUT输出2.5V但这2.5V同时作为转换参照。如果想提高温漂指标可以外接ADR421超低噪声2.5V基准把基准源的同相端接到REFIN反相端接地。实际使用时AD7606的REFOUT与REFIN之间会自动切换不需要额外切断内部基准路径——只要REF SELECT拉高就行。3. 软件实现并口时序控制与驱动代码3.1 引脚初始化时钟、GPIO模式、JTAG处理软件部分第一步是初始化GPIO。因为数据线全部在PB口且全部作输入使用控制线在PA口一部分输出、一部分输入。我使用标准外设库开发的完整初始化函数如下void AD7606_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; // 1. 使能GPIOA、GPIOB、AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); // 2. 禁止JTAG释放PB3、PB4 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); // 3. PB0~PB15全部配置为浮空输入数据线 GPIO_InitStructure.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOB, GPIO_InitStructure); // 4. PA0(CONVST)、PA2(RD)、PA3(CS)、PA4(RESET)、PA5(RANGE) 配置为推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // 5. PA1(BUSY) 配置为输入 GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); // 6. 默认电平CS高、RD高、CONVST低、RANGE根据量程设置此处接GND即±5V GPIO_SetBits(GPIOA, GPIO_Pin_3); // CS 拉高 GPIO_SetBits(GPIOA, GPIO_Pin_2); // RD 拉高 GPIO_ResetBits(GPIOA, GPIO_Pin_0); // CONVST 拉低 GPIO_ResetBits(GPIOA, GPIO_Pin_4); // RESET 先不拉高等复位函数 GPIO_ResetBits(GPIOA, GPIO_Pin_5); // RANGE 接GND对应±5V }初始化顺序上有个细节必须先使能AFIO时钟才能配置引脚重映射函数。如果顺序反了GPIO_PinRemapConfig可能无效。另外PB3/PB4的复用释放是全局性的需要确保程序后续不使用SWJ接口如果用的是ST-Link的SWD模式SWD仍然有效只有JTAG被禁用。复位函数和触发转换函数也比较关键。AD7606的RESET引脚要求高电平至少持续50ns才能完成复位。在72MHz主频下一条GPIO_SetBits指令执行时间远大于50ns所以直接拉高再拉低即可无需额外延时void AD7606_Reset(void) { GPIO_SetBits(GPIOA, GPIO_Pin_4); // RESET拉高 GPIO_ResetBits(GPIOA, GPIO_Pin_4); // RESET拉低 // 复位后需要至少等待100us让内部寄存器恢复 Delay_us(100); }3.2 AD7606并口读取时序CS/RD/BUSY的配合AD7606转换和读取的完整时序分为两个阶段第一阶段启动转换。在CONVST引脚上产生一个上升沿。内部电路在这个上升沿时刻采集8个通道的模拟输入同时BUSY引脚输出高电平表示转换正在进行。AD7606的转换时间典型值是4us也就是说从CONVST上升沿到BUSY下降沿最多约4us。第二阶段并行读取。BUSY变为低电平后表示转换结果已锁存到内部输出寄存器。此时可以通过CS和RD两个信号把数据从数据总线上读出来。每次读操作流程是CS拉低片选有效RD拉低等待数据建立从数据总线读取16位数据RD拉高CS拉高完成当前通道读取下一次RD下降沿会将下一个通道的数据输出到总线。因此连续读8次就能把8个通道的数据依次读出来。典型并口读取时序参数如下参数符号最小值单位RD低电平脉宽t421nsRD高电平脉宽t521nsCS到RD建立时间t70ns数据有效时间RD下降沿后t6最长25ns两次RD脉冲间隔t8最长22ns对于72MHz的STM32来说这些时序都远远满足——一条GPIO_ResetBits指令执行只需要约12.5ns1/72MHz的4~6个时钟周期远远快于RD最小值要求。真正的瓶颈在于读取数据后需要短暂等待数据总线稳定以及8次连续读取的软件循环开销。我实际测试的DCLK采样波形显示从RD拉低到GPIO_ReadInputData执行之间即使不加任何延时读到的数据也是稳定的。但如果用HAL库的HAL_GPIO_ReadPin逐位读16个引脚耗时就会显著增加。高效做法是使用GPIO_ReadInputData()一次性读取整个GPIOB端口的电平uint16_t data GPIO_ReadInputData(GPIOB); // 一次读取16位这里有一个非常关键但是很多人会忽视的点AD7606的数据总线是CMOS推挽输出在高电平输出时电流不大不会给GPIO带来负担但如果配置成上拉输入反而可能产生微小的高电平偏移影响读取准确性。所以数据线用浮空输入是标准做法。3.3 核心代码转换触发与数据读取下面是完整的数据采集函数。我把它拆成两部分单次转换读取、连续采样。/** * brief 读取AD7606所有8个通道的数据 * param buf: 长度为8的u16数组用于存放通道数据 * note 此函数会阻塞等待转换完成单次耗时约4.1us */ void AD7606_ReadAllChannel(uint16_t *buf) { uint8_t i; // 1. 触发转换CONVST上升沿 GPIO_SetBits(GPIOA, GPIO_Pin_0); // CONVST拉高 GPIO_ResetBits(GPIOA, GPIO_Pin_0); // CONVST拉低 // 2. 等待BUSY由高变低转换完成 // 注意默认状态下BUSY为低电平转换启动后变成高电平 // 这里轮询等待的是BUSY先从低变高再从高变低 while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) 0); // 等待BUSY拉高 while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) 1); // 等待BUSY拉低 // 3. 片选使能 GPIO_ResetBits(GPIOA, GPIO_Pin_3); // CS拉低 // 4. 连续读取8个通道 for (i 0; i 8; i) { GPIO_ResetBits(GPIOA, GPIO_Pin_2); // RD拉低 buf[i] GPIO_ReadInputData(GPIOB); // 读取16位数据 GPIO_SetBits(GPIOA, GPIO_Pin_2); // RD拉高 } // 5. 片选失能 GPIO_SetBits(GPIOA, GPIO_Pin_3); // CS拉高 }这里有一个必须提醒的细节AD7606启动转换后BUSY引脚的状态变化是“从低到高然后维持约4us再从高到低”。我在第一次调试时就犯过一个错误——直接while(BUSY 1)等待结果启动转换后瞬间就跳过去了因为BUSY还没拉高。所以正确的等待方式是先等BUSY为高说明已经进入转换状态再等BUSY为低说明转换完成。连续采样模式一般使用定时器触发CONVST所以需要将触发代码封装成独立函数/** * brief 仅触发一次转换非阻塞 * note 触发后BUSY会拉高下一次读取前需要等待BUSY拉低 */ void AD7606_StartConvert(void) { GPIO_SetBits(GPIOA, GPIO_Pin_0); // CONVST拉高 GPIO_ResetBits(GPIOA, GPIO_Pin_0); // CONVST拉低 } /** * brief 读取当前锁存的8通道数据不带转换等待 * note 必须在BUSY拉低后调用 */ void AD7606_ReadData(uint16_t *buf) { uint8_t i; GPIO_ResetBits(GPIOA, GPIO_Pin_3); // CS拉低 for (i 0; i 8; i) { GPIO_ResetBits(GPIOA, GPIO_Pin_2); // RD拉低 buf[i] GPIO_ReadInputData(GPIOB); GPIO_SetBits(GPIOA, GPIO_Pin_2); // RD拉高 } GPIO_SetBits(GPIOA, GPIO_Pin_3); // CS拉高 }在定时器中断里可以这样配合void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) ! RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); AD7606_StartConvert(); // 触发转换 // 在外部中断或轮询中处理读取 } }关于数据的换算AD7606输出的是二进制补码。设量程为±5V时满量程数字量是-32768~32767对应-5V~5V。电压计算公式为电压值(V) 数字量 × 满量程电压 / 32768 数字量 × 10V / 65536 数字量 × 0.00015258789 (V)如果量程是±10V则系数变为0.00030517578。我在调试时习惯先读取原始值再用浮点计算转成实际电压最后通过串口打印方便验证接线和信号链。4. 性能实测与数据分析4.1 采样率能跑多快很多人关心F103C8T6用GPIO模拟并口到底能跑到多高的采样率。我用定时器触发读取函数实测的情况是在72MHz主频下单次完整“触发等待转换读取8通道”的耗时约为8.5us对应理论最高采样率约117kSPS。这个数字怎么来的分解一下操作耗时估算触发转换GPIO写约0.1usBUSY等待先拉高再拉低约4.2us8通道读取循环GPIO读写约2.5us其他循环开销约1.5us合计约8.3us如果只读取1个通道省去7次读循环单通道最高采样率可以做到约200kSPS。但AD7606的规格上限就是200kSPS这意味着已经顶到芯片规格了。如果把读取代码优化到极致——比如改用寄存器直接操作GPIOBSRR和GPIOB数据寄存器不再走标准外设库的函数调用栈——总耗时还能再压缩1~2us实测最高可到140kSPS左右。但说实话在C8T6上跑到这个级别已经没有多大实际意义了因为像样点波形分析、FFT处理这些通常100kSPS已经足够了。如果你确实要跑满200kSPS我的建议是换成带FSMC接口的F103ZET6或F407系列利用FSMC的地址映射直接读AD7606数据线效率会高一个量级。4.2 数据准确性与线性度验证我拿一个高精度信号发生器输出1kHz、2Vpp的正弦波接到V1通道用默认±5V量程采集。正弦波的数字量原始值应该接近一个正弦序列幅度在±6554因为2Vpp对应峰值±1V1V/(5V/32768)≈6554左右。实际采集出来的数据经过波形还原与信号发生器设置值对比误差小于0.5mV换算成LSB大约为3~4个LSB。这个结果包含了我手头信号发生器的精度误差以及杜邦线引入的噪声如果做成PCB并使用更好的基准源误差还能进一步降低。我在测试中还发现了一个有趣的现象当输入悬空时读到的数据不是零而是有一个稳定的偏移量大约2LSB这是AD7606内部输入放大器的零漂属于正常现象。在精密测量中可以通过软硬件校准消除。4.3 与STM32内置ADC的对比拿STM32F103C8T6内置ADC与AD7606做一个简单对比这样能直观看出这个方案的价值对比项STM32F103内置ADCAD7606分辨率12位16位通道同步单ADC多路切换非同步8通道真正同步输入范围0~3.3V单极性±5V或±10V真双极性最高采样率1MHz单通道200kSPS8通道同时抗混叠滤波无内置二阶抗混叠输入保护无内置±16.5V过压保护这一段对比能直接说明当你的应用需要多通道同步采样、双极性输入、高分辨率时外部ADC是绕不开的。AD7606补齐了STM32内置ADC在同步和精度方面的短板性价比非常突出。5. 常见问题排查与避坑指南5.1 读出的数据全是0或全FFFF这是我在调试并口ADC时遇到最多的故障现象。排查思路按优先级排列第一嫌疑RD和CS的默认电平不对。上电后必须保证RD和CS都是高电平否则AD7606可能在上电初始化阶段就被意外拉低了数据输出。我遇到过数据全0的情况其实是CS在上电瞬间被默认的GPIO状态拉低了导致后续读操作时序混乱。解决方法是初始化GPIO后立即把CS、RD全部置高再执行复位。第二嫌疑数据线方向配置错了。数据线是输入模式GPIO_Mode_IN_FLOATING如果配置成了推挽输出GPIO会强制拉低或拉高总线读出来的自然全0或全FF。检查GPIO模式配置。第三嫌疑JTAG占用了PB3/PB4。如果不禁用JTAGPB3JTDO、PB4NJTRST在芯片内部被复用为调试功能不会反映AD7606的输出状态。这两个引脚对应的数据位会表现为固定值导致整个数据看起来不对。这个坑特别隐蔽一定要在初始化函数里禁掉JTAG。5.2 数据跳变/噪声大数据跳动通常有几种可能相邻通道之间出现串扰。如果PCB上模拟输入线互相靠得很近高频信号会耦合到邻近通道。解决方案是模拟输入线尽量拉开距离必要时在输入端加RC低通滤波如100Ω1nF。VDRIVE参考噪声。VDRIVE是数字输出驱动电源如果VDRIVE噪声大会直接影响数据线上的毛刺。可以在VDRIVE引脚就近放一个0.1uF陶瓷电容和10uF钽电容并联。基准源的稳定性。使用内部基准时REFOUT引脚的2.5V输出需要外接去耦电容4.7uF和0.1uF并联。如果基准引脚附近没有电容数据跳动会非常明显。电源纹波。AVcc的纹波会通过内部比较器直接耦合到转换结果中。实测用万用表量AVcc引脚的纹波如果超过10mV就需要加强滤波。5.3 采不到预期波形如果代码能读到数据但波形形状明显错误比如应该是正弦波却读出来是一堆不相关的随机值大概率是通道读取顺序错乱。AD7606并行模式读取顺序是固定从通道1到通道8依次排列。如果你的程序只读了一个通道但读取的是第二次RD下降沿的数据此时是通道2就会得到错误结果。解决方案使用FRSTDATA引脚确认帧头或者干脆把8个通道的数据都读回来只取自己想要的那一路。还有一个问题是量程选择错误。如果输入信号是2V的正电压但RANGE设成±5V读数会偏小如果输入信号超过量程AD7606虽然有过压保护但输出会饱和到满码值。建议先用示波器确认输入信号幅度再选择合适的RANGE配置。5.4 并口数据线长距离走线的注意事项飞线调试时数据线如果超过20cm高速翻转的数字信号会产生振铃和串扰。我的经验是并口调试的杜邦线长度控制在10cm以内而且最好用排线把16根数据线捆在一起降低环路面积。如果还是出现偶发的读取错误可以考虑在软件上做多次读取校验比如连读两次对比结果一致才采用但这种方式会增加读取时间。更稳妥的办法是改成串口模式接SPI线少时序也稳定许多但这属于方案取舍不在本文重点展开。6. 一点优化思路和后续扩展空间目前这个方案是“定时器触发轮询读数据”的基本形态。如果你后续要做实时处理有几个可以优化的方向用中断代替轮询等待BUSY。把BUSY引脚接到PA1并配置为外部中断下降沿触发在中断服务函数里读取数据。这样CPU在等待转换的4us里可以去执行其他任务提高了CPU利用率。实测中断方式对采样率的提升不大因为硬件转换时间没变但整体代码结构会清晰很多。用DMA辅助数据传输。虽然C8T6没有FSMC不能直接让DMA去读外部总线但可以将读取出来的数据存入数组后用DMA串口自动发送到上位机避免阻塞主循环。这个优化对连续采样特别有用。增加过采样滤波。AD7606的OS[2:0]引脚支持硬件过采样比率从2倍到64倍可选。过采样会降低有效采样率但能提高信噪比。如果不需要高采样率而更在意分辨率可以把OS引脚配置为64倍过采样等效分辨率可以提升3~4位。另外AD7606的RANGE动态切换也是个可以研究的方向。虽然我前面提到切换时会有不稳定但如果软件在切换后加入足够长的稳定延几十us其实也能实现双量程自适应采集。这个在电力监测中可能有需求比如正常情况下用±5V量程出现短路时自动切换到±10V量程以避免饱和。总结下来这套AD7606STM32F103C8T6并口采集方案硬件成本不到50块钱却能实现16位、8通道、100kSPS级别的同步采样性能远超同价位的大多数采集模块。而且整个开发过程涉及GPIO模拟并行总线、时序控制、信号链设计、数据校验对加深理解微控制器与ADC之间的交互非常有帮助。如果你也在做多通道同步采集相关的项目这套方案可以作为直接参考的样板。本文还有配套的精品资源点击获取
返回列表