介绍:
TLC549是 TI公司生产的一种低价位、高性能的8位 A/D转换器,采用了CMOS工艺,它以8位开关电容逐次逼近的方法实现 A/D转换,其转换速度小于 17us,最大转换速率为 40Khz,4MHZ典型内部系统时钟,电源为 3V至 6V。采用三线串行接口方式与各种微处理器连接,构成各种廉价的测控应用系统。
工作原理
REF+:正基准电压输入 2.5V≤REF+≤Vcc+0.1。
REF-:负基准电压输入端,-0.1V≤REF-≤2.5V。且要求:(REF+)-(REF-)≥1V。
GND:接地端。
CS:芯片选择输入端,要求输入高电平 VIN≥2V,输入低电平 VIN≤0.8V。
DATA OUT:转换结果数据串行输出端,与 TTL 电平兼容,输出时高位在前,低位在后。
ANALOG IN:模拟信号输入端,0≤ANALOGIN≤Vcc,当 ANALOGIN≥REF+电压时,转换结果为全“1”(0FFH),ANALOGIN≤REF-电压时,转换结果为全“0”(00H)。
I/O CLOCK:外接输入/输出时钟输入端,同于同步芯片的输入输出操作,无需与芯片内部系统时钟同步。
运用:
时序图:
根据工作时序所示。
当CS为高时,数据输出(DATA OUT)端处于高阻状态,此时I/O CLOCK不起作用。
当CS为低时,AD前一次转换的数据A的最高位A7立马出现在数据线DATA OUT上,其余七位在I/O CLOCK的下降沿依次由时钟同步输出,,所以可在I/O CLOCK的上升沿读取数据,从第8个 I/O CLOCK 信号的下降沿使片内采样/保持电路进入保持状态并启动 A/D开始转换。片选信号CS置高,每次转换不超过17us,开始于CS拉低后的第八个I/O CLOCK的下降沿,没有转换完成标志,没有启动控制端,只要读取前一次数据后就马上可以开始新的AD转换,转换完成进入保持状态。其中需要注意的是:tsu(cs)至少要1.4us;2.I/O CLOCK不能超过1.1MHz。
接线图:
实验目的:可以用FPGA得到TLC549输出的数据
模块框图:
状态图:
模块代码
module ad1549(
input wire data_dat,
input wire rst,
input wire clk,
output reg dat_clk,
output reg cs,
output reg flag_data,
output reg [7:0]data_out
);
parameter IDLE = 3'b001,
ONE = 3'b010,
TUW = 3'b100;
parameter sum_7_max =3'd7;
parameter sum_1mh_max =10'd999;
parameter sum_cs_max =11'd1_999;
parameter sum_20us_max =15'd1_999_9;
parameter sum_cs_f_max =16'd4_999_9;
reg data_dat1;
reg data_dat2;
reg [0:2] state;
reg sum_cs_flag;
reg [0:9]sum_1mh;
reg [0:2]sum_7;
reg [0:10]sum_cs;
reg [0:14]sum_20us;
reg [0:15]sum_cs_f;
reg [7:0]data_out_s;
//对其数据
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
data_dat1 <= 1'd0;
else
data_dat1 <= data_dat;
end
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
data_dat2 <= 1'd0;
else
data_dat2 <= data_dat;
end
//计数器模块
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
sum_20us <= 15'd0;
else if( sum_20us== sum_20us_max)
sum_20us <= 15'd0;
else if(sum_cs_flag==1'b0)
sum_20us <= sum_20us+15'd1;
end
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
sum_1mh <= 10'd0;
else if( sum_1mh== sum_1mh_max)
sum_1mh <= 10'd0;
else
sum_1mh <= sum_1mh+10'd1;
end
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
sum_cs_f <= 16'd0;
else if( sum_cs_f== sum_cs_f_max)
sum_cs_f <= 16'd0;
else
sum_cs_f <= sum_cs_f+16'd1;
end
//flag模块
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
sum_cs_flag <= 1'd0;
else if((sum_cs== 11'b0)&&(cs == 1'd0))
sum_cs_flag <= 1'd1;
else
sum_cs_flag <= 1'd0;
end
//dat_clk:clk_out模块
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
dat_clk <= 1'b0;
else if( sum_1mh== sum_1mh_max)
dat_clk <= ~dat_clk;
else
dat_clk <= dat_clk;
end
//sum_7模块
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
sum_7 <= 3'd0;
else if(sum_cs_flag == 1'd0)
sum_7 <= 3'd0;
else if((sum_1mh== sum_1mh_max)&&(sum_cs_flag == 1'd1))
sum_7 <= sum_7+3'd1;
else
sum_7 <= sum_7;
end
//cs信号模块
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
cs <= 1'd1;
else if(sum_cs_f== sum_cs_f_max)
cs <= ~cs;
else
cs <= cs;
end
//读取信号模块
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
data_out_s <= 8'd0;
else if((sum_7<=sum_7_max)&&(sum_1mh== sum_1mh_max))
data_out_s <= {data_dat2,data_out_s[7:1]};
else
data_out_s <=data_out_s;
end
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
data_out <= 8'd0;
else if(sum_7==sum_7_max)
data_out <= data_out_s;
else
data_out <=data_out;
end
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
state <= IDLE;
else
case (state)
IDLE: if((cs==1'b0)&&(sum_cs==sum_cs_max)) state <= ONE;
ONE: if((cs==1'b0)&&(sum_7 ==sum_7_max)) state <=TUW;
TUW: if((cs==1'b1)&&(sum_20us== sum_20us_max)) state <=IDLE;
default : state <= IDLE;
endcase
end
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
flag_data <= 1'd0;
else if(state==ONE)
flag_data <= 1'd1;
else
flag_data <= 1'd0;
end
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
sum_cs <= 11'd0;
else if( state!= IDLE)
sum_cs <= 11'd0;
else if( sum_cs== sum_cs_max )
sum_cs <= sum_cs;
else if( state == IDLE)
sum_cs <= sum_cs+11'd1;
end
endmodule