最近在做微型光谱仪,用到了东芝的CCD芯片TCD1305DG,该芯片是单行3648像素,输出信号是时间上离散的模拟信号,典型输出速率为0.5M,即每2000ns输出一个像素值(模拟信号),芯片内部集成了相关双采样电路,直接输出稳定的像元电压值,而不是传统的三阶梯信号。TCD1305DG需要三路驱动信号,分别是主时钟CLK,移位输出信号SH,积分清除信号ICG,芯片手册上给出的时序波形如下:

图1 TCD1305DG驱动时序

该CCD的基本工作原理如下:光敏元接收外部光信号并将其转换为电荷储存在光敏元下方的电子势阱中,当积分清除栅ICG为低电平时,如果检测到转移栅SH信号下降沿,就会将电子势阱中积累的电荷转移到模拟移位寄存器中,等待ICG回到高电平后,模拟移位寄存器中的电荷就在主时钟CLK作用下逐个的输出到OS管脚上,每四个主时钟周期输出一个像素电压值,所以ICG的高电平的持续时间需保证所有的像素电荷都已经输出,故ICG的高电平持续时间称为转移时间。而ICG低电平时SH的下降沿到SH的前一个下降沿之间的时间间隔称为积分时间(如图2所示),在这段时间里光敏元不断地积累电荷,线阵CCD的成像效果与积分时间有着密切的关系。

图2 积分时间示意图

一. TCD1305DG驱动时序设计

本设计中根据TCD1305DG芯片手册将积分时间设为50us,主时钟周期为500ns,取图1中的t2为500ns,t3为2500ns,ICG低电平持续时间为8000ns,ICG高电平期间输出3696个像素值(实际上只有3694个像素,此处取为3696是为了与SH信号同步:3696 X (500 X 4) + 8000 = N*50us)。三路驱动信号的波形图设计如下:

图3 驱动信号波形设计参数

下面分别介绍这三路信号的产生方法:

1. 主时钟CLK

主时钟CLK周期为2M,可以直接对晶振分频得到,此处采用100M晶振,对其50分频就可以得到2M的时序信号,设计verilog代码如下:

