基于PYNQ的AD采集系统

系统概述

打算用PYNQ-Z2开发板做MMC变化器的控制,遇到的第一个问题就是做MMC控制需要采集大量的电容电压、电流信号。但是考虑到XILINX官方的PYNQ-Z2开发板管脚很少,所以使用另一块XLINX的FPGA(SPANTAN-6)接两片黑金的AN706AD进行数据采集,通过SPI协议把采集到的数据从SPI从机传输到位于PYNQ开发板上的SPI主机上。最后通过AXI4-Lite总线传输到ARM核上。系统的总图如下:
在这里插入图片描述

AN706的控制

关于AN706AD的控制,这里直接使用黑金官方的例程就可以了,就是注意去理解其时序,如下图所示:
在这里插入图片描述
直接上代码:

module ad7606(
	input          clk,
	input          rst_n,
        input [15:0]   ad_data,    
        input          ad_busy,    
        input          first_dat
        output [2:0]   ad_os,      
        output reg     ad_cs,      
        output reg     ad_rd,      
        output reg     ad_reset,   
        output reg     ad_convstab,
        output reg [15:0] ad_ch1,
        output reg [15:0] ad_ch2,
        output reg [15:0] ad_ch3,
        output reg [15:0] ad_ch4,
        output reg [15:0] ad_ch5,
        output reg [15:0] ad_ch6,
        output reg [15:0] ad_ch7,
        output reg [15:0] ad_ch8,
        output reg ad_finish
        );
reg [15:0]  cnt;           
reg [5:0] i;               
reg [3:0] state;           
                           
parameter IDLE=4'd0;       
parameter AD_CONV=4'd1;    
parameter Wait_1=4'd2;     
parameter Wait_busy=4'd3;  
parameter READ_CH1=4'd4;   
parameter READ_CH2=4'd5;   
parameter READ_CH3=4'd6;   
parameter READ_CH4=4'd7;   
parameter READ_CH5=4'd8;   
parameter READ_CH6=4'd9;   
parameter READ_CH7=4'd10;  
parameter READ_CH8=4'd11;  
parameter READ_DONE=4'd12; 
                           
