基于FPGA的温控风扇(2) - 图文

更新时间:2024-06-23 00:31:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

温控风扇的设计

摘 要: 温控风扇在现代社会中的生产以及人们的日常生活中都有广

泛的应用,如工业生产中大型机械散热系统中的风扇、现在笔记本电脑上的广泛应用的智能CPU风扇等。本文设计了基于altera FPGA温控风扇系统,采用FPGA作为控制器,利用温度传感器DS18B20作为温度采集元件,并根据采集到的温度,通过放大电路驱动风扇电机。采用热释电红外传感器,并根据检测到的温度与系统设定的温度的比较实现风扇电机的自动启动和停止,并能根温度的变化自动改变风扇电机的转速,同时在LCD1602显示检测到的温度与设定的温度。

【关键词】altera cyclone IV;按键模块;LCD1602显示模块;人体模块;

目 录

第1章 前言 ............................................. 3 第2章 整体方案设计 .................... 错误!未定义书签。 2.1系统整体设计..........................................4 2.2 方案论证.............................................5

2.2.1 温度传感器的选择..........................................5

2.2.2 调速方式的选择............................................6

第3章 各单元模块的硬件设计...........................7 3.1系统主要件.................................................7

3.2系统器件介.................................................7

3.2.1 DS18B20单线数字温度传感器简介..............................7 3.2.2 DAC0832芯片的简介..........................................7

第4章 软件设计...................................8

4.1程序设置.............................................8

第5章时序分析和综合..............................9

5.1 RTL Viewer.............................................................................................9 5.2 Technology Map Viewer............................................................................9 5.3 时序仿真............................................................................................10

第6章 硬件实物..................................10 第7章 结论......................................14 参考文献.........................................15 附录 程序代码.................................................................15

第1章 前言

随着人们生活水平及科技水平的不断提高,现在家用电器在款式、功能等方面日益求精,并朝着健康、安全、多功能、节能等方向发展。过去的电器不断的显露出其不足之处。电风扇作为家用电器的一种,同样存在类似的问题。

现在电风扇的现状:大部分只有手动调速,再加上一个定时器,功能单一。

存在的隐患或不足:比如说人们常常离开后忘记关闭电风扇,浪费电且不说还容易引发火灾,长时间工作还容易损坏电器。之所以会产生这些隐患的根本原因是:缺乏对环境的检测。

如果能使电风扇具有对环境进行检测的功能,当温度下降时能自动的减小风速甚至关闭风扇,这样一来就避免了上述的不足。

第2章 整体方案设计

2.1系统整体设计

本设计的整体思路是:以altera FPGA作为控制中心,通过提取热释电红外传感器感应到的人体红外线信息,并利用温度传感器DS18B20检测环境温度并直接输出数字温度信号给FPGA进行处理,在LCD1602上显示当前环境温度值以及预设温度值。通过独立键盘输入预设温度值,其中预设温度值只能为整数形式,检测到的当前环境温度可精确到小数点后一位。同时采用OCL放大电路方式来改变直流风扇电机的转速。并通过两个按键改变预设温度值,一个提高预设温度,另一个降低预设温度值。系统结构框图如下:

按键输入 人体红外传感器模块 Altera FPGA LCD1602显示模块 温度传感(DS18B20) D/.A转换(或PWM驱动) 2.2 方案论证 放大电路 直流电机 本设计要实现风扇直流电机的温度控制,使风扇电机能根据环境温度的变化自动启停及改变转速,需要比较高的温度变化分辨率以及稳定可靠的换挡停机控制部件。 2.2.1 温度传感器的选择 在本设计中,温度传感器的选择有以下两种方案: 方案一:采用热敏电阻作为检测温度的核心元件,并通过运算放大器放大,由于热敏电阻会随温度变化而变化,进而产生输出电压变化的微弱电压变化信号,再经模数转换芯片DAC0832将微弱电压变化信号转化为数字信号输入FPGA处理。 方案二:采用数字式的集成温度传感器DS18B20作为温度检测的核心元件,由其检测并直接输出数字温度信号给FPGA进行处理。 对于方案一,采用热敏电阻作为温度检测元件,有价格便宜,元件易购的优点,但热敏电阻对温度的细微变化不太敏感,在信号采集、放大以及转

