收藏 分销(赏)

TLC5620串行DA控制实验.doc

上传人:pc****0 文档编号:9010330 上传时间:2025-03-11 格式:DOC 页数:13 大小:354KB
下载 相关 举报
TLC5620串行DA控制实验.doc_第1页
第1页 / 共13页
TLC5620串行DA控制实验.doc_第2页
第2页 / 共13页
点击查看更多>>
资源描述
实 验 报 告 实验名称: [TLC5620串行D/A实验] 姓 名: [古毅] 学 号: [2011082408] 指导教师: [解武] 实验时间: [2014年3月17日] 信息与通信工程学院 TLC5620串行D/A实验 1 实验目的 熟练掌握基本的编程语句;能够运用所学知识理解给出的程序,并按照要求修改程序。 2 实验要求 TLC5620是4通道8位的串行D/A转换器。 任务1: 观察已给程序的实验现象,并结合实验结果理解原程序语句的含义,体会基本句话,模块的用法。在掌握整个程序工作的原理后,修改程序,使其实现单通道的DA转换;在按下通道的按键之后,用数码管显示输入的数字量;停止按键,数码管计数停止,继续按键则继续计数。按下复位键,则系统清零,数码管显示0值。将转换后的模拟电压加到LED两端,观察LED亮度变化是否符合理论规律。 任务2: 在任务1的基础上,进一步体会程序的编写思想,将顶层图形文件修改成一个用语言描述的模块,实现原程序所要求的各项功能:通过4个按键选择不同通道,每个通道的数字量输入都可以在数码管上进行显示。松开按键,则计数显示保持前一状态,按下按键继续计数。设置复位键,按下复位键,系统清零。每个通道对应的模拟电压通过LED的亮度显示。通过硬件实现,观察实验结果。 3 实验原理 3.1 TLC5620基本原理 TLC5620封装如实验图1所示,是一个4通道8位的串行数模(D/A)转换器,其最大转换速度可达1MBps。其管脚REFA~REFD为四个通道的参考电压,实验平台的参考电压均为2.5V;DACA~DACD为4路四个模拟信号输出通道;DATA为串行数据输入;CLK为DAC串行数据输入时钟,其下降沿锁存输入数据DATA;LOAD为串行数据锁存信号,低电平锁存。LDAC为DAC输出更新控制信号,当LDAC为低电平时,则把锁存在锁存器的数据送到DAC并转换为模拟信号,在相应的通道进行输出,故可以始终把LDAC信号置为低电平,也就是说加载信号一旦产生,数据立刻转换输出。 表1为TLC5620各引脚功能介绍。 图1 TLC5620封装示意图 表1 TLC5620引脚功能 引脚 输入/输出 功能描述 名称 序号 GND 1 I 地回路及参考终端 DACA 12 O DAC A模拟信号输出 DACB 11 O DAC B模拟信号输出 DACC 10 O DAC C模拟信号输出 DACD 9 O DAC D模拟信号输出 DATA 6 I 串行数字数据输入接口,在CLK下降沿时将输入的数字量转发到串行接口寄存器里 CLK 7 I 串行接口时钟,用于控制串行数据的输入 LDAC 13 I 加载DAC。当引脚出现高电平时,即使有数字量被读入串行口也不会对DAC的输出进行更新。只有当引脚从高电平变为低电平时,DAC输出才更新。 LOAD 8 I 串口加载控制。当LDAC是低电平,并且LOAD引脚出现下降沿时数字量被保存到锁存器,随后输出端产生模拟电压。 REFA 2 I 输入到DAC A的参考电压。这个电压定义了输出模拟量的范围。 REFB 3 I 输入到DAC B的参考电压。这个电压定义了输出模拟量的范围。 REFC 4 I 输入到DAC C的参考电压。这个电压定义了输出模拟量的范围。 REFD 5 I 输入到DAC D的参考电压。这个电压定义了输出模拟量的范围。 VDD 14 I 输入电源正极 因为TLC5620为四通道的数模转换器,只有一个DATA数据输入端,所以传送的数据中要包含通道的信息,以便DAC能识别出该数据属于哪个通道,转换完成后的模拟信号输出到相应的通道中。TLC5620传输的一帧数据位11位,先传送高位,最后传送低位,帧格式如表2所示。 表2 TLC5620的数据结构 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 通道选择 输出模式RNG 8位数据D7~D0 D10、D9为通道选择位,00~11分别选择DACA~DACD通道。RNG的数值为0或者1,为输出倍数。TLC5620的输出电压为: DAC内部有移位寄存器和锁存器,要在工程中实现在LOAD高电平时把11位数据在CLK的下降沿逐位(由高位到低位)发送到DATA端,发送完毕后,LOAD置为低电平,指示DAC进行模数转换。 TLC5620的访问时序图如图2所示。 图2 TLC5620访问时序图 3.2 TLC5620与FPGA连接电路图 图3 TLC5620与FPGA连接示意图 LOAD的低电平的最小保持时间(LOAD)为250ns,各个和的最小保持时间为50ns。为了尽可能最大利用DAC的转换速度,为此状态机选用5000Hz(200ns)左右的输入时钟,在LOAD低电平时要等待 12个状态机时钟CLK0.5M。为此采用计数器判断等待时间是否满足条件,该计数器使用LOAD的高电平为异步复位信号,低电平时,对CLK0.5M进行计数,当计数器计数值大于12 时,说明LOAD为低电平的时间(LOAD)已满足,状态机可跳转到下一态。 在LOAD高电平时,需要产生11个DAC的CLK,同样采用计数器计数值判断,该计数器中,LOAD的低电平为异步复位信号,LOAD为高电平时对DA_CLK计数,满足计数器的值>11时,说明已经送入了11bit的串行数据,可以进行置LOAD为低电平,对11bit数据锁存进行数模转换。 3.3 任务原理 3.3.1任务原理1 将给定程序的4通道转换改成单通道的DA转换:修改程序,将四个通道的按键修改成一个按键,用一个5HZ的时钟信号进行采样,并将采样的数字信号传输给TLC5620,按照其时序要求,对5620初始化,使其将采样的按键的数字信号按照上述提供的公式转化为模拟信号,并输出给LED灯,并且随着按键时间延长,数字输入的增大,转换为的模拟电压增大,LED灯的亮度增加。同时,将采样的数字信号通过数码管显示。从而完成整个功能。 3.3.1任务原理2 将给定的程序模块合在一个顶层模块中,不使用图形文件作为顶层:使用verilog VHDL建立顶层文件,在顶层文件中设置连线型变量,调用事先写好的模块,用线型变量将两个模块需要连接的管脚连接在一起,从而形成一个完整功能的大模块。 3.4 实验流程图 4 FPGA所用的管脚分配 选用FPGA为Altera公司的CycloneII系列EP2C8Q208C8。主时钟50MHz。管脚分配如下。 5 实验结果 1、按不同的通道,数码管显示数字输入量,数字变化的频率和程序模块中分频的频率一致;停止按键,则数字不发生变化,继续按相同通道的按键,则数码管继续计数;若按下复位键,则数码管显示清零。 2、当数字输入显示超过1500时,可以观察到转化成模拟量的电压足以使LED灯发光,并且输入数字量越大,转化成的模拟电压越高,观察到的LED发光越亮。 3、当将程序修改成为只有一个通道的,同样可以实现显示,数字量转化为模拟量的变化。同样,将程序改为一个总程序时,也可以实现相应功能。 6 实验心得 通过这次实验,我的收获如下: 第一、了解 TLC5620串行D/A的工作原理,能熟练掌握基本的编程语句,并且能够运用所学知识理解给出的程序,按照要求基本修改程序。 第二、相比前一次的实验对verilog语言有了一个更加清醒的认识,在阅读程序、修改程序的过程中更加熟悉了verilog语言,掌握了基本的修改程序的技巧和能力。 第三、在学习了verilog语言编程的时候,将其与在上学期学习数字电路课程时,从门电路的角度出发,通过真值表、表达式、卡诺图、状态表、状态转换图、特征方程等方式用图形法或者基本的逻辑器件实现想要的功能,进行对比学习,这使我意识到,不能单从原有的思维方式出发进行分析和编程,必须建立整体的概念,从输入输出的整体功能出发用程序建立模块,并通过模块和模块的嵌套或者连接实现相应功能。 7 参考文献 [1] 王金明. 《数字系统设计与Verilog HDL》第3版 电子工业出版社, 2009 TP271/W24. [2] 施齐云 潘大鹏 黄湘松 数字电子技术实践教程 哈尔滨工程大学出版社 附录:实验程序清单 //TASK 1:单通道数码管计数显示 //D/A 5620 运行程序顶层文件: module top(clk,reset,key,tlc5620_clk,tlc5620_data,tlc5620_load,tlc5620_ldac,sel,ky1,ledcom,leddata); input clk; input reset; input key; output tlc5620_clk; output tlc5620_data; output tlc5620_load; output tlc5620_ldac; output[2:0] sel; output ky1; output[7:0] ledcom; output[7:0] leddata; wire a; wire[10:0] b; tlc5620(.clk(clk),.rst(reset),.write_n(a),.wr_data(b),.dac_clk(tlc5620_clk),.dac_data(tlc5620_data),.dac_load(tlc5620_load),.dac_ldac(tlc5620_ldac)); dac_test(.clk(clk),.rst(reset),.key(key),.wr_n(a),.wr_data(b),.seg_com(ledcom),.seg_data(leddata)); assign ky1=0; assign sel[2]=0; assign sel[1]=0; assign sel[0]=1; endmodule //D/A 5620驱动程序: module tlc5620(clk,rst,write_n,wr_data,dac_clk,dac_data,dac_load,dac_ldac); input clk; input rst; input write_n; input[10:0] wr_data; output dac_clk; output dac_data; output dac_load; output dac_ldac; wire dac_done; reg dac_clk_r; reg dac_data_r; reg [5:0] counter; reg [31:0] DCLK_DIV; parameter CLK_FREQ = 'D50_000_000; //系统时钟50MHZ parameter DCLK_FREQ = 'D1_000_000; //AD_CLK输出时钟1M/2HZ always @(posedge clk) if(DCLK_DIV < (CLK_FREQ / DCLK_FREQ)) DCLK_DIV <= DCLK_DIV+1'b1; else begin DCLK_DIV <= 0; dac_clk_r <= ~dac_clk_r; end always @(posedge dac_clk_r or negedge rst) begin if(!rst) counter <= 0; else if(counter<='d13) counter <= counter + 1'b1; else counter <= 0; end assign dac_load = (counter == 4'd12) ? 1'b0 : 1'b1; assign dac_clk = (counter > 'd0 && counter < 'd12) ? dac_clk_r : 1'b0; assign dac_ldac = (counter == 4'd13) ? 1'b0 : 1'b1; assign dac_done = (counter <= 4'd11) ? 1'b0 : 1'b1; assign dac_data = dac_data_r; /*先高位,把11位数据传输给DAC芯片*/ always @(counter[3:0] or wr_data or dac_done or write_n) begin if(!dac_done && !write_n) case(counter[3:0]) 4'd1: dac_data_r <= wr_data[10]; 4'd2: dac_data_r <= wr_data[9]; 4'd3: dac_data_r <= wr_data[8]; 4'd4: dac_data_r <= wr_data[7]; 4'd5: dac_data_r <= wr_data[6]; 4'd6: dac_data_r <= wr_data[5]; 4'd7: dac_data_r <= wr_data[4]; 4'd8: dac_data_r <= wr_data[3]; 4'd9: dac_data_r <= wr_data[2]; 4'd10: dac_data_r <= wr_data[1]; 4'd11: dac_data_r <= wr_data[0]; default: dac_data_r <= 1'b1; endcase else dac_data_r <= 1'b1; end endmodule //D/A 5620 测试程序: /* DAC_TLC5620测试模块 * 按KEY1键,通道A的电压值递增; * 通道的电压值显示于数码管. */ module dac_test(clk,rst,key,wr_n,wr_data,seg_com,seg_data); input clk; input rst; Input key; output wr_n; output [10:0] wr_data; output [7:0]seg_data; output [7:0]seg_com; parameter CLK_FREQ = 'D50_000_000; //系统时钟50MHZ parameter DCLK_FREQ = 'D10; //AD_CLK输出时钟10/2HZ always @(posedge clk) if(DCLK_DIV < (CLK_FREQ / DCLK_FREQ)) DCLK_DIV <= DCLK_DIV+1'b1; else begin DCLK_DIV <= 0; CLK_DIV <= ~CLK_DIV; end /*高2位为通道选择,低8位为DA数据,第9位 RNG 为1时输出0到2倍Vref,为0时输出0到Vref*/ assign wr_data = {channel,1'b1,data_code_r}; assign wr_n = 1'b0; always @(posedge CLK_DIV or negedge rst ) if(!rst) begin key0_r <= 8'h00; data_code_r <= 8'h00; end else case(key) begin channel <= 2'b00; key0_r <= key0_r + 1'b1; data_code_r <= key0_r; end default : begin end endcase /*将各通道的电压值显示于数码管上,单位mv */ always @(negedge rst or negedge CLK_DIV ) begin if(!rst) begin datain[0]<=8'b00000000; datain[1]<=8'b00000000; datain[2]<=8'b00000000; datain[3]<=8'b00000000; datain[4]<=8'b00000000; datain[5]<=8'b00000000; datain[6]<=8'b00000000; datain[7]<=8'b00000000; end else begin /*电压值Vo=Vref * (RNG+1) * CODE / 256 */ vo_r = data_code_r * 13'd5000/9'd256; datain[0]<=vo_r%10; datain[1]<=vo_r/10%10; datain[2]<=vo_r/100%10; datain[3]<=vo_r/1000%10; datain[4]<=vo_r/10000%10; datain[5]<=vo_r/100000%10; datain[6]<=vo_r/1000000%10; datain[7]<=vo_r/10000000%10; end end always @(posedge clk) begin count=count+1; end always @(count[14:12]) begin case(count[14:12]) 3'b000: begin bcd_led = datain[0]; seg_com = 8'b00000001; end 3'b001: begin bcd_led=datain[1]; seg_com=8'b00000010; end 3'b010: begin bcd_led=datain[2]; seg_com=8'b00000100; end 3'b011: begin bcd_led=datain[3]; seg_com=8'b00001000; end 3'b100: begin bcd_led=datain[4]; seg_com=8'b00010000; end 3'b101: begin bcd_led=datain[5]; seg_com=8'b00100000; end 3'b110: begin bcd_led=datain[6]; seg_com=8'b01000000; end 3'b111: begin bcd_led=datain[7]; seg_com=8'b10000000; end endcase end always @(seg_com or bcd_led) begin case(bcd_led[3:0]) 4'h0:seg_data=8'hc0; 4'h1:seg_data=8'hf9; 4'h2:seg_data=8'ha4; 4'h3:seg_data=8'hb0; 4'h4:seg_data=8'h99; 4'h5:seg_data=8'h92; 4'h6:seg_data=8'h82; 4'h7:seg_data=8'hf8; 4'h8:seg_data=8'h80; 4'h9:seg_data=8'h90; 4'ha:seg_data=8'h88; 4'hb:seg_data=8'h83; 4'hc:seg_data=8'hc6; 4'hd:seg_data=8'ha1; 4'he:seg_data=8'h86; 4'hf:seg_data=8'h8e; endcase end endmodule //TASK 2: 将两个模块合成一个 //D/A 5620 运行程序顶层文件: module top(clk,reset,key,tlc5620_clk,tlc5620_data,tlc5620_load,tlc5620_ldac,sel,ky1,ledcom,leddata); input clk; input reset; input[3:0] key; output tlc5620_clk; output tlc5620_data; output tlc5620_load; output tlc5620_ldac; output[2:0] sel; output ky1; output[7:0] ledcom; output[7:0] leddata; wire a; wire[10:0] b; tlc5620(.clk(clk),.rst(reset),.write_n(a),.wr_data(b),.dac_clk(tlc5620_clk),.dac_data(tlc5620_data),.dac_load(tlc5620_load),.dac_ldac(tlc5620_ldac)); dac_test(.clk(clk),.rst(reset),.key(key),.wr_n(a),.wr_data(b),.seg_com(ledcom),.seg_data(leddata)); assign ky1=0; assign sel[2]=0; assign sel[1]=0; assign sel[0]=1; endmodule ////D/A 5620驱动程序: module tlc5620(clk,rst,write_n,wr_data,dac_clk,dac_data,dac_load,dac_ldac); parameter CLK_FREQ = 'D50_000_000; //系统时钟50MHZ parameter DCLK_FREQ = 'D1_000_000; //AD_CLK输出时钟1M/2HZ always @(posedge clk) if(DCLK_DIV < (CLK_FREQ / DCLK_FREQ)) DCLK_DIV <= DCLK_DIV+1'b1; else begin DCLK_DIV <= 0; dac_clk_r <= ~dac_clk_r; end always @(posedge dac_clk_r or negedge rst) begin if(!rst) counter <= 0; else if(counter<='d13) counter <= counter + 1'b1; else counter <= 0; end assign dac_load = (counter == 4'd12) ? 1'b0 : 1'b1; assign dac_clk = (counter > 'd0 && counter < 'd12) ? dac_clk_r : 1'b0; assign dac_ldac = (counter == 4'd13) ? 1'b0 : 1'b1; assign dac_done = (counter <= 4'd11) ? 1'b0 : 1'b1; assign dac_data = dac_data_r; /*先高位,把11位数据传输给DAC芯片*/ always @(counter[3:0] or wr_data or dac_done or write_n) begin if(!dac_done && !write_n) case(counter[3:0]) 4'd1: dac_data_r <= wr_data[10]; 4'd2: dac_data_r <= wr_data[9]; 4'd3: dac_data_r <= wr_data[8]; 4'd4: dac_data_r <= wr_data[7]; 4'd5: dac_data_r <= wr_data[6]; 4'd6: dac_data_r <= wr_data[5]; 4'd7: dac_data_r <= wr_data[4]; 4'd8: dac_data_r <= wr_data[3]; 4'd9: dac_data_r <= wr_data[2]; 4'd10: dac_data_r <= wr_data[1]; 4'd11: dac_data_r <= wr_data[0]; default: dac_data_r <= 1'b1; endcase else dac_data_r <= 1'b1; end endmodule /////D/A 5620 测试程序: /* DAC_TLC5620测试模块 * 按KEY1键,通道D的电压值递增; * 按KEY2键,通道C的电压值递增; * 按KEY3键,通道B的电压值递增; * 按KEY4键,通道A的电压值递增; * 各通道的电压值显示于数码管. */ module dac_test(clk,rst,key,wr_n,wr_data,seg_com,seg_data); reg [7:0] key3_r; reg [31:0] vo_r; parameter CLK_FREQ = 'D50_000_000;//系统时钟50MHZ parameter DCLK_FREQ = 'D10;//AD_CLK输出时钟10/2HZ always @(posedge clk) if(DCLK_DIV < (CLK_FREQ / DCLK_FREQ)) DCLK_DIV <= DCLK_DIV+1'b1; else begin DCLK_DIV <= 0; CLK_DIV <= ~CLK_DIV; end /*高2位为通道选择,低8位为DA数据,第9位 RNG 为1时输出0到2倍Vref,为0时输出0到Vref*/ assign wr_data = {channel,1'b1,data_code_r}; assign wr_n = 1'b0; /*根据按键不同,选择不同的DA通道,其值递增*/ always @(posedge CLK_DIV or negedge rst ) if(!rst) begin key0_r <= 8'h00; key1_r <= 8'h00; key2_r <= 8'h00; key3_r <= 8'h00; data_code_r <= 8'h00; end else case(key) 4'b1110 : begin //key4 channel <= 2'b00; key0_r <= key0_r + 1'b1; data_code_r <= key0_r; end 4'b1101 : begin //key3 channel <= 2'b01; key1_r <= key1_r + 1'b1; data_code_r <= key1_r; end 4'b1011 : begin //key2 channel <= 2'b10; key2_r <= key2_r + 1'b1; data_code_r <= key2_r; end 4'b0111 : begin //key1 channel <= 2'b11; key3_r <= key3_r + 1'b1; data_code_r <= key3_r; end default : begin end endcase /*将各通道的电压值显示于数码管上,单位mv */ always @(negedge rst or negedge CLK_DIV ) begin if(!rst) begin datain[0]<=8'b00000000; datain[1]<=8'b00000000; datain[2]<=8'b00000000; datain[3]<=8'b00000000; datain[4]<=8'b00000000; datain[5]<=8'b00000000; datain[6]<=8'b00000000; datain[7]<=8'b00000000; end else begin /*电压值Vo=Vref * (RNG+1) * CODE / 256 */ vo_r = data_code_r * 13'd5000/9'd256; datain[0]<=vo_r%10; /*% 表示取模*/ datain[1]<=vo_r/10%10; datain[2]<=vo_r/100%10; datain[3]<=vo_r/1000%10; end end always @(posedge clk) begin count=count+1; end always @(count[14:12]) begin case(count[14:12]) 3'b000: begin bcd_led = datain[0]; //数码管扫描 seg_com = 8'b00000001; //数码管共阳极 end 3'b001: begin bcd_led=datain[1]; seg_com=8'b00000010; end 3'b010: begin bcd_led=datain[2]; seg_com=8'b00000100; end 3'b011: begin bcd_led=datain[3]; seg_com=8'b00001000; end 3'b100: begin bcd_led=datain[4]; seg_com=8'b00010000; end 3'b101: begin bcd_led=datain[5]; seg_com=8'b00100000; end 3'b110: begin bcd_led=datain[6]; seg_com=8'b01000000; end 3'b111: begin bcd_led=datain[7]; seg_com=8'b10000000; end endcase end always @(seg_com or bcd_led) begin case(bcd_led[3:0]) 4'h0:seg_data=8'hc0; //11000000 显示 0 4'h1:seg_data=8'hf9; //11111001 显示 1 4'h2:seg_data=8'ha4; //..... 4'h3:seg_data=8'hb0; //..... 4'h4:seg_data=8'h99; //..... 4'h5:seg_data=8'h92; 4'h6:seg_data=8'h82; 4'h7:seg_data=8'hf8; 4'h8:seg_data=8'h80; 4'h9:seg_data=8'h90; 4'ha:seg_data=8'h88; 4'hb:seg_data=8'h83;
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传
相似文档                                   自信AI助手自信AI助手

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服