手机版    二维码   标签云  厨具企业大全

fpga学习系列:29. 数字电压表设计(ad)

2024-05-14 17:57:29 来源:网络 作者/编辑: 浏览次数:8210 手机访问 使用手机“扫一扫”以下二维码,即可分享本文到“朋友圈”中。

设计背景:

模数转换器,又称a/d转换器,简称adc,通常是指一个将模拟信号转换为抗干扰性更强的数字信号的电子器件。一般的adc是将一个输入电压信号转换为一个输出的数字信号。由于数字信号本身不具有实际意义,仅仅表示一个相对大小,故任何一个adc都需要一个参考模拟量作为转换标准。比较常见的参考标准为最大的可转换信号大小,而输出的数字量则表示输入信号相对于参考信号的大小。本设计则通过对模数转换芯片(tlc549)的采样控制,实现一个简易的数字电压表。

设计原理:

tlc549典型的配置电路如下图所示:

tlc549的端口描述如下:

tlc549是一个8位的串行模数转换器,a/d转换时间最大为17us,最大转换速率为4mhz。下图为tlc549的访问时序,从图中可以看出,tlc549的使用只需对外接输入输出时钟(i/o clk)和芯片选择(/cs)、输入的模拟信号(analog in)的控制。

分析时序图可知:当片选信号(/cs)拉低时,adc前一次的转换数据(a)的最高位a7立即出现在数据线data out上,之后的数据在时钟i/o clock的下降沿改变,可在i/o clock的上升沿读取数据。转换时,/cs要置为高电平。在设计操作时,要注意tsu(cs)、tconv、twh(cs)和i/o clock的频率这几个参数。tsu(cs)为cs拉低到i/o clock第一个时钟到来的时间,至少要1.4us;twh(cs)为adc的转换时钟,不超过17us,tconv的值也不超过17us;i/o clock为 1.1mhz。其他参数可参考数据手册。

由于adc是8位的,所以采样的电压值为:

v =(d*vref)/256

其中v为采样的电压值;d为adc转换后读取的8位二进制数;vref为参考电压值,此处为2.5v。

设计架构图:

本设计通过调节电位器rw1改变adc的模拟输入值,数据采样读取后由数码管显示,最后用万用表测量输入电压,并与读取在数码管上的数据(单位为mv)作比较。设计的架构图如下:

设计架构图对应端口的功能描述表:

tlc549_driver模块采用序列机实现接口访问时序,并且产生1mhz的adc_clk和采集到adc_data;control模块,将采集到的adc数据(adc_data)换算成对应的电压值,并经过二进制到bcd转换以后传送到数码管;dig_led_drive模块负责数码管的驱动,将传递过来的数据显示出来。

设计代码:

tlc549_driver模块代码:

0moduletlc549_driver(clk,rst_n,en,adc_din,adc_clk,adc_cs_n,data,get_flag);

1

2inputclk;//系统50mhz时钟输入

3inputrst_n;//全局复位

4inputen;//adc转换使能,高电平有效

5

6inputadc_din;//adc串行数据输入

7

8outputregadc_clk;//adc时钟信号输出

9outputregadc_cs_n;//adc片选信号输出

10outputregget_flag;//数据转换完成标志

11outputreg[7:0]data;//adc转换以后的电压值

12

13reg[10:0]cnt1;//系统时钟计数器

14reg[7:0]data_tmp;//数据寄存器

15

16//系统时钟上升沿计数

17always@(posedgeclkornegedgerst_n)

18begin

19if(!rst_n)

20cnt1<=11'd0;

21elseif(!en)

22cnt1<=11'd0;

