verilog 的DHT22 程序(可用)

研阵以待 2019-05-23 08:27:56
//addr=4 湿度高8位
//addr=3 湿度低8位
//addr=2 温度高8位
//addr=1 温度低8位
//addr=0 校验和8位 (该地址读取后启动温湿度转换)

module DHT22 (sys_clk, IO_port, nReset, nCS, nOE, addr, busy, data);

input sys_clk; //系统时钟 1Mhz
input nCS, nOE, nReset; //芯片选择|读取数据|芯片复位
input [2:0] addr; //数据高低8位选择
inout IO_port; //DHT数据引脚
output [7:0] data; //8位数据双向总线
output busy; //正在读取中

wire CHIP_RST;
tri1 IO_port;
//date接口滤波变量
reg F_OUT; //滤波后的IO-clk
//芯片复位
reg RST;
//开始复位DHT22数据
reg R_FIN; //复位完成
reg IO_OUT; //复位端口
//准备读取DHT22数据
reg read_enable; //准备读取DHT22数据
//位读取保持
reg Read_Begin;
//数据位计数
reg [5:0] read_clk_count; //IO读取时钟计数器(状态时序)
reg in_rdy; //读取完成
//位读取时钟生成
reg read_pulse; //位读取脉冲
//开始读取DHT22数据接口时序进程
reg [39:0] in_buff; //读取数据缓冲
//选择数据位
reg [7:0] select_bit;


initial //上电初始化内部寄存器
begin
in_rdy <= 0;
RST <= 0;
read_pulse <= 0;
Read_Begin <= 0;
R_FIN <= 0;
IO_OUT <= 0;
end

assign data = (!nOE && !nCS)? select_bit : 8'bz; //三态8位数据总线,外部读取PS2数据
assign IO_port = (IO_OUT)? 1'b0 : 1'bz;
assign busy = read_enable ;
assign CHIP_RST = ~nReset | RST;

//选择数据位
always
begin : select
case (addr) /* synthesis full_case */
3'd0:
begin
select_bit[7:0] = in_buff[7:0];
end
3'd1:
begin
select_bit[7:0] = in_buff[15:8];
end
3'd2:
begin
select_bit[7:0] = in_buff[23:16];
end
3'd3:
begin
select_bit[7:0] = in_buff[31:24];
end
3'd4:
begin
select_bit[7:0] = in_buff[39:32];
end
endcase
end

//IO接口滤波
always @(posedge sys_clk or negedge nReset)
begin: Filter
reg [1:0] IOdat_s; //采样计数器

if (!nReset) begin
IOdat_s <= 2'b0;
F_OUT <= 1'b1;
end
else begin
if (F_OUT != IO_port) begin //检测data时钟跳变
if (IOdat_s == 2'd3) begin //3次采样ps_clk
F_OUT <= IO_port;
IOdat_s <= 0;
end
else begin
IOdat_s = IOdat_s + 2'b1;
end
end
else begin
IOdat_s <= 0;
end
end
end

//芯片复位
always @(nOE)
begin : C_RST
if ((addr == 3'd0) && !nCS && !nOE) begin
RST <= 1;
end
else begin
RST <= 0;
end
end

//准备读取DHT22数据
always @(negedge nReset or negedge nOE or posedge in_rdy)
begin : read_first
if (in_rdy || !nReset) begin
read_enable <= 1'b0;
end
else begin
if ((addr == 3'd0) && !nCS && !in_rdy) begin
read_enable <= 1'b1;
end
end
end

//开始复位DHT22数据时序进程
always @(posedge sys_clk or posedge CHIP_RST or negedge read_enable)
begin: ResetPort
reg [8:0] R_TIM; //复位时间

if (CHIP_RST || !read_enable) begin
R_TIM <= 0;
R_FIN <= 0;
IO_OUT <= 0;
end
else begin
if (!R_FIN) begin
R_TIM <= R_TIM + 9'd1;

if (R_TIM==9'd510) begin
R_FIN <= 1;
IO_OUT <= 0;
end
else begin
IO_OUT <= 1;
end
end
end
end

//位读取保持
always @(posedge F_OUT or posedge read_pulse or posedge CHIP_RST)
begin : Read_keep
if (read_pulse || CHIP_RST) begin
Read_Begin <= 0;
end
else begin
if (read_clk_count>1 && read_clk_count<42) begin
Read_Begin <= 1;
end
else Read_Begin <= 0;
end
end


//位读取时钟生成
always @(posedge sys_clk)
begin : Read_clk
reg [5:0] sc;

read_pulse <= 0;
if (CHIP_RST) sc <= 0;
else if (Read_Begin && read_enable) begin
if (sc<6'd40) sc <= sc + 6'b1;
else read_pulse <= 1;
end
else begin
sc <= 0;
end
end

//数据位计数
always @(posedge F_OUT or negedge read_enable or posedge CHIP_RST)
begin: bit_count
if (!read_enable || CHIP_RST) begin
read_clk_count <= 0;
in_rdy <= 0;
end
else begin
read_clk_count <= read_clk_count + 6'd1;
if (read_clk_count > 6'd41) in_rdy <= 1;
end
end

//开始读取DHT22数据接口时序进程
always @(posedge read_pulse or negedge nReset)
begin: ReadIOData
if (!nReset) in_buff = 0;
else begin
in_buff[39:1] <= in_buff[38:0];
in_buff[0] <= F_OUT;
end
end

endmodule
...全文
157 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

2,425

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 其他硬件开发
社区管理员
  • 其他硬件开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