本項目開發了一個使用 Xilinx 公司的 SPARTAN3A-DSP FPGA 作為目標開發板,采集數字和模擬傳感器數據,并將傳感器數據采用 I2C 接口與上級無線傳感器網絡進行通信的環境監測系統。使用 VHDL 語言編寫了溫濕度數字傳感器(SHT1x)和氣壓模擬傳感器(MPX599D)的接口模塊、I2C 輸出接口模塊和總控模塊。制作了與 SPARTAN3A-DSP 與接口電路板,接入模擬、數字傳感器信號量。本項目利用FPGA 的可編程特性,搭載不同的傳感器,與無線傳感器網絡相結合,可以提高無線傳感器網絡系統承載不同傳感器應用的能力。I2C 的標準輸出接口也使得系統具有擴展連接各類上級微控器的能力。
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 的引腳分布及功能簡介
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 程序經調試后運行成功。
評論
查看更多