基于FPGA的数字温度计.docx

上传人:b****7 文档编号:16032778 上传时间:2023-07-10 格式:DOCX 页数:30 大小:552.12KB
下载 相关 举报
基于FPGA的数字温度计.docx_第1页
第1页 / 共30页
基于FPGA的数字温度计.docx_第2页
第2页 / 共30页
基于FPGA的数字温度计.docx_第3页
第3页 / 共30页
基于FPGA的数字温度计.docx_第4页
第4页 / 共30页
基于FPGA的数字温度计.docx_第5页
第5页 / 共30页
基于FPGA的数字温度计.docx_第6页
第6页 / 共30页
基于FPGA的数字温度计.docx_第7页
第7页 / 共30页
基于FPGA的数字温度计.docx_第8页
第8页 / 共30页
基于FPGA的数字温度计.docx_第9页
第9页 / 共30页
基于FPGA的数字温度计.docx_第10页
第10页 / 共30页
基于FPGA的数字温度计.docx_第11页
第11页 / 共30页
基于FPGA的数字温度计.docx_第12页
第12页 / 共30页
基于FPGA的数字温度计.docx_第13页
第13页 / 共30页
基于FPGA的数字温度计.docx_第14页
第14页 / 共30页
基于FPGA的数字温度计.docx_第15页
第15页 / 共30页
基于FPGA的数字温度计.docx_第16页
第16页 / 共30页
基于FPGA的数字温度计.docx_第17页
第17页 / 共30页
基于FPGA的数字温度计.docx_第18页
第18页 / 共30页
基于FPGA的数字温度计.docx_第19页
第19页 / 共30页
基于FPGA的数字温度计.docx_第20页
第20页 / 共30页
亲,该文档总共30页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

基于FPGA的数字温度计.docx

《基于FPGA的数字温度计.docx》由会员分享,可在线阅读,更多相关《基于FPGA的数字温度计.docx(30页珍藏版)》请在冰点文库上搜索。

基于FPGA的数字温度计.docx

基于FPGA的数字温度计

1题目要求

基本要求:

基于FPGA设计一个测量室温的温度计,能够实时的显示温度。

附加功能:

Ⅰ、达到设置的预定温度值可报警;Ⅱ、统计温度测量期内的最高温以及最低温

提供硬件:

cycloneEP1C6Q240C8N开发板

开发板资源:

按键四个;

共阳数码管四位;

PS2接口;

USB接口;

蜂鸣器;

四位拨码开关;

LCD——1602;

VGA接口;

RS232接口;

FLASH;

SDRAM;

2设计方案(或设计分析)

外设:

鉴于要测量温度,而开发板没有测量温度的设备,所以最基本是要添加外设数字温度传感器ds18b20。

.ds18b20外形与三极管一样,一只脚传输数据,另外两只脚分别接地与高电平使之工作。

Ds18b20实时测得的室温将转化成9到2位的串行数据,对串行数据进行“翻译”就可以得出实时室温。

传输途径:

传输途径是指9到12位的串行数据传输,我们考虑两种传输途径,一种是无线传输,一种是有限传输。

如果是无线传输就会使成品温度记的测温更加灵活方便,不局限于线的长度,但必须再增加外设,而且编程肯定会更难更复杂,所以我们的初始方案是第二种,就是有线传输,在实现了基本测温功能之后如果有时间就再设计无线发送接收的模块。

连接:

开发板上提供了众多的引脚,我们只需选择其中一个接口与ds18b20的传输脚连接,将开发板上的地和+5v与ds18b20的其他两脚连接就可完成外围电路的连接,这个虽然比较简单,但是在调试阶段我们的连接还是忽略了一点问题,这将在设计中遇到的问题中述说。

程序的编写:

程序的编写我们打算用模块化得方式。

总的来说数字温度记程序的设计不算复杂,不分模块写下来应该也不会难以读懂,但模块化的程序编写的一个良好习惯,这样在编写复杂程序的时候才会调理清晰容易读懂,而且模块化有利于组内分工,充分调动大家,积极参与到课程设计中。