assign ad_os=3'b000;
always@(posedge clk)      
 begin                    
    if(cnt<16'hffff) begin
        cnt<=cnt+1;       
        ad_reset<=1'b1;   
      end                 
      else                
        ad_reset<=1'b0;   
   end
always @(posedge clk)                       
 begin                                      
  if (ad_reset==1'b1) begin                 
    state<=IDLE;                            
    ad_ch1<=0;                              
    ad_ch2<=0;                              
    ad_ch3<=0;                              
    ad_ch4<=0;                              
    ad_ch5<=0;                              
    ad_ch6<=0;                              
    ad_ch7<=0;                              
    ad_ch8<=0;                              
    ad_cs<=1'b1;                            
    ad_rd<=1'b1;                            
    ad_convstab<=1'b1;                      
    i<=0;                                   
    ad_finish<=1'b0;                        
  end                                       
  else begin                                
    case(state)                             
    IDLE: begin                             
     ad_cs<=1'b1;                           
     ad_rd<=1'b1;                           
     ad_convstab<=1'b1;                     
     if(i==20) begin                        
      i<=0;                                 
      state<=AD_CONV;                       
     end                                    
     else                                   
      i<=i+1'b1;                            
    end                                     
    AD_CONV: begin                          
     if(i==2) begin                       
      i<=0;                                 
      state<=Wait_1;                        
      ad_convstab<=1'b1;                    
      ad_finish<=1'b0;                      
     end                                    
     else begin                             
      i<=i+1'b1;                            
      ad_convstab<=1'b0;                    
     end                                    
    end                                     
    Wait_1: begin                           
     if(i==5) begin                         
      i<=0;                                 
      state<=Wait_busy;                     
     end                                    
     else                                   
      i<=i+1'b1;                            
    end                                     
    Wait_busy: begin                        
     if(ad_busy==1'b0) begin                
      i<=0;                                 
      state<=READ_CH1;                      
     end                                    
    end                                     
    READ_CH1: begin                         
     ad_cs<=1'b0;                           
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch1<=ad_data;                      
      state<=READ_CH2;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH2: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch2<=ad_data;                      
      state<=READ_CH3;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH3: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch3<=ad_data;                      
      state<=READ_CH4;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH4: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch4<=ad_data;                      
      state<=READ_CH5;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH5: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch5<=ad_data;                      
      state<=READ_CH6;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH6: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch6<=ad_data;                      
      state<=READ_CH7;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH7: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch7<=ad_data;                      
      state<=READ_CH8;                      
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_CH8: begin                         
     if(i==3) begin                         
      ad_rd<=1'b1;                          
      i<=0;                                 
      ad_ch8<=ad_data;                      
      state<=READ_DONE;                     
     end                                    
     else begin                             
      ad_rd<=1'b0;                          
      i<=i+1'b1;                            
     end                                    
    end                                     
    READ_DONE:begin                         
      ad_rd<=1'b1;                          
      ad_cs<=1'b1;                          
      state<=IDLE;                          
      ad_finish<=1'b1;                      
    end                                     
    default: state<=IDLE;                   
    endcase                                 
    end                                     
                                            
 end                                        
                                            
endmodule                                                       
       

这里在黑金官方的代码的基础上加入了ad_finish这个输出信号,目的是每次AD读完8个通道的值后告知SPI从机可以进行数据传输了。

SPI通讯

在两个FPGA之间的通讯,准备采用SPI模式,但是因为数据的流动方向只是从SPANTAN-6流向PYNQ-Z2,所以在这里对SPI通讯协议进行了修改。首先在传统的4线SPI模式中,去掉MOSI这根线,其次为了在传输时加大传输速度,把MISO的数据位宽改为16位,与AD输出的位宽相同。传输时遵从在时钟的下降沿从机准备好需要传输的数据,在时钟的上升沿主机采集数据。
下面直接上代码:

从机
//下降沿发送数据                                                                 
module SPI_SLAVE                                                          
(                                                                         
    input clk,                                                            
    input rst_n,                                                          
    input CS_N,                                                           
    input SCK,                                                            
    input tx_en,   //                                                     
    output reg [15:0]MISO,                                                
    input [16*16-1:0] txd_data                                            
);                                                                        
//---------------------spi_slaver send data---------------------------    
reg [3:0] txd_state;                                                      
always@(negedge SCK or negedge rst_n)                                     
begin                                                                     
    if(!rst_n)                                                            
        begin                                                             
            txd_state <= 1'b0;                                            
            MISO<=0;                                                      
        end                                                               
    else if(!CS_N)                                                        
        begin                                                             
            case(txd_state)                                               
                4'd0:begin                            
  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FPGA 读写SD卡音乐播放例程Verilog逻辑源码Quartus工程文件+文档说明,,FPGA型号Cyclone4E系列中的EP4CE6F17C8,Quartus版本17.1。 实验简介 在其他实验中我们已经完成了 SD 卡读写和音频模块的录音播放,本实验通过搜索 SD 卡中 WAV 音乐文件,然后送到音频模块播放,完成一个简单音乐播放器的功能。 2 实验原理 本实验一个关键是在没有文件系统的情况下,搜索 SD 卡每个扇区的内容,匹配出 WAV 文件, 这里有一个假设:假设每一个文件都是从一个扇区第一个字节开始而且文件是连续存储的,经过 大量实验,发现 FAT32 文件格式中的文件确实如此。 2.1 WAV 文件格式 大部分的文件都有文件头,WAV 也丌例外,我们通过分析 SD 卡一个扇区的前几个字节,判 断这个文件是否为 WAV 文件。 WAV 文件作为多媒体中使用的声波文件格式之一,它是以 RIFF 格式为标准的。RIFF 是英文 Resource Interchange File Format 的缩写,每个 WAV 文件的头四个字节便是“RIFF”,所以本实验 就简单的以每个扇区的前 4 个字节是否为“RIFF”判断该文件是否为 WAV 文件,紧接着 4 个字节 表示文件的大小,这样我们就可以确定要读取的数据量。WAV 文件头大小是 88 字节,在播放时 要把前 88 个字节的文件头去掉。 module top( input clk, input rst_n, input key1, input wm8731_bclk, //audio bit clock input wm8731_daclrc, //DAC sample rate left right clock output wm8731_dacdat, //DAC audio data output input wm8731_adclrc, //ADC sample rate left right clock input wm8731_adcdat, //ADC audio data input inout wm8731_scl, //I2C clock inout wm8731_sda, //I2C data output sd_ncs, //SD card chip select (SPI mode) output sd_dclk, //SD card clock output sd_mosi, //SD card controller data output input sd_miso, //SD card controller data input output [5:0] seg_sel, output [7:0] seg_data ); wire[9:0] lut_index; wire[31:0] lut_data; wire[3:0] state_code; wire[6:0] seg_data_0; //I2C master controller i2c_config i2c_config_m0( .rst (~rst_n ), .clk (clk ),
下面是基于单片机的AD采集程序,以AT89C51单片机为例。 ```c #include <reg51.h> sbit ADC_CS = P2^1; //模拟量输入通道选择端口 sbit ADC_CLK = P2^2; //ADC时钟端口 sbit ADC_DIN = P2^3; //模拟量输入端口 sbit ADC_DOUT = P2^4; //ADC数据输出端口 //ADC转换函数 unsigned int ADC_Read(unsigned char ch) { unsigned char i; unsigned int dat = 0; ADC_CS = 1; //拉高通道选择端口,准备转换 ADC_CLK = 0; //ADC时钟置低 ADC_DIN = 0; //清零模拟量输入端口 //发送起始转换命令 ADC_CS = 0; ADC_CLK = 0; ADC_DIN = 1; ADC_CLK = 1; ADC_DIN = 1; ADC_CLK = 0; //发送通道选择命令 for (i = 0; i < 3; i++) { ADC_CLK = 0; ADC_DIN = ch & 0x80; ch <<= 1; ADC_CLK = 1; } //接收ADC转换结果 for (i = 0; i < 12; i++) { ADC_CLK = 0; ADC_CLK = 1; dat <<= 1; dat |= ADC_DOUT; } ADC_CS = 1; //转换完成,拉高通道选择端口 return dat; } void main() { unsigned int adc_data; P0 = 0x00; //初始化P0口为输出 P2 = 0xff; //初始化P2口为输入 while (1) { P0 = 0x00; //将P0口清零 adc_data = ADC_Read(0); //读取ADC转换结果 P0 = adc_data >> 4; //将ADC转换结果输出到P0口 } } ``` 该代码实现了单通道ADC采样,并将转换结果通过P0口输出。其中,ADC_Read函数用于进行ADC转换,参数ch表示需要采样的模拟量输入通道,返回值为转换结果。在主函数中,首先进行了端口初始化,然后进入循环,不断采样并输出结果。注意,ADC转换过程中需要保证时序的正确性,因此需要仔细按照代码中的时序进行实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值