找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6412|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

FAGA+ADS1118+異步FIFO+串口源程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:264904 發(fā)表于 2017-12-21 16:55 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
該資源為FPGA工程文件,基于Quartus II 15.1開發(fā)環(huán)境,使用verilog編寫,備注詳細(xì)。16bit四通道模數(shù)轉(zhuǎn)換芯片ADS1118采集模擬電壓信號(通道可選,電壓范圍可變),通過SPI接口和FPGA通信,數(shù)據(jù)在自己編寫的異步FIFO緩存,經(jīng)過UART接口,將數(shù)據(jù)傳輸至PC,使用串口調(diào)試助手可查看接收數(shù)據(jù),經(jīng)驗證可在工程中使用。



源程序如下:
  1. //---------------------------------------------------------------------------
  2. //--        文件名                :        ADS1118_module.v
  3. //--        作者                :        Chen.s.y
  4. //--        描述                :        ADS1118模/數(shù)轉(zhuǎn)換芯片驅(qū)動時序
  5. //--        修訂歷史        :        2017-8-20
  6. //---------------------------------------------------------------------------

  7. `define SCLK_TIME                        11'd2000                        //0.025M=25khz, 40us,40 / (1 / 50M) = 2000
  8. `define SCLK_TIME_HALF        10'd1000                        //40us / 2 = 20us  10 / 2 = 1000

  9. module ADS1118_module(CLK_50M,RST,CS,DIN,DOUT,SCLK,fifo_wclk,ADC_result);

  10. /*parameter ADS_config_AIN0=16'h458A;        //ADS1118配置數(shù)據(jù)(模擬通道0)0100_0101_1000_1010
  11. parameter ADS_config_AIN1=16'h558A;        //ADS1118配置數(shù)據(jù)(模擬通道1)0101_0101_1000_1010
  12. parameter ADS_config_AIN2=16'h658A;        //ADS1118配置數(shù)據(jù)(模擬通道2)0110_0101_1000_1010
  13. parameter ADS_config_AIN3=16'h758A;        //ADS1118配置數(shù)據(jù)(模擬通道3)0111_0101_1000_1010*/
  14. /*parameter ADS_config_AIN0=16'h448A;        //ADS1118配置數(shù)據(jù)(模擬通道0)0100_0100_1000_1010
  15. parameter ADS_config_AIN1=16'h548A;        //ADS1118配置數(shù)據(jù)(模擬通道1)0101_0100_1000_1010
  16. parameter ADS_config_AIN2=16'h648A;        //ADS1118配置數(shù)據(jù)(模擬通道2)0110_0100_1000_1010
  17. parameter ADS_config_AIN3=16'h748A;        //ADS1118配置數(shù)據(jù)(模擬通道3)0111_0100_1000_1010*/

  18. parameter ADS_config_AIN0=16'hC2E3;        //ADS1118配置數(shù)據(jù)(模擬通道0)1100_0010_1110_0011
  19. parameter ADS_config_AIN1=16'hC2E3;        //ADS1118配置數(shù)據(jù)(模擬通道1)0101_0100_1000_1010
  20. parameter ADS_config_AIN2=16'hE2E3;        //ADS1118配置數(shù)據(jù)(模擬通道2)1110_0010_1110_0011
  21. parameter ADS_config_AIN3=16'hE2E3;        //ADS1118配置數(shù)據(jù)(模擬通道3)0111_0100_1000_1010

  22. //---------------------------------------------------------------------------
  23. //--        外部端口聲明
  24. //---------------------------------------------------------------------------
  25. input  CLK_50M,RST;
  26. input  DOUT;                                                                //The result of ADC
  27. output CS;                                                                        //The signal of starting converting
  28. output DIN;                                                                        //The signal of serial input       
  29. output SCLK;                                                                //The clock siganl of ADC chip
  30. output fifo_wclk;                                                        //The write clk of fifo module
  31. output [ 7:0]ADC_result;                                //The 8bit data of ADC

  32. //---------------------------------------------------------------------------
  33. //--        內(nèi)部端口聲明
  34. //---------------------------------------------------------------------------
  35. wire                                         DIN;                                        //AD串行數(shù)據(jù)輸入
  36. reg                                        DIN_N;                                //DIN的下一個狀態(tài)
  37. reg                                        CS;                                        //AD片選信號
  38. reg                                        CS_N;                                        //CS的下一個狀態(tài)
  39. reg                                        SCLK;                                        //AD時鐘,最大不超過4MHz,最小為35.71Hz,這里設(shè)置為2.5MHz
  40. reg                                        SCLK_N;                                //SCLK的下一個狀態(tài)

  41. reg                [ 2:0]        fsm_cs;                                //狀態(tài)機(jī)的當(dāng)前狀態(tài)
  42. reg                [ 2:0]        fsm_ns;                                //狀態(tài)機(jī)的下一個狀態(tài)


  43. reg                [ 11:0]        time_cnt;                        //用于記錄一個時鐘所用時間的定時器
  44. reg                [ 11:0]        time_cnt_n;                        //time_cnt的下一個狀態(tài)
  45. reg                [ 4:0]        bit_cnt;                                //用來記錄時鐘周期個數(shù)的計數(shù)器
  46. reg                [ 4:0]        bit_cnt_n;                        //bit_cnt的下一個狀態(tài)

  47. reg                 [ 1:0]        flag;                                        //用來標(biāo)記四個通道采樣的順序
  48. reg                 [ 1:0]        flag_n;                                //flag的下一個狀態(tài)

  49. reg                [15:0]        ADC_DATA;                        //用來保存穩(wěn)定的16bit AD數(shù)據(jù)
  50. reg                [15:0]        ADC_DATA_n;                        //ADC_DATA的下一個狀態(tài)
  51. reg                [15:0]        ad_data_reg;                //用于保存數(shù)據(jù)的移位寄存器
  52. reg                [15:0]        ad_data_reg_n;                //ad_data_reg的下一個狀態(tài)

  53. reg                [15:0]        ADS_config_data;        //ADS1118配置寄存器

  54. reg                                        wfifo_clk_n1;                //fifo_wclk_n的下一個狀態(tài)
  55. reg                                        wfifo_clk_n2;                //fifo_wclk_n的下一個狀態(tài)
  56. reg                [15:0]        wfifo_clk_cnt;                //用于計數(shù)ADC_DATA的脈寬
  57. reg                [15:0]        wfifo_clk_cnt_n;        //wfifo_clk_cnt的下一個狀態(tài)

  58. reg                                        data_flag;                        //16bit ADC數(shù)據(jù)拆分為8bit的標(biāo)志
  59.                                                                                                 //1:發(fā)送低8位
  60.                                                                                                 //0:發(fā)送高八位
  61. reg                [ 7:0]        ADC_result;                        //拆分ADS芯片16bit的采樣結(jié)果(便于串口傳輸)

  62. //---------------------------------------------------------------------------

  63. assign DIN = DIN_N;
  64. assign fifo_wclk=~wfifo_clk_n1;

  65. parameter        FSM_IDLE                        = 3'h0;        //狀態(tài)機(jī)的初始狀態(tài)
  66. parameter        FSM_CS0                        = 3'h1;        //CS下降沿到第一個SCK上升沿的等待狀態(tài),最小為值100ns
  67. parameter        FSM_DATA                        = 3'h2;        //讀取16個數(shù)據(jù)狀態(tài)
  68. parameter        FSM_CS1                        = 3'h3;        //最后一個SCK下降沿到CS上升沿的等待狀態(tài),最小為值100ns
  69. parameter        FSM_END                        = 3'h4;        //結(jié)束的狀態(tài)

  70. //---------------------------------------------------------------------------
  71. //--        邏輯功能實現(xiàn)       
  72. //---------------------------------------------------------------------------
  73. //時序電路,用來給fsm_cs寄存器賦值
  74. always @ (posedge CLK_50M or negedge RST)
  75. begin
  76.         if(!RST)                                                                        //判斷復(fù)位
  77.                 fsm_cs <= 1'b0;                                        //初始化ad_fsm_cs值
  78.         else
  79.                 fsm_cs <= fsm_ns;                                        //用來給ad_fsm_ns賦值
  80. end

  81. //組合電路,用來實現(xiàn)狀態(tài)機(jī)
  82. always @ (*)
  83. begin
  84.         case(fsm_cs)                                                        //判斷狀態(tài)機(jī)的當(dāng)前狀態(tài)
  85.        
  86.         //---------------------------------------------------------------------//
  87.                 FSM_IDLE:
  88.                                                                                                 //2 x SCLK_TIME用于初始化延時
  89.                         if((bit_cnt == 5'd1 ) && (time_cnt == `SCLK_TIME))
  90.                                 fsm_ns = FSM_CS0;                        //完成就進(jìn)入CS下降沿到第一個SCK上升沿的等待狀態(tài)
  91.                         else
  92.                                 fsm_ns = fsm_cs;                        //否則保持原狀態(tài)不變
  93.         //---------------------------------------------------------------------//
  94.                 FSM_CS0:
  95.                                                                                                 //2 x SCLK_TIME 用于等待延時
  96.                         if((bit_cnt == 5'd1 ) && (time_cnt == `SCLK_TIME))
  97.                                 fsm_ns = FSM_DATA;                //完成就進(jìn)入讀取數(shù)據(jù)狀態(tài)
  98.                         else
  99.                                 fsm_ns = fsm_cs;                  //否則保持原狀態(tài)不變

  100.         //---------------------------------------------------------------------//
  101.                 FSM_DATA:
  102.                                                                                                 //讀取數(shù)據(jù)16位,1~16個時鐘脈沖
  103.                         if((bit_cnt == 5'd16 ) && (time_cnt == `SCLK_TIME))
  104.                                 fsm_ns = FSM_CS1;                        //如果讀取數(shù)據(jù)狀態(tài)完成就進(jìn)入結(jié)束狀態(tài)
  105.                         else
  106.                                 fsm_ns = fsm_cs;                        //否則保持原狀態(tài)不變               
  107.                                
  108.         //---------------------------------------------------------------------//
  109.                 FSM_CS1:
  110.                                                                                                 //2 x SCLK_TIME 用于等待延時
  111.                         if((bit_cnt == 9'd1 ) && (time_cnt == `SCLK_TIME))
  112.                                 fsm_ns = FSM_END;                        //完成就進(jìn)入結(jié)束狀態(tài)
  113.                         else
  114.                                 fsm_ns = fsm_cs;                  //否則保持原狀態(tài)不變
  115.         //---------------------------------------------------------------------//
  116.                 FSM_END:                                                               
  117.                                 fsm_ns = FSM_IDLE;                //完成一次數(shù)據(jù)轉(zhuǎn)換,進(jìn)入下一次轉(zhuǎn)換
  118.                        
  119.                 default:fsm_ns = FSM_IDLE;                               
  120.         endcase
  121. end

  122. //時序電路,用來給time_cnt寄存器賦值
  123. always @ (posedge CLK_50M or negedge RST)
  124. begin
  125.         if(!RST)                                                                        //判斷復(fù)位
  126.                 time_cnt <= 12'h0;                                        //初始化time_cnt值
  127.         else
  128.                 time_cnt <= time_cnt_n;                        //用來給time_cnt賦值
  129. end

  130. //組合電路,實現(xiàn)SCLK_TIME的定時計數(shù)器
  131. always @ (*)
  132. begin
  133.         if(time_cnt == `SCLK_TIME)                        //判斷SCLK_TIME時間
  134.                 time_cnt_n = 12'h0;                                //如果到達(dá)SCLK_TIME,定時器清零
  135.         else
  136.                 time_cnt_n = time_cnt + 12'h1;        //如果未到SCLK_TIME,定時器繼續(xù)加1
  137. end

  138. //時序電路,用來給bit_cnt寄存器賦值
  139. always @ (posedge CLK_50M or negedge RST)
  140. begin
  141.         if(!RST)                                                                        //判斷復(fù)位
  142.                 bit_cnt <= 5'h0;                                        //初始化bit_cnt值
  143.         else
  144.                 bit_cnt <= bit_cnt_n;                        //用來給bit_cnt賦值
  145. end

  146. //組合電路,用來記錄時鐘周期個數(shù)的計數(shù)器
  147. always @ (*)
  148. begin
  149.         if(fsm_cs != fsm_ns)                                        //判斷狀態(tài)機(jī)的當(dāng)前狀態(tài)
  150.                 bit_cnt_n = 5'h0;                                        //如果當(dāng)前的狀態(tài)不等于下一個狀態(tài),計時器就清零
  151.         else if(time_cnt == `SCLK_TIME_HALF)//判斷SCLK_TIME_HALF時間
  152.                 bit_cnt_n = bit_cnt + 5'b1;        //如果到達(dá)SCLK_TIME_HALF,計數(shù)器就加1
  153.         else
  154.                 bit_cnt_n = bit_cnt;                                //否則計數(shù)器保持不變
  155. end

  156. //時序電路,用來給AD_CLK寄存器賦值
  157. always @ (posedge CLK_50M or negedge RST)
  158. begin
  159.         if(!RST)                                                                        //判斷復(fù)位
  160.                 SCLK <= 1'h0;                                                //初始化AD_CLK值
  161.         else
  162.                 SCLK <= SCLK_N;                                        //用來給AD_CLK賦值
  163. end

  164. //組合電路,用來生成AD的時鐘波形
  165. always @ (*)
  166. begin
  167.         if(fsm_cs != FSM_DATA)                       
  168.                 SCLK_N = 1'h0;                                                //如果當(dāng)前的狀態(tài)不等于讀取數(shù)據(jù)狀態(tài),SCLK_N就置0
  169.         else if(time_cnt == `SCLK_TIME_HALF)//判斷SCLK_TIME_HALF時間
  170.                 SCLK_N = 1'h1;                                                //如果到達(dá)SCLK_TIME_HALF,SCLK_N就置1
  171.         else if(time_cnt == `SCLK_TIME)        //判斷SCLK_TIME時間
  172.                 SCLK_N = 1'h0;                                                //如果到達(dá)SCLK_TIME,SCLK_N就置0
  173.         else
  174.                 SCLK_N = SCLK;                                                //否則保持不變
  175. end

  176. //時序電路,用來給CONVST寄存器賦值
  177. always @ (posedge CLK_50M or negedge RST)
  178. begin
  179.         if(!RST)                                                                        //判斷復(fù)位
  180.                 CS <= 1'h0;                                                        //初始化CS值
  181.         else
  182.                 CS <= CS_N;                                                        //用來給CS賦值
  183. end

  184. //組合電路,用來生成AD的CONVST
  185. always @ (*)
  186. begin
  187.         if((fsm_cs == FSM_DATA)||(fsm_cs == FSM_CS0)||(fsm_cs == FSM_CS1))
  188.                 CS_N = 1'h0;                                                //CS置1的狀態(tài)
  189.         else
  190.                 CS_N = 1'h1;                                                //CS置0的狀態(tài)
  191. end

  192. //時序電路,用來給ad_data_reg寄存器賦值
  193. always @ (posedge CLK_50M or negedge RST)
  194. begin
  195.         if(!RST)                                                                        //判斷復(fù)位
  196.                 ad_data_reg <= 8'h0;                                //初始化ad_data_reg值
  197.         else
  198.                 ad_data_reg <= ad_data_reg_n;        //用來給ad_data_reg賦值
  199. end

  200. //組合電路,將AD線上的數(shù)據(jù)保存到移位寄存器中
  201. always @(*)
  202. begin
  203.         if((fsm_cs == FSM_DATA) && (!SCLK) && (SCLK_N))
  204.                                                                                                 //判斷每一個時鐘的上升沿
  205.                 ad_data_reg_n = {ad_data_reg[14:0],DOUT};
  206.                                                                                                 //將數(shù)據(jù)存入移位寄存器中,高位優(yōu)先
  207.         else
  208.                 ad_data_reg_n = ad_data_reg;        //否則保持不變
  209. end

  210. //時序電路,用來給data_out寄存器賦值
  211. always @ (posedge CLK_50M or negedge RST)
  212. begin
  213.         if(!RST)                                                                        //判斷復(fù)位
  214.                 ADC_DATA <= 0;                                                //初始化data_out值
  215.         else
  216.                 ADC_DATA <= ADC_DATA_n;                        //用來給data_out賦值
  217. end

  218. //組合電路,將移位寄存器中的數(shù)據(jù)存入data_out中,可用于輸出
  219. always @ (*)
  220. begin
  221.         if(fsm_cs == FSM_END)
  222.                 ADC_DATA_n = ad_data_reg;
  223.         else
  224.                 ADC_DATA_n = ADC_DATA;
  225. end

  226. always @ (posedge CLK_50M)
  227. begin
  228.         case(flag)
  229.                 2'd0:ADS_config_data <= ADS_config_AIN3;
  230.                 2'd1:ADS_config_data <= ADS_config_AIN0;
  231.                 2'd2:ADS_config_data <= ADS_config_AIN1;
  232.                 2'd3:ADS_config_data <= ADS_config_AIN2;
  233.                 default:ADS_config_data <= ADS_config_AIN0;
  234.         endcase
  235. end


  236. //時序電路,用來給DIN_N寄存器賦值
  237. always @ (posedge CLK_50M or negedge RST)
  238. begin
  239.         if(!RST)
  240.                 DIN_N<=0;
  241.         else if(fsm_cs == FSM_DATA)
  242.                 case(bit_cnt)
  243.                                 5'd0,5'b1:DIN_N<=ADS_config_data[15];
  244.                                 5'd2:DIN_N<=ADS_config_data[14];
  245.                                 5'd3:DIN_N<=ADS_config_data[13];
  246.                                 5'd4:DIN_N<=ADS_config_data[12];
  247.                                 5'd5:DIN_N<=ADS_config_data[11];
  248.                                 5'd6:DIN_N<=ADS_config_data[10];
  249.                                 5'd7:DIN_N<=ADS_config_data[9];
  250.                                 5'd8:DIN_N<=ADS_config_data[8];
  251.                                 5'd9:DIN_N<=ADS_config_data[7];
  252.                                 5'd10:DIN_N<=ADS_config_data[6];
  253.                                 5'd11:DIN_N<=ADS_config_data[5];
  254.                                 5'd12:DIN_N<=ADS_config_data[4];
  255.                                 5'd13:DIN_N<=ADS_config_data[3];
  256.                                 5'd14:DIN_N<=ADS_config_data[2];
  257.                                 5'd15:DIN_N<=ADS_config_data[1];
  258.                                 5'd16:DIN_N<=ADS_config_data[0];
  259.                                 default:DIN_N<= 0;
  260.                 endcase
  261.         else
  262.                 DIN_N<= DIN_N;
  263. end


  264. always @ (posedge CLK_50M or negedge RST)
  265. begin
  266.         if(!RST)                                                                        //判斷復(fù)位
  267.                 flag <= 2'b0;                                        //初始化bit_cnt值
  268.         else
  269.                 flag <= flag_n;                                //用來給bit_cnt賦值
  270. end

  271. //組合電路,用來記錄時鐘周期個數(shù)的計數(shù)器
  272. always @ (*)
  273. begin
  274.         if((!CS)&&(CS_N))
  275.                 flag_n <= flag + 2'b1;
  276.         else
  277.                 flag_n = flag;
  278. end


  279. always @ (posedge CLK_50M or negedge RST)
  280. begin
  281.         if(!RST)
  282.                 wfifo_clk_cnt <= 16'b0;
  283.         else
  284.                 wfifo_clk_cnt <= wfifo_clk_cnt_n;
  285. end


  286. always @ (*)
  287. begin
  288.         if((fsm_cs == FSM_DATA)||(fsm_cs == FSM_CS0)||(fsm_cs == FSM_CS1)||(fsm_cs == FSM_IDLE))
  289.                 wfifo_clk_cnt_n <= wfifo_clk_cnt + 16'b1;
  290.         else if(fsm_cs == FSM_END)
  291.                 wfifo_clk_cnt_n <= 16'b0;
  292.         else
  293.                 wfifo_clk_cnt_n <= wfifo_clk_cnt;
  294. end

  295. always @ (posedge CLK_50M or negedge RST)
  296. begin
  297.         if(!RST)                                                                       
  298.                 wfifo_clk_n1 <= 0;
  299.         else
  300.                 wfifo_clk_n1 <= wfifo_clk_n2;
  301. end

  302. always @(*)
  303. begin
  304.         if((wfifo_clk_cnt == 16'd9504)||(wfifo_clk_cnt == 16'd19009)||(wfifo_clk_cnt == 16'd28513)||(wfifo_clk_cnt == 16'd38018))
  305.                 wfifo_clk_n2 <= ~wfifo_clk_n1;
  306.         else
  307.                 wfifo_clk_n2 <= wfifo_clk_n1;
  308. end

  309. always @(negedge wfifo_clk_n1 or negedge RST)
  310. begin
  311.         if(!RST)
  312.                 data_flag <= 1'b0;
  313.         else
  314.                 data_flag <= data_flag+1'b1;
  315. end

  316. always @(posedge wfifo_clk_n1 or negedge RST)
  317. begin
  318.         if(!RST)
  319.                 ADC_result <= 8'b0;
  320.         else if(data_flag == 1'b0)
  321.                 ADC_result <= ADC_DATA[15:8];
  322.         else
  323.                 ADC_result <= ADC_DATA[ 7:0];
  324. end

  325. endmodule
復(fù)制代碼

所有資料51hei提供下載:
ADS1118_FIFO_MODULE.zip (6.65 MB, 下載次數(shù): 80)




分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:234676 發(fā)表于 2017-12-21 21:52 | 只看該作者
學(xué)習(xí)一波
回復(fù)

使用道具 舉報

板凳
ID:360598 發(fā)表于 2018-6-27 21:22 | 只看該作者
希望對我有用,謝謝
回復(fù)

使用道具 舉報

地板
ID:360598 發(fā)表于 2018-7-4 06:30 | 只看該作者
解釋很詳細(xì),正好是我需要的,謝謝
回復(fù)

使用道具 舉報

5#
ID:818590 發(fā)表于 2020-9-13 19:44 | 只看該作者
正好要學(xué)習(xí)ADS1118,解釋很到位!
回復(fù)

使用道具 舉報

6#
ID:1042417 發(fā)表于 2023-8-30 14:04 | 只看該作者
可以實現(xiàn)多通道一塊采集嗎
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表