//------------generate CCD_CLK, 2M-------------------
reg [5:0] cnt_clk;
always @ (posedge clk or negedge rst_n)
if(!rst_n)cnt_clk <= 6'd0;
else if(cnt_clk == 6'd49)  // 1/50 divide, 100M TO 2Mcnt_clk <= 6'd0;
else    cnt_clk <= cnt_clk + 1'b1;always @ (posedge clk or negedge rst_n)
if(!rst_n)CCD_CLK <= 1'b1;
else if(cnt_clk == 6'd25)CCD_CLK <= 1'B0;
else if(cnt_clk == 6'd0)CCD_CLK <= 1'B1;
//--------------------------------------------------

2. 移位信号SH

移位信号的周期就是积分时间,此处为50us,每个周期内的波形为500ns电平、2500ns高电平以及47000ns低电平(图3),产生SH的方法如下:首先由晶振分频产生周期为500ns的使能时钟clk1,clk1的0-490ns为低,490-0ns为高;由clk1控制计数器 cnt_sh的变化,cnt_sh每500ns计一个数,计满100个数后归零,由cnt_sh就可以生成周期为50us的时序信号SH,具体过程如图4所示:

图4 移位信号SH生成方法

根据以上原理设计verilog代码如下:

//----------generate clk1, 490ns-low, 50ns-high-------
reg clk1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)clk1 <= 1'b0;
else if(cnt_clk == 6'd49) clk1 <= 1'b1;
elseclk1 <= 1'b0;
//----------------------------------------------------//----------generate SH ----------------------------
reg [6:0] cnt_sh;
always @ (posedge clk or negedge rst_n)
if(!rst_n)cnt_sh <= 7'd0;
else if((cnt_sh == 7'd99) && clk1)  // attention!! - clk1cnt_sh <= 7'd0;
else if(clk1)cnt_sh <= cnt_sh + 1'b1;always @ (posedge clk or negedge rst_n)
if(!rst_n)SH <= 1'B0;
else if((cnt_sh == 7'd0) && clk1)SH <= 1'B1;
else if((cnt_sh == 7'd5) && clk1)SH <= 1'B0;
//--------------------------------------------------

3. 积分清除信号ICG

积分清除信号ICG的产生方法与SH的产生方法相同,由使能时钟clk1控制cnt_icg的变化,再由cnt_icg生成ICG信号,具体过程参考图4,此处仅给出对应的verilog代码:

//------------generate ICG--------------------------
reg [13:0] cnt_icg;
always @ (posedge clk or negedge rst_n)
if(!rst_n)cnt_icg <= 14'd0;
else if((cnt_icg == 14'd14799) && clk1)cnt_icg <= 14'd0;
else if(clk1)cnt_icg <= cnt_icg + 1'b1;always @ (posedge clk or negedge rst_n)
if(!rst_n)ICG <= 1'B1;
else if(cnt_icg == 14'd0)ICG <= 1'B0;
else if((cnt_icg == 14'd15) && clk1)  // 8000ns-lowICG <= 1'B1;
else if((cnt_icg == 14'd14799) && clk1) ICG <= 1'B0;
//--------------------------------------------------

二. AD芯片AD9200驱动时序设计

从CCD输出的光谱信号为时间上离散的模拟信号,经过AD转换电路后转换为数字信号输出,本设计中的AD转换芯片为AD9200,其驱动波形如下图:

图5 AD9200驱动波形

由图可知,在芯片输入时钟的上升沿采集模拟信号,经过三个时钟周期后,转换后得到的数字信号将出现在输出总线上,因此只需要为AD9200提供一个时钟信号,其频率与CCD输出频率一致,取为0.5MHz,当CCD输出一个有效像素模拟信号时,经过三个时钟周期,就可以在AD9200的输出总线上得到这个有效像素的数字信号。

像素的输出是在ICG的高电平期间进行的,所以可以将ICG的上升沿作为AD转换的启动信号,AD芯片的时钟AD_CLK与像素的输出速率一致,为0.5MHz,在AD_CLK的上升沿采集CCD输出的模拟信号,设计AD_CLK的上升沿与输出像素的中点对齐,如下图所示:

图6 AD转换时序设计图

根据图6设计verilog代码如下:

//------------generate AD_CLK-----------------------
reg AD_START;
//start AD at posedge ICG, stop AD at negedge ICG
always @ (posedge clk or negedge rst_n)
if(!rst_n)AD_START <= 1'B0;
else if(cnt_icg == 14'd0)  //negedge ICGAD_START <= 1'B0;
else if((cnt_icg == 14'd15) && clk1)  // posedge ICGAD_START <= 1'B1;reg [6:0] cnt_ad;
always @ (posedge clk or negedge rst_n)
if(!rst_n)cnt_ad <= 7'd0;
else if((cnt_ad == 7'd99) || !AD_START)  // 1/200 dividecnt_ad <= 7'd0;
elsecnt_ad <= cnt_ad + 1'b1;always @ (posedge clk or negedge rst_n)
if(!rst_n)AD_CLK <= 1'B0;
else if(cnt_ad == 7'd99)  // AD_CLK = 0.5MAD_CLK <= ~AD_CLK;
//-------------------------------------------------------

三. 完整的verilog代码

下面给出完整的verilog代码:

//CCD drive signal generate,
//output: CCD_CLK, SH, ICG
//2015/07/02module sig_gen
(input clk,  //OSC = 100Minput rst_n, //async resetoutput reg CCD_CLK,  //clock for CCD, 2Moutput reg SH,  output reg ICG,output reg AD_CLK  //clock for AD
);//------------generate CCD_CLK, 2M-------------------
reg [5:0] cnt_clk;
always @ (posedge clk or negedge rst_n)
if(!rst_n)cnt_clk <= 6'd0;
else if(cnt_clk == 6'd49)  // 1/50 divide, 100M TO 2Mcnt_clk <= 6'd0;
else    cnt_clk <= cnt_clk + 1'b1;always @ (posedge clk or negedge rst_n)
if(!rst_n)CCD_CLK <= 1'b1;
else if(cnt_clk == 6'd25)CCD_CLK <= 1'B0;
else if(cnt_clk == 6'd0)CCD_CLK <= 1'B1;
//--------------------------------------------------//----------generate clk1, 490ns-low, 50ns-high-------
reg clk1;
always @ (posedge clk or negedge rst_n)
if(!rst_n)clk1 <= 1'b0;
else if(cnt_clk == 6'd49) clk1 <= 1'b1;
elseclk1 <= 1'b0;
//----------------------------------------------------//----------generate SH ----------------------------
reg [6:0] cnt_sh;
always @ (posedge clk or negedge rst_n)
if(!rst_n)cnt_sh <= 7'd0;
else if((cnt_sh == 7'd99) && clk1)  // attention!! - clk1cnt_sh <= 7'd0;
else if(clk1)cnt_sh <= cnt_sh + 1'b1;always @ (posedge clk or negedge rst_n)
if(!rst_n)SH <= 1'B0;
else if((cnt_sh == 7'd0) && clk1)SH <= 1'B1;
else if((cnt_sh == 7'd5) && clk1)SH <= 1'B0;
//--------------------------------------------------//------------generate ICG--------------------------
reg [13:0] cnt_icg;
always @ (posedge clk or negedge rst_n)
if(!rst_n)cnt_icg <= 14'd0;
else if((cnt_icg == 14'd14799) && clk1)cnt_icg <= 14'd0;
else if(clk1)cnt_icg <= cnt_icg + 1'b1;always @ (posedge clk or negedge rst_n)
if(!rst_n)ICG <= 1'B1;
else if(cnt_icg == 14'd0)ICG <= 1'B0;
else if((cnt_icg == 14'd15) && clk1)  // 8000ns-lowICG <= 1'B1;
else if((cnt_icg == 14'd14799) && clk1) ICG <= 1'B0;
//--------------------------------------------------//------------generate AD_CLK-----------------------
reg AD_START;
//start AD at posedge ICG, stop AD at negedge ICG
always @ (posedge clk or negedge rst_n)
if(!rst_n)AD_START <= 1'B0;
else if(cnt_icg == 14'd0)  //negedge ICGAD_START <= 1'B0;
else if((cnt_icg == 14'd15) && clk1)  // posedge ICGAD_START <= 1'B1;reg [6:0] cnt_ad;
always @ (posedge clk or negedge rst_n)
if(!rst_n)cnt_ad <= 7'd0;
else if((cnt_ad == 7'd99) || !AD_START)  // 1/200 dividecnt_ad <= 7'd0;
elsecnt_ad <= cnt_ad + 1'b1;always @ (posedge clk or negedge rst_n)
if(!rst_n)AD_CLK <= 1'B0;
else if(cnt_ad == 7'd99)  // AD_CLK = 0.5MAD_CLK <= ~AD_CLK;
//-------------------------------------------------------endmodule

以上代码已经过仿真验证,可以准确地生成CCD和AD的驱动时序。

转载于:https://www.cnblogs.com/xiaoxie2014/p/4623735.html

东芝线阵CCD芯片TCD1305DG驱动时序设计相关推荐

  1. 利用STM32的定时器中断功能编写线阵CCD(ILX554B)的驱动时序

    利用STM32的定时器中断功能编写线阵CCD(ILX554B)的驱动时序 1.利用定时器完成线阵CCDILX554B的驱动时序,采用两个管脚1个用于产生ROG信号,一个用于产生CLK信号 2.使用一个 ...

  2. 基于FPGA的线阵CCD实时图像采集系统

    基于FPGA的线阵CCD实时图像采集系统 2015年微型机与应用第13期 作者:章金敏,张 菁,陈梦苇 2016/2/8 20:52:00 关键词: 实时采集 电荷耦合器件 现场可编程逻辑器件 信号处 ...

  3. 基于FPGA的线阵CCD图像测量系统研究——笔记

    本文是对基于FPGA的线阵CCD图像测量系统研究(作者:高尚)的阅读笔记 第一章绪论 1. 读读看 读了前面的摘要依然没有看懂作者要做什么.接着往下读....终于看到了一个字眼"基于机器视觉 ...

  4. 线阵CCD FPGA CCD测量 直径测量 FPGA代码 CCD光学传感器 TCD1501

    线阵CCD FPGA CCD测量 直径测量 FPGA代码 CCD光学传感器 TCD1501,自制USB接口线阵CCD驱动板及核心控制电路板四层单板,包括FPGA线阵CCD驱动程序&STM32单 ...

  5. 线阵CCD相机与面阵相机的区别

    一.线阵相机 线阵CCD工业相机主要应用于工业.医疗.科研与安全领域的图象处理.在机器视觉领域中,线阵工业相机是一类特殊的视觉机器.与面阵工业相机相比,它的传感器只有一行感光元素,因此使高扫描频率和高 ...

  6. 线阵CCD(摄像机)与面阵CCD(摄像机)的区别

    (1)线阵CCD图像传感器是由一列MOS(金属-氧化物-半导体)光敏单元和一列CCD移位寄存器并行而构成的.如果要用线阵CCD获取二维图像,必须配以扫描运动,而且为了能确定图像每一像素点在被测件上的对 ...

  7. LCAMV06-TCD1304线阵CCD模组

    LCAMV06-TCD1304线阵CCD模组 LCAMV06系列是我司自主研发的低噪声线阵CCD模组 ,搭配TCD1304 sensor,电路采用了16bit专业ccd处理器,有TTL接口和Micro ...

  8. 线阵CCD和面阵CCD

        面阵CCD的优点是可以获取二维图像信息,测量图像直观.缺点是像元总数多,而每行的像元数一般较线阵少,帧幅率受到限制,因此其应用面较广,如面积.形状.尺寸.位置,甚至温度等的测量.由于生产技术的 ...

  9. DALSA线阵CCD相机开发 之 OpenCV配置

    DALSA线阵CCD相机开发 之 OpenCV配置 如果出现以下情况: 在VS MFC中其他程序使用加载OpenCV没有问题. 在dalsa中可以包含头文件,并且代码输入时有提示OpenCV的函数,同 ...

最新文章

  1. 一起聊聊好玩的Openresty
  2. 这些Java8官方挖的坑,你踩过几个?
  3. 微型计算机步进电机控制,步进电机的微型计算机控制
  4. 阿里云API网关相关操作
  5. 深度学习表征的不合理有效性——从头开始构建图像搜索服务(一)
  6. 2纳米芯片问世!芯片性能要起飞?!
  7. Appium移动自动化测试之获取appPackage和appActivity
  8. oracle 主键列创建自增长,powerdesigner创建oracle 数据库表,设置表主键列为自动增长。 ....
  9. PHP5.3以上版本没有libmysql.dll,以及由此带来的困扰
  10. TextureMerger1.6.6 一:Egret MovieClip的制作和使用
  11. 服务器Linux系统下常见的软件包有哪些
  12. php微信开发之微信卡券
  13. 我的世界服务器无限时间,我的世界无限时间版本
  14. python中ttk_ttk/Python中的按钮图像问题
  15. xlsx表格怎么筛选重复数据_excel怎么筛选两个表中相同数据
  16. 将m3u8文件转MP4、TS、flv、mkv等文件
  17. java二级程序题两个角度_两个角度图_【SCME大一】使用JAVA语言深入理解程序逻辑答案_学小易找答案...
  18. Figma又崩了,但我们P事没有
  19. 西瓜口袋拼团商城系统搭建相关问题
  20. UI基础一:简单的BOL查询

热门文章

  1. 我对ChatGPT的一些看法与思考
  2. 20 | 搞清楚幻读本质(搞清楚什么读?搞什么幻读?什么清楚幻读)
  3. 小唐开始学 Spring Boot——(1)IDEA 2021.3.2和Maven的安装配置
  4. 提升电脑开机速度,解决大部分开机缓慢问题
  5. android的cooipad手机,苹果COO库克:Android平板电脑是大号智能手机
  6. 面试新媒体运营你学会了吗
  7. 「内容管理系统」34个无头CMS应该在你的技术雷达上
  8. 攻防世界 来自银河的信号
  9. 小程序开发时openid和unionid
  10. 想要使用C#编程创建3D PDF转换器?Aspose.PDF必不可少!