而程序的分块将在模块实现中分析。

附加功能:

在实现基本测温功能的前提下,我们考虑使其功能更强大更切合实际,所以打算添加功能,一个是警报功能,就是温度达到某个设定的温度时使蜂鸣器响一声并使灯亮;另一个功能是最高温与最低温的记录,在不按按键的时候显示的是实时室温,在按下一个或者两个按键时可以分别显示温度计启动开始到目前为止的最高室温与最低室温。

3模块实现

分析:

首先要对DS18B20的外围电路进行配置:

Ds18b20的工作方式看似简单,只是单线传输,直接解读,其实初始化与读写操作比较复杂,时序要求非常精确,如下面图片所示:

初始化:

读写:

写时间隙

当主机把数据线从逻辑高电平拉到逻辑低电平的时候,写时间隙开始。

有两种写时间隙:

写1时间隙和写0时间隙。

所有写时间隙必须最少持续60μs,包括两个写周期间至少1μs的恢复时间。

I/O线电平变低后,DS1820在一个15μs到60μs的窗口内对I/O线采样。

如果线上是高电平,就是写1,如果线上是低电平,就是写0。

主机要生成一个写1时间隙,必须把数据线拉到低电平然后释放,在写时间隙开始后的15μs内允许数据线拉到高电平。

主机要生成一个写0时间隙,必须把数据线拉到低电平并保持60μs。

读时间隙

当从DS1820读取数据时,主机生成读时间隙。

当主机把数据线从高高平拉到低电平时,写时

间隙开始。

数据线必须保持至少1μs;从DS1820输出的数据在读时间隙的下降沿出现后15

μs内有效。

因此,主机在读时间隙开始后必须停止把I/O脚驱动为低电平15μs,以读取

I/O脚状态(见图12)。

在读时间隙的结尾,I/O引脚将被外部上拉电阻拉到高电平。

所有

读时间隙必须最少60μs,包括两个读周期间至少1μs的恢复时间。

而对DS18B20的操作可以用下表表示:

温度转换和插补(外部电源供电且只有一只DS1820)

控制器状态

数据(LSB在前)

内容

TX

复位

复位脉冲

TR

存在

存在脉冲

TX

CCh

SkipROM命令

TX

44h

ConvertT命令

RX

<1个字节的数据>

读8次忙标志。

控制器一字节(或位)接一个字节读下去,直到数据为FFh(所有位都为1)

TX

复位

复位脉冲

RX

存在

存在脉冲

TX

CCh

SkipROM命令

TX

Beh

ReadScratchpad命令

RX

<9个数据字节>

读整个暂存器加上CRC;控制器重新计算从暂存读到的8个数据字节的CRC,把计算的CRC和读取的CRC进行比较,如果相同,数据就是有效的。

控制器存储温度值并分别存储计数寄存器的内容和每度计数值寄存器的内容,做为COUNT_REMAIN和COUNT_PER_C。

TX

复位

复位脉冲

RX

存在

存在脉冲

——

——

CPU按手册中的方法计算温度值以得到更高的分辨力。

时钟:

为了在初始化程序的编写方面那些延时比较直观准确和七段显示管的显示正常工作,我们设置了两个时钟分频模块。

把原开发板上5MHZ的始终频率分成1MHZ和10KHZ,前者为串行数据处理与ds18b20初始化模块提供时钟,后者为并行数据处理与显示模块提供时钟。

并行数据处理与显示:

数码管的温度显示方面,编程可以比较独立,而且单独编程容易查错,所以独立设置了一个模块。

在后期的添加功能阶段,最高温与最低温记录与报警功能没有单独设置一个模块,而是根据实际直接在此模块上稍作改动。