23elseif(cnt1==11'd1310)

24cnt1<=11'd0;

25else

26cnt1<=cnt1+1'b1;

27end

28

29always@(posedgeclkornegedgerst_n)

30begin

31if(!rst_n)

32begin

33adc_clk<=1'b0;

34adc_cs_n<=1'b1;

35data_tmp<=8'd0;

36data<=8'd0;

37end

38elseif(en)

39begin

40case(cnt1)

411:adc_cs_n<=1'b0;//1~71(tsu)

4271:beginadc_clk<=1;data_tmp[7]<=adc_din;end

4396:adc_clk<=0;

44121:beginadc_clk<=1;data_tmp[6]<=adc_din;end

45146:adc_clk<=0;

46171:beginadc_clk<=1;data_tmp[5]<=adc_din;end

47196:adc_clk<=0;

48221:beginadc_clk<=1;data_tmp[4]<=adc_din;end

49246:adc_clk<=0;

50271:beginadc_clk<=1;data_tmp[3]<=adc_din;end

51296:adc_clk<=0;

52321:beginadc_clk<=1;data_tmp[2]<=adc_din;end

53346:adc_clk<=0;

54371:beginadc_clk<=1;data_tmp[1]<=adc_din;end

55396:adc_clk<=0;

56421:beginadc_clk<=1;data_tmp[0]<=adc_din;end

57446:beginadc_clk<=0;adc_cs_n<=1'b1;get_flag<=1;end

58447:begindata<=data_tmp;get_flag<=0;end//447~1310(twh)

591310:;

60default:;

61endcase

62end

63else

64begin

65adc_cs_n<=1'b1;

66adc_clk<=1'b0;

67end

68end

69

70endmodule

control模块代码:

0modulecontrol(clk,rst_n,get_flag,adc_data,seg_data);

1

2inputclk;//系统时钟输入

3inputrst_n;//系统复位

4inputget_flag;//adc采集数据完成标志

5input[7:0]adc_data;//adc采集数据输入

6

7outputreg[23:0]seg_data;//数码管待显示数据

8

9reg[3:0]qianwei;//千位

10reg[3:0]baiwei;//百位

11reg[3:0]shiwei;//十位

12reg[3:0]gewei;//个位

13reg[15:0]tenvalue;//采样的电压值

14

15//采集电压值计算

16always@(posedgeclkornegedgerst_n)

17begin

18if(!rst_n)

19tenvalue<=0;

20elseif(get_flag)//新的数据采集完成,可以进行计算

21tenvalue<=(adc_data*100*25)/256;

22end

23

24//二进制转bcd值

25always@(posedgeclkornegedgerst_n)

26begin

27if(!rst_n)

28begin

29qianwei<=0;

30baiwei<=0;

31shiwei<=0;

32gewei<=0;

33end

34else

35begin

36qianwei<=tenvalue/1000;//2

37baiwei<=(tenvalue/100)%10;//5

38shiwei<=(tenvalue/10)%10;//0

39gewei<=tenvalue%10;//0

40end

41end

42

43//数码管显示数值

44always@(posedgeclkornegedgerst_n)

45begin

46if(!rst_n)

47seg_data<=0;

48else

49seg_data<={

50qianwei,//千位

51baiwei,//百位

52shiwei,//十位

53gewei,//个位

548'hff//空闲

55};

56end

57

58endmodule

dig_led_drive模块代码:

0

1

2

3moduledig_led_drive(clk,rst_n,data,dig_led_seg,dig_led_sel);

4

5inputclk;//系统时钟输入

6inputrst_n;//系统复位

7input[23:0]data;//待显示数据

8

9output[7:0]dig_led_seg;//数码管段选

10output[2:0]dig_led_sel;//数码管位选

11

12parametersystem_clk=50_000_000;

13

14//  localparam cnt1_max = 24;

15localparamcnt1_max=system_clk/1000/2-1;

16

17reg[14:0]cnt1;//分频计数器

18regclk_1k;//扫描时钟,1khz

19reg[2:0]sel_r;//数码管位选

20reg[7:0]seg_r;//数码管段选

21reg[3:0]disp_data;//单位显示数据缓存

22

23//1khz时钟分频计数器

24always@(posedgeclk)

25begin

26if(!rst_n)cnt1<=0;

27elseif(cnt1==cnt1_max)cnt1<=0;

28elsecnt1<=cnt1+1'b1;

29end

30

31//得到1khz时钟

32always@(posedgeclkornegedgerst_n)

33begin

34if(!rst_n)

35clk_1k<=0;

36elseif(cnt1==cnt1_max)

37clk_1k<=~clk_1k;

38end

39

40//位选信号控制

41always@(posedgeclk_1kornegedgerst_n)

42begin

43if(!rst_n)

44sel_r<=3'd0;

45elseif(sel_r==3'd3)

46sel_r<=3'd0;

47else

48sel_r<=sel_r+1'b1;

49end

50

51//根据不同的数码管位选择不同的待显示数据

52always@(*)

53begin

54if(!rst_n)

55disp_data=4'd0;

56else

57begin

58case(sel_r)

593'd0:disp_data=data[23:20];

603'd1:disp_data=data[19:16];

613'd2:disp_data=data[15:12];

623'd3:disp_data=data[11:8];

633'd4:disp_data=data[7:4];

643'd5:disp_data=data[3:0];

65default:disp_data=4'd0;

66endcase

67end

68end

69

70//数据译码,将待显示数据翻译为符合数码管显示的编码

71always@(*)

72begin

73if(!rst_n)

74seg_r=8'hff;

75else

76begin

77case(disp_data)

784'd0:seg_r=8'hc0;

794'd1:seg_r=8'hf9;

804'd2:seg_r=8'ha4;

814'd3:seg_r=8'hb0;

824'd4:seg_r=8'h99;

834'd5:seg_r=8'h92;

844'd6:seg_r=8'h82;

854'd7:seg_r=8'hf8;

864'd8:seg_r=8'h80;

874'd9:seg_r=8'h90;

884'd10:seg_r=8'h88;

894'd11:seg_r=8'h83;

904'd12:seg_r=8'hc6;

914'd13:seg_r=8'ha1;

924'd14:seg_r=8'h86;

934'd15:seg_r=8'h8e;

94default:seg_r=8'hff;

95endcase

96end

97end

98

99assigndig_led_seg=seg_r;

100assigndig_led_sel=sel_r;

101

102endmodule

ad_tlc549顶层模块代码:

0modulead_tlc549(clk,rst_n,adc_din,adc_clk,adc_cs_n,dig_led_sel,dig_led_seg);

1

2inputclk;

3inputrst_n;

4inputadc_din;

5

6outputadc_clk;

7outputadc_cs_n;

8output[2:0]dig_led_sel;

9output[7:0]dig_led_seg;

10

11wireget_flag;

12wire[7:0]adc_data;

13wire[23:0]seg_data;

14

15tlc549_drivertlc549_driver(

16.clk(clk),

17.rst_n(rst_n),

18.en(1'b1),

19.adc_din(adc_din),

20.adc_clk(adc_clk),

21.adc_cs_n(adc_cs_n),

22.data(adc_data),

23.get_flag(get_flag)

24);

25

26controlcontrol(

27.clk(clk),

28.rst_n(rst_n),

29.get_flag(get_flag),

30.adc_data(adc_data),

31.seg_data(seg_data)

32);

33

34dig_led_drivedig_led_drive(

35.clk(clk),

36.rst_n(rst_n),

37.data(seg_data),

38.dig_led_seg(dig_led_seg),

39.dig_led_sel(dig_led_sel)

40);

41

42endmodule

ad_tlc549_tb顶层测试代码如下:

0`timescale1ns/1ps

1

2modulead_tlc549_tb;

3

4regclk;

5regrst_n;

6regadc_din;

7

8wireadc_clk;

9wireadc_cs_n;

10wire[2:0]dig_led_sel;

11wire[7:0]dig_led_seg;

12

13initialbegin

14clk=1;

15rst_n=0;

16adc_din=0;

17#200.1

18rst_n=1;

19

20#1400adc_din=1;//aa

21#1000adc_din=0;

22#1000adc_din=1;

23#1000adc_din=0;

24#1000adc_din=1;

25#1000adc_din=0;

26#1000adc_din=1;

27#1000adc_din=0;

28

29#17000

30#1400adc_din=1;//98

31#1000adc_din=0;

32#1000adc_din=0;

33#1000adc_din=1;

34#1000adc_din=1;

35#1000adc_din=0;

36#1000adc_din=0;

37#1000adc_din=0;

38

39end

40

41ad_tlc549ad_tlc549_dut(

42.clk(clk),

43.rst_n(rst_n),

44.adc_din(adc_din),

45.adc_clk(adc_clk),

46.adc_cs_n(adc_cs_n),

47.dig_led_sel(dig_led_sel),

48.dig_led_seg(dig_led_seg)

49);

50

51always#10clk=~clk;

52

53endmodule

仿真图:

设计仿真图如下所示:

来源:网络

以上是网络信息转载,信息真实性自行斟酌。

 
本条标题:fpga学习系列:29. 数字电压表设计(ad)
本条信息网址:
文本助手 资讯搜索 分享好友 打印本文 关闭窗口
阅读关键词
  • 手机浏览本文

    手机应用中扫描本文二维码,即可浏览本文或分享到您的社交网络中。

  • 微信公众号

    扫描二维码,关注中华厨具网微信公众号,实时了解行业最新动态。

版权/免责声明:
一、本文图片及内容来自网络,不代表本站的观点和立场,如涉及各类版权问题请联系及时删除。
二、凡注明稿件来源的内容均为转载稿或由企业用户注册发布,本网转载出于传递更多信息的目的;如转载稿涉及版权问题,请作者联系我们,同时对于用户评论等信息,本网并不意味着赞同其观点或证实其内容的真实性。
三、转载本站原创文章请注明来源:中华厨具网

0相关评论
今日热点文章更多
品牌聚焦更多
推荐品牌更多
热门频道
关闭广告
合作伙伴:
中华厨具网 鲁ICP备2021046805号         鲁公网安备 37162502000363号 (c)2018-2026SYSTEM All Rights Reserved 投资有风险 加盟需谨慎
关闭广告
关闭广告