这个基于EGO1开发板的温度监测系统,通过DS18B20数字温度传感器采集环境温度,在数码管上实时显示当前温度值,并支持用户通过按键设置报警阈值。当温度超过设定阈值时,系统会触发LED报警提示。整个系统采用Verilog HDL语言实现,完全运行在FPGA硬件上。
提示:DS18B20是一款常用的单总线数字温度传感器,具有±0.5℃的精度,测量范围-55℃~+125℃,非常适合嵌入式系统使用。
系统主要功能特点:
系统采用模块化设计,顶层模块temperature_alarm_top负责连接各功能模块:
verilog复制module temperature_alarm_top(
input clk, // 100MHz系统时钟
input rst_n, // 低电平复位
input key_add, // 阈值加按键
input key_sub, // 阈值减按键
inout ds18b20_dq, // DS18B20数据线
output [7:0] seg_data, // 数码管段选
output [3:0] seg_en, // 数码管位选
output alarm_led, // 报警LED
output alarm_beep // 蜂鸣器(EGO1未使用)
);
顶层模块实例化了5个子模块:
| 信号名称 | 方向 | 位宽 | 描述 |
|---|---|---|---|
| temp_data | 输出 | 16 | DS18B20原始温度数据 |
| temp_valid | 输出 | 1 | 温度数据有效标志 |
| disp_temp | 输出 | 16 | 待显示实时温度 |
| disp_thresh | 输出 | 16 | 待显示温度阈值 |
| alarm_en | 输出 | 1 | 报警使能信号 |
DS18B20采用单总线通信协议,所有通信都通过DQ线完成。协议特点:
verilog复制// 时间参数定义(单位us)
localparam T_WRITE0_LOW = 63; // 写0低电平时间
localparam T_WRITE1_LOW = 10; // 写1低电平时间
localparam T_SLOT = 70; // 单比特读写时隙
localparam T_CONV_MAX = 750000;// 最大转换时间
localparam T_RST_LOW = 480; // 复位低电平时间
localparam T_PRES_WAIT = 65; // 存在脉冲等待时间
DS18B20驱动采用状态机实现完整工作流程:
verilog复制localparam
S_IDLE = 5'd0, // 空闲状态
S_RST1 = 5'd1, // 第一次复位
S_WAIT_PRES1 = 5'd2, // 等待第一次存在脉冲
S_SKIP_ROM1 = 5'd3, // 第一次跳过ROM
S_CONV_T = 5'd4, // 发送转换指令
S_WAIT_CONV = 5'd5, // 等待转换完成
S_RST2 = 5'd6, // 第二次复位
S_WAIT_PRES2 = 5'd7, // 等待第二次存在脉冲
S_SKIP_ROM2 = 5'd8, // 第二次跳过ROM
S_READ_SCR = 5'd9, // 发送读取暂存器指令
S_READ_DATA = 5'd10, // 读取温度数据
S_DONE = 5'd11; // 完成状态
状态机工作流程:
DS18B20输出的温度数据为16位补码格式:
verilog复制// 温度数据解析
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
temp_conv <= 16'd0;
end else if(temp_valid) begin
// 取高5位符号+整数,低11位小数→取整到0.5℃
temp_conv <= {temp_data[15], temp_data[10:4] << 1 | temp_data[3]};
end
end
机械按键存在抖动问题,需要硬件消抖处理:
verilog复制// 消抖参数
parameter DEBOUNCE_CNT = 21'd1_999_999; // 20ms消抖计数(100MHz时钟)
// 按键同步打拍(消除亚稳态)
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
key_add_r1 <= 1'b1;
key_add_r2 <= 1'b1;
end else begin
key_add_r1 <= key_add;
key_add_r2 <= key_add_r1;
end
end
// 消抖逻辑
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt_add <= 21'd0;
key_add_stable <= 1'b1;
end else if(key_add_r2 != key_add_stable) begin
cnt_add <= cnt_add + 1'd1;
if(cnt_add == DEBOUNCE_CNT) begin
key_add_stable <= key_add_r2;
cnt_add <= 21'd0;
end
end else begin
cnt_add <= 21'd0;
end
end
阈值范围0~99.5℃,步长0.5℃:
verilog复制// 阈值范围参数
parameter THRESH_MIN = 16'd0; // 0℃
parameter THRESH_MAX = 16'd199; // 99.5℃(99.5×2=199)
// 阈值调整逻辑
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
thresh_reg <= 16'd50; // 默认25℃
end else begin
if(thrsh_add && thresh_reg < THRESH_MAX) begin
thresh_reg <= thresh_reg + 1'd1; // +0.5℃
end else if(thrsh_sub && thresh_reg > THRESH_MIN) begin
thresh_reg <= thresh_reg - 1'd1; // -0.5℃
end
end
end
4位数码管显示安排:
显示模式每3秒切换一次:
verilog复制// 数码管扫描参数
parameter SCAN_CNT = 17'd99_999; // 1kHz扫描频率
parameter SWITCH_CNT = 29'd299_999_999; // 3s显示切换
// 数码管段码定义
parameter SEG0 = 8'b11111100; // 0
parameter SEG1 = 8'b01100000; // 1
// ...其他数字段码
parameter SEG_NEG = 8'b00000010; // 负号
parameter SEG_T = 8'b10001100; // T
parameter SEG_BLANK = 8'b00000000; // 空白
// 数码管扫描
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
scan_cnt <= 17'd0;
seg_sel <= 2'd0;
end else if(scan_cnt >= SCAN_CNT) begin
scan_cnt <= 17'd0;
seg_sel <= seg_sel + 1'd1;
end else begin
scan_cnt <= scan_cnt + 1'd1;
end
end
verilog复制// 超温判定
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
alarm_en <= 1'b0;
end else begin
alarm_en <= (temp_conv > thresh_reg) ? 1'b1 : 1'b0;
end
end
verilog复制// LED报警闪烁(1Hz)
parameter LED_FREQ = 32'd49_999_999; // 500ms周期
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
led_cnt <= 32'd0;
alarm_led <= 1'b0;
end else if(alarm_en) begin
if(led_cnt >= LED_FREQ) begin
led_cnt <= 32'd0;
alarm_led <= ~alarm_led;
end else begin
led_cnt <= led_cnt + 1'd1;
end
end else begin
alarm_led <= 1'b0;
end
end
DS18B20无响应:
温度显示异常:
按键响应不灵敏:
降低功耗:
提高精度:
扩展功能:
环境适应性:
安装注意事项:
维护建议:
这个FPGA温度监测系统展示了如何利用Verilog HDL实现完整的嵌入式系统,从传感器接口到用户交互,全部通过硬件逻辑实现。系统具有实时性强、响应速度快、可靠性高等特点,非常适合工业控制、环境监测等应用场景。