数码管的七段的七位输入是一样的,所以要在四个数码管上显示不同的数字需要逐个扫描,每个时钟周期只选通一个数码管,然后输入要显示的数字的七位码,这样由于视觉暂留时间,虽然每个数码管的显示是分别在四个周期的时间段,但看起来是同时显示的,这是显示的基本方式。

如下:

1

2

3

视觉所见:

1

2

3

报警功能:

报警功能的实现与最高最低温的记录原理差不多,对输入的十二位并行数据(温度的编码)进行检测,如果达到某个设定的温度就给蜂鸣器一个电平使其想一声并给led灯电平使其亮,而温度记录则要比较后一个输入的十二位数据与前一位十二位数据,看其表示的温度,比前一位大就把数据保存取代前一位最高,并设置按钮使其按下就显示此最高温度,比前一位小就把数据保存取代前一位最低,并设置不同按钮使其按下显示此最低温度。

串行数据处理与初始化:

由于ds18b20的操作相对比较复杂,所以单独设置一个模块专门处理其初始化,鉴于数码管的显示模块设置时并行输入的,所以此模块兼备ds18b20的传输数据处理,把串行数据处理成并行数据。

此模块的输入就一个是时钟,另一个就是ds18b20的串行实时温度代码(12位),其与ds18b20之间就一根线相连,实现对其初始化与数据就收,还要对接收的串行数据进行储存使之可以并行输出,以提供给显示模块。

整机模块组合:

 

另附各程序如下:

时钟分频模块:

1:

--分频器——生成一个频率为1MHz的时钟信号,

--以供显示及报警模块作为触发信号使用。

LIBRARYIEEE;

USEIEEE.STD_LOGIC_1164.ALL;

entityclk_divis

port(clk:

instd_logic;

clk_div:

outstd_logic

);

endentity;

architecturebehavofclk_divis

begin

process(clk)

variablecount:

integerrange0to50;

begin

ifrising_edge(clk)then

count:

=count+1;

ifcount=50thenclk_div<='1';count:

=0;--开发板内部时钟为50MHz,计数变量count=50使时钟输出为1MHz

elseclk_div<='0';--分频器以1MHz的频率置“1”其余保持低电平

endif;

endif;

endprocess;

endbehav;

2:

--分频器——生成一个频率为10000Hz的时钟信号,

--以供显示及报警模块作为触发信号使用。

LIBRARYIEEE;

USEIEEE.STD_LOGIC_1164.ALL;

entityclk_div2is

port(clk:

instd_logic;

clk_div2:

outstd_logic

);

endentity;

architecturebehavofclk_div2is

begin

process(clk)

variablecount:

integerrange0to5000;

begin

ifrising_edge(clk)then

count:

=count+1;

ifcount=5000thenclk_div2<='1';count:

=0;--开发板内部时钟为50MHz,计数变量count=5000使时钟输出为10000Hz

elseclk_div2<='0';--分频器以10000Hz的频率置“1”其余保持低电平

endif;

endif;

endprocess;

endbehav;

DS18B20初始化与串行数据处理模块:

---温度传感器初始化以及命令的读写、温度检测

libraryIEEE;

useIEEE.STD_LOGIC_1164.ALL;

useIEEE.STD_LOGIC_ARITH.ALL;

useIEEE.STD_LOGIC_UNSIGNED.ALL;

entitywendu_chuanganis

port(clk:

instd_logic;

dq:

inoutstd_logic;

wendu:

outstd_logic_vector(15downto0));

endwendu_chuangan;

architecturebehavofwendu_chuanganis

typestate_typeis(s0,s1,s2,s3,s4,s5,s6,s7,write_0,write_1,write_01,write_11,read0,read1,read2,read3);

signalstate:

state_type;

signalreset:

std_logic;

signali:

integerrange0to1000000;

signaldate:

std_logic_vector(15downto0);

begin

wendu<=date;--内部暂存数据赋给“wendu”输出一个16位的数值

process(clk,reset)--通常作用实现是变量i=i+1,而当reset=1,则i置“0”

