1. 项目概述:FPGA测温系统的核心价值
在工业自动化、环境监测和医疗设备等领域,温度测量一直是个基础但关键的环节。传统基于MCU的方案虽然成熟,但在响应速度、并行处理能力和可定制性上存在天然局限。这正是FPGA(现场可编程门阵列)大显身手的地方——通过硬件并行处理能力,我们可以实现微秒级温度采集,同时保持系统的高度灵活性。
这个基于FPGA的测温系统项目,使用Verilog HDL进行硬件逻辑设计,配套Quartus Prime开发环境,开箱即用。不同于学校实验室里的demo程序,这个项目特别注重工业场景下的实用性:
- 支持常见PT100/PTC/NTC等多种温度传感器
- 内置数字滤波算法消除环境噪声
- 提供可配置的报警阈值功能
- 通过PWM输出实现温度控制闭环
提示:即使标注"可直接使用",实际部署时仍需根据具体传感器型号调整ADC接口参数。我在多个工业现场验证过,忽略这步会导致±3℃以上的测量偏差。
2. 硬件架构设计解析
2.1 传感器接口方案选型
项目默认采用三线制PT100接法,这是工业环境最稳定的方案之一。核心是通过恒流源驱动配合差分测量消除引线电阻影响。在FPGA内部,我们实现了以下关键模块:
verilog复制// 恒流源控制模块示例
module current_source(
input clk_1MHz,
output reg current_en
);
parameter PERIOD = 1000; // 1ms周期
reg [9:0] counter;
always @(posedge clk_1MHz) begin
counter <= (counter == PERIOD-1) ? 0 : counter + 1;
current_en <= (counter < 500); // 50%占空比
end
endmodule
实测中发现,当环境温度超过60℃时,普通贴片电阻的温漂会显著影响测量精度。建议在高温场合:
- 选用金属膜电阻替换常规0805封装电阻
- 将恒流源驱动电流降至1mA以下
- 增加温度补偿查找表(LUT)
2.2 ADC接口设计要点
系统适配ADI的AD7793这类24位Σ-Δ ADC,通过SPI接口与FPGA通信。这里有个容易踩坑的地方:许多开发者会直接使用Altera的SPI IP核,但在高精度采样时会出现时序问题。我的经验是:
- 手动实现SPI状态机,将SCLK频率控制在1MHz以内
- 在CS下降沿后插入至少100ns延时
- 对DOUT信号进行三级寄存器同步消除亚稳态
verilog复制// 可靠的SPI接收逻辑
always @(posedge clk) begin
case(spi_state)
IDLE: if(!cs) begin
delay_cnt <= 0;
spi_state <= DELAY;
end
DELAY: if(delay_cnt == DELAY_CYCLES) begin
bit_cnt <= 0;
spi_state <= RECEIVE;
end else delay_cnt <= delay_cnt + 1;
RECEIVE: begin
rx_buf <= {rx_buf[22:0], din};
if(bit_cnt == 23) spi_state <= DONE;
else bit_cnt <= bit_cnt + 1;
end
endcase
end
3. 数字信号处理实现
3.1 滑动平均滤波的硬件优化
原始代码中使用了简单的8点滑动平均滤波,这在工业现场往往不够。我改进后的版本包含:
- 可配置窗口大小(4/8/16/32点可选)
- 异常值剔除机制(3σ原则)
- 动态权重调整(对最新数据赋予更高权重)
verilog复制// 加权滑动平均实现
reg [15:0] data_buffer[0:31];
reg [4:0] wr_ptr;
always @(posedge adc_ready) begin
// 存入新数据
data_buffer[wr_ptr] <= adc_data;
wr_ptr <= wr_ptr + 1;
// 计算加权和
integer i;
reg [31:0] sum, weight_sum;
always @(*) begin
sum = 0; weight_sum = 0;
for(i=0; i<WINDOW_SIZE; i=i+1) begin
weight = (i == wr_ptr) ? 4 : 1; // 最新数据权重4倍
sum = sum + data_buffer[i] * weight;
weight_sum = weight_sum + weight;
end
end
filtered_data <= sum / weight_sum;
end
3.2 温度线性化处理
PT100的电阻-温度关系是非线性的,常规做法是用查找表,但会消耗大量存储资源。这个项目采用了更巧妙的方案——分段线性逼近:
- 将-50℃~150℃分为5个区间
- 每个区间存储斜率和截距
- 通过比较器自动选择计算参数
verilog复制// 分段线性计算模块
module linearize(
input [15:0] adc_value,
output reg [15:0] temp_out
);
parameter [15:0] SEG1_SLOPE = 327; // 0.1℃/LSB
parameter [15:0] SEG1_OFFSET = 500; // -50℃
always @(*) begin
if(adc_value < 1000) begin
temp_out = (adc_value * SEG1_SLOPE) >> 10 + SEG1_OFFSET;
end
// 其他区间类似...
end
endmodule
4. 系统校准与调试技巧
4.1 三点校准法实操
高精度测温必须进行现场校准,推荐使用冰水混合物(0℃)、沸水(100℃)和标准温度源(如50℃)三个点:
- 将传感器依次放入三个温场
- 记录ADC原始读数
- 解方程组计算校准系数
verilog复制// 校准系数计算示例
// 设测得三点ADC值为A0,A50,A100
// 解方程:
// K*A0 + B = 0
// K*A100 + B =100
// 则:
parameter K = 100 * 65536 / (A100 - A0);
parameter B = -K * A0 / 65536;
注意:沸点受海拔影响很大,我在拉萨(海拔3650m)实测沸点只有88℃。建议使用专业温度校准源。
4.2 时序约束关键点
在Quartus中必须正确设置时序约束,否则高温环境下会出现采样错误:
code复制# 时钟约束
create_clock -name clk_50MHz -period 20 [get_ports clk]
# SPI接口约束
set_input_delay -clock clk_50MHz -max 3 [get_ports din]
set_output_delay -clock clk_50MHz -max 2 [get_ports dout]
# 跨时钟域信号
set_false_path -from [get_clocks clk_1MHz] -to [get_clocks clk_50MHz]
常见问题排查表:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 温度跳变大 | 电源噪声 | 增加LC滤波,改用LDO供电 |
| 读数恒为0 | SPI相位错误 | 调整时钟极性CPHA参数 |
| 高温段不准 | 自热效应 | 降低恒流源电流至0.5mA |
5. 功能扩展方向
5.1 多通道采集方案
通过时分复用,单个FPGA可以轻松管理多个温度传感器:
- 使用模拟开关(如ADG704)切换通道
- 为每个通道分配独立校准系数
- 采用轮询方式采集,间隔可配置
verilog复制// 多通道控制状态机
parameter CH_NUM = 4;
reg [1:0] current_ch;
always @(posedge sample_trig) begin
// 切换通道
current_ch <= (current_ch == CH_NUM-1) ? 0 : current_ch + 1;
case(current_ch)
0: begin cs1<=0; cs2<=1; end
1: begin cs1<=1; cs2<=0; end
// ...
endcase
// 存储各通道数据
temp_buf[current_ch] <= filtered_data;
end
5.2 网络化接口
通过添加W5500等硬件TCP/IP芯片,可实现温度数据的远程监控:
- 在FPGA内实现Modbus TCP协议栈
- 定义保持寄存器映射温度数据
- 配置看门狗防止网络异常锁死
verilog复制// 简化的寄存器映射示例
reg [15:0] holding_regs[0:15];
always @(*) begin
holding_regs[0] = temp_buf[0]; // 通道1温度
holding_regs[1] = temp_buf[1]; // 通道2温度
holding_regs[2] = alarm_threshold;
end
在多个工业现场部署后,我总结出几个提升可靠性的细节:
- 对网络数据包添加CRC校验
- 关键寄存器采用写保护机制
- 实现软复位功能,可通过特定命令重启系统
这个FPGA测温系统的真正价值在于其可定制性——你可以轻松修改Verilog代码来适应各种特殊需求,比如添加温度变化率报警、实现PID控制输出,或者与其它传感器数据融合处理。比起固定功能的ASIC方案,这种灵活性在原型开发阶段尤其宝贵。