换的过程中还会产生失真和误差,并且由于热敏电阻的R-T关系的非线性,其自身电阻对温度的变化存在较大误差,虽然可以通过一定电路来修正,但这不仅将使电路变得更加复杂,而且在人体所处环境温度变化过程中难以检测到小的温度变化。故该方案不适合本系统。

对于方案二,由于数字式集成温度传感器DS18B20的高度集成化,大大降低了外接放大转化等电路的误差因数,温度误差变得很小,并且由于其检测温度的原理与热敏电阻检测的原理有着本质的不同,使得其温度分辨力极高。温度值在器件内部转化成数字量直接输出,简化了系统程序设计,又由于该温度传感器采用先进的单总线技术,与FPGA的接口变得非常简洁,抗干扰能力强,因此该方案适用于本系统。

2.2.2 调速方式的选择

方案一:采用数模转换芯片DAC0832来控制,由FPGA根据当前环境温度值输出相应数字量到DAC0832中,再由DAC0832产生相应模拟信号控制晶闸管的导通角,从而通过无级调速电路实现风扇电机转速的自动调节。

方案二:采用其他串行口数转换芯片,或FPGA软件编程实现PWM(脉冲宽度调制)调速的方法。PWM是按一定的规律改变脉冲序列的脉冲宽度,以调节输出量和波形的一种调节方式,在PWM驱动控制的调节系统中,最常用的是矩形波PWM信号,在控制时需要调节PWM波得占空比。

对于方案一,该方案能够实现对直流风扇电机的无级调速,速度变化灵。

对于方案二,相对于其他用硬件或者软硬件相结合的方法实现对电机进行调速而言,采用PWM 用纯软件的方法来实现调速过程,具有更大的灵活性能够充分发挥FPGA的功能,对于简单速度控制系统的实现提供了一种有效的途径。

第3章 各单元模块的硬件设计

3.1系统主要器件

DS18B20温度传感器、Altera FPGA、LCD1602、风扇直流电机。

3.2系统器件简介

3.2.1 DS18B20单线数字温度传感器简介

单线数字温度传感器DS18B20简介新的\一线器件\体积更小、适用电压更宽、更经济 Dallas 半导体公司的数字化温度传感器DS1820是世界上第一片支持 \一线总线\接口的温度传感器。一线总线独特而且经济的特点,使用户可轻松地组建传感器网络,为丈量系统的构建引进全新概念。DS18B20、 DS1822 \一线总线\数字化温度传感器 同DS1820一样,DS18B20也 支持\一线总线\接口,丈量温度范围为 -55°C~+125°C,在-10~+85°C范围内,精度为±0.5°C。DS1822的精度较差为± 2°C 。现场温度直接以\一线总线\的数字方式传输,大大进步了系统的抗干扰性。

DS18B20内部结构主要有四部分:64位ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。其管脚有三个,其中DQ为数字信号端,GND为电源地,VDD为电源输入端。 3.2.2 DAC0832芯片的简介

DAC0832是8分辨率的D/A转换集成芯片。与微处理器完全兼容。这个DA芯片以其价格低廉、接口简单、转换控制容易等优点,在单片机应用系统中得到广泛的应用。D/A转换器由8位输入锁存器、8位DAC寄存器、8位D/A转换电路及转换控制电路构成。

根据对DAC0832的数据锁存器和DAC寄存器的不同的控制方式,DAC0832有三种工作方式:直通方式、单缓冲方式和双缓冲方式。 DAC0832引脚功能电路应用原理图DAC0832是采样频率为八位的D/A转换芯片,集成电路内有两级输入寄存器,使DAC0832芯片具备双缓冲、单缓冲和直通三种输入方式,以便适于各种电路的需要(如要求多路D/A异步输入、同步转换等)。所以这个芯片的应用很广泛,关于DAC0832应用的一些重要资料见下图: D/A转换结果采用电流形式输出。若需要相应的模拟电压信号,可通过一个高输入阻抗的线性运算放大器实现。运放的反馈电阻可通过RFB端引用片内固有电阻,也可外接。DAC0832逻辑输入满足TTL电平,可直接与TTL电路或微机电路连接。 第

