东芝线阵CCD芯片TCD1305DG驱动时序设计
最近在做微型光谱仪,用到了东芝的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 2M
- cnt_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;
- else
- clk1 <= 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!! - clk1
- cnt_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-low
- ICG <= 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 ICG
- AD_START <= 1'B0;
- else if((cnt_icg == 14'd15) && clk1) // posedge ICG
- AD_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 divide
- cnt_ad <= 7'd0;
- else
- cnt_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.5M
- AD_CLK <= ~AD_CLK;
- //-------------------------------------------------------
三. 完整的verilog代码
下面给出完整的verilog代码:
- //CCD drive signal generate,
- //output: CCD_CLK, SH, ICG
- //2015/07/02
- module sig_gen
- (
- input clk, //OSC = 100M
- input rst_n, //async reset
- output reg CCD_CLK, //clock for CCD, 2M
- output 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 2M
- cnt_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;
- else
- clk1 <= 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!! - clk1
- cnt_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-low
- ICG <= 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 ICG
- AD_START <= 1'B0;
- else if((cnt_icg == 14'd15) && clk1) // posedge ICG
- AD_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 divide
- cnt_ad <= 7'd0;
- else
- cnt_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.5M
- AD_CLK <= ~AD_CLK;
- //-------------------------------------------------------
- endmodule
以上代码已经过仿真验证,可以准确地生成CCD和AD的驱动时序。
东芝线阵CCD芯片TCD1305DG驱动时序设计的更多相关文章
- 基于FPGA的线阵CCD实时图像采集系统
基于FPGA的线阵CCD实时图像采集系统 2015年微型机与应用第13期 作者:章金敏,张 菁,陈梦苇2016/2/8 20:52:00 关键词: 实时采集 电荷耦合器件 现场可编程逻辑器件 信号处理 ...
- 基于FPGA的线阵CCD图像测量系统研究——笔记
本文是对基于FPGA的线阵CCD图像测量系统研究(作者:高尚)的阅读笔记 第一章绪论 1. 读读看 读了前面的摘要依然没有看懂作者要做什么.接着往下读....终于看到了一个字眼“基于机器视觉的图像测量 ...
- 线阵CCD-TCD1209采集系统&驱动设计
关键字:CPLD+AD9945+TCD1209+CY7C68013A TCD1209,一款经典的CCD线阵单色传感器.本次设计一款基于usb2.0高速采集图像. CPLD+AD9945+TCD1209 ...
- LCD显示--Ht1621b芯片显示屏驱动
Ht1621b芯片显示屏驱动 关于HT1621b芯片的具体信息能够參考数据手冊上的内容:百度文库HT1621b中文资料 CS : 片选输入接一上拉电阻当/CS 为高电平读写HT1621的数据和命令无效 ...
- 基于STM32F1的时钟芯片DS1302驱动
目录 DS1302.h源代码 DS1302.c源代码 DS1302.h源代码 /** ********************************************************* ...
- 关于basler线阵相机和Mtrox采集卡的安装
说明: 本系列博文是我自己研究生课题,采用做一步记录一步,在论文答辩结束或者机器设计结束之后才会附上源代码! 以前都是用opencv,直接拿个照片去处理,基本都是软件的使用,这次做课题要用到Matro ...
- 基于STM32F1的语音合成芯片SYN6288驱动
目录 说明 SYN6288.h SYN6288.c 说明 基于USART2制作,封装了各种通信协议 SYN6288.h #ifndef _SYN6288_H_ #define _SYN6288_H_ ...
- Linux设备驱动框架设计
引子 Linux操作系统的一大优势就是支持数以万计的芯片设备,大大小小的芯片厂商工程师都在积极地向Linux kernel提交设备驱动代码.能让这个目标得以实现,这背后隐藏着一个看不见的技术优势:Li ...
- [连载]《C#通讯(串口和网络)框架的设计与实现》-3.设备驱动的设计
目 录 第三章 设备驱动的设计... 2 3.1 初始化设备... 4 3.2 运行设备接口设计... 4 3.3 ...
随机推荐
- Spring boot 入门三:SpringBoot用JdbcTemplates访问Mysql 实现增删改查
建表脚本 -- create table `account`DROP TABLE `account` IF EXISTSCREATE TABLE `account` ( `id` int(11) NO ...
- Linux排查Java程序占用CPU很高的解决办法
Java的工具集相当强大,学习成本也很低,处理线上问题时,jstack这个工具就比微软的windbg,好学好用很多,3步找出占用CPU很高的源所在.而windbg反人类的各种命令,实在不敢恭维. 故意 ...
- ubuntu下使用python3的有些库时,解决"raise ImportError(str(msg) + ', please install the python3-tk package') ImportError: No module named '_tkinter', please install the python3-tk package"的错误
问题: 在Ubuntu下使用matplotlib这个库时,运行时出现如下错误: raise ImportError(str(msg) + ', please install the python3-t ...
- Android开发时,那些相见恨晚的工具或网站!
本文来我在知乎话题Android开发时你遇到过什么相见恨晚的工具或网站?下的回答! 在实际Android开发过程确实会有很多相见恨晚的工具或网站出现,下面是我自己的一些分享. 1.源码网站 https ...
- RadioGroup实现类似ios的分段选择(UISegmentedControl)控件
在ios7中有一种扁平风格的控件叫做分段选择控件UISegmentedControl,控件分为一排,横放着几个被简单线条隔开的按钮,每次点击只能选择其中一个按钮,他类似于tabbar但是又稍微有点区别 ...
- zookeeper应用 - 配置服务
一端不停的更新配置,另一端监听这个配置的变化. 需要注意的是:监听端不一定读取到所有的变化.在zk服务器发送通知到客户端,客户端读取数据注册监听之间可能发生了多次数据变化,这些数据变化是得不到 ...
- Claims-based认证解析
Claims-based认证相关的两个重要的类ClaimsIdentity以及ClaimsPrincipal解析 ClaimsIdentity以及ClaimsPrincipal是.NET下Claims ...
- Re:LieF ~親愛なるあなたへ~ 后感
遇到烦恼就能有个安逸的地方逃避.这个想法真好.遗憾现实并不能如此.若是觉得这款纯爱作有些许的感人之处,那定时因为受众玩家正在通过玩游戏来逃避现实.“虚拟世界的感情是真实的.” 这件事在旁人看来或许是笑 ...
- Windows 安装 python MySQLdb模块
pip install wheel 去这个网站查找whl格式的MYSQL-python http://www.lfd.uci.edu/~gohlke/pythonlibs/#mysql-python ...
- C#判断奇偶数的函数
// 现代流行的"程序员"public static bool IsOdd(int n) { while (true) { switch (n) ...