ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AD9826 FPGA驱动完整攻略:从CDS原理到时序代码实战

AD9826 FPGA驱动完整攻略:从CDS原理到时序代码实战 做FPGA图像采集或者工业相机相关项目的人大概率绕不开一个芯片AD9826。这是一颗ADI出品的老牌CCD/CIS传感器信号处理器虽然芯片已经有很多年头了但在扫描仪、条码识别、部分工业视觉对焦模块里依然大量服役。它内部集成了相关双采样CDS、可编程增益放大器PGA和一颗16位ADC核心工作就是把CCD传感器那微弱的模拟信号调理成干净的、可以直接送进FPGA做后续处理的数字信号。最近我把这颗芯片从驱动到时序完整调通了一遍踩了不少坑尤其是时序分析那块对着数据手册画波形图画到眼睛花。这篇博文就把AD9826的工作机制、时序关键点以及我最终调通的Verilog驱动代码从头到尾讲一遍。既有对芯片内部工作原理的拆解也有可直接抄作业的代码实现还会有我个人实测中遇到的典型问题排查实录。适合正在用这颗芯片、准备用这颗芯片或者纯粹想了解工业级ADC驱动时序逻辑的朋友参考。1. 内容整体设计与思路拆解1.1 为什么偏偏是AD9826这颗芯片到底解决什么问题先聊个实际场景。CCD传感器输出的是像素电荷经过转换后的模拟电压信号这个信号有几个“难伺候”的地方幅度非常小一般只有几百毫伏带很强的复位噪声因为CCD每个像素读取前都要复位复位电平会叠加在有效信号上不同的传感器暗电流和增益特性还不一样。如果直接把这种信号送给普通ADC去采样出来的图像会花到没法看——固定模式噪声、复位噪声全混在里面。AD9826干的事情就是把信号链做完整。它的输入端有一个相关双采样电路也就是CDS专门对付复位噪声后面跟了PGA可编程增益放大器能把小信号放大到ADC满量程范围附近最大增益能到12dB左右从-2dB到12dB多档可调再后面就是一颗16位、最高采样率12MSPS的ADC。输出侧是二进制补码格式的并行数字信号跟FPGA对接非常直观。这基本上就是一条完整的模拟前端信号链了不需要你自己用运放和分立ADC去搭稳定性和精度都更容易保证。1.2 整体工作流程从模拟输入到数字输出要经过哪些环节如果你只看AD9826的数据手册会看到一大推寄存器配置和时序图容易一头雾水。但本质上它的工作流程可以拆成下面几步第一配置阶段。芯片上电之后通过三线SPI接口把工作参数写进内部寄存器包括输入极性选择、CDS模式、PGA增益、偏置电平、输出格式等。这些寄存器配置好之后芯片就进入固定工作状态不会再变了。第二像素采样阶段。在SCLK时钟的驱动下AD9826对每个像素周期执行两次采样一次采复位电平也就是所谓的前沿一次采信号电平也就是后沿。CDS电路把这两个电平相减就得到了干净的像素电压。第三数字化输出阶段。芯片每个时钟周期处理一个像素在CDS完成之后ADC完成转换结果经过输出寄存器在数据有效信号DOUTVALID的伴随下从D0到D15这16根数据线上并行输出。从时序控制的角度看FPGA侧的任务就是两件事给芯片提供正确的SCLK、CDS采样点位置和转换时序然后把输出的16位数据正确地读回来再根据输出帧同步信号通常是CCD传感器自己的行/帧同步信号AD9826内部也有相关标志位把像素数据组织拼接成完整图像。1.3 时序方案选型考量FPGA和AD9826之间到底谁主动我刚开始搞这个项目的时候有个误区以为FPGA只要给个持续时钟AD9826自己就能把活干完FPGA在边上等数据就行。实际上这个方案需要对“谁是主”理解清楚。AD9826的高速转换CDS时序完全由外部输入的SCLK决定芯片自己只有一个内部参考时钟用于控制逻辑它不会自动产生采样脉冲。也就是说所有采样动作、转换动作、输出动作都跟着你给的那个主时钟走。这跟我们平时用SPI从机芯片不一样SPI从机至少还能靠片选信号来圈定一次传输的边界AD9826是纯流水的时钟不停它就一直采根本不管你是不是想要这个像素。所以正确的方案是FPGA主动控制整个时序SCLK给多少、什么相位关系、每个像素周期怎么划分全部由FPGA根据CCD传感器的驱动波形来设计。AD9826只是被动响应。理解了这一点你就知道为什么时序分析这么重要——时序不对后面全白搭。我最终选择的方案是用FPGA内部PLL把像素时钟打进AD9826作为SCLK然后根据AD9826数据手册要求的时序关系在FPGA内部生成对应的内部采样脉冲和数据读出窗口。SCLK频率我设为6MHz这是CCD传感器行输出速率和AD9826最高12MSPS之间取的一个平衡点。6MHz也方便后续FPGA内部处理逻辑按像素周期翻倍计算。2. 核心细节解析与实操要点2.1 深入理解CDS相关双采样为什么能消掉复位噪声CDS是AD9826最核心的功能模块理解它的原理直接决定你能不能调出干净的图像。CCD像素读取过程大致是先把像素电容复位到一个固定电平然后光生电荷逐渐转移并充放这个电容使电平线性下降或者上升具体极性取决于CCD类型。问题在于每次读取像素之前那个复位电平并不是完全一致的会有热噪声和残余电荷差异如果不处理每一个像素都叠了一个随机直流偏置图像就呈现出网状噪声。CDS的做法很巧妙在复位电平和信号电平期间各采样一次然后把两次采样值做减法。复位噪声在两次采样中几乎是共模的减法操作把它抵消掉了。留下的是真正的光生信号电压差。这就像你拿一个称去称东西两次称重之间的系统零点偏了但你把两次读数相减之后零点偏置就没了。AD9826内部的CDS实现方式是在外部SCLK的特定相位控制下依次启动两个片内采样保持电容的开关一个存复位值一个存信号值然后在后级相减。具体到AD9826数据手册上的典型时序可以看到每个像素周期SCLK有两个上升沿或者两个有效沿取决于配置第一个沿控制复位电平采样第二个沿控制信号电平采样。这里有一个关键点不是所有的SCLK周期都必须执行两次采样AD9826支持多种CDS模式包括普通CDS、无CDS光电二极管模式、单采样模式等。对于CCD传感器一般都用普通CDS模式。2.2 盯住这张图AD9826核心时序参数解析数据手册里画了几张时序图其中最核心的是CDS采样时序和输出数据时序。我重点分析一下这几个参数时钟频率范围SCLK最高12MHz最低没有硬性限制但考虑到芯片内部电容的漏电建议不要低于1MHz否则采样保持的电压会掉。我最终用6MHz就是考虑到这个余量。CDS采样脉冲宽度数据手册给出tCDS参数也就是CDS采样脉冲的典型宽度在20ns左右。如果SCLK周期是166ns6MHz这个20ns只占12%的时间窗口看起来不大但对FPGA来说关键是采样脉冲必须落在正确的位置即输入模拟信号已经稳定并且CCD输出已经稳定后。内部延迟参数tP、tDout等这些定义了从CDS采样完成到数据出现在输出引脚之间的时间。这个延迟不是固定值与SCLK频率有一定关系但整体上接近一个像素周期减去一小段内部路径延迟。输出锁存点这是FPGA侧最容易出错的地方。AD9826在DOUTVALID信号拉高期间输出有效数据FPGA必须在DOUTVALID为高且数据已经稳定以后再采样不能一看到时钟边沿就去读。我把关键时序参数整理成表方便参考参数符号典型值备注SCLK最高频率fCLK12MHz我实测6MHz最稳CDS采样脉冲宽度tCDS20ns芯片内部自动产生SCLK高电平时间tCLKH25ns占空比40%-60%数据建立时间tDS15ns对FPGA侧而言数据保持时间tDH10ns对FPGA侧而言输出延迟tD12-20nsSCLK沿到数据有效通道间串扰-60dB越小越好这里着重说一下输出数据时序的理解。AD9826的输出数据由SCLK的某个边沿触发更新数据在DOUTVALID有效期间保持稳定。FPGA读数据的时候很多人图省事直接用SCLK的同一个边沿去采数据结果发现时对时不对。原因在于芯片内部有一个很大的延迟从SCLK沿发生到数据真正稳定在引脚上需要一个过程。如果FPGA采样沿太靠近芯片数据变化沿建立时间不够采到毛刺或者中间态太正常了。正确的做法是用SCLK的反相沿也就是相对于芯片数据触发沿偏移了半个时钟周期来锁存数据这样留给数据足够的稳定时间。这点在后面代码实现部分有具体体现。2.3 PGA和偏置电平配置别让图像产生“削顶”或“黑底发灰”PGA增益设置关系到图像质量这个环节很多初次调试的人会忽略。AD9826的PGA增益范围是从-2dB到12dB通过寄存器字节的低六位来配置每步0.27dB左右。你可能觉得增益嘛随便设个中间值就行。但实际调试中我发现如果增益过大信号被ADC削顶高光部分的细节全部丢失图像上一片死白如果增益过小整个画面灰蒙蒙的暗部噪声都被放大了。我的经验是先用示波器看CCD输出最亮处的电压幅度假设是Vmax目标是把Vmax放大到ADC满量程的85%左右。因为ADC是16位的满量程参考电压内部默认约4V具体看寄存器配置那目标电压大约3.4V。初始增益设为目标电压除以Vmax听起来很简单但实际工程上CCD边缘像素和中心像素响应不一致保险起见把增益设低一档留出余量等整体图像出来再慢慢调。偏置电平CLAMP和OB相关是另一个容易出问题的地方。AD9826有黑电平箝位功能可以把CCD暗像素的输出电平钳制到AD转换的零点附近确保黑色是纯黑而不是偏灰。如果这个没处理好图像的暗部会有很明显的底色。3. 实操过程与核心环节实现3.1 Verilog接口模块设计先看外部长什么样在设计代码之前先梳理一下AD9826的引脚和FPGA的对应关系。AD9826接口侧主要引脚包括SCLK时钟输入、SDATASPI数据输入、LOADSPI加载相当于芯片选择、CDS控制相关的输入以及数字输出D0-D15、DOUTVALID数据有效标志、HSYNC输出等。我写驱动代码时拆成两大部分寄存器配置模块和像素数据读取模块。这两个模块分开的好处是后续调试的时候可以单独仿真、单独定位问题。寄存器配置模块就是普通的SPI写时序把需要的参数按手册指定的地址和数据格式写给芯片像素数据读取模块则是等配置完成后持续跟踪SCLK和DOUTVALID把有效数据采进来。核心接口定义如下module ad9826_driver #( parameter DATA_WIDTH 16 )( input wire clk, // 系统时钟 input wire rst_n, // 复位 // AD9826 接口 output wire adc_sclk, // 像素时钟输出 output wire adc_load, // SPI加载信号 output wire adc_sdata, // SPI数据线 input wire adc_doutvalid,// 数据有效 input wire [DATA_WIDTH-1:0] adc_dout, // 16位并行数据 // 给上层的数据 output reg [DATA_WIDTH-1:0] pixel_data, // 输出的像素数据 output reg pixel_valid, // 像素数据有效标志 input wire cfg_start, // 启动配置 output reg cfg_done // 配置完成 );这里有个细节adc_sclk虽然是输入到AD9826的时钟但它是从系统时钟分频或者PLL产生的。考虑到数据读取的时序关系我在模块内部产生一个sclk_gen信号一方面输出给AD9826的SCLK引脚另一方面用一个延迟版本作为内部数据采样的时钟使能这样能精确控制采样位置。3.2 SPI寄存器配置这些参数别配错AD9826的SPI配置是三线的SCLK、SDATA和LOAD。芯片规定数据在SCLK的下降沿被写入LOAD拉高时加载到锁存器。仔细看手册有一句话LOAD应该在最后一个SCLK边沿之后拉高并且在下一个字节开始前拉低。这里最容易出错的是LOAD拉高的时机如果最后一个SCLK下降沿还没出现就拉高LOAD最后一位数据可能没写进去。我第一次调试就是这个原因寄存器写入老是失败排查了半天。AD9826的寄存器地址我列一下最关键的几个寄存器地址功能重要位配置寄存器00x00CDS模式、输入极性等bit2: 输入极性配置寄存器10x01偏置电流、输出格式bit0: 二进制补码/偏移码增益寄存器0x02PGA增益设置8位整数增益相位寄存器0x03采样相位调整各bit对应延迟箝位寄存器0x04黑电平箝位箝位门控设置相位寄存器值得单独说一句。AD9826的CDS采样点相对SCLK的位置可以通过相位寄存器微调步进标称约1.2ns。实际调试中如果你发现图像明暗交界的边缘有偏色或者拖尾往往可以通过微调这个寄存器改善。但这个寄存器修改要非常谨慎每次改一个step然后看图像改多了容易弄巧成拙。我的经验是先用默认值等确认整体链路没问题了再回头微调。配置模块的Verilog代码我用一个简单的状态机来做。值得注意的地方是发送完一个字节后要把LOAD信号保持高电平至少一个SCLK周期让芯片内部锁存可靠。具体代码片段如下// SPI写寄存器状态机 localparam IDLE 3d0; localparam WRITE_BYTE 3d1; localparam LOAD_PULSE 3d2; localparam NEXT_REG 3d3; localparam ALL_DONE 3d4; reg [2:0] state; reg [7:0] reg_addr; reg [7:0] reg_data; reg [4:0] bit_cnt; reg [3:0] reg_cnt; always (posedge clk or negedge rst_n) begin if (!rst_n) begin state IDLE; adc_load 1b0; adc_sdata 1b0; cfg_done 1b0; end else begin case (state) IDLE: begin if (cfg_start) begin state WRITE_BYTE; bit_cnt 5d15; // 8位地址8位数据从最高位发 reg_cnt 4d0; cfg_done 1b0; end end WRITE_BYTE: begin // 前8位是地址后8位是数据在SCLK下降沿发送 adc_sdata (bit_cnt 8) ? config_regs[reg_cnt][bit_cnt-8] : config_regs[reg_cnt][7:0][bit_cnt]; // 此处省略sclk分频逻辑 if (sclk_fall) begin bit_cnt bit_cnt - 1b1; if (bit_cnt 0) state LOAD_PULSE; end end LOAD_PULSE: begin adc_load 1b1; if (load_done) begin adc_load 1b0; reg_cnt reg_cnt 1b1; if (reg_cnt 4d4) state ALL_DONE; else state WRITE_BYTE; end end ALL_DONE: begin cfg_done 1b1; state ALL_DONE; end endcase end end写SPI配置的关键点总结一是SCLK尽量用低速配置过程不需要快几百kHz到几MHz都行二是LOAD信号的时序严格按照手册来拉高保持在SCLK停止之后三是每写一个寄存器之后最好留一点延时再写下一个避免芯片内部状态还没稳定就收到新的配置字。我在FPGA里加了一个计数器做了几十个时钟周期的延时实测非常稳妥。3.3 像素数据读取核心代码与锁存时机分析像素数据读取模块是整个驱动里最关键的。前面说了数据锁存时机要避开芯片输出数据的翻转沿。我的做法是内部维护一个sclk_delay信号这个信号相对于adc_sclk延迟了大约90度相位四分之一周期用这个信号来产生采样使能。具体逻辑如下AD9826在SCLK的上升沿更新输出数据对大多数工作模式是这样那么当SCLK上升沿到来时数据线上实际上是旧的、在变化的、新的这三者的混合状态。为了保证FPGA采到的是新的稳定数据就需要在当前SCLK上升沿之后、下一个上升沿之前的某个时间点去采样。理论上这个时间点越靠近下一个上升沿数据稳定储备越充足。但也不能太靠后万一芯片内部有个走线延迟导致数据更新点比理想位置晚怎么办折中方案就是用90度相位偏移来采样。代码实现时我用系统时钟对SCLK周期进行计数。假设系统时钟100MHzSCLK是6MHz那么SCLK周期大约是16.7个系统时钟周期。我用一个计数器从0数到16刚好一个SCLK周期。当计数到8的时候就是SCLK周期的中间点也就是相位偏移90度的位置。此时采样模块去锁存数据。// 数据采样逻辑在SCLK中间点采样 reg [4:0] clk_cnt; reg sclk_mid; wire sclk_r adc_sclk; // 输入回芯片的时钟占空比50% always (posedge clk or negedge rst_n) begin if (!rst_n) begin clk_cnt 5b0; sclk_mid 1b0; end else if (clk_cnt 5d16) begin clk_cnt 5b0; sclk_mid 1b1; // 一个周期只产生一个周期中点脉冲 end else begin clk_cnt clk_cnt 1b1; sclk_mid 1b0; end end // 用sclk_mid去锁存数据确保避开输出翻转沿 always (posedge clk or negedge rst_n) begin if (!rst_n) begin pixel_data 16b0; pixel_valid 1b0; end else begin pixel_valid 1b0; // 默认无效只有采样时刻有效 if (sclk_mid adc_doutvalid) begin pixel_data adc_dout; pixel_valid 1b1; end end end用DOUTVALID信号做闸门只有它拉高时采的数据才有效。AD9826的DOUTVALID和图像数据的对齐关系手册里有时序图我在实际调试中也用ILAIntegrated Logic Analyzer抓过波形验证确实验证了数据是在DOUTVALID拉高之后不久就有效了。采样的时钟中点脉冲位置我做了参数化设计就是为了方便调节。如果后续发现采到的数据有毛刺可以调整这个参数往前或往后移几个系统时钟周期。3.4 数据定标与像素重组从16位原始码到可显示图像拿到16位原始数据之后不能直接往显示器上扔。AD9826默认输出是二进制补码格式也就是说满量程中点对应数字0负信号对应负数正信号对应正数。这是一种有符号表示如果直接当无符号数传给后面的图像模块画面会乱。我处理方式是判断数据MSB是否为1如果是负数就取反加一得到绝对值再移位量化到目标位宽。但更简单且常见的做法是直接把16位有符号数加上一个固定偏移转换成无符号偏移码。因为CCD信号经过CDS之后是一个正的电压差理论上应该是正值加上偏移之后变成无符号表示就很自然。差分模式下的数据定标逻辑我这样写// 二进制补码转偏移码并截取高12位用于图像显示 reg [15:0] offset_bin; reg [11:0] pixel_out; always (posedge clk or negedge rst_n) begin if (!rst_n) begin offset_bin 16b0; pixel_out 12b0; end else begin offset_bin pixel_data 16h8000; // 加偏移转偏移码 pixel_out offset_bin[15:4]; // 右移4位为截取高12位 end end加0x8000这个偏移在数学上就是把原本以0为中心的补码范围映射到0到65535的无符号整数范围。这样做的效果是黑色的像素大约在0附近白色的像素在65535附近。截取高12位是因为图像显示或者后续算法处理不一定需要完整的16位精度12位已经可以有4096级灰度了。如果做医学影像或者科学应用需要高精度可以直接保留16位。3.5 仿真与上板验证自己踩过的坑和检查方法代码写完之后我先做了行为级仿真。仿真环境里我需要给AD9826的行为建模但如果手头没有仿真模型最简单的做法是根据手册的时序参数来写一个简化模型接收SCLK按寄存器配置的输出时序产生DOUTVALID和DOUT。仿真重点关注三件事第一SPI配置是否正确写入第二AD9826的SCLK频率和占空比是否满足要求第三数据采样点是否在有效窗口内。仿真通过之后就是上板调试。我用的是Xilinx的FPGA开发板抓波形的工具是ILA核。上板调试第一件事不是看图像而是先把SCLK测一下看引脚上输出的是不是6MHz占空比是否合理。如果占空比不对后面全是玄学错误。然后抓DOUTVALID和数据。我第一次上板时发现DOUTVALID几乎一直为高数据也是乱的排查了半天结果是我把AD9826的SPI配置写错了——寄存器地址位和数据位顺序搞反了。手册上明确说了先发地址再发数据我代码里发的是现发数据再发地址检查仿真波形的时候居然没发现因为仿真模型没有严格校验。后来我把配置模块的仿真代码写得严谨了一些每个寄存器的值都验证了一遍问题就暴露出来了。这里强烈建议有条件的在AD9826数据手册里把每个寄存器的默认值、推荐值再核一遍。很多问题不是我写的代码而是寄存器配置和数据手册不符比如相位寄存器的默认值在某些版本芯片上表现不一样。4. 常见问题与排查技巧实录4.1 图像出现固定竖条纹或网纹多半不是FPGA的锅这类问题的根源往往是模拟信号质量。CCD输出到AD9826输入之间的走线如果太长、屏蔽不好或者电源噪声偏大CDS采样后叠加了共模干扰很难在后端滤除。排查的时候我习惯先用示波器看CCD输出节点、AD9826模拟输入引脚的波形。正常情况下每个像素周期对应的电压台阶应该是清晰稳定的如果看到有高频毛刺叠加在台阶上先解决模拟走线。CDS本身对低频共模干扰抑制得不错但对高频干扰效果有限。AD9826的模拟电源和数字电源要分开走最好在芯片电源引脚旁边就近放0.1uF和10uF的去耦电容。这是一个很小的细节但我见过很多项目因为这一步没做好图像质量始终上不去。4.2 数据对不上像素数和CCD实际输出数差一个CCD传感器一行像素可能是2000个但AD9826输出的数据可能是2005个或者1998个。这个问题多半是同步没找对。AD9826输出的HSYNC信号对应的图像数据在它之后的一个或两个像素周期才出现不同传感器差距很明显。我调试时用了一个笨办法也最有效CCD传感器给一个全黑遮光环境然后观察HSYNC之后输出的数据。理论上黑色像素的数值应该在零点附近如果有几个像素明显偏大那就是同步偏了。调整方法是在FPGA侧对HSYNC打拍延迟1到2个像素周期对齐数据起始位置。具体操作是在像素读取模块里加一个行同步计数器HSYNC拉高后第N个像素视为行首N根据实测调整。我在系统里做了一个寄存器来动态配置N调试时用ILA观察数据直到黑色行数据的起始位置正确为止。4.3 图像左右错位很有可能是采样相位不对这个问题的特征是对着一个竖直的对比强烈的条纹目标图像上黑白分界线左右偏移或者边缘模糊。因为CCD上同一个物理像素被采样到哪个位置取决于你对AD9826输出数据的取样时刻。如果采样点太靠近数据变化沿采到的可能是上一像素和当前像素的混合值表现出来就是边缘模糊。处理方法是微调前面提到的采样相位参数。我在代码里预留了一个samp_delay参数可以在线通过串口工具调整每次调整约3ns观察图像边缘锐度变化。实测下来当采样点落在数据窗口中间偏后35%的位置时图像表现最好。这个比例和AD9826手册上推荐的建立时间有关太多余的延时会吃进下一个像素的数据一定要注意。4.4 寄存器写不进或配置偶尔失效检查LOAD时序和SCLK频率这个问题我遇到过一次表现是芯片上电后第一次配置有效复位后再次配置偶尔失效。排查发现是我配置模块的LOAD拉高持续时间太短只有两个系统时钟周期约20ns远小于手册要求的至少一个SCLK周期的LOAD高电平时间。修改方案是LOAD拉高后保持至少四个系统时钟周期并且等SCLK完全停止在高电平之后再拉高LOAD。修改后问题没有再出现过。另外还需要注意SPI配置在SCLK下降沿发送数据这个细节。AD9826手册里有一句口吻很明确的话“Data is clocked into the part on the falling edge of SCLK。”我在仿真里一直用下降沿打数据上板的时候实际波形才反映出来。如果你用的是上升沿触发发送的SPI配置有时候能成功有时候失败很影响调试心情。4.5 一个容易被忽略的问题输出数据位序和字节顺序AD9826是16位并行输出但它在内部输出格式上有一个选择可以输出高字节在前也可以输出低字节在前。手册里配置寄存器1的bit1控制这个格式。我当时没仔细设置发现图像数据MSB和LSB颠倒整个图像变成乱码一样的噪点。配置寄存器1的bit1设为0时输出高字节优先D15是最高位设为1时则相反。我们常用的是高字节优先所以把这个位配置为0。如果你自己用的系统是小端对齐那就设1关键是和你的后续数据使用方保持一致。我第一次调的时候这个位忘设了图像出来全是雪花排查了很久才发现是数据位序问题。4.6 调试经验速查表遇到问题先去查哪里我把这段时间调试遇到的所有问题整理成一个速查表下次再遇到类似现象可以直接对号入座现象大概率原因排查优先级图像全是雪花噪点数据位序错误/采样相位严重偏移高图像有网纹模拟电源噪声/走线干扰高图像偏灰底黑电平箝位没配置好中高光处一片白PGA增益太大中整体很暗且噪声大PGA增益太小中行方向错位HSYNC对齐参数不对高图像边缘模糊采样相位偏早或偏晚中寄存器配置无效LOAD时序/数据位序错误低但调试时第一优先级5. 扩展思路与后续演进方向AD9826驱动调通只是一个起点实际项目中它前面的CCD驱动时序和后面的图像处理往往是更大的工作量。关于CCD传感器驱动时序常见的是需要FPGA产生CCD的水平转移时钟、垂直转移时钟、复位栅极脉冲等。AD9826虽然集成了CDS但并不会为CCD生成这些驱动脉冲它只是被动采样CCD输出信号。所以一个完整的图像采集系统要有两套时序引擎一套是CCD的驱动时序生成器另一套是AD9826的采样数据读取器。这两套时序必须严格同步通常做法是共用同一个像素时钟计数器从计数器的不同相位切出各自需要的脉冲。后续如果需要在FPGA侧做实时图像处理比如滤波、自动曝光、直方图均衡AD9826输出的数据流是逐像素同步的处理逻辑可以按行像素进行流水线设计。这里特别提醒一点AD9826的像素速率如果是6MHz那么一行2000像素的时间大约是333us一秒钟3000行这对于大多数FPGA的实时图像处理绰绰有余。但如果在高速应用里用满12MSPS的采样率那么数据处理管道每个像素只有约83ns的时间这时候FPGA时序布局就要格外留意了。在项目演进过程中我从AD9826转向过更现代的AFE芯片比如AD9995、ADDI7000等它们的原理和AD9826类似不过把CDS、PGA、ADC做得更精细寄存器也更多了。但有了AD9826的调试经验新芯片上手速度快很多因为底层都是相同的信号链逻辑配置、采样、锁存、数据重组。这也是我为什么把这篇时序分析和代码经验写这么细——技术会换代但方法论可以沉淀下来反复用。最后再分享一个我自己的习惯不管芯片有多老拿到数据手册先别急着写代码静下心把每一张时序图看明白把每一个参数的意义搞清楚。AD9826是一颗已经成熟了十几年的芯片资料非常全踩过的坑也都在各个老工程师的博客和论坛帖子里出现过。花半天时间研读时序图比上板瞎调一星期有效得多。
返回列表