zoukankan      html  css  js  c++  java
  • 用FPGA实现多路电压采集器:(1)在FPGA上实现异步串口通信

    前几周微机课上布置了一个Project,要求用FPGA实现多路电压采集器,对多路模拟信号采集并显示其电压幅值。我们小组的设计思路是利用ADC芯片对模拟电压输入信号进行采集,转换为数字信号,然后交由FPGA进行处理,最后将处理结果通过串口传输给电脑并由串口助手显示读数。基本框图如下

    经过好几天的努力,现在来做一个小小总结。

    所谓多路电压采集器,指的是在同一时刻采集到的数据,虽然好多AD都能实现多路数据的采集,但大多是串行的,即采集完这一路,再采集下一路模拟信号,总是会有时间差,并非,Project的目的是用多片AD(每一片只用一路信号输入)同时采集,实现真正的多路信号同时采集,模拟量选用0~5v的电压

    硬件:1.老师给发的DIGICUBE,XILINX SPARTAN3的FPGA,XC3S50,clk1=18.4320M,clk2=8M

       2.AD芯片是ADC0809,淘宝直接买的模块,后期有时间自己焊电路

         3.下载线,USB转串口线(用于串口通信)

    软件:ISE13.3,串口助手

    使用Verilog HDL

    实现串口通信的代码是是学长们留下来的,稍作修改并增加注释

    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Company: 
    // Engineer: 
    // 
    // Create Date:     
    // Design Name: 
    // Module Name:   
    // Project Name: 
    // Target Devices: 
    // Tool versions: 
    // Description: 
    //
    // Dependencies: 
    //
    // Revision: 
    // Revision 0.01 - File Created
    // Additional Comments: 
    //
    //////////////////////////////////////////////////////////////////////////////////
    //同济大学11级自动化
    module uart(reset, clk, rx_in, tx_out);
    
    //Port declaration
    //clk, reset, rx, tx
    input            reset;
    input            clk;
    input            rx_in;
    output        tx_out;
    
    //reg for tx
    reg [7:0]    tx_reg;//发送数据寄存器,相当于buffer
    wire [7:0]    tx_data;
    reg [15:0]    tx_sample_cnt;//采样计数器
    reg [3:0]    tx_cnt;
    reg            tx_done;
    reg            tx_out;
    reg            tx_enable;
    
    //reg for rx
    reg [7:0]    rx_reg;
    wire [7:0]    rx_data;
    reg [15:0]    rx_sample_cnt;
    reg [3:0]     rx_cnt;//接收到的数据位计数器
    reg            rx_frame_err;//接收帧错误标记,未使用
    reg            rx_done;
    reg            rx_busy;
    reg            rx_d;
    reg            rx_enable;
    
    assign    rx_data = (rx_done)?rx_reg:8'hzz;//zz为高阻状态
    assign    tx_data = rx_data;
    
    
    //uart rx logic
    always@(posedge clk or posedge reset)
    if(reset)
    begin
        rx_sample_cnt <= 0;
        rx_cnt <= 0;
        rx_frame_err <= 0;
        rx_done <= 0;
        rx_busy <= 0;
        rx_d <= 0;
        rx_enable <= 1;
    end
    
    else
    begin
        rx_d <= rx_in;//rx_in是从串口读入的数据,rx_d只有一位,数据帧开始的标志是0,结束是1(第9位)
        
        if(rx_done)
        begin
            rx_done <= 0;//接收完毕后,done标记位清零开始下一次接收
        end
        
        if(rx_enable)//若接收使能
        begin
            //Check if just received start of frame检查是否为一帧的开始
            if(!rx_busy && !rx_d)//busy为0时表示不忙,d为0表示一帧的开始
            begin//如果不忙...进入接收状态,使busy位置1,为了进行后面的处理
                rx_busy <= 1;//busy置1后要对接收的数据进行处理
                rx_sample_cnt <= 1;
                rx_cnt <= 0;
                rx_done <= 0;
            end
            
            //Start of frame detected, proceed with rest of data检测到一帧的开始
            if(rx_busy)//busy置1后要对接收的数据进行处理
            begin
                rx_sample_cnt <= rx_sample_cnt+1;//计数器每次+1
                if(rx_sample_cnt == 1920)//clk=18.432MHz,clk/1920=9600
                begin
                    rx_sample_cnt <= 0;
                end
                
                //logic to sample at middle of data
                if(rx_sample_cnt == 960)//中间处采样
                begin
                    if((rx_d==1) && (rx_cnt==0))
                    begin
                        rx_busy <= 0;
                        rx_done <= 0;
                    end
                    
                    else
                    begin
                        rx_cnt <= rx_cnt+1;
                        rx_done <= 0;
                        
                        //start storing the rx data
                        if(rx_cnt>0 && rx_cnt<9)
                        begin
                            rx_reg[rx_cnt-1] <= rx_d;//reg=rx_buffer,rx_d是接收到的每一位
                        end
                        
                        if(rx_cnt == 9)
                        begin
                            rx_busy <= 0;//接收完毕后把busy位置0
                            
                            //check if end of frame received correctly
                            if(rx_d == 0)//第9位为停止位,若停止位为0则报错
                            begin
                                rx_frame_err <=1;
                            end
                            
                            else//否则接收完成
                            begin
                                rx_done <= 1;
                                rx_frame_err <= 0;
                            end
                        end
                    end
                end
            end
        end
        
        if(!rx_enable)//若接收使能为0,即不能接收则
        begin
            rx_busy <= 0;
            rx_done <= 0;
        end
    end
    
    
    //uart tx logic,和rx类似
    always@(posedge clk or posedge reset)
    if(reset)
    begin
        tx_reg <= 8'hff;
        tx_done <= 1;
        tx_out <= 1;
        tx_cnt <= 0;
        tx_sample_cnt <= 0;
        tx_enable <= 1;
    end
    
    else
    begin
        if(rx_done && tx_done && !tx_cnt)
        begin
            tx_reg <= tx_data;
            tx_done <= 0;
            tx_out <= 0;
            tx_cnt <= 1;
            tx_sample_cnt <= 0;
        end
        
        else
        begin
            tx_sample_cnt <= tx_sample_cnt+1;
            
            if(tx_sample_cnt == 1920)
            begin
                tx_sample_cnt <= 0;
                
                if(tx_enable && !tx_done)
                begin
                    tx_cnt <= tx_cnt+1;
                    if(tx_cnt >0 && tx_cnt<9)
                    begin
                        tx_out <= tx_reg[tx_cnt-1];
                    end
                    
                    if(tx_cnt == 9)
                    begin
                        tx_out <= 1;
                        tx_cnt <= 0;
                        tx_done <= 1;
                    end
                end
                
                if(!tx_enable)
                begin
                    tx_cnt <= 0;
                    tx_sample_cnt <= 0;
                    tx_reg <= 8'hff;
                    tx_out <= 1;
                    tx_done <= 1;
                end
                
                if(tx_done)
                begin
                    tx_out <= 1;
                end
            end
        end
    end
    endmodule

    实现的功能就是串口收发,把收到的数据再发回去

    用usb转串口线脸上笔记本,打开选择相应端口号和9600的波特率即可测试

  • 相关阅读:
    webpack 性能优化
    Bert模型实现垃圾邮件分类
    基于SKLearn的SVM模型垃圾邮件分类——代码实现及优化
    sklearn中,数据集划分函数 StratifiedShuffleSplit.split() 使用踩坑
    mysql5.7安装教程【转载】
    Postman 使用小技巧/指南
    如何知道 window 的 load 事件已经触发
    前端常用库 CDN
    使用 rollup 打包可按需加载的 NPM 包
    webpack 4 快速搭建
  • 原文地址:https://www.cnblogs.com/Cmfvacks-IsLjj/p/3448483.html
Copyright © 2011-2022 走看看