0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

FPGA学习交流 2018-08-15 14:07 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

设计背景:

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

设计原理:

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

image.png

TLC549的端口描述如下:

image.png

TLC549是一个8位的串行模数转换器,A/D转换时间最大为17us,最大转换速率为4MHz。下图为TLC549的访问时序,从图中可以看出,TLC549的使用只需对外接输入输出时钟I/O CLK和芯片选择(/CS)、输入的模拟信号(ANALOG IN)的控制。

image.png


分析时序图可知:当片选信号(/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)作比较。设计的架构图如下:

image.png


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

image.png


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~71Tsu

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/*数码管扫描模块,位选为外部74hc138译码器进行控制*/

1/*仿真时请将本文件设置为顶层,并在代码中根据相应注释中的内容选择cnt1_MAX = 24*/

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
    +关注

    关注

    1656

    文章

    22305

    浏览量

    630820
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    数字电压表设计教程之使用FPGA实现SPI协议通讯

    LTC2308通过一个标准4线SPI数字接口进行通信。LTC2308模数转换芯片有8个ADC通道和12位的分辨率,输入信号时钟频率范围不超过500KHz,按照Nyquist采样定理则建议输入信号在250KHz以下。
    的头像 发表于 10-07 09:22 1541次阅读
    <b class='flag-5'>数字</b><b class='flag-5'>电压表</b>设计教程之使用<b class='flag-5'>FPGA</b>实现SPI协议通讯

    求助,简单的电压表怎么能用多个测量串联电池组的每个电池电压

    本帖最后由 JackieMa81 于 2025-8-19 09:35 编辑 两块钱一个的电压表,三线的,测试端和供电端两个正极,共用负极。简单抄了一下电路图现在想给我的16串电池组同时
    发表于 08-19 05:36

    基于FPGA和LTC2308模数转换芯片的数字电压表设计

    通过FPGA对模数转换芯片(LTC2308)的采样控制,实现一个简易的数字电压表
    的头像 发表于 08-16 08:58 5181次阅读
    基于<b class='flag-5'>FPGA</b>和LTC2308模数转换芯片的<b class='flag-5'>数字</b><b class='flag-5'>电压表</b>设计

    【RA-Eco-RA6M4开发板评测】ADC 电压表

    总结 本文介绍了 RA-Eco-RA6M4-100PIN-V1.0 开发板实现基于串口打印、ADC 采集、ADC 电压转换的电压表设计,包括工程创建、工程代码、测试效果等流程,为 Renesas 系列产品 ADC 相关的开发
    发表于 07-25 12:33

    热电偶电压表调零应该在什么状态

    热电偶电压表作为工业测温领域的重要工具,其测量精度直接影响生产过程的控制质量。在实际操作中,调零环节是确保测量准确性的关键步骤,但许多技术人员对调零时热电偶应处的状态存在认知误区。本文将系统阐述
    的头像 发表于 07-13 17:42 631次阅读

    Analog Devices Inc. ADMX3652Z ±20V数字电压表数据手册

    Analog Devices ADMX3652Z ±20V数字电压表是一款6½位数字电压表 (DVM),具有1kSPS的快速吞吐量。Analog Devices ADMX3652Z具有
    的头像 发表于 06-11 11:47 669次阅读

    进群免费领FPGA学习资料!数字信号处理、傅里叶变换与FPGA开发等

    进群免费领FPGA学习资料啦!小编整理了数字信号处理、傅里叶变换与FPGA开发等FPGA必看资料,需要的小伙伴可以加小助手(微信:elecf
    发表于 04-07 16:41

    数字电压表的主要指标_数字电压表由什么构成

     数字电压表的主要技术指标包括以下几个方面:   一、测量范围   测量范围指数字电压表可测量的电压区间。不同的
    的头像 发表于 01-28 14:19 1631次阅读

    数字电压表的使用方法

    数字电压表的使用方法通常包括以下几个步骤:   一、准备阶段   了解电压表:   在使用前,先了解数字电压表的基本功能、
    的头像 发表于 01-28 14:18 2926次阅读

    数字电压表概述_数字电压表的作用

    数字电压表(Digital Voltmeter,简称DVM)是一种采用数字化测量技术,将连续的模拟量转换成不连续、离散的数字形式并加以显示的电子仪器。以下是对
    的头像 发表于 01-28 14:14 2330次阅读

    数字电压表的工作特性_数字电压表工作原理

     数字电压表的工作特性主要体现在以下几个方面:   一、高精度   数字电压表采用数字化技术,其精度远高于模拟
    的头像 发表于 01-28 13:54 2209次阅读

    TLC7226通过电压表测得REF脚实际电压只有4V不到,这是什么原因呢?

    我用图一所示的升压电路得到15V,然后通过分压电阻接到TLC7226的REF脚,但是我通过电压表测得REF脚实际电压只有4V不到,这是什么原因呢?难道REF一定要接电压跟随吗?
    发表于 01-17 06:07

    ADS1146芯片采集电压,用SPI通信读到是数据计算出来和用电压表测得的值总有误差,怎么解决?

    我用到ADS1146芯片采集电压,我的芯片REF电压是0.6163V,芯片工作电压是3.3V。用SPI通信读到是数据计算出来和用电压表测得的值总有误差,最大误差是3mv,误差是线性误
    发表于 01-07 06:34

    3456A数字电压表操作和维修手册

    电子发烧友网站提供《3456A数字电压表操作和维修手册.pdf》资料免费下载
    发表于 12-19 14:15 1次下载

    村田贴片电容的电压表示方法

    村田贴片电容的电压表示方法主要通过其编码系统来体现。每个村田贴片电容都有一个独特的编码,其中包含了关于电容的多种信息,包括其额定电压。以下是村田贴片电容电压表示方法的详细说明: 编码结构 村田贴片
    的头像 发表于 12-16 14:37 1042次阅读
    村田贴片电容的<b class='flag-5'>电压表</b>示方法