4章 软件设计

4.1程序设置

程序设计部分主要包括主程序、DS18B20初始化函数、DS18B20温度转换函数、温度读取函数、键盘扫描函数、LCD1602显示函数、温度处理函数以及DAC0832转换。DS18B20初始化函数完成对DS18B20的初始化;DS18B20温度转换函数完成对环境温度的实时采集;温度读取函数完成主机对温度传感器数据的读取及数据换算,键盘扫描函数则根据需要完成初值的加减设定;温度处理函数对采集到的温度进行分析出理,为DAC0832的转换提供条件;风扇电机控制函数则根据温度的数值,再经过功率放大电路对电机转速及启停的控制。

LCD160 2显示模

人体红外检测模块 键盘模块 温度测量模块 D/A转换模块 顶层文件开始 第5章时序分析和综合

5.1 RTL Viewer

5.2 Technology Map Viewer

5.3 时序仿真

第6章 硬件实物

1.以上两图为上电后检测的室温

2.为温度自动控制风扇档位

3.为手动调风扇档位

第7章 结论

本课题设计是基于FPGA的温控风扇,作为一个入门简易的课题。

现在电风扇的现状:大部分只有手动调速,再加上一个定时器,功能单一。 存在的隐患或不足:比如说人们常常离开后忘记关闭电风扇,浪费电且不说还容易引发火灾,长时间工作还容易损坏电器。之所以会产生这些隐患的根本原因是:缺乏对环境的检测。

如果能使电风扇具有对环境进行检测的功能,当温度下降时能自动的减小风速甚至关闭风扇,这样一来就避免了上述的不足。

在整个设计过程中,充分发挥了组员们的主观能动性。程序编写中,由于思路不清晰,开始时遇到了很多的问题,后经和同学讨论,向老师请教,最终完成对程序的编写。通过实际程序设计和调试,逐步掌握模块化程序设计方法和调试技术,提高软件设计、调试能。最终较好的完成了设计,达到了预期的目的。

但是由于个人能力的原因,整个系统看起来还是显得较为简单,只实现了一些最基本的功能,还有许多可以扩展的地方,当然,也存在许多不足之处。

参考文献