begin

if(reset='1')then

i<=0;

elsifrising_edge(clk)then

i<=i+1;

endif;

endprocess;

process(clk)

variablej:

integerrange0to60;

variablecnt:

integerrange0to16;

begin

if(clk'eventandclk='1')then

casestateis--s0-s4为初始化过程,包括复位和存在脉冲

whens0=>--对传感器输入一个拉低电平

dq<='0';

reset<='1';

state<=s1;

whens1=>--保持低电平500μs,之后释放传感器的数据I/O管脚并置高阻态

reset<='0';

if(i=500)then

dq<='Z';

state<=s2;

reset<='1';

endif;

whens2=>--等待45μs

reset<='0';

if(i=45)then

reset<='1';

state<=s3;

endif;

whens3=>--如果检测到DQ输出低电平则跳转到s4,如果为高电平则跳转到s0

if(dq='0')then

state<=s4;

elsif(dq='1')then

state<=s0;

endif;

whens4=>--保持存在低电平200μs,之后跳转到s5

reset<='0';

if(i=200)then

reset<='1';

state<=s5;

endif;

whens5=>--命令写入

if(j=0orj=1)then--写入命令CCh,即SkipROM命令

state<=write_0;

j:

=j+1;

elsif(j=2orj=3)then

state<=write_1;

j:

=j+1;dq<='0';

elsif(j=4orj=5)then

state<=write_0;

j:

=j+1;

elsif(j=6orj=7)then

state<=write_1;

j:

=j+1;dq<='0';

elsif(j=8orj=9)then--写入命令44h,即ConvertT命令

state<=write_0;

j:

=j+1;

elsif(j=10)then

state<=write_1;

j:

=j+1;dq<='0';

elsif(j=11)then

state<=write_0;

j:

=j+1;

elsif(j=12orj=13)then

state<=write_0;

j:

=j+1;

elsif(j=14)then

state<=write_1;

j:

=j+1;dq<='0';

elsif(j=15)then

state<=write_0;

j:

=j+1;

elsif(j=16)then

j:

=20;

state<=s6;

dq<='Z';

elsif(j=20orj=21)then--写入命令CCh,即SkipROM命令

state<=write_0;

j:

=j+1;

elsif(j=22orj=23)then

state<=write_1;

j:

=j+1;dq<='0';

elsif(j=24orj=25)then

state<=write_0;

j:

=j+1;

elsif(j=26orj=27)then

state<=write_1;

j:

=j+1;dq<='0';

elsif(j=28)then--写入命令BEh,即ReadScratchpad命令

state<=write_0;

j:

=j+1;

elsif(j=29orj=30orj=31)then

state<=write_1;

j:

=j+1;dq<='0';

elsif(j=32orj=33)then

state<=write_1;

j:

=j+1;dq<='0';

elsif(j=34)then

state<=write_0;

j:

=j+1;

elsif(j=35)then

state<=write_1;

j:

=j+1;dq<='0';

elsif(j=36)then

state<=s7;j:

=40;

endif;

whens6=>--写入命令44h后,释放DQ管脚,并等待750ms

reset<='0';

if(i=750000ordq='1')then

state<=s0;

reset<='1';

endif;

whenwrite_0=>--主机生成一个写0时间隙,必须把数据线拉到低电平并保持70μs。

dq<='0';

reset<='0';

if(i=70)then

dq<='Z';--释放DQ管脚,使其有1μs的恢复时间

reset<='1';

state<=write_01;

endif;

whenwrite_01=>

state<=s5;

whenwrite_1=>--主机生成一个写“1”时间隙,必须把数据线拉到低电平然后释放,1μs后把数据线DQ拉到高电平,并保持70μs

state<=write_11;

whenwrite_11=>

dq<='1';

reset<='0';

if(i=70)then

reset<='1';

state<=s5;

endif;

whens7=>--从DQ管脚读出连续串行的16个数值

if(j<55)then

j:

=j+1;state<=read0;cnt:

=cnt+1;dq<='0';

elsif(j=55)thenj:

=60;state<=read0;cnt:

=15;dq<='0';

elsif(j=60)thenj:

=0;state<=s0;

endif;

whenread0=>--DQ写入一个低电平,此处等待1μs

state<=read1;

whenread1=>--释放DQ,当10μs后转到read2把读出的数值赋给寄存器date

dq<='Z';

reset<='0';

if(i=10)then

reset<='1';

state<=read2;

endif;

whenread2=>

date(cnt)<=dq;

state<=read3;

whenread3=>--读时间隙再保持55μs,合67μs

reset<='0';

if(i=55)then

reset<='1';

state<=s7;

endif;

whenothers=>

state<=s0;

endcase;

endif;

endprocess;

endbehav;

七段数码管显示外加温度记录与报警功能模块:

--并行数据处理与显示模块

LIBRARYieee;

USEieee.std_logic_1164.all;

USEieee.std_logic_unsigned.all;

USEieee.std_logic_arith.all;

entityd18b20is

GENERIC(LED_0:

STD_LOGIC_VECTOR(7DOWNTO0):

="00000011";--LED驱动不包括小数点

LED_1:

STD_LOGIC_VECTOR(7DOWNTO0):

="10011111";

LED_2:

STD_LOGIC_VECTOR(7DOWNTO0):

="00100101";

LED_3:

STD_LOGIC_VECTOR(7DOWNTO0):

="00001101";

LED_4:

STD_LOGIC_VECTOR(7DOWNTO0):

="10011001";

LED_5:

STD_LOGIC_VECTOR(7DOWNTO0):

="01001001";

LED_6:

STD_LOGIC_VECTOR(7DOWNTO0):

="01000001";

LED_7:

STD_LOGIC_VECTOR(7DOWNTO0):

="00011111";

LED_8:

STD_LOGIC_VECTOR(7DOWNTO0):

="00000001";

LED_9:

STD_LOGIC_VECTOR(7DOWNTO0):

="00001001";

LED0:

STD_LOGIC_VECTOR(7DOWNTO0):

="00000010";--LED驱动包括小数点

LED1:

STD_LOGIC_VECTOR(7DOWNTO0):

="10011110";

LED2:

STD_LOGIC_VECTOR(7DOWNTO0):

="00100100";

LED3:

STD_LOGIC_VECTOR(7DOWNTO0):

="00001100";

LED4:

STD_LOGIC_VECTOR(7DOWNTO0):

="10011000";

LED5:

STD_LOGIC_VECTOR(7DOWNTO0):

="01001000";

LED6:

STD_LOGIC_VECTOR(7DOWNTO0):

="01000000";

LED7:

STD_LOGIC_VECTOR(7DOWNTO0):

="00011110";

LED8:

STD_LOGIC_VECTOR(7DOWNTO0):

="00000000";

LED9:

STD_LOGIC_VECTOR(7DOWNTO0):

="00001000");

port(clk,dip1,dip2:

instd_logic;

temp:

instd_logic_vector(15downto0);

led77:

outstd_logic_vector(7downto0);

led44:

outstd_logic_vector(3downto0);

led:

outstd_logic_vector(7downto0);

beep:

outstd_logic);

endentity;

architecturebehavofd18b20is

signalj:

std_logic_vector(1downto0);

signalled71:

std_logic_vector(7downto0);

signalled72:

std_logic_vector(7downto0);

signalled73:

std_logic_vector(7downto0);

signalled74:

std_logic_vector(7downto0);

typestate_typeis(s0,s1,s2,s3);

signalstate:

state_type;

signalr:

std_logic_vector(15downto0);

typestate_type_firstis(w0,w1,w2);

signalstate_first:

state_type_first;

begin

counter:

process(clk)

begin

if(clk'eventandclk='1')then

j<=j+1;

endif;

endprocess;

scan:

process(j

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2