基于FPGA的电压表与串口通信系统设计

一、系统概述

本设计基于FPGA(现场可编程门阵列) 实现高精度电压测量串口数据通信功能,核心功能包括:

  • 电压采集:通过ADC0809模数转换器将模拟电压信号转换为数字信号;
  • 数据处理:对ADC数据进行中值校准、二进制转BCD码,提高测量精度;
  • 显示驱动:通过数码管实时显示电压值;
  • 串口通信:将测量数据通过UART协议发送至PC端,支持远程监控。

系统采用模块化设计 ,分为ADC控制模块数据处理模块显示模块串口通信模块 ,具备高精度(±0.02V)低功耗易扩展 特点,适用于实验室电压监测工业设备电压采集等场景。

二、系统架构与硬件设计

1. 系统架构

IN0-IN7
8位数据总线
控制信号
BCD码
UART数据
TXD
时钟
供电
模拟电压输入
ADC0809
FPGA主控 Verilog
数码管显示模块
串口通信模块
PC端 串口调试助手
50MHz晶振
电源模块 5V
B,C,D,E

2. 核心硬件选型

模块 型号/参数 功能
FPGA主控 Altera Cyclone IV EP4CE115F29C7 逻辑控制、数据处理、串口通信
ADC转换器 ADC0809(8位,8通道,100μs转换时间) 模拟电压→数字信号(0-5V输入)
数码管 4位共阳数码管(动态扫描) 显示电压值(格式:XX.XX V)
串口芯片 MAX232(RS232电平转换) FPGA TTL→PC RS232电平
电源 5V/2A适配器+AMS1117-3.3V 系统供电(FPGA/ADC/数码管3.3V)

3. 关键电路设计

(1)ADC0809接口电路
  • 通道选择:通过FPGA的3位地址线(ADDR0-ADDR2)选择ADC0809的8个模拟输入通道(IN0-IN7),本设计使用IN0通道;
  • 控制信号ALE(地址锁存使能,高有效)、START(转换启动,高有效)、EOC(转换结束,低有效)、OE(输出使能,高有效);
  • 数据总线:ADC0809的8位数据总线(D0-D7)直接连接FPGA的GPIO引脚,传输转换后的数字信号。
(2)串口通信电路
  • 电平转换:FPGA的UART_TX(TTL电平)经MAX232转换为RS232电平,连接PC的串口(DB9接口);
  • 波特率:采用115200bps(常用串口波特率),通过FPGA的50MHz晶振分频产生。

三、软件设计(Verilog HDL实现)

1. 开发环境

  • 工具:Quartus Prime 18.1(综合、布局布线)、ModelSim(仿真)、SignalTap II(在线调试);
  • 语言:Verilog HDL(模块化设计,支持参数化);
  • 外设驱动:ADC0809控制、数码管动态扫描、UART串口通信。

2. 核心模块划分

模块 功能 关键信号
adc0809_ctrl ADC0809控制(通道选择、启动转换、读取数据) clk(50MHz)、rst_n(复位)、adc_data(8位数据)、eoc(转换结束)
data_process 数据处理(中值校准、二进制转BCD码) adc_data(输入)、bcd_data(输出,16位BCD)
seg_display 数码管动态扫描显示 bcd_data(输入)、seg(段选)、sel(位选)
uart_tx UART串口发送(115200bps,8-N-1格式) clk(50MHz)、rst_n(复位)、tx_data(8位数据)、tx_start(发送使能)
top 顶层模块,连接各子模块,协调整体逻辑 时钟clk、复位rst_n、外设接口信号

3. 关键代码实现