[1]Verilog HDL入门(第3版)J.BHASKER 著 北京航空航天大学出版社 [2]ALtera FPGA_CPLD应用_基础篇 王诚、薛小刚等著 人民邮电出版社 [3Altera FPGA_CPLD设计_高级篇 EDA先锋工作室 王诚、吴继华等著 人民邮电出版社

附录程序代码

//**************顶层模块**************//

module da18(clk,rs, rw, en,dat,one_wire,button,buttona,men,data);

input clk;

input men,button,buttona; inout one_wire; output dat; output rs,rw,en; output [7:0] data;

//output [15:0] tem;

//output [3:0] dig; //output [7:0] seg; wire [15:0] temperature; wire [7:0] dat,data;

wire rs,rw,en,men,button,buttona;

Temperature Temperature(.clk(clk),.one_wire(one_wire),.temperature(temperature)); //DS1820程序元件例化

//scan scan(.clk(clk),.dig(dig),.seg(seg),.temperature(temperature));

lcd lcd(.clk(clk),.temperature(temperature),.rs(rs),.rw(rw),.en(en),.dat(dat)); //LCD1602程序元件例化

da0832 da0832 (.clk(clk),.temperature(temperature),.button(button), //DA0832程序元件例化

.buttona(buttona),.men(men),.data(data)); endmodule

//**************LCD1602显示温度模块*******************// module lcd(clk, rs, rw, en,dat,temperature); input clk;

input [15:0] temperature; output [7:0] dat; output rs,rw,en; //tri en; reg e; reg [7:0] dat; reg rs;

reg [15:0] counter; reg [4:0] current,next; reg clkr; reg [1:0] cnt; wire [3:0] a,b,c,d;

assign a = {temperature[3:0]}; assign b = {temperature[7:4]}; assign c = {temperature[11:8]}; assign d = {temperature[15:12]};

parameter set0=4'h0; parameter set1=4'h1; parameter set2=4'h2; parameter set3=4'h3;

parameter dat0=4'h4; parameter dat1=4'h5; parameter dat2=4'h6; parameter dat3=4'h7; parameter dat4=4'h8; parameter dat5=4'h9;

parameter dat6=4'hA; parameter dat7=4'hB; parameter dat8=4'hC; parameter dat9=4'hD; parameter dat10=4'hE; parameter dat11=5'h10;

always @(posedge clk) // 10MHZ begin

counter=counter+1; if(counter==16'h0005) clkr=~clkr; end

always @(posedge clkr ) begin

current=next; case(current)

set0: begin rs<=0; dat<=8'h30; next<=set1; end set1: begin rs<=0; dat<=8'h0c; next<=set2; end set2: begin rs<=0; dat<=8'h6; next<=set3; end set3: begin rs<=0; dat<=8'h1; next<=dat0; end dat0: begin rs<=1; dat<=\ dat1: begin rs<=1; dat<=\

dat2: begin rs<=1; dat<=\ dat3: begin rs<=1; dat<=\ dat4: begin

if(c==4'b0000) begin rs<=1; dat<=\ else if (c==4'b0001) begin rs<=1; dat<=\ else if (c==4'b0010) begin rs<=1; dat<=\ else if (c==4'b0011) begin rs<=1; dat<=\ else if (c==4'b0100) begin rs<=1; dat<=\ else if (c==4'b0101) begin rs<=1; dat<=\ else if (c==4'b0110) begin rs<=1; dat<=\ else if (c==4'b0111) begin rs<=1; dat<=\ else if (c==4'b1000) begin rs<=1; dat<=\ else if (c==4'b1001) begin rs<=1; dat<=\end

dat5: begin

if(b==4'b0000) begin rs<=1; dat<=\ else if (b==4'b0001) begin rs<=1; dat<=\ else if (b==4'b0010) begin rs<=1; dat<=\ else if (b==4'b0011) begin rs<=1; dat<=\ else if (b==4'b0100) begin rs<=1; dat<=\ else if (b==4'b0101) begin rs<=1; dat<=\ else if (b==4'b0110) begin rs<=1; dat<=\ else if (b==4'b0111) begin rs<=1; dat<=\ else if (b==4'b1000) begin rs<=1; dat<=\ else if (b==4'b1001) begin rs<=1; dat<=\end

dat6: begin rs<=1; dat<=\

dat7: begin

if(a==4'b0000) begin rs<=1; dat<=\

else if (a==4'b0001) begin rs<=1; dat<=\ else if (a==4'b0010) begin rs<=1; dat<=\ else if (a==4'b0011) begin rs<=1; dat<=\ else if (a==4'b0100) begin rs<=1; dat<=\ else if (a==4'b0101) begin rs<=1; dat<=\ else if (a==4'b0110) begin rs<=1; dat<=\ else if (a==4'b0111) begin rs<=1; dat<=\ else if (a==4'b1000) begin rs<=1; dat<=\ else if (a==4'b1001) begin rs<=1; dat<=\end

dat8: begin rs<=1; dat<=8'hdf; next<=dat9; end dat9: begin rs<=1; dat<=\

endcase

end

//assign en=clkr|e; assign en=clkr; assign rw=0; endmodule

//****************************温控模块***************************************// module Temperature(

input clk, // 50MHz时钟 //input rst_n, // 异步复位 inout one_wire, // One-Wire总线

output [15:0] temperature // 输出温度值 );

reg rst_n; reg [19:0]count; always@(posedge clk) begin

if(count<20'h80000) //? begin rst_n<=1;

count<=count+1; end

else if(count<20'h8ffff) //? begin rst_n<=0;

count<=count+1; end else

rst_n<=1; end

//++++++++++++++++++++++++++++++++++++++ // 分频器50MHz->1MHz 开始

//++++++++++++++++++++++++++++++++++++++ reg [5:0] cnt; // 计数子

always @ (posedge clk, negedge rst_n) if (!rst_n)

cnt <= 0; else

if (cnt == 49) cnt <= 0; else

cnt <= cnt + 1'b1;

reg clk_1us; // 1MHz 时钟

always @ (posedge clk, negedge rst_n) if (!rst_n) clk_1us <= 0; else

if (cnt <= 24) // 24 = 50/2 - 1 clk_1us <= 0; else

clk_1us <= 1;

//-------------------------------------- // 分频器50MHz->1MHz 结束 //--------------------------------------

//延时模块的使用

//++++++++++++++++++++++++++++++++++++++ // 延时模块 开始

//++++++++++++++++++++++++++++++++++++++ reg [19:0] cnt_1us; // 1us延时计数子 reg cnt_1us_clear; // 请1us延时计数子

always @ (posedge clk_1us) //可设定时N ns if (cnt_1us_clear) cnt_1us <= 0; else

cnt_1us <= cnt_1us + 1'b1; //加一次1us //-------------------------------------- // 延时模块 结束

//--------------------------------------

//++++++++++++++++++++++++++++++++++++++ // DS18B20状态机 开始

//++++++++++++++++++++++++++++++++++++++ //++++++++++++++++++++++++++++++++++++++ // 格雷码

parameter S00 = 5'h00; //步数 parameter S0 = 5'h01; parameter S1 = 5'h03; parameter S2 = 5'h02; parameter S3 = 5'h06; parameter S4 = 5'h07; parameter S5 = 5'h05; parameter S6 = 5'h04; parameter S7 = 5'h0C; parameter WRITE0 = 5'h0D; parameter WRITE1 = 5'h0F; parameter WRITE00 = 5'h0E; parameter WRITE01 = 5'h0A; parameter READ0 = 5'h0B;

parameter READ1 = 5'h09; parameter READ2 = 5'h08; parameter READ3 = 5'h18;

reg [4:0] state; // 状态寄存器 //-------------------------------------

reg one_wire_buf; // One-Wire总线 缓存寄存器

reg [15:0] temperature_buf; // 采集到的温度值缓存器(未处理) reg [5:0] step; // 子状态寄存器 0~50 reg [3:0] bit_valid; // 有效位

always @(posedge clk_1us, negedge rst_n) //clk_1us即每1us执行一次 begin if (!rst_n) begin

one_wire_buf <= 1'bZ; step <= 0;

state <= S00; //s00为变量名 end else begin case (state)

S00 : begin

temperature_buf <= 16'h001F; state <= S0; end

S0 : begin // 初始化

cnt_1us_clear <= 1;

one_wire_buf <= 0; state <= S1; end S1 : begin

cnt_1us_clear <= 0;

if (cnt_1us == 500) // 延时500us begin

cnt_1us_clear <= 1;

one_wire_buf <= 1'bZ; // 释放总线 state <= S2; end end S2 : begin

cnt_1us_clear <= 0; //cnt_1us_clear有效时cnt_1us清零 if (cnt_1us == 100) // 等待100us begin

cnt_1us_clear <= 1; state <= S3; end end

S3 : if (~one_wire) // 若18b20拉低总线,初始化成功 one_wire输入 state <= S4;

else if (one_wire) // 否则,初始化不成功,返回S0 state <= S0; S4 : begin

cnt_1us_clear <= 0;

if (cnt_1us == 400) // 再延时400us begin

cnt_1us_clear <= 1; state <= S5; end end

S5 : begin // 写数据

if (step == 0) // 0xCC begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 1) begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 2) begin one_wire_buf <= 0;

step <= step + 1'b1; state <= WRITE01; end

else if (step == 3) begin

one_wire_buf <= 0; step <= step + 1'b1;

state <= WRITE01; end

跳过ROM //

else if (step == 4) begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 5) begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 6) begin

one_wire_buf <= 0;

step <= step + 1'b1; state <= WRITE01; end

else if (step == 7) begin

one_wire_buf <= 0;

step <= step + 1'b1; state <= WRITE01; end

else if (step == 8) // 0x44 begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 9)

启动转换

begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 10) begin

one_wire_buf <= 0;

step <= step + 1'b1; state <= WRITE01; end

else if (step == 11) begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 12) begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 13) begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 14) begin

