概念
傳感器輸出經過標定的數字信號輸出,通過標準的I2C接口傳輸數據;
相對濕度的分辨率在0.024%RH,工作范圍為0~100%RH;
溫度值的分辨率在0.01℃,工作范圍為-40~85℃;
AHT10的供電范圍為1.8~3.6V,推薦使用3.3V供電;
接口包含了完全靜態邏輯,因而不存在最小串行時鐘SCL頻率;
IIC協議,同步半雙工通信協議
起始位:主機在時鐘高電平期間拉低總線;
數據位:主機在時鐘低電平期間發送數據,主機在高電平期間保持不變;從機在時鐘高電平期間采樣數據;
應答為:主機收到數據后發送應答,從機才會發送下一字節數據;
停止位:主機在時鐘高電平期間釋放總線,主機在低電平期間保持不變;
可使用的I2C通信模式有經典型和高速模式,經典模式最小時鐘周期是250us,高速模式最小時鐘周期是100us;
AHT10配置與通信
I2C通信通過設備地址與從機進行通信,
首先上電啟動傳感器,啟動后需要先等待40ms(設備才開始正常工作),然后發送8‘h71 來獲取狀態字節,狀態寄存器說明如下:
獲取到校準使能位后,查看其是否已校準,若已校準則跳過當前步驟;若未校準則發送8‘hE1,進行初始化,然后發送8’h08,8‘h00;
接著開始觸發測量,測量先發送8’hAC,然后發送8‘h33,8'h00;
測量命令發送完成后,需要等待80ms,用于溫濕度的測量;之后再發送命令8‘h71,以讀取狀態寄存器是否處于空閑狀態(bit7 => idle);若是空閑狀態,可以直接讀取之后六個字節的溫濕度數值;
讀取溫濕度數據構成
相對濕度和溫度轉換公式
將接收到的濕度值轉換成%RH的格式:
R H [ % ] = ( S R H / 2 20 ) RH [\%] = (SRH/2^{20}) RH[%]=(SRH/220)
溫度轉換成℃表示:
T ( ℃ ) = ( S T / 2 20 ) . T(℃) = (ST/2^{20}). T(℃)=(ST/220).
設計框架
整個模塊的設計,首先是上位機通過UART,發送命令打開AHT10驅動控制模塊、數碼管顯示模塊以及串口模塊;設備驅動用控制模塊實現,通信接口使用I2C與AHT10進行通信,然后將讀取的溫濕度值先進行數值轉換并取整,并轉換成ASCII碼方便查看溫濕度值;然后將數據緩存到FIFO中,當緩存了一組完整的溫度值數據后進行輸出,發送給上位機,或是直接通過數碼管顯示;
I2C模塊
I2C接口模塊狀態機如上圖所示,從空閑狀態可以先發送起始位再讀寫一個字節數據,或直接讀寫一個字節數據,然后是收發應答位;最后發送停止位,就完成了一組數據的讀寫;
對于I2C通信,數據的傳輸速率選擇的是50M/250 Bps;
include"param.v"modulei2c_master( input clk , input rst_n , input req , input [3:0] cmd , input [7:0] din , output [7:0] dout , output done , output slave_ack , output i2c_scl , input i2c_sda_i , output i2c_sda_o , output i2c_sda_oe );//狀態機參數定義localparam IDLE =7'b000_0001, START =7'b000_0010, WRITE =7'b000_0100, RACK =7'b000_1000, READ =7'b001_0000, SACK =7'b010_0000, STOP =7'b100_0000;//reg [6:0] state_c ; reg [6:0] state_n ; reg [8:0] cnt_scl ;//產生i2c時鐘wire add_cnt_scl ; wire end_cnt_scl ; reg [3:0] cnt_bit ;//傳輸數據 bit計數器wire add_cnt_bit ; wire end_cnt_bit ; reg [3:0] bit_num ; reg scl ;//輸出寄存器reg sda_out ; reg sda_out_en ; reg [7:0] rx_data ; reg rx_ack ; reg [3:0] command ; reg [7:0] tx_data ;//發送數據wire idle2start ; wire idle2write ; wire idle2read ; wire start2write ; wire start2read ; wire write2rack ; wire read2sack ; wire rack2stop ; wire sack2stop ; wire rack2idle ; wire sack2idle ; wire stop2idle ; //狀態機always@(posedgeclkornegedgerst_n)beginif(rst_n==0)begin state_c <= IDLE ; ? ? ? ?endelsebegin? ? ? ? ? ? ?state_c <= state_n; ? ? ??endendalways?@(*)?begincase(state_c) ? ? ? ? ? ? ? IDLE :beginif(idle2start) ? ? ? ? ? ? ? ? ? ? state_n = START ; ? ? ? ? ? ? ? ?elseif(idle2write) ? ? ? ? ? ? ? ? ? ? state_n = WRITE ; ? ? ? ? ? ? ? ?elseif(idle2read) ? ? ? ? ? ? ? ? ? ? state_n = READ ; ? ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?START :beginif(start2write) ? ? ? ? ? ? ? ? ? ? state_n = WRITE ; ? ? ? ? ? ? ? ?elseif(start2read) ? ? ? ? ? ? ? ? ? ? state_n = READ ; ? ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?WRITE :beginif(write2rack) ? ? ? ? ? ? ? ? ? ? state_n = RACK ; ? ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?RACK :beginif(rack2stop) ? ? ? ? ? ? ? ? ? ? state_n = STOP ; ? ? ? ? ? ? ? ?elseif(rack2idle) ? ? ? ? ? ? ? ? ? ? state_n = IDLE ; ? ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?READ :beginif(read2sack) ? ? ? ? ? ? ? ? ? ? state_n = SACK ; ? ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?SACK :beginif(sack2stop) ? ? ? ? ? ? ? ? ? ? state_n = STOP ; ? ? ? ? ? ? ? ?elseif(sack2idle) ? ? ? ? ? ? ? ? ? ? state_n = IDLE ; ? ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?STOP :beginif(stop2idle) ? ? ? ? ? ? ? ? ? ? state_n = IDLE ; ? ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?enddefault?: state_n = IDLE ; ? ? ? ?endcaseendassign?idle2start ?= state_c==IDLE ?&& (req && (cmd&`CMD_START)); ? ?assign?idle2write ?= state_c==IDLE ?&& (req && (cmd&`CMD_WRITE)); ? ?assign?idle2read ? = state_c==IDLE ?&& (req && (cmd&`CMD_READ )); ? ?assign?start2write = state_c==START && (end_cnt_bit && (command&`CMD_WRITE)); ? ?assign?start2read ?= state_c==START && (end_cnt_bit && (command&`CMD_READ )); ? ?assign?write2rack ?= state_c==WRITE && (end_cnt_bit); ? ?assign?read2sack ? = state_c==READ ?&& (end_cnt_bit); ? ?assign?rack2stop ? = state_c==RACK ?&& (end_cnt_bit && (command&`CMD_STOP )); ? ?assign?sack2stop ? = state_c==SACK ?&& (end_cnt_bit && (command&`CMD_STOP )); ? ?assign?rack2idle ? = state_c==RACK ?&& (end_cnt_bit && (command&`CMD_STOP ) ==?0); ? ?assign?sack2idle ? = state_c==SACK ?&& (end_cnt_bit && (command&`CMD_STOP ) ==?0); ? ?assign?stop2idle ? = state_c==STOP ?&& (end_cnt_bit); ? ??//計數器always?@(posedge?clk?ornegedge?rst_n)?beginif?(rst_n==0)?begin? ? ? ? ? ? ?cnt_scl <=?0; ? ? ? ? ?endelseif(add_cnt_scl)?beginif(end_cnt_scl) ? ? ? ? ? ? ? ? cnt_scl <=?0; ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ?cnt_scl <= cnt_scl+1?; ? ? ??endendassign?add_cnt_scl = (state_c != IDLE); ? ?assign?end_cnt_scl = add_cnt_scl ?&& cnt_scl == (`SCL_PERIOD)-1?; ? ?always?@(posedge?clk?ornegedge?rst_n)?beginif?(rst_n==0)?begin? ? ? ? ? ? ?cnt_bit <=?0; ? ? ? ? ?endelseif(add_cnt_bit)?beginif(end_cnt_bit) ? ? ? ? ? ? ? ? cnt_bit <=?0; ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ?cnt_bit <= cnt_bit+1?; ? ? ??endendassign?add_cnt_bit = (end_cnt_scl); ? ?assign?end_cnt_bit = add_cnt_bit ?&& cnt_bit == (bit_num)-1?; ? ?always? @(*)beginif(state_c == WRITE | state_c == READ)?begin? ? ? ? ? ? ?bit_num =?8; ? ? ? ?endelsebegin? ? ? ? ? ? ? bit_num =?1; ? ? ? ?endend//commandalways? @(posedge?clk?ornegedge?rst_n)beginif(~rst_n)begin? ? ? ? ? ? ?command <=?0; ? ? ? ?endelseif(req)begin? ? ? ? ? ? ?command <= cmd; ? ? ? ?endend//tx_dataalways? @(posedge?clk?ornegedge?rst_n)beginif(~rst_n)begin? ? ? ? ? ? ?tx_data <=?0; ? ? ? ?endelseif(req)begin? ? ? ? ? ? ?tx_data <= din; ? ? ? ?endend//sclalways? @(posedge?clk?ornegedge?rst_n)beginif(~rst_n)begin? ? ? ? ? ? ?scl <=?1'b1; ? ? ? ?endelseif(idle2start | idle2write | idle2read)begin//開始發送時,拉低? ? ? ? ? ? ?scl <=?1'b0; ? ? ? ?endelseif(add_cnt_scl && cnt_scl == `SCL_HALF-1)begin? ? ? ? ? ? ? scl <=?1'b1; ? ? ? ?endelseif(end_cnt_scl && ~stop2idle)begin? ? ? ? ? ? ? scl <=?1'b0; ? ? ? ?endend//sda_outalways? @(posedge?clk?ornegedge?rst_n)beginif(~rst_n)begin? ? ? ? ? ? ?sda_out <=?1'b1; ? ? ? ?endelseif(state_c == START)begin//發起始位if(cnt_scl == `LOW_HLAF)begin//時鐘低電平時拉高sda總線? ? ? ? ? ? ? ? ?sda_out <=?1'b1; ? ? ? ? ? ?endelseif(cnt_scl == `HIGH_HALF)begin//時鐘高電平時拉低sda總線?? ? ? ? ? ? ? ? ?sda_out <=?1'b0; ? ? ? ? ? ? ? ?//保證從機能檢測到起始位endendelseif(state_c == WRITE && cnt_scl == `LOW_HLAF)begin//scl低電平時發送數據 ? 并串轉換? ? ? ? ? ? ?sda_out <= tx_data[7-cnt_bit]; ? ? ? ? ? ? ??endelseif(state_c == SACK && cnt_scl == `LOW_HLAF)begin//發應答位? ? ? ? ? ? ?sda_out <= (command&`CMD_STOP)?1'b1:1'b0; ? ? ? ?endelseif(state_c == STOP)begin//發停止位if(cnt_scl == `LOW_HLAF)begin//時鐘低電平時拉低sda總線? ? ? ? ? ? ? ? ?sda_out <=?1'b0; ? ? ? ? ? ?endelseif(cnt_scl == `HIGH_HALF)begin//時鐘高電平時拉高sda總線?? ? ? ? ? ? ? ? ?sda_out <=?1'b1; ? ? ? ? ? ? ? ?//保證從機能檢測到停止位endendend//sda_out_en ?總線輸出數據使能always? @(posedge?clk?ornegedge?rst_n)beginif(~rst_n)begin? ? ? ? ? ? ?sda_out_en <=?1'b0; ? ? ? ?endelseif(idle2start | idle2write | read2sack | rack2stop)begin? ? ? ? ? ? ?sda_out_en <=?1'b1; ? ? ? ?endelseif(idle2read | start2read | write2rack | stop2idle)begin? ? ? ? ? ? ? sda_out_en <=?1'b0; ? ? ? ?endend//rx_data ? ? ? 接收讀入的數據always? @(posedge?clk?ornegedge?rst_n)beginif(~rst_n)begin? ? ? ? ? ? ?rx_data <=?0; ? ? ? ?endelseif(state_c == READ && cnt_scl == `HIGH_HALF)begin? ? ? ? ? ? ?rx_data[7-cnt_bit] <= i2c_sda_i; ? ?//串并轉換endend//rx_ackalways? @(posedge?clk?ornegedge?rst_n)beginif(~rst_n)begin? ? ? ? ? ? ?rx_ack <=?1'b1; ? ? ? ?endelseif(state_c == RACK && cnt_scl == `HIGH_HALF)begin? ? ? ? ? ? ?rx_ack <= i2c_sda_i; ? ? ? ?endend//輸出信號assign?i2c_scl ? ?= scl ? ? ? ? ; ? ?assign?i2c_sda_o ?= sda_out ? ? ; ? ?assign?i2c_sda_oe = sda_out_en ?; ? ?assign?dout = rx_data; ? ?assign?done = rack2idle | sack2idle | stop2idle; ? ?assign?slave_ack = rx_ack;endmodule
`include"param.v"moduleaht_ctrl ( input sys_clk , input rst_n ,inputdriver_en, output req , output [3:0] cmd , output [7:0] data , input done , input [7:0] rd_data , output[19:0]hum_data, output [19:0]temp_data, output dout_vld );//localparam START = 7'b000_0001, INIT = 7'b000_0010, CHECK_INIT =7'b000_0100, IDLE = 7'b000_1000, TRIGGER = 7'b001_0000, WAIT = 7'b010_0000, READ = 7'b100_0000; parameterDELAY_40MS =200_0000 , DELAY_80MS =400_0000 , DELAY_500MS =2500_0000; reg [7:0] state_c ; reg [7:0] state_n ; reg [2:0] cnt_byte ; wire add_cnt_byte ; wire end_cnt_byte ; reg tx_req ; reg [3:0] tx_cmd ; reg [7:0] tx_data ; reg[47:0]read_data; reg[27:0]cnt; wireadd_cnt; wireend_cnt; reg[24:0]delay; regfinish_init; wirestart2init; wireinit2check; wirecheck2idle; wirecheck2init; wireidle2trigger; wiretrigger2wait; wirewait2read; wireread2idle;regdriver_en_r1;regdriver_en_r2;wirene_driver;// ne_driveralways@(posedgesys_clkornegedgerst_n)beginif(!rst_n)begindriver_en_r1 <=?0?; ?driver_en_r2 ?<=?0?; ?endelsebegin?driver_en_r1 ?<= driver_en ; driver_en_r2 ?<= driver_en_r1 ;endendassign?ne_driver = (~driver_en_r1 && driver_en_r2) ;//statealways?@(posedge?sys_clk?ornegedge?rst_n)?beginif?(rst_n==0)?begin? ? ? ? ? ? ?state_c <= START ; ? ? ? ?endelsebegin? ? ? ? ? ? ?state_c <= state_n; ? ? ??endend//狀態轉移always?@(*)?begincase(state_c) ? ? ? ? ? ? ? START :beginif(ne_driver)?begin?state_n = state_c ; ?endelseif(start2init)?begin? ? ? ? ? ? ? ? ? ? ?state_n = INIT ;endelsebegin? ? ? ? ? ? ? ? ? ? ? state_n = state_c ;endend? ? ? ? ? ? ?INIT :beginif(ne_driver)?begin?state_n = START ;endelseif(init2check)begin? ? ? ? ? ? ? ? ? ? ?state_n = IDLE ;endelse? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?CHECK_INIT :beginif(ne_driver)?begin?state_n = START ;endelseif(check2idle)begin? ? ? ? ? ? ? ? ? ? ?state_n = IDLE ;endelseif(check2init)?begin? ? ? ? ? ? ? ? ? ? ?state_n = INIT; ? ? ? ? ? ? ? ?endelse? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?IDLE :beginif(ne_driver)begin?state_n = START ;endelseif(idle2trigger)begin? ? ? ? ? ? ? ? ? ? ?state_n = TRIGGER ;endelse? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?TRIGGER :beginif(ne_driver)begin?state_n = START ;endelseif(trigger2wait)begin? ? ? ? ? ? ? ? ? ? ?state_n = WAIT ;endelse? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?WAIT :beginif(ne_driver)begin?state_n = START ;endelseif(wait2read) ? ? ? ? ? ? ? ? ? ? state_n = READ ; ? ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?end? ? ? ? ? ? ?READ :beginif(ne_driver)begin?state_n = START ;endelseif(read2idle) ? ? ? ? ? ? ? ? ? ? state_n = IDLE ; ? ? ? ? ? ? ? ?else? ? ? ? ? ? ? ? ? ? ? state_n = state_c ; ? ? ? ? ? ?enddefault?: state_n = START ; ? ? ? ?endcaseendassign?start2init = state_c == START && (end_cnt); ? ?assign?init2check = state_c == INIT && (end_cnt_byte); ? ?assign?check2idle = state_c == CHECK_INIT && (finish_init) && end_cnt_byte; ? ?assign?check2init = state_c == CHECK_INIT && (~finish_init)&& end_cnt_byte; ? ?assign?idle2trigger = state_c == IDLE && (end_cnt); ? ?assign?trigger2wait = state_c == TRIGGER && (end_cnt_byte); ? ?assign?wait2read = state_c == WAIT && (end_cnt); ? ?assign?read2idle = state_c == READ && (end_cnt_byte); ? ??// delayalways?@(posedge?sys_clk?ornegedge?rst_n)?beginif(!rst_n)?begin? ? ? ? ? ? ?delay <= DELAY_40MS; ? ? ? ?endelseif(state_c == START)?begin? ? ? ? ? ? ?delay <= DELAY_40MS; ? ? ? ?endelseif(state_c == WAIT)?begin? ? ? ? ? ? ?delay <= DELAY_80MS; ? ? ? ?endelseif(state_c == IDLE)?begin? ? ? ? ? ? ?delay <= DELAY_500MS; ? ? ? ?endend// cntalways?@(?posedge?sys_clk?ornegedge?rst_n )?beginif?( !rst_n )?begin? ? ? ? ? ? ?cnt <=?0; ? ? ? ?endelseif?( add_cnt )?beginif?( end_cnt )?begin? ? ? ? ? ? ? ? ?cnt <=?0; ? ? ? ? ? ?endelsebegin? ? ? ? ? ? ? ? ?cnt <= cnt +?1; ? ? ? ? ? ?endendelsebegin? ? ? ? ? ? ?cnt <=?0; ? ? ? ?endendassign?add_cnt = (state_c == START || state_c == WAIT || state_c == IDLE) && driver_en_r2; ? ?assign?end_cnt = cnt == delay -?1?&& add_cnt || ne_driver ;// cnt_bytealways?@(posedge?sys_clk?ornegedge?rst_n)?beginif(!rst_n)begin? ? ? ? ? ? ?cnt_byte <=?0; ? ? ? ?endelseif(add_cnt_byte)?beginif(end_cnt_byte)?begin? ? ? ? ? ? ? ? ?cnt_byte <=?0; ? ? ? ? ? ?endelse? ? ? ? ? ? ? ? ?cnt_byte <= cnt_byte +?1; ? ? ? ?endendassign?add_cnt_byte = (state_c == INIT || state_c == CHECK_INIT ||state_c == TRIGGER || state_c == READ) && done; ? ?assign?end_cnt_byte = (cnt_byte == (state_c == READ?6:3) && add_cnt_byte) || ne_driver ;//always? @(*)begincase?(state_c) ? ? ? ? ? ? INIT : ? ? ? ? ? ? ? ? ?case(cnt_byte) ? ? ? ? ? ? ? ? ? ?0? ? ? ? ? ?:TX(1'b1,{`CMD_START | `CMD_WRITE},{`I2C_ADR,1'b0}); ? ? ? ? ? ? ? ? ? ?1? ? ? ? ? ?:TX(1'b1, `CMD_WRITE ,`CMD_INIT); ? ? ? ? ? ? ? ? ? ? ??2? ? ? ? ? ?:TX(1'b1,`CMD_WRITE ,8'b000_1000); ? ? ? ? ? ? ? ? ? ? ?3? ? ? ? ? ?:TX(1'b1,{`CMD_WRITE | `CMD_STOP} ,8'b0000_0000); ? ? ? ? ? ? ? ? ? ? ?default? ? ?:TX(1'b0,tx_cmd,tx_data); ? ? ? ? ? ? ? ?endcase? ? ? ? ? ? ? CHECK_INIT: ? ? ? ? ? ? ? ?case(cnt_byte) ? ? ? ? ? ? ? ? ? ?0? ? ? ? ? ?:TX(1'b1,{`CMD_START | `CMD_WRITE},{`I2C_ADR,1'b0}); ? ? ? ? ? ? ? ? ? ?1? ? ? ? ? ?:TX(1'b1,`CMD_WRITE ,`CMD_CHECK); ? ? ? ? ? ? ? ? ? ? ??2? ? ? ? ? ?:TX(1'b1,{`CMD_START | `CMD_WRITE},{`I2C_ADR,1'b1}); ? ? ? ? ? ? ? ? ? ?3? ? ? ? ? ?:TX(1'b1,{`CMD_READ | `CMD_STOP},0); ? ? ? ? ? ? ? ? ? ? ??default? ? ?:TX(1'b0,tx_cmd,tx_data); ? ? ? ? ? ? ? ?endcase? ? ? ? ? ? ?TRIGGER: ? ? ? ? ? ? ? ? ?case(cnt_byte) ? ? ? ? ? ? ? ? ? ?0? ? ? ? ? ?:TX(1'b1,{`CMD_START | `CMD_WRITE},{`I2C_ADR,1'b0});//1? ? ? ? ? ?:TX(1'b1,`CMD_WRITE ,`CMD_TRIGGER); ? ? ? ? ? ? ? ? ? ? ?2? ? ? ? ? ?:TX(1'b1,`CMD_WRITE ,`DATA_0); ? ? ? ? ? ? ? ? ? ? ??3? ? ? ? ? ?:TX(1'b1,{`CMD_WRITE | `CMD_STOP},`DATA_1); ? ? ? ? ? ? ? ? ? ? ?default? ? ?:TX(1'b0,tx_cmd,tx_data); ? ? ? ? ? ? ? ?endcase? ? ? ? ? ? ? ? ?READ : ? ? ? ? ? ? ? ? ? ? ? ? ? ??case(cnt_byte) ? ? ? ? ? ? ? ? ? ?0? ? ? ? ? ?:TX(1'b1,{`CMD_START | `CMD_WRITE},{`I2C_ADR,1'b1}); ? ? ? ? ? ? ? ? ? ?1? ? ? ? ? ?:TX(1'b1,`CMD_READ ,0); ? ? ? ? ? ? ? ? ? ? ??2? ? ? ? ? ?:TX(1'b1,`CMD_READ ,0); ? ? ? ? ? ? ? ? ? ? ??3? ? ? ? ? ?:TX(1'b1,`CMD_READ ,0); ? ? ? ? ? ? ? ? ? ? ??4? ? ? ? ? ?:TX(1'b1,`CMD_READ ,0); ? ? ? ? ? ? ? ? ? ? ??5? ? ? ? ? ?:TX(1'b1,`CMD_READ ,0); ? ? ? ? ? ? ? ? ? ? ??6? ? ? ? ? ?:TX(1'b1,{`CMD_READ | `CMD_STOP},0); ? ? ? ? ? ? ? ? ? ?default? ? ?:TX(1'b0,tx_cmd,tx_data); ? ? ? ? ? ? ? ?endcasedefault: TX(1'b0,0,0); ? ? ? ?endcaseend// finish_initalways?@(posedge?sys_clk?ornegedge?rst_n)?beginif(!rst_n)?begin? ? ? ? ? ? ?finish_init <=?0; ? ? ? ?endelseif(state_c == CHECK_INIT && done && rd_data[3])?begin? ? ? ? ? ? ?finish_init <=?1; ? ? ? ?endend// read_dataalways?@(posedge?sys_clk?ornegedge?rst_n)?beginif(!rst_n)?begin? ? ? ? ? ? ?read_data <=?0; ? ? ? ?endelseif(state_c == READ && cnt_byte >0&& done)begin read_data <= {read_data[39:0],rd_data}; ? ? ? ?endend//task?TX; ? ? ? ? ? ?input? ? ? ? ? ? ? ? ? ?req ? ? ; ? ? ? ?input? ? ? ?[3:0] ? ? ? command ; ? ? ? ?input? ? ? ?[7:0] ? ? ? data ? ?; ? ? ? ?begin? ? ? ? ? ? ? tx_req ?= req; ? ? ? ? ? ? tx_cmd ?= command; ? ? ? ? ? ? tx_data = data; ? ? ? ?endendtask//outassign?req ? ? = tx_req ; ? ? ?assign?cmd ? ? = tx_cmd ; ? ? ?assign?data ? ?= tx_data; ? ? ?assign?hum_data = read_data[39:20]; ? ?assign?temp_data = read_data[19:0]; ? ?assign?dout_vld = read2idle;endmodule
其它模塊
然后將溫濕度數值按照上述格式轉換:
temp_data_r<= (((temp_data*2000)>>12) - (500)); hum_data_r<= ((hum_data *1000) >>12);
再將數據轉換成ASCII碼:
always@(posedge sys_clk or negedge rst_n)begin case(cnt) 1: dout_r <=?8'hce; ? ? ? ? ?2?: dout_r <=?8'hc2; ? ? ? ?3?: dout_r <=?8'hb6; ? ? ? ?4?: dout_r <=?8'hc8; ? ? ? ?5?: dout_r <=?8'h3a; ? ? ? ? ?6?: dout_r <= (temp_data_r /?100?%?10?)+48; ? ? ? ?7?: dout_r <= (temp_data_r /?10?%?10? )+48; ? ? ? ?8?: dout_r <=?8'h2e; ? ? ? ?9?: dout_r <= (temp_data_r %?10? )+48; ? ? ? ?10?: dout_r <=?8'ha1; ? ? ? ? ?11?: dout_r <=?8'he6; ? ? ? ?12: dout_r <=?9; ? ? ? ? ?13: dout_r <=?8'hca; ? ? ? ? ?14: dout_r <=?8'haa; ? ? ? ?15: dout_r <=?8'hb6; ? ? ? ?16: dout_r <=?8'hc8; ? ? ? ?17: dout_r <=?8'h3a; ? ? ? ?18: dout_r <= (hum_data_r /?100?%?10?)+48; ? ? ? ?19: dout_r <= (hum_data_r /?10?%?10?)+48; ? ? ? ?20: dout_r <=?8'h2e; ? ? ? ?21: dout_r <= (hum_data_r %?10? )+48; ? ? ? ?22: dout_r <=?8'h25; ? ? ? ?default: dout_r <=?0; ? ?endcaseend
最后將數值通過FIFO緩存完整的22字節數據后輸出即可;
同時還可以將數據轉換成bcd碼顯示到數碼管上;
-
FPGA
+關注
關注
1644文章
22007瀏覽量
616333 -
數字信號
+關注
關注
2文章
996瀏覽量
48234 -
溫濕度傳感器
+關注
關注
5文章
593瀏覽量
36439 -
I2C接口
+關注
關注
1文章
141瀏覽量
25972
原文標題:基于FPGA的AHT10(溫濕度傳感器)驅動設計
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
aht10溫濕度傳感器的特點有哪些呢
怎樣去讀取溫濕度傳感器(AHT10)及無線發送數據呢
【沁恒微CH32V307評估板試用體驗】使用AHT10獲取溫濕度
在Art-Pi開發板上使用AHT10溫濕度模塊
aht10溫濕度傳感器特點及使用介紹

AHT10溫濕度傳感器的使用
用國產高精度溫濕度傳感器AHT10,接入機智云實現數據傳輸

基于RVB2601開發板的AHT10溫濕度傳感器

CW32模塊使用案例 AHT10溫濕度傳感器

評論