該資源為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)
2017-12-21 16:54 上傳
點擊文件名下載附件
|