one_wire_buf <= 0;

step <= step + 1'b1;

state <= WRITE01; end

else if (step == 15) begin

step <= step + 1'b1; state <= WRITE0; end

// 第一次写完,750ms后,跳回S0 else if (step == 16) begin

one_wire_buf <= 1'bZ; step <= step + 1'b1;

state <= S6; end

// 再次置数0xCC和0xBE

else if (step == 17) // 0xCC begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 18) begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 19)

//s6为延时步骤 //再始化后通过step变量寻至此步

begin

one_wire_buf <= 0;

step <= step + 1'b1;

state <= WRITE01; end

else if (step == 20) begin

step <= step + 1'b1; state <= WRITE01; one_wire_buf <= 0; end

else if (step == 21) begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 22) begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 23) begin

one_wire_buf <= 0;

step <= step + 1'b1; state <= WRITE01; end

else if (step == 24) begin

one_wire_buf <= 0;

step <= step + 1'b1;

state <= WRITE01; end

else if (step == 25) // 0xBE DS模块输出数据 begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 26) begin

one_wire_buf <= 0;

step <= step + 1'b1;

state <= WRITE01; end

else if (step == 27) begin

one_wire_buf <= 0;

step <= step + 1'b1;

state <= WRITE01; end

else if (step == 28) begin

one_wire_buf <= 0;

step <= step + 1'b1;

state <= WRITE01; end

else if (step == 29)

begin

one_wire_buf <= 0;

step <= step + 1'b1; state <= WRITE01; end

else if (step == 30) begin

one_wire_buf <= 0;

step <= step + 1'b1; state <= WRITE01; end

else if (step == 31) begin

step <= step + 1'b1; state <= WRITE0; end

else if (step == 32) begin

one_wire_buf <= 0;

step <= step + 1'b1; state <= WRITE01; end

// 第二次写完,跳到S7,直接开始读数据 else if (step == 33) begin

step <= step + 1'b1; state <= S7; end

通过步骤数step控制程序进程

end S6 : begin

cnt_1us_clear <= 0;

if (cnt_1us == 750000 | one_wire) // 延时750ms!!!! begin

cnt_1us_clear <= 1;

state <= S0; // 跳回S0,再次初始化 end end

S7 : begin // 读数据 if (step == 34) begin

bit_valid <= 0; one_wire_buf <= 0;

step <= step + 1'b1; state <= READ0; end

else if (step == 35) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1; state <= READ0; end

else if (step == 36) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1; state <= READ0; end

else if (step == 37) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0; end

else if (step == 38) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0; end

else if (step == 39) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0; end

else if (step == 40) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0; end

else if (step == 41) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1; state <= READ0; end

else if (step == 42) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0; end

else if (step == 43) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1; state <= READ0; end

else if (step == 44) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0;

end

else if (step == 45) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0; end

else if (step == 46) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0; end

else if (step == 47) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0; end

else if (step == 48) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0; end

else if (step == 49) begin

bit_valid <= bit_valid + 1'b1; one_wire_buf <= 0;

step <= step + 1'b1;

state <= READ0; //READ0通过一串指向后返回s7,结合step回到当前步骤数 end

else if (step == 50) begin

step <= 0; state <= S0; end

end

//++++++++++++++++++++++++++++++++ // 写状态机

//++++++++++++++++++++++++++++++++ WRITE0 : begin

cnt_1us_clear <= 0;

one_wire_buf <= 0; // 输出0 if (cnt_1us == 80) // 延时80us begin

cnt_1us_clear <= 1;

one_wire_buf <= 1'bZ; // 释放总线,自动拉高 state <= WRITE00; end

end

WRITE00 : // 空状态 延时 state <= S5;

WRITE01 : // 空状态 state <= WRITE1; WRITE1 : begin

cnt_1us_clear <= 0;

one_wire_buf <= 1'bZ; // 输出1 释放总线,自动拉高 if (cnt_1us == 80) // 延时80us begin

cnt_1us_clear <= 1; state <= S5; end end

//-------------------------------- // 写状态机

//--------------------------------

//++++++++++++++++++++++++++++++++ // 读状态机

//++++++++++++++++++++++++++++++++ READ0 : state <= READ1; // 空延时状态 READ1 : begin

cnt_1us_clear <= 0;

one_wire_buf <= 1'bZ; // 释放总线 if (cnt_1us == 10) // 再延时10us

begin

cnt_1us_clear <= 1; state <= READ2; end end

READ2 : // 读取数据 begin

temperature_buf[bit_valid] <= one_wire; state <= READ3; end READ3 : begin

cnt_1us_clear <= 0;

if (cnt_1us == 55) // 再延时55us begin

cnt_1us_clear <= 1; state <= S7; end end

//-------------------------------- // 读状态机

//------------------------------- default : state <= S00; endcase end end

assign one_wire = one_wire_buf; // 注意双向口的使用//-------------------------------------- // DS18B20状态机 结束

串联输送数据

//--------------------------------------

//++++++++++++++++++++++++++++++++++++++ // 对采集到的温度进行处理 开始

//++++++++++++++++++++++++++++++++++++++

wire [15:0] t_buf = temperature_buf & 16'h07FF; //temperature_buf上述读数据程序的临时寄存器

assign temperature[3:0] = (t_buf[3:0] * 10) >> 4; // 小数点后一位

assign temperature[7:4] = (t_buf[7:4] >= 10) ? (t_buf[7:4] - 10) : t_buf[7:4]; // 个位 assign temperature[11:8] = (t_buf[7:4] >= 10) ? (t_buf[11:8] + 1) : t_buf[11:8]; // 十位 assign temperature[15:12] = temperature_buf[12] ? 1 : 0; // 正负位,0正1负

//-------------------------------------- // 对采集到的温度进行处理 结束 //-------------------------------------- Endmodule

// ********************DA转换模块(手动调速与温控调速结合)程序部分********************// module da0832(clk,temperature,button,buttona,men,data);

input clk,men,button,buttona; input [15:0] temperature; output [7:0] data;

reg en;

reg [1:0] start,next,abs; wire [3:0] a,b,c,d; reg [7:0] data;

assign a = {temperature[3:0]}; //合并赋值?

assign b = {temperature[7:4]}; //个 assign c = {temperature[11:8]}; //十 assign d = {temperature[15:12]};

parameter se0=4'h0; //parameter 类似常量

parameter se1=4'h1;

parameter se2=4'h2; parameter se3=4'h3;

always @(negedge buttona) begin //调节档位 abs <= abs + 1'b1; end

always @(posedge clk) begin en <= men;

if(!en) begin //无人风扇关闭 data <= 8'h0; end

else if (en ==1 && button == 0) begin strat ,next两个变量,可单一变量 start = next; case (start) se0 : begin if(c >= 4'd2 && b >= 4'd3) begin

data <= 'h4b; 共4b份=1.5v

//温控调档

//23 度时开

//1.5v 每份5/255 v

end

else

next <= se1;

end

se1 : begin

if(c >= 4'd2 && b >= 4'd7) begin

data <= 'h80; //非阻塞赋值case语句中必须

end

//2.5v

else

next <= se2;

end

se2 : begin

if(c >= 4'd3 && b >= 4'd2) begin

data <= 'hb8; //3.5v

end

else

next <= se0;

end

endcase end

else begin //手动档位 档位输出 case(abs)

00 : data <= 'h4b; //if(data >= 'hb8) data =0; //case为并行语句 01 : data <= 'h80;

10 : data <= 'hb0; //用b0非b8以防输出过大 endcase end end

endmodule

本文来源:https://www.bwwdw.com/article/85f3.html

Top