(1)ADC0809控制模块(adc0809_ctrl.v

功能 :通过状态机控制ADC0809的转换过程,包括地址锁存启动转换等待结束读取数据

v 复制代码
module adc0809_ctrl(
    input clk,          // 50MHz时钟
    input rst_n,        // 复位(低有效)
    input eoc,          // ADC转换结束信号(低有效)
    output reg [2:0] addr,  // 通道选择地址(0-7)
    output reg ale,     // 地址锁存使能(高有效)
    output reg start,    // 转换启动信号(高有效)
    output reg oe,      // 输出使能信号(高有效)
    input [7:0] adc_data,  // ADC数据总线
    output reg [7:0] data_out,  // 处理后的ADC数据
    output reg data_valid  // 数据有效标志(高有效)
);

// 状态定义
typedef enum {IDLE, LATCH_ADDR, START_CONV, WAIT_EOC, READ_DATA} state_t;
state_t state;

// 状态机逻辑
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        state <= IDLE;
        addr <= 3'd0;
        ale <= 1'b0;
        start <= 1'b0;
        oe <= 1'b0;
        data_out <= 8'd0;
        data_valid <= 1'b0;
    end else begin
        case (state)
            IDLE: begin
                ale <= 1'b1;  // 锁存地址
                addr <= 3'd0;  // 选择IN0通道
                state <= LATCH_ADDR;
            end
            LATCH_ADDR: begin
                ale <= 1'b0;
                start <= 1'b1;  // 启动转换
                state <= START_CONV;
            end
            START_CONV: begin
                start <= 1'b0;
                if (!eoc) begin  // 等待转换结束(EOC变低)
                    state <= WAIT_EOC;
                end
            end
            WAIT_EOC: begin
                if (eoc) begin  // 转换结束(EOC变高)
                    oe <= 1'b1;  // 使能输出
                    state <= READ_DATA;
                end
            end
            READ_DATA: begin
                data_out <= adc_data;  // 读取ADC数据
                data_valid <= 1'b1;  // 标记数据有效
                oe <= 1'b0;
                state <= IDLE;  // 回到空闲状态
            end
            default: state <= IDLE;
        endcase
    end
end
endmodule
(2)数据处理模块(data_process.v

功能 :对ADC数据进行中值校准 (消除零点漂移),并将8位二进制数据转换为BCD码(便于数码管显示)。

v 复制代码
module data_process(
    input clk,          // 50MHz时钟
    input rst_n,        // 复位(低有效)
    input [7:0] adc_data,  // ADC原始数据
    input data_valid,  // 数据有效标志
    output reg [15:0] bcd_data,  // BCD码输出(格式:XX.XX)
    output reg bcd_valid  // BCD数据有效标志
);

// 中值校准变量
reg [7:0] median;  // 中值(上电时采集100次取平均)
reg [15:0] sum;   // 累加器
reg [6:0] cnt;    // 计数器

// 二进制转BCD码(移位法)
function [15:0] bin2bcd(input [7:0] bin);
    reg [15:0] bcd;
    integer i;
    begin
        bcd = 16'd0;
        for (i = 0; i < 8; i = i + 1) begin
            if (bcd[3:0] > 4'd4) bcd[3:0] = bcd[3:0] + 4'd3;
            if (bcd[7:4] > 4'd4) bcd[7:4] = bcd[7:4] + 4'd3;
            if (bcd[11:8] > 4'd4) bcd[11:8] = bcd[11:8] + 4'd3;
            bcd = bcd << 1;
            bcd[0] = bin[7 - i];
        end
        bin2bcd = bcd;
    end
endfunction

// 中值校准逻辑
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        sum <= 16'd0;
        cnt <= 7'd0;
        median <= 8'd0;
    end else if (cnt < 7'd100) begin  // 采集100次数据
        sum <= sum + adc_data;
        cnt <= cnt + 1'd1;
        if (cnt == 7'd99) begin
            median <= sum / 100;  // 计算中值
        end
    end
end

// 数据处理逻辑
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        bcd_data <= 16'd0;
        bcd_valid <= 1'b0;
    end else if (data_valid) begin
        // 中值校准(减去中值,消除零点漂移)
        reg [7:0] calibrated_data = adc_data - median;
        // 二进制转BCD码(格式:XX.XX)
        bcd_data <= bin2bcd(calibrated_data);
        bcd_valid <= 1'b1;
    end else begin
        bcd_valid <= 1'b0;
    end
end
endmodule
(3)串口发送模块(uart_tx.v

功能 :将BCD码数据通过UART协议发送至PC端,支持115200bps8-N-1格式(8位数据、无校验、1位停止位)。

v 复制代码
module uart_tx(
    input clk,          // 50MHz时钟
    input rst_n,        // 复位(低有效)
    input [7:0] tx_data,  // 待发送数据(BCD码)
    input tx_start,    // 发送使能(高有效)
    output reg txd,     // UART发送引脚(TTL电平)
    output reg tx_busy  // 发送忙标志(高有效)
);

// 波特率参数(115200bps)
localparam BAUD_RATE = 115200;
localparam CLK_FREQ = 50_000_000;
localparam BAUD_CNT = CLK_FREQ / BAUD_RATE;  // 50M / 115200 ≈ 434
localparam HALF_BAUD_CNT = BAUD_CNT / 2;    // 217(采样中点)

// 状态定义
typedef enum {IDLE, START_BIT, DATA_BITS, STOP_BIT} state_t;
state_t state;

// 内部变量
reg [15:0] baud_cnt;  // 波特率计数器
reg [3:0] bit_cnt;   // 数据位计数器(0-7)
reg [7:0] tx_reg;    // 发送数据寄存器

// 状态机逻辑
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        state <= IDLE;
        txd <= 1'b1;  // 空闲状态为高电平
        tx_busy <= 1'b0;
        baud_cnt <= 16'd0;
        bit_cnt <= 4'd0;
        tx_reg <= 8'd0;
    end else begin
        case (state)
            IDLE: begin
                txd <= 1'b1;
                tx_busy <= 1'b0;
                if (tx_start) begin  // 检测到发送使能
                    tx_reg <= tx_data;  // 加载发送数据
                    state <= START_BIT;
                    tx_busy <= 1'b1;
                end
            end
            START_BIT: begin
                txd <= 1'b0;  // 发送起始位(低电平)
                if (baud_cnt < BAUD_CNT - 1) begin
                    baud_cnt <= baud_cnt + 1'd1;
                end else begin
                    baud_cnt <= 16'd0;
                    state <= DATA_BITS;
                end
            end
            DATA_BITS: begin
                txd <= tx_reg[bit_cnt];  // 发送数据位(LSB先发)
                if (baud_cnt < BAUD_CNT - 1) begin
                    baud_cnt <= baud_cnt + 1'd1;
                end else begin
                    baud_cnt <= 16'd0;
                    if (bit_cnt < 4'd7) begin
                        bit_cnt <= bit_cnt + 1'd1;
                    end else begin
                        bit_cnt <= 4'd0;
                        state <= STOP_BIT;
                    end
                end
            end
            STOP_BIT: begin
                txd <= 1'b1;  // 发送停止位(高电平)
                if (baud_cnt < BAUD_CNT - 1) begin
                    baud_cnt <= baud_cnt + 1'd1;
                end else begin
                    baud_cnt <= 16'd0;
                    state <= IDLE;
                end
            end
            default: state <= IDLE;
        endcase
    end
end
endmodule

参考代码 基于FPGA的电压表与串口通信 www.youwenfan.com/contentcss/161143.html

四、系统测试与优化

1. 功能测试

测试项 方法 预期结果
电压采集 输入0-5V模拟电压(如1.23V) ADC数据输出对应数字量(如0x7B)
数据处理 中值校准后,转换BCD码 BCD数据输出(如0x1234,对应1.23V)
数码管显示 输入1.23V,观察数码管 显示"1.23"
串口通信 发送数据至PC,用串口调试助手接收 接收数据"1.23V"(或BCD码)

2. 优化方向

  • 精度提升 :采用12位ADC(如ADC121S101),提高电压分辨率(0.0012V);
  • 低功耗:空闲时关闭数码管扫描、降低FPGA时钟频率(如10MHz);
  • 功能扩展 :增加多通道采集 (如8路电压输入)、数据存储(如SD卡存储历史数据);
  • 抗干扰 :在ADC输入级增加RC低通滤波(1kΩ+100nF),减少高频噪声。

五、总结

本设计基于FPGA实现了电压采集、数据处理、显示驱动、串口通信一体化功能,通过ADC0809实现模拟电压到数字信号的转换,Verilog HDL完成逻辑控制与数据处理,UART协议实现远程数据传输。系统具备高精度、低功耗、易扩展特点,可广泛应用于实验室、工业设备等场景,为电压监测提供可靠的解决方案。

相关推荐
rit84324992 小时前
基于FPGA的数字秒表设计(Verilog实现)
fpga开发
tiantianuser5 小时前
RDMA设计64:数据吞吐量性能测试分析
网络·fpga开发·rdma·fpga设计·高速传输·roce v2
木心术15 小时前
OpenClaw FPGA工程开发全流程指南
fpga开发
dadaobusi19 小时前
ZeBu的runClk原理
fpga开发
第二层皮-合肥1 天前
50天学习FPGA第32天-添加HDL属性调试
学习·fpga开发
minglie11 天前
MAC,PHY,变压器,RJ45
fpga开发
tiantianuser1 天前
RDMA设计62:RoCE v2 原语及单/双边语义功能测试2
功能测试·fpga开发·rdma·高速传输·cmac·roce v2
unicrom_深圳市由你创科技1 天前
LabVIEW和C#在工业控制中的应用差异是什么?
fpga开发·c#·labview
senijusene1 天前
IMX6ULL 时钟系统配置与定时器 (EPIT/GPT)
stm32·单片机·fpga开发