ARTICLE DETAIL

资讯详情

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

FPGA+CIS图像采集系统实战:AD9822时序设计与调试

FPGA+CIS图像采集系统实战:AD9822时序设计与调试 用FPGA拼图像采集这种活说难不算难说简单也真不简单。尤其是接到一个带接触式图像传感器CIS的扫描类项目信号链长、时序环节多从传感器驱动到模拟前端再到FPGA数据采集哪一环没对齐出来的图像就是花屏、条纹、或者亮度不均匀排查起来极其耗时间。前阵子我刚好完成了一套基于FPGA加AD9822的CIS高速图像采集系统目标是300DPI扫描分辨率实测整行采集、连续扫描都稳定想把这个项目的整体思路、关键设计和时序调试心得整理出来给正在做类似图像采集方案的朋友一个参考。这套系统能做的事情通俗讲就是把CIS传感器输出的一行模拟信号通过AD9822做相关双采样和模数转换再由FPGA控制像素节拍、完成数据接收、缓存和上传。对于做文档扫描、票据识别、嵌入式图像处理的人来说这套方案可以直接落地也能作为学习FPGA高速接口和模拟前端时序控制的项目模板。我会把方案选型、AD9822的配置、FPGA时序设计、以及我亲手踩过的调试坑都写清楚尽量不保留。其实这类项目最核心的地方不在于某一个模块多复杂而在于“每个环节的时间关系是否严丝合缝”CIS的驱动时序、AD9822的采样窗口、FPGA的读取节拍这三个东西必须在一个时钟体系下协调工作。一旦把这条时间链理顺了剩下的就是寄存器配置和数据搬运的问题了。1. 项目整体设计与方案选型思路1.1 为什么是FPGA而不是MCU或DSP很多人做图像采集第一反应是用带DCMI接口的单片机或者DSP但遇到CIS这种需要精细模拟信号采样控制的场景MCU就不太够用了。CIS传感器本身不带复杂的时序生成电路SP、CL1、CL2这些驱动信号需要外部主动给而且采样像素时钟一旦跑起来就是几兆赫兹的持续数据流MCU用IO翻转模拟时序不仅CPU占用高抖动也大直接会影响图像稳定性。FPGA的优势在于所有时序都由硬件并行产生时钟边界稳定像素时钟和采样控制能做到确定性的延迟。调试时还能用逻辑分析仪抓到内部信号修改时序只需要改RTL重新综合不用动PCB。所以在这个项目里FPGA负责三件事生成CIS驱动时序、配置AD9822并接收转换数据、做数据缓存和接口上传。整个系统没有CPU干涉数据通路图像采集效率很高。1.2 选CIS而不是CCD的理由图像传感器这块CIS和CCD是两条不同路线。CCD灵敏度高、动态范围好但需要多路高压驱动时钟电路复杂功耗也高。CIS内部把光电二极管和移位寄存器集成在一起直接输出模拟电压信号驱动时钟简单模块体积轻薄特别适合扫描仪、点钞机、证件识读这类场景。这套项目选CIS还有一个现实原因CIS是接触式传感器光学系统几乎不需要镜片和光路调校传感器贴着稿面走结构设计简单很多。300DPI的分辨率对CIS来说属于常规操作如果光源均匀性控制好图像质量足够满足文档归档和OCR识别要求。但CIS也有个痛点就是模拟输出信号微弱容易受干扰所以模拟前端的处理能力直接决定了图像质量。1.3 AD9822在系统里的角色AD9822是ADI出的一款三通道16位模拟前端芯片专门为扫描仪和CIS/CCD传感器设计。它内部集成了相关双采样CDS电路、可编程增益放大器PGA和16位ADC当然每个通道还可以独立配置增益和失调这样RGB三路信号或者多路CIS输出都能分别调节。CIS输出的模拟信号不是干净的直流电平而是一段时间内先被复位、再被光照积分最后输出到模拟总线上的过程。在这个过程中复位电平会叠加噪声如果直接把信号给ADC图像上会出现明显的固定模式噪声和列噪声。AD9822的CDS电路会先采样复位电平再采样信号电平两者相减把共模噪声和复位噪声消掉只留下有效积分信号。这就是为什么选AD9822而不直接用一个普通ADC的原因。1.4 系统整体架构和信号流整个系统可以分成四个大块。传感器板上的CIS输出模拟信号经过抗混叠滤波后进入AD9822AD9822完成CDS采样和A/D转换输出16位并行数据FPGA作为主控根据行列时序生成CIS驱动信号同时接收AD9822的数据并写入FIFO最后数据通过USB或者以太网接口上传到上位机显示。我用的FPGA是Xilinx Artix-7系列自带丰富的IO资源和Block RAMFIFO可以直接用IP核生成省了不少事。FPGA和AD9822之间是3线SPI配置接口加并行数据接口CIS和FPGA之间则是一组驱动时钟信号加模拟输出。整体布线上我特意把模拟区域和数字区域做了分地处理AD9822的模拟电源和数字电源分别滤波这个对后续图像质量影响很大后面会单独说。2. AD9822配置要点与CDS采样原理2.1 AD9822内部结构和关键信号AD9822从功能上看是一条完整的模拟采集链路。每个输入通道的模拟信号先进钳位电路然后进入CDS相关双采样模块经过PGA放大后送给16位ADC量化最终通过并行数据总线输出。芯片的配置接口是标准三线SPI主机写入寄存器即可设置增益、失调、工作模式和采样时序。芯片上几个关键信号需要特别注意。MCLK是主时钟输入所有内部转换时序都由它产生数据输出也是和它同步的。CDS模块有两个内部采样保持开关分别采集复位电平和信号电平这两次采样的间隔和顺序由MCLK相位决定所以MCLK的质量直接影响采样精度。SLOAD、SDAT、SCLK三个引脚是SPI配置口上电后需要先写寄存器芯片才能按预期模式工作。2.2 相关双采样到底在做什么CIS的像元输出信号中复位噪声是主要的非理想因素。每次像素复位后光敏二极管上的残余电荷会有一个不确定量这个不确定量叠加在后续的信号上就形成了噪声。CDS的思路是先把这个像素的复位电平采样保持下来等积分信号出来后再采样信号电平然后将两者相减复位阶段的不确定量就被抵消了。这个原理很像拿一个天平称东西先把空盘子重量清零再放上物品称量得到的就是净重量。从频域上看复位噪声主要集中在低频CDS相当于一个高通滤波器能把这部分噪声压下去。AD9822内部就是干这个事的如果禁用CDS直接用单端采样图像的暗部会非常脏所以配置的时候务必打开CDS功能。2.3 寄存器配置流程和关键参数AD9822有多个配置寄存器需要按照芯片手册写入。配置时首先设置工作模式把CDS使能、ADC分辨率、输出格式等参数确定下来。然后是PGA增益和失调校准增益根据CIS信号的幅度来定失调则用于调整黑电平。最后设置采样时序相关的寄存器确定CDS采样点在MCLK周期中的位置。我在这个项目里用了6MHz的主时钟每通道16位输出。PGA增益设在2倍左右因为CIS输出幅度大约0.5V到1.2VAD9822输入满量程约3V留出余量防止饱和。失调寄存器先写零然后通过上位机看黑电平值再反向修正。配置完成后一定要读回寄存器验证防止SPI时序毛刺导致配置错误。2.4 配置过程中容易犯的错AD9822的SPI接口是标准三线但很多人第一次调的时候容易把数据手册上的时序图看错导致寄存器写入失败。实际调试时可以在FPGA里用ILA逻辑分析仪抓SLOAD、SCLK和SDAT三根线对比手册时序确认波形对了再往下走。另一个常见错误是配置完寄存器后没有做有效的复位造成某些通道PGA设置没生效输出图像三条颜色亮度不一致。我建议上电后先等待电源稳定和时钟稳定再执行SPI配置配置完成后软复位一次然后通过读寄存器确认所有值。这个过程我封装成了一个状态机每次初始化时自动执行很方便。3. FPGA侧关键逻辑与时序设计3.1 时钟规划与跨时钟域处理这套系统里FPGA至少涉及两个频率域一个是像素时钟域用来驱动CIS和采样AD9822的数据这个时钟是6MHz另一个是系统时钟域用来控制FIFO读写、USB上传等我跑的是100MHz。两个时钟域之间用异步FIFO缓冲像素数据避免数据丢失和亚稳态。异步FIFO我用Xilinx的FIFO Generator IP生成读时钟100MHz写时钟6MHz数据位宽16位深度4096足够缓存一整行CIS数据。需要注意FIFO的空满信号从不同时钟域传递IP内部会自动做两级同步处理但我们在逻辑里判断空满时也要留出几个周期的余量防止边界情况读空或写满。3.2 CIS驱动信号的产生方法CIS传感器需要三组定时信号SP是移位脉冲代表一行的开始CL1和CL2是两相传输时钟控制内部电荷转移和模拟输出节拍。以我用的CIS为例在SP高电平期间内部寄存器载入当前行信号之后每个CLK周期输出一个像素的模拟电压。在FPGA里实现就是一组计数器加组合逻辑。用6MHz像素时钟作为基准每个像素周期输出一个移位脉冲每采集完一行像素数量就拉高一次SP作为行同步同时传感器开始下一行的转移。关键是SP的宽度和位置要跟CIS手册的数据表对齐有些传感器要求SP在CLK高电平期间有效有些要求在低电平期间有效做错了会整行错位或图像翻转。3.3 AD9822像素数据的同步接收AD9822在MCLK的驱动下输出转换结果数据在时序上不是和MCLK严格同沿的一般在MCLK的下降沿之后输出有效。FPGA接收时需要在MCLK的上升沿采样数据并且要在采样路径上多打几拍消除IO延迟带来的建立保持问题。我实际用的接收逻辑很简单就是两级触发器打拍。第一级用MCLK上升沿抓Dout第二级再打一拍保证进入FIFO的数据在后续逻辑里稳定。这里有一个细节MCLK不能直接作为FPGA内部全局时钟使用因为它是外部引入的高频时钟直接驱动普通逻辑容易造成布局布线困难。更好的方式是用MMCM或者BUFG处理或者把MCLK当作普通信号采样内部逻辑全部用系统时钟跑。3.4 行缓存与数据拼接逻辑AD9822输出的是16位并行数据但每个像素对应几个通道的数据还需要按行重组。对于单色CIS一行像素就是一个16位灰度值直接写入FIFO即可。如果是RGB三通道CISAD9822的三个通道会同时输出三个16位数据需要在FPGA里做一下数据拼接按R、G、B顺序打包或者分别存储。我做的项目是单色CIS所以省了一步拼接。但为了以后扩展彩色扫描我在逻辑里预留了一个通道选择寄存器可以配置当前启用哪个通道或者按RGB顺序输出。这个设计很值得推荐因为硬件不用改只需要更新FPGA配置就能适配不同CIS类型。3.5 核心Verilog代码思路整体逻辑我拆成了几个模块clk_gen产生像素时钟和复位信号cis_driver生成SP、CL1、CL2ad9822_cfg通过SPI配置AD9822ad9822_capture接收16位像素数据并写入FIFOfifo_wrapper封装异步FIFO顶层模块把数据送上传接口。用Verilog写起来并不复杂关键代码逻辑大概是这样的。// CIS行时序发生器 always (posedge clk_pixel or negedge rst_n) begin if (!rst_n) begin cnt_pixel 0; sp 0; clk1 0; clk2 0; end else begin clk1 ~clk1; clk2 ~clk1; if (cnt_pixel PIXELS_PER_LINE - 1) begin cnt_pixel 0; sp 1; end else begin cnt_pixel cnt_pixel 1; sp 0; end end end// AD9822数据采样使用系统时钟域处理 always (posedge clk_sys or negedge rst_n) begin if (!rst_n) begin dout_r1 0; dout_r2 0; end else begin dout_r1 ad9822_dout; dout_r2 dout_r1; end end当然这是简化的示意实际项目里还要处理AD9822的MCLK相位调节、FIFO空满使能控制、上位机握手信号等。总的思想是所有时序都以像素时钟为基准数据进入FIFO后与系统时钟域解耦。4. 时序调试心得与问题排查实录4.1 先看模拟波形再调数字逻辑我调试这套系统时第一步不是抓FPGA内部信号而是用示波器看CIS输出到AD9822输入端的模拟波形。这一步很关键CIS输出信号是否正确直接决定后面所有数字处理有没有意义。用示波器单次触发抓SP信号上升沿然后看模拟输出应该出现一个跟随像素节拍的阶梯波形。正常波形应该是SP高电平之后模拟输出端出现一串脉冲状波形每个像素周期有一个平台期平台幅值随着灰度变化。如果看到的是一条近似直线多半是CIS驱动时序没对或者传感器供电有问题。如果波形有脉冲但是幅度极小可能CIS曝光时间不够或者光源没亮。模拟波形没问题了再进数字调试不然容易把问题带偏。4.2 数据错位和图像偏移的排查一次调试中发现图像整体偏移了一段就跟我之前设想的SP时序位置有关。查了CIS手册发现SP需要在CLK的某个相位之后拉高我原来写的SP和CLK同沿变化正好差了半个周期导致传感器第一个像素输出的是无效数据。把SP拉高时间调整到CLK上升沿之后的第二个像素时钟上升沿图像位置马上正常了。这个问题的启发是CIS的SP时序不能用“看差不多”的方式去写必须对着数据手册的时序图逐拍分析并且用逻辑分析仪抓FPGA输出的SP、CL1、CL2确认与手册保持一致。很多CIS手册还会给出SP最小脉宽、CLK高低电平最小时间等参数都需要在综合时满足。4.3 CDS采样点位置对图像的影响还有一次图像出现从左到右逐渐变暗、中间夹杂一条条竖条纹的现象一开始以为是光源没做匀光后来排查发现是AD9822的CDS采样位置没设对。AD9822内部采样点可以在MCLK周期内调整如果采样点落在模拟信号上升沿或者下降沿附近采到的电压就不稳定图像就会出现亮度不均或条纹。我在寄存器里把CDS采样点向后调了一小段时间让采样窗口稳稳落在模拟信号的平台区图像亮度随即变得均匀。做这类调试时最好用灰度测试卡或者均匀白纸做输入这样图像亮度变化可以直接反映采样点位置是否合适比自己猜效率高得多。4.4 电源噪声和PCB布局的教训AD9822属于模拟前端芯片对电源噪声特别敏感。我第一次布板时模拟3.3V和数字3.3V用了同一个LDO输出结果图像上出现周期性噪声条纹怎么看都不像时序问题。后来把模拟电源和数字电源分开供电模拟区域的地单点连接噪声立即没了。经验是无论FPGA资源多紧张模拟前端供电不能省。AD9822的AVDD和DRVDD要用不同LDO或者至少做好磁珠隔离模拟地和数字地单点连接AD9822的REF引脚旁边放高质量去耦电容这些细节不处理好图像信噪比会差很多而且很难在软件和逻辑层面弥补。4.5 连续扫描丢行问题的定位单行采集调通后开始连续扫描时出现了丢行现象表现在上位机接收的图像每隔几行就有一条黑线。用ILA抓FIFO空满信号发现是FIFO满了之后写使能被拉低导致后续像素数据丢失。原因是我上位机的USB读取速率跟不上CIS连续采集速率FIFO来不及被读走就写满了。解决办法有两个一是降低连续扫描时的像素时钟把6MHz降到4MHz二是在FPGA端增加双缓冲机制一帧数据写FIFO、同时另一帧通过DMA上传避免读写互锁。我后来用了双缓冲加USB批量传输丢行问题彻底解决。5. 300DPI分辨率换算与系统性能分析5.1 300DPI对应的像素数量和行数所谓300DPI是指在每英寸长度上采样300个像素点。那么扫描宽度为216mm约等于A4纸宽度时需要的像素数为216毫米除以25.4得到8.5英寸再乘以300DPI等于2551像素。考虑到CIS传感器边缘可能有无效像素实际选型我用的是2700像素的CIS中间2551个像素归一化后作为有效数据。纵向分辨率同样受步进电机或走纸速度影响。如果走纸步距是0.085毫米即每步0.0033英寸那么纵向采样密度也接近300点每英寸。FPGA需要根据编码器或步进脉冲每隔固定距离采集一行。我这边是固定行频连续采集上位机根据速度信息做行距校准也能达到精确300DPI。5.2 数据率和存储带宽计算图像数据率计算很简单像素时钟6MHz16位灰度单通道数据率就是96Mbps约12MB/s。如果扫描一页A4纸3500行每行2700像素每像素2字节一页的数据量大约是18.9MB。以当前12MB/s的采集速率扫一页大约需要1.6秒左右。如果改成彩色RGB三通道每像素6字节数据量翻三倍整页大约56MB1.6秒的扫描时间会变成4秒多。这时候12MB/s的速率就不够看了需要提高像素时钟或者压缩传输数据。所以项目预留了JPEG压缩接口在FPGA里如果带宽不够可以先做无损压缩再上传。5.3 系统瓶颈和优化方向这套系统目前的瓶颈主要在传输接口而不是FPGA内部处理。如果后续做更高分辨率或更高速度的扫描可以改用千兆以太网或者USB3.0传输FPGA端的FIFO深度也要相应增大。另一个优化方向是流水线设计CIS采集、数据预处理、图像传输三级流水化减少等待时间。我也考虑过在FPGA内做实时坏点校正因为CIS使用时间长了会出现少量固定坏点表现为一行上某个像素始终偏亮或偏暗。FPGA内做一个简单的坏点表检测到坏点位置就用相邻像素均值替换对图像质量提升很明显。5.4 实测效果评估整个系统调通后我用标准分辨率测试卡做了扫图评估300DPI下水平分辨率测试线可以清晰分辨没有明显的花屏、条纹和亮度不均。OCR软件对扫描后的文档识别率也达到预期。可以说这套FPGAAD9822CIS的方案性能上满足普通的300DPI扫描需求而且因为FPGA可重构后续增加算法处理也很方便。实测中我还发现一个有意思的现象光源的色温和亮度对图像影响很大。如果光源偏暗PGA增益就得调高但噪声也会跟着放大。后来我加了一个光源亮度传感器反馈到FPGA动态调整曝光时间和PGA增益图像稳定性提升了一个档次。6. 一些总体体会和后续扩展建议这套FPGAAD9822方案做下来我个人最大的感受是硬件设计和软件调试要同时进行很多问题表面看是代码逻辑错误实际上是芯片时序或电源设计的问题。比如CDS采样点调整虽然是通过寄存器设置但根本上取决于模拟波形的好坏。所以建议做类似项目的朋友模拟前端部分多留测试点方便示波器抓波形。还有一个经验是芯片手册里的时序参数要逐项对照。CIS的SP脉宽、CLK高低电平时间、AD9822的MCLK建立保持时间、数据输出延迟这些参数全部要确认你的设计能满足不能想当然。我花了最多时间的地方恰恰是不起眼的SP时序而不是AD9822的配置。后续这个项目的扩展空间挺大的。可以在FPGA里加入自动增益控制和坏点校正提高图像一致性也可以把传输接口升级到USB3.0实现更高帧率连续扫描。如果做彩色扫描可以把AD9822三通道全部利用起来配套RGB三路LED光源实现真彩色图像采集整套硬件不用大改。希望这篇文章对打算做CIS图像采集的朋友有点帮助至少可以少走一些我踩过的弯路。
返回列表