该资源为FPGA工程文件,基于Quartus II 15.1开发环境,使用verilog编写,备注详细。16bit四通道模数转换芯片ADS1118采集模拟电压信号(通道可选,电压范围可变),通过SPI接口和FPGA通信,数据在自己编写的异步FIFO缓存,经过UART接口,将数据传输至PC,使用串口调试助手可查看接收数据,经验证可在工程中使用。
源程序如下:
- //---------------------------------------------------------------------------
- //-- 文件名 : ADS1118_module.v
- //-- 作者 : Chen.s.y
- //-- 描述 : ADS1118模/数转换芯片驱动时序
- //-- 修订历史 : 2017-8-20
- //---------------------------------------------------------------------------
- `define SCLK_TIME 11'd2000 //0.025M=25khz, 40us,40 / (1 / 50M) = 2000
- `define SCLK_TIME_HALF 10'd1000 //40us / 2 = 20us 10 / 2 = 1000
- module ADS1118_module(CLK_50M,RST,CS,DIN,DOUT,SCLK,fifo_wclk,ADC_result);
- /*parameter ADS_config_AIN0=16'h458A; //ADS1118配置数据(模拟通道0)0100_0101_1000_1010
- parameter ADS_config_AIN1=16'h558A; //ADS1118配置数据(模拟通道1)0101_0101_1000_1010
- parameter ADS_config_AIN2=16'h658A; //ADS1118配置数据(模拟通道2)0110_0101_1000_1010
- parameter ADS_config_AIN3=16'h758A; //ADS1118配置数据(模拟通道3)0111_0101_1000_1010*/
- /*parameter ADS_config_AIN0=16'h448A; //ADS1118配置数据(模拟通道0)0100_0100_1000_1010
- parameter ADS_config_AIN1=16'h548A; //ADS1118配置数据(模拟通道1)0101_0100_1000_1010
- parameter ADS_config_AIN2=16'h648A; //ADS1118配置数据(模拟通道2)0110_0100_1000_1010
- parameter ADS_config_AIN3=16'h748A; //ADS1118配置数据(模拟通道3)0111_0100_1000_1010*/
- parameter ADS_config_AIN0=16'hC2E3; //ADS1118配置数据(模拟通道0)1100_0010_1110_0011
- parameter ADS_config_AIN1=16'hC2E3; //ADS1118配置数据(模拟通道1)0101_0100_1000_1010
- parameter ADS_config_AIN2=16'hE2E3; //ADS1118配置数据(模拟通道2)1110_0010_1110_0011
- parameter ADS_config_AIN3=16'hE2E3; //ADS1118配置数据(模拟通道3)0111_0100_1000_1010
- //---------------------------------------------------------------------------
- //-- 外部端口声明
- //---------------------------------------------------------------------------
- input CLK_50M,RST;
- input DOUT; //The result of ADC
- output CS; //The signal of starting converting
- output DIN; //The signal of serial input
- output SCLK; //The clock siganl of ADC chip
- output fifo_wclk; //The write clk of fifo module
- output [ 7:0]ADC_result; //The 8bit data of ADC
- //---------------------------------------------------------------------------
- //-- 内部端口声明
- //---------------------------------------------------------------------------
- wire DIN; //AD串行数据输入
- reg DIN_N; //DIN的下一个状态
- reg CS; //AD片选信号
- reg CS_N; //CS的下一个状态
- reg SCLK; //AD时钟,最大不超过4MHz,最小为35.71Hz,这里设置为2.5MHz
- reg SCLK_N; //SCLK的下一个状态
- reg [ 2:0] fsm_cs; //状态机的当前状态
- reg [ 2:0] fsm_ns; //状态机的下一个状态
- reg [ 11:0] time_cnt; //用于记录一个时钟所用时间的定时器
- reg [ 11:0] time_cnt_n; //time_cnt的下一个状态
- reg [ 4:0] bit_cnt; //用来记录时钟周期个数的计数器
- reg [ 4:0] bit_cnt_n; //bit_cnt的下一个状态
- reg [ 1:0] flag; //用来标记四个通道采样的顺序
- reg [ 1:0] flag_n; //flag的下一个状态
- reg [15:0] ADC_DATA; //用来保存稳定的16bit AD数据
- reg [15:0] ADC_DATA_n; //ADC_DATA的下一个状态
- reg [15:0] ad_data_reg; //用于保存数据的移位寄存器
- reg [15:0] ad_data_reg_n; //ad_data_reg的下一个状态
- reg [15:0] ADS_config_data; //ADS1118配置寄存器
- reg wfifo_clk_n1; //fifo_wclk_n的下一个状态
- reg wfifo_clk_n2; //fifo_wclk_n的下一个状态
- reg [15:0] wfifo_clk_cnt; //用于计数ADC_DATA的脉宽
- reg [15:0] wfifo_clk_cnt_n; //wfifo_clk_cnt的下一个状态
- reg data_flag; //16bit ADC数据拆分为8bit的标志
- //1:发送低8位
- //0:发送高八位
- reg [ 7:0] ADC_result; //拆分ADS芯片16bit的采样结果(便于串口传输)
- //---------------------------------------------------------------------------
- assign DIN = DIN_N;
- assign fifo_wclk=~wfifo_clk_n1;
- parameter FSM_IDLE = 3'h0; //状态机的初始状态
- parameter FSM_CS0 = 3'h1; //CS下降沿到第一个SCK上升沿的等待状态,最小为值100ns
- parameter FSM_DATA = 3'h2; //读取16个数据状态
- parameter FSM_CS1 = 3'h3; //最后一个SCK下降沿到CS上升沿的等待状态,最小为值100ns
- parameter FSM_END = 3'h4; //结束的状态
- //---------------------------------------------------------------------------
- //-- 逻辑功能实现
- //---------------------------------------------------------------------------
- //时序电路,用来给fsm_cs寄存器赋值
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST) //判断复位
- fsm_cs <= 1'b0; //初始化ad_fsm_cs值
- else
- fsm_cs <= fsm_ns; //用来给ad_fsm_ns赋值
- end
- //组合电路,用来实现状态机
- always @ (*)
- begin
- case(fsm_cs) //判断状态机的当前状态
-
- //---------------------------------------------------------------------//
- FSM_IDLE:
- //2 x SCLK_TIME用于初始化延时
- if((bit_cnt == 5'd1 ) && (time_cnt == `SCLK_TIME))
- fsm_ns = FSM_CS0; //完成就进入CS下降沿到第一个SCK上升沿的等待状态
- else
- fsm_ns = fsm_cs; //否则保持原状态不变
- //---------------------------------------------------------------------//
- FSM_CS0:
- //2 x SCLK_TIME 用于等待延时
- if((bit_cnt == 5'd1 ) && (time_cnt == `SCLK_TIME))
- fsm_ns = FSM_DATA; //完成就进入读取数据状态
- else
- fsm_ns = fsm_cs; //否则保持原状态不变
- //---------------------------------------------------------------------//
- FSM_DATA:
- //读取数据16位,1~16个时钟脉冲
- if((bit_cnt == 5'd16 ) && (time_cnt == `SCLK_TIME))
- fsm_ns = FSM_CS1; //如果读取数据状态完成就进入结束状态
- else
- fsm_ns = fsm_cs; //否则保持原状态不变
-
- //---------------------------------------------------------------------//
- FSM_CS1:
- //2 x SCLK_TIME 用于等待延时
- if((bit_cnt == 9'd1 ) && (time_cnt == `SCLK_TIME))
- fsm_ns = FSM_END; //完成就进入结束状态
- else
- fsm_ns = fsm_cs; //否则保持原状态不变
- //---------------------------------------------------------------------//
- FSM_END:
- fsm_ns = FSM_IDLE; //完成一次数据转换,进入下一次转换
-
- default:fsm_ns = FSM_IDLE;
- endcase
- end
- //时序电路,用来给time_cnt寄存器赋值
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST) //判断复位
- time_cnt <= 12'h0; //初始化time_cnt值
- else
- time_cnt <= time_cnt_n; //用来给time_cnt赋值
- end
- //组合电路,实现SCLK_TIME的定时计数器
- always @ (*)
- begin
- if(time_cnt == `SCLK_TIME) //判断SCLK_TIME时间
- time_cnt_n = 12'h0; //如果到达SCLK_TIME,定时器清零
- else
- time_cnt_n = time_cnt + 12'h1; //如果未到SCLK_TIME,定时器继续加1
- end
- //时序电路,用来给bit_cnt寄存器赋值
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST) //判断复位
- bit_cnt <= 5'h0; //初始化bit_cnt值
- else
- bit_cnt <= bit_cnt_n; //用来给bit_cnt赋值
- end
- //组合电路,用来记录时钟周期个数的计数器
- always @ (*)
- begin
- if(fsm_cs != fsm_ns) //判断状态机的当前状态
- bit_cnt_n = 5'h0; //如果当前的状态不等于下一个状态,计时器就清零
- else if(time_cnt == `SCLK_TIME_HALF)//判断SCLK_TIME_HALF时间
- bit_cnt_n = bit_cnt + 5'b1; //如果到达SCLK_TIME_HALF,计数器就加1
- else
- bit_cnt_n = bit_cnt; //否则计数器保持不变
- end
- //时序电路,用来给AD_CLK寄存器赋值
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST) //判断复位
- SCLK <= 1'h0; //初始化AD_CLK值
- else
- SCLK <= SCLK_N; //用来给AD_CLK赋值
- end
- //组合电路,用来生成AD的时钟波形
- always @ (*)
- begin
- if(fsm_cs != FSM_DATA)
- SCLK_N = 1'h0; //如果当前的状态不等于读取数据状态,SCLK_N就置0
- else if(time_cnt == `SCLK_TIME_HALF)//判断SCLK_TIME_HALF时间
- SCLK_N = 1'h1; //如果到达SCLK_TIME_HALF,SCLK_N就置1
- else if(time_cnt == `SCLK_TIME) //判断SCLK_TIME时间
- SCLK_N = 1'h0; //如果到达SCLK_TIME,SCLK_N就置0
- else
- SCLK_N = SCLK; //否则保持不变
- end
- //时序电路,用来给CONVST寄存器赋值
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST) //判断复位
- CS <= 1'h0; //初始化CS值
- else
- CS <= CS_N; //用来给CS赋值
- end
- //组合电路,用来生成AD的CONVST
- always @ (*)
- begin
- if((fsm_cs == FSM_DATA)||(fsm_cs == FSM_CS0)||(fsm_cs == FSM_CS1))
- CS_N = 1'h0; //CS置1的状态
- else
- CS_N = 1'h1; //CS置0的状态
- end
- //时序电路,用来给ad_data_reg寄存器赋值
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST) //判断复位
- ad_data_reg <= 8'h0; //初始化ad_data_reg值
- else
- ad_data_reg <= ad_data_reg_n; //用来给ad_data_reg赋值
- end
- //组合电路,将AD线上的数据保存到移位寄存器中
- always @(*)
- begin
- if((fsm_cs == FSM_DATA) && (!SCLK) && (SCLK_N))
- //判断每一个时钟的上升沿
- ad_data_reg_n = {ad_data_reg[14:0],DOUT};
- //将数据存入移位寄存器中,高位优先
- else
- ad_data_reg_n = ad_data_reg; //否则保持不变
- end
- //时序电路,用来给data_out寄存器赋值
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST) //判断复位
- ADC_DATA <= 0; //初始化data_out值
- else
- ADC_DATA <= ADC_DATA_n; //用来给data_out赋值
- end
- //组合电路,将移位寄存器中的数据存入data_out中,可用于输出
- always @ (*)
- begin
- if(fsm_cs == FSM_END)
- ADC_DATA_n = ad_data_reg;
- else
- ADC_DATA_n = ADC_DATA;
- end
- always @ (posedge CLK_50M)
- begin
- case(flag)
- 2'd0:ADS_config_data <= ADS_config_AIN3;
- 2'd1:ADS_config_data <= ADS_config_AIN0;
- 2'd2:ADS_config_data <= ADS_config_AIN1;
- 2'd3:ADS_config_data <= ADS_config_AIN2;
- default:ADS_config_data <= ADS_config_AIN0;
- endcase
- end
- //时序电路,用来给DIN_N寄存器赋值
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST)
- DIN_N<=0;
- else if(fsm_cs == FSM_DATA)
- case(bit_cnt)
- 5'd0,5'b1:DIN_N<=ADS_config_data[15];
- 5'd2:DIN_N<=ADS_config_data[14];
- 5'd3:DIN_N<=ADS_config_data[13];
- 5'd4:DIN_N<=ADS_config_data[12];
- 5'd5:DIN_N<=ADS_config_data[11];
- 5'd6:DIN_N<=ADS_config_data[10];
- 5'd7:DIN_N<=ADS_config_data[9];
- 5'd8:DIN_N<=ADS_config_data[8];
- 5'd9:DIN_N<=ADS_config_data[7];
- 5'd10:DIN_N<=ADS_config_data[6];
- 5'd11:DIN_N<=ADS_config_data[5];
- 5'd12:DIN_N<=ADS_config_data[4];
- 5'd13:DIN_N<=ADS_config_data[3];
- 5'd14:DIN_N<=ADS_config_data[2];
- 5'd15:DIN_N<=ADS_config_data[1];
- 5'd16:DIN_N<=ADS_config_data[0];
- default:DIN_N<= 0;
- endcase
- else
- DIN_N<= DIN_N;
- end
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST) //判断复位
- flag <= 2'b0; //初始化bit_cnt值
- else
- flag <= flag_n; //用来给bit_cnt赋值
- end
- //组合电路,用来记录时钟周期个数的计数器
- always @ (*)
- begin
- if((!CS)&&(CS_N))
- flag_n <= flag + 2'b1;
- else
- flag_n = flag;
- end
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST)
- wfifo_clk_cnt <= 16'b0;
- else
- wfifo_clk_cnt <= wfifo_clk_cnt_n;
- end
- always @ (*)
- begin
- if((fsm_cs == FSM_DATA)||(fsm_cs == FSM_CS0)||(fsm_cs == FSM_CS1)||(fsm_cs == FSM_IDLE))
- wfifo_clk_cnt_n <= wfifo_clk_cnt + 16'b1;
- else if(fsm_cs == FSM_END)
- wfifo_clk_cnt_n <= 16'b0;
- else
- wfifo_clk_cnt_n <= wfifo_clk_cnt;
- end
- always @ (posedge CLK_50M or negedge RST)
- begin
- if(!RST)
- wfifo_clk_n1 <= 0;
- else
- wfifo_clk_n1 <= wfifo_clk_n2;
- end
- always @(*)
- begin
- if((wfifo_clk_cnt == 16'd9504)||(wfifo_clk_cnt == 16'd19009)||(wfifo_clk_cnt == 16'd28513)||(wfifo_clk_cnt == 16'd38018))
- wfifo_clk_n2 <= ~wfifo_clk_n1;
- else
- wfifo_clk_n2 <= wfifo_clk_n1;
- end
- always @(negedge wfifo_clk_n1 or negedge RST)
- begin
- if(!RST)
- data_flag <= 1'b0;
- else
- data_flag <= data_flag+1'b1;
- end
- always @(posedge wfifo_clk_n1 or negedge RST)
- begin
- if(!RST)
- ADC_result <= 8'b0;
- else if(data_flag == 1'b0)
- ADC_result <= ADC_DATA[15:8];
- else
- ADC_result <= ADC_DATA[ 7:0];
- end
- endmodule
复制代码
所有资料51hei提供下载:
ADS1118_FIFO_MODULE.zip
(6.65 MB, 下载次数: 80)
|