1.概述
1.1 项目背景
在随着微处理器的发展,各类设备日趋向网络化发展,物联网 2009 年已引起了广泛关注,据预测 2010 年无线传感器应用将成为最新的电子智能社会的热点。随着材料科学、电化学科学、生物科学的不断发展,新类型的传感器产品层出不穷。而目前市面上所售的传感器采集板,都是一经定型就无法改变的。FPGA产品的特性在于可以进行反复修改硬件设计。为此,产生使用 FPGA 来设计各类传感器接入的思考。其系统优点在于,当系统接入的传感器发生改变时,可以重新设计 FPGA 接口电路模块使得其容纳新产品。为此,本项目试用 FPGA 将无线传感器网络和典型的数字、模拟传感器相连,满足环境监测的需要。
如图 1-1 所示,其中,虚线框表示外部自然环境、圆形表示传感器,方框表示基于 FPGA 的环境监测系统,天线表示 I2C 接口设备、云表示无线传感器网络、PC 机表示用户终端。
整个工作流程为:传感器通过 FPGA 上 的 EXP 接 口与环境监测系统相连。系统通过发送命令,从传感器上采集数据。数据采集后,系统将从传感器采集来的数据使用 I2C 接口输出,例如可以通过无线传感器网络传输,并最终将结果输出到终端。从而实现对外部环境的监测。
图 1-2. 基于 FPGA 的环境监测系统框图
2.基于 FPGA 的环境监控系统的 总控模块设计
2.1 模块功能概述
FPGA 在环境网络中的检测既是指 FPGA 对温湿 度及气压传感器的测量数据进行读取,存储并上交给上级端口的过程。本模块完成的是其中的核心部分——即FPGA 通过计数器完成对温湿度传感器以及气压传感器的轮询,并将接收到的数据存储起来,通过与上级连通的 I2C 接口将数 据发送至上级端口。
本模块的另一个作用是创建时钟数据包,将引入的 FPGA 内部晶振时钟转化为项目所需的时钟(即计数器所需时钟,温湿度传感器所需时钟,气压传感器所需时钟,上级 I2C 端口所需时钟)。如图 2-1 所示。
图 2-1 端口模块原理图
2.2 底层模块设计
2.2.1 CLK 分频端口模块设计
图 2-2 分频端口模块
SCK 为 FPGA 内部晶振时钟,时钟频率 125MHZ;
CLK 端口的作用是将 FPGA 内部的晶振时钟转化为项目所需的时钟。转化方法为通过四个分频器将输入的晶振时钟 SCK 分别转化为计数器所需的 CLK1,温湿度传感器所需的时钟 CLK2,气压传感器所需的 CLK3 以及上级端口所需的 CLK4。
其中计数器所需的时钟频率较低,所以需要分频器 1 需要对 SCK 进行 10 万倍的分频。而 clk2 需要 1MHZ 的时钟,所以要对 分频器 2 进行 125 分频。
相关程序为:
entity cl k is
Port ( sck : in STD_LOGIC;
clk1 : out STD_LOGIC;
clk2 : out STD_LOGIC;
clk3 : out STD_LOGIC;
clk4 : out STD_LOGIC);
end clk;
architecture Behavioral of clk is --分频器 1,为计数器提供时钟 CLK1
begi n
process(sck)
variable x:std_l ogic;
variable n:integer range 0 t o 49999:=0; --因计数器频率较低,故对 FPGA 内部
- -振进行 10 万倍分频
begin
x:='0';
clk1<=x;
if(rising_edge(sck))then
if(n=49999)then
n:=0;
x:=not x;
else n:= n+1;
end if;
end if;
end process;
process(sck) --分频器 2 产生温湿度传感器所需时钟
variable n:integer range 0 t o 124:=0; --时钟为 125 分频,将 125MHZ 的晶振
--钟转化为 1MHZ 的传感器所需时钟
variable x1,x2:std_logic;
begin
x1:='0';
x2:='1';
clk2<=x1 xor x2;
if(rising_edge(sck))then
if(n=124)then
n:=0;
x1:= not x1;
else n:= n+1;
end if;
end if;
if(falling_edge(sck))then
if(n=62)then
x2:= not x2;
end if;
end if;
clk3<=sck;
clk4<=sck;
end process;
end Behavioral;
2.2.2 计数器模块
图 2.3 计数器模块
计数器模块的作用是对两个端口模块进行轮询,使两个端口模块能够依次启动,并最终让存储模块依次接收到温度,湿度以及气压的数据。
具体方法为:计数器模块内部是一个 0 到 150 循环计数的计数器。计数器接收输入的时钟信号,使计数器在时钟上升沿到来时启动一次。
当 N=1 时,计数器向温湿度端口模块发送启动温度检测的指令。接下来计数器开始计数,即 N 开始自加。
在 1<=N<50 的时间里,计数器无任何新指令,这是给温湿度端口模块充足的时间,使其能完成其内部功能(既接对温湿度传感器发送温度检测指令,收温湿度传感器发送的温度数据,并将其传送给存储模块)。
类似于温度指令的处理方法,在 N=50 时计数器 向温湿度端口模块发送湿度检测指令,并在 50
在 N=151 时,温度,湿度以及气压的测量数据 都已经存储在储存模块当中了,这时将 N 置 0,开始新一轮的轮询。
相关程序为:
entity count is
Port ( clk1 : in STD_LOGIC;
com1 : out STD_LOGIC_VECTOR (1 downto 0); --向温湿度接口模
--块发送启动指令的端口
com2 : out STD_LOGIC); --向气压接口模块发送启动指令的端口
end count;
architecture Behavioral of count is
begin
process(clk1)
variable n:integer range 0 to 200:=0;
begin
if(rising_edge(clk1))then
if(n=151)then
n:=0; --在 n=151 时将 N 置 0,开始新一次的轮询
com1<="11";
com2<='1';
else n:=n+1;
end if;
if(n=1)then --在 n=1 时,发送温度检测指令
com1<="01";
com2<='1';
--等待,保证端口功能的实现
elsif(n=50)then --发送湿度检测指令
com1<="10";
com2<='1';
--等待,保证端口功能的实现
elsif(n=100)then --发送气压检测指令
com1<="11";
com2<='0';
--等待,保证端口功能的实现
end if;
end if;
end process;
end Behavioral;
2.2.3 存储与转发模块
本模块旨在按顺序接收由温湿度传感器端口模块与气压传感器端口模块发出的测量数据(即一组 12 位的 2 进制数字),并 再接收完毕后将数据编码并发送给上级串行端口,其元器件内部结构如下:
图 2-4 存储与转发模块
在这其中,COM1 与 COM2 的作用是对存储器 VALUE1,VALUE2,VALUE3 发出“接收数据”的指令。在温湿度接口模块将温度的测量数据接收完成时,接口模块就通过 COM1 发出指令,“通知”存储模块接收数 据。同理 com1 还可以发送湿度数据的“接收”指令。而 com2 由气压传感器端 口模块引出,用于在气压测量数据读取完成时发送气压数据的“接收”指令。
由于计数器已经完成了轮询机制,对个端口模块的启动顺序有了安排,所以本模块不涉及解决数据的接收顺序的问题。接收数据时发生“冲突”(几多了数据同时给出接收指令)的问题也不由本接口解决。在这里使用了单片机的方法来完成数据的接收与发送。
具体的单片机时序如下:
图 2-5 状态机
如上图所示,本状态机分为五个状态,IDLE 为空闲状态,亦为状态机的初始状态。当存储器接收到温度数据的接收指令之后,状态机转入状态 s0。
在 s 0 状态,存储模块将数据接收 到 VALUE1 当 中,等到收到湿度数据接收指令时,状态机进入 S1 状态。
同理接收湿度数据,转入状态 S2,并在气压端口模块的接受指令输入之后接收气压数据,当气压数据接受完成后,转入状态 S3。
在 S3 状态,所接收的温湿度及气压数据被编成 长度为 45 位 2 进制编码,并存储于 VALUE 中。最中通 过 I2C 串行接口转发 给上级。具体方法为通过接入 I2C所需的 I2C_CLK,通过捕捉上升沿发送数据,并最终将编码发送给上级。
编码发送完成后,状态机回到空闲状态,等待下一次启动(轮询启动由计数器完成)。
相关程序为:
entity logic_2 is
Port (
clk4 : in STD_LOGIC;
com1 : in std_logic_vector(1 downto 0);
com2 : in std_logic;
data_in1 : in STD_LOGIC_vector(11 downto 0);
data_in2 : in STD_LOGIC_vector(11 downto 0);
data_out : out STD_LOGIC);
end logic_2;
architecture Behavioral of logic_2 is
type xn is (idle,s0,s1,s2,s3);
signal state:xn;
signal value1,value2,value3:std_logic_vector(11 downto 0);
signal value:std_logic_vector(44 downto 0);
begin
process(clk4,com1,com2,state,data_in1,data_in2)
variable n:integer range 0 to 50;
begin
case state is
when idle=>
if(com1="01")then
state<=s0;
end if;
when s0=>
value1<=data_in1;
if(com1<="10")then
state<=s1;
end if;
when s1=>
value2<=data_in1;
if(com2<='0')then
state<=s2;
end if;
when s2=>
value3<=data_in2;
state<=s3;
when s3=>
n:=0;
value<=value3&"011"&value2&"010"&value1&"000";
if(rising_edg e(clk4))then
data_out<=value(n);
if(n>=0 and n<44)then n:=n+1;
elsif(n=44)then state<=idle;
else null;
end if;
end if;
end case;
end process;
end Behavioral;
2.2.4 传输模块
本模块的作用是接收存储模块的启动指令并接收从存储模块传输过来的以编码完成的数据,并将这个 45 位的 2 进制编码 通过 I2C 串口发送给上级接口,其内部结构图如下:
图 2-6 传输模块
当接收模块收到存储模块发来的启动信号(COMX=’0’)时,I2C_DATA 开始接收 DATA_IN 传输来的数据。具体方法为:通过捕捉 CLK 上升沿,每次上升沿计数器加 1,每次传输 1 字节的数据。这样计数 45 次,便能把 45 位的数据从 I2C_DATA串行接口 1 字节 1 字节的发送给上级端口。
当 45 位编码全部传输完毕后,传输模块便会向存储模块发送“发送完毕”指令,回到等待状态。
2.3 顶层模块设计
顶层模块的主要作用是将上述时钟分频模块,计数器模块与存储转发模块连接起来,主要使用元件例化语句。
具体语句如下:
entity su mmar y1 is
Port ( sck : in STD_LOGIC;
reset: in std_log ic;
com_in1:in std_log ic_vector(1 downto 0);
com_in2:in std_log ic;
com_out1 :out std_lo gic_vector(1 downto 0);
com_out2 :out std_lo gic;
data_in1 : in STD_LOGIC_vector(11 downto
0);
data_in2 : in STD_LOGIC_vector(11 do wnto 0);
data_o ut:out std_logic);
用
end summar y1 ;
architecture Behavioral o f summar y1 is
component clk is --CLK 分频模块调
Port ( sck : in STD_LOGIC;
clk1 : out STD_LOGIC;
clk2 : out STD_LOGIC;
clk3 : out STD_LOGIC;
clk4 : out STD_LOGIC);
end compo nent;
component count is --计数器模块调用
Port ( clk1 : in STD_LOGIC;
com1 : o ut STD_LOGIC_VECTOR (1 downto 0);
com2 : o ut STD_LOGIC);
end compo nent;
用
0);
component logic_2 is --存储转发模块调
Port (
clk4 : in STD_LOGIC;
com1 : in std_logic_vector(1 downto 0);
com2 : in std_logic;
data_in1 : in STD_LOGIC_vector(11 downto 0);
data_in2 : in STD_LOGIC_vector(11 downto
data_o ut : out STD_LOGIC);
end compo nent;
signal clk1,clk2,clk3,clk4:std_lo gic;
begin
u0:clk po rt map(sck,clk1,clk2,clk3,clk4);
u1:count po rt map(clk1,co m_out1,co m_o ut2);
--端口映射
u2:logic_2 port map( clk4,com_in1,com_in2,data_ in1,data_in2,data_out)
end Behavio ral;
3.气压传感器的接口模块介绍
3.1 概述
3.1.1 特性
该气压传感器的温度补偿为0——85 C°,适合于基于微控制器或者微处理器的系统,目前已取得硅剪气压应变仪标准量度的专利。
3.1.2 输入、输出关系与接口介绍
图3-1 气压传感器输入输出关系
如下图所示:传感器上,自左向右的管脚依次编为接口1至接口6。其中接口1、6将不被使用。接口2须接地,接口3、5分别接VOU+和VOUT-,接口4需要与电源相连。
图 3-2 接口模块编程实现
3.2 接口模块编程实现
该接口模块的程序流程如图 3-3 所示。
图 3-3 接口模块程序流程图
如上图所示,当程序开始执行,使能端连接 A/D 转换盒。当输入为为高电平时,不接收数据;当输入为低电平,且在时钟上升沿,传感器开始工作,它将传感器输出结果传入 FPGA 开发板。如果循环变量 i 小于 11,则 i 自加,并且返回上一步,继续传输结果。否则,当循环变量 i 大于等于 11 时,则意味着传输完毕,程序结束运行。
3.3 MCP3201 的介绍
3.3.1 主要特性
采用12 位分辨率,转换精度不超过+ / - 1 LSB,采用SPI兼容串行接口,单电源工作电压为2.7~5.5 V。当电源为最高的5.5V时,转换速率最高为100k/s,当电源为最低的2.7V时,转换速率是50k/s。当电源为5V时,500nA的典型机电流最大不超过400μA的工作电流。它的工作温度范围是-40~85℃。8个引脚的有PDIP,SOIC,TSSOP等多种封装。
图 3-4 MCP3210 引脚分布图
3.3.2 MCP3201 的引脚分布及功能简介
引脚分布如图 3-4 所示。
MCP3201 引脚分布中,VDD为2.7~5.5V电源引脚,VSS接地,IN+为正极性信号输入引脚,输入电压范围为VIN-~(VREF+VIN-)。IN-为负极性信号输入引脚,输入电压范围为(VSS-100mV)~(VS+100mV)。CS/ SHDN为片选/ 关闭控制引脚,此引脚被拉低时将初始化与该芯片的通讯,被拉高时将结束当前转换或通讯并使芯片处于关闭状态。在任何相邻的两次转换之间,该引脚必须被拉高。CLK为串行时钟输入引脚,用于启动本次转换及提供,转换结果串行输出的同步信号。DOUT :数据输出端,用于串行输出模数转换的结果,在转换完成之后的时钟下降沿自动更新位数据。VREF为参考电压输入引脚,电压范围0.25V~VDD。
3.3.3 工作时序图
图3-5 工作时序图
通过时序图的描述,可以看出:转换输出在 CL K 控制下进行,从 DOUT 引脚串行输出。每个 CL K 下降沿到来时,转换结 果移出一位。此时序图采用的是高位在前的标准模式。
用标准SPI 兼容串行接口与该器件进行通信。当CS变为低电平时,启动与MCP3201 的通信。如果器件上电时CS引脚为低电平,则必须先将此引脚拉为高电平,然后再恢复至低电平以启动通信。器件将在 CS 变为低电平后在第一个上升沿开始对模拟输入信号进行采样。采样周期将在第二个时钟周期的下降沿结束,此时器件将输出一个低电平空位。接下来的12 个时钟脉冲将以首先发送MSB位的格式输出转换结果,如图1所示。器件总是在时钟下降沿输出数据。所有12个数据位均发送完毕后,如果器件继续接收时钟脉冲,而CS保持为低电平,则器件将以首先发送LSB的格式输出转换结果,如图2所示。如果在CS保持为低电平时继续向器件提供时钟脉冲(在以首先发送LSB的格式发送完数据后),器件将持续输出零。
3.4 接口模块编程实现
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity sip is
port
(
dein,clk : in Std_Logic;
serialin : in Std_Logic;
parallelout : out Std_Logic_Vector (11 downto 0 );
rst : out Std_Logic;
deout : out Std_Logic);
end entity;
architecture a of sipo is
begin
rst<= dein; //AD盒连接使能端//
process (clk,dein)
variable i : integer range 0 to 11; //定义i的范围是0-11//
begin
if dein='1' then //如果输入信号为1//
deout<='1'; //则不接收数据//
i:=0;
elsif rising_edge(clk) then parallelout(i) <= serialin; //当有上升沿时,将
感器输出结果传
入FPGA开发板 //
if i<11 then i:=i+1; //串并行转换//
elsif i=11 then deout<='0';
else null;
end if;
end if;
end process;
end a;
4.温湿度传感器的接口模块介绍
4.1 模块功能
4.1.1 硬件介绍
SHT1x 系列是高度集成的温湿度传感器芯片, 提供全标定的数字输出。传感器包括一个电容性聚合体测湿敏感元件、一个用能隙材料制成的测温元件,并在同一芯片上,与14 位的A/D 转换器以及串行接口电路实现无缝连接。校准系数以程序形式储存在OTP 内存中,在标定的过程中使用。两线制的串行接口与内部的电压调整。
4.1.2 模块功能概览
如上图所示
图 4-1 SHT1x 温湿度传感器框图
A. 该模块利用各种接口与 FPGA 连接进行数据传 输及功能实现。
B. 该模块接 口分为: SCK(in), COMMAND(in) ,DATA(out),等 ,分别主要 实现接收控制器的时钟,以及控制器发出的口令(进行温度 or 湿度测量),和数据的接 收与存储,进而 待控制器执行完 其他任务后需要测 量的数据时对其进行数据传输。
C. 模块功能框图:
图 4-2
D.模块功能及与 FPGA 的连接:
通过 FPGA 与传感器的控制器传出的时钟 SCK,完成进程;在启动时序后,
经过控制器传输的命令 COMMAND(00000011 温 度测量;00000101 湿度测量),
进行测量时序;测量等待时序后,进行数据的接收及储存,并等待控制器发
出对数据传输的命令。
4.2 内部模块实现
4.2.1 程序流程概述
A.流程图:
图 4-3 程序启动时序图
如图4-3所示,程序的启动流程为:
1. 启动传输时序:
当SCK 时钟高电平时DATA 翻转为低电平,紧接着SCK 变为低电平,随后是
在SCK 时钟高电平时DATA 翻转为高电平。
2.测量时序及数据读取时序:
发布一组测量命令后,控制器要等待测量结束。这个过程需要大约55ms,对
应12bit 测量。SHTxx 通过下拉DATA 至低电平并进入空闲模式,表示测量的结
束。控制器在再次触发SCK 时钟前,必须等待这个“数据备妥”信号来读出数据。
检测数据可以先被存储,这样控制器可以继续执行其它任务在需要时再读出数
据。
4.2.2 接口模块编程实现
A.接口定义:单向的 SCK,COMMAND 的 STD_LOGI C 定义,以及 DATA 串行双向
接口的定义,其中 COMMAND 为 8 位命令位(00 0 地址位+5 位命令位)
B.由于流程为顺序时序则将整个流程用 PROCESS.
C. DATA 三态门用于数据的读取。DATA 在SCK 时钟下降沿之后改变状态,
并仅在SCK 时钟上升沿有效。数据传输期间,在SCK 时钟高电平时,DATA必须保
持稳定。为避免信号冲突,微处理器应驱动DATA 在低电平。即:
data1 <= (others => '0');
IF(sck'event AND sck='1')THEN
data1 <= d; --Data三态门
END IF;
D. 启动传输:当SCK 时钟高电平时DATA 翻转为低电平,紧接着SCK 变为低
电平,随后是在SCK 时钟高电平时DATA 翻转为高电平。即:
WAIT UNTIL sck='1';
data1 <= NOT d;
WAIT UNTIL sck='0'
data1 <= d;
E.测量时序:
c <= 'command';
WAIT ON sck UNTIL (sck'event AND sck = '1') FOR 55 ms; --测量数据
F.数据传输:
IF(c='00000011')
a<=data; --数据传输
ELSIF(c='00000101')
b<=data;
END IF;
G.数据存储:该程序是用于传感器对测量完妥的数据进行暂时的存储,以备
控制器完成其他任务或进程后,对数据的完整接收。
entity Dataout is
Port ( sck : in STD_LOGIC;
rst : in STD_LOGIC;
serialin : in STD_LOGIC;
parallelout : out STD_LOGIC_vector(7 downto 0));
end Dataout;
architecture a of Dataout is
signal para : std_logic_vector(7 downto 0);
begi n
process (sck)
variable i : integer range 0 to 7;
begin
if rst='1' then i:=0;
elsif rising_edge(sck) then
if i<7 then
para <= para(6 downto 0) & serialin;
i:=i+1;
else
parallelout<=para;
i:=i+1;
end if;
else null;
end if;
end process;
end;
4.3 调试结果
A.SHT2x 程序进行调试后出现以下 3 个问题:
ERROR:HDLParsers:164 - "D:/!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1/sht2x.vhd" Line 57.
unexpected IDENTIFIER, expecting SEMICOLON
parse error,
ERROR:HDLParsers:1015
statement unsupported.
"D:/!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1/sht2x.vhd"
Li ne
61.
Wait
for
ERROR:HDLParsers:164 - "D:/!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1/sht2x.vhd" Line 63.
unexpected TICK
parse error,
主要是有关数据类型的问题;
B.Dataout 程序经调试后运行成功。