找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6364|回复: 5
收起左侧

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

[复制链接]
ID:264904 发表于 2017-12-21 16:55 | 显示全部楼层 |阅读模式
该资源为FPGA工程文件,基于Quartus II 15.1开发环境,使用verilog编写,备注详细。16bit四通道模数转换芯片ADS1118采集模拟电压信号(通道可选,电压范围可变),通过SPI接口和FPGA通信,数据在自己编写的异步FIFO缓存,经过UART接口,将数据传输至PC,使用串口调试助手可查看接收数据,经验证可在工程中使用。

0.png

源程序如下:
  1. //---------------------------------------------------------------------------
  2. //--        文件名                :        ADS1118_module.v
  3. //--        作者                :        Chen.s.y
  4. //--        描述                :        ADS1118模/数转换芯片驱动时序
  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配置数据(模拟通道0)0100_0101_1000_1010
  11. parameter ADS_config_AIN1=16'h558A;        //ADS1118配置数据(模拟通道1)0101_0101_1000_1010
  12. parameter ADS_config_AIN2=16'h658A;        //ADS1118配置数据(模拟通道2)0110_0101_1000_1010
  13. parameter ADS_config_AIN3=16'h758A;        //ADS1118配置数据(模拟通道3)0111_0101_1000_1010*/
  14. /*parameter ADS_config_AIN0=16'h448A;        //ADS1118配置数据(模拟通道0)0100_0100_1000_1010
  15. parameter ADS_config_AIN1=16'h548A;        //ADS1118配置数据(模拟通道1)0101_0100_1000_1010
  16. parameter ADS_config_AIN2=16'h648A;        //ADS1118配置数据(模拟通道2)0110_0100_1000_1010
  17. parameter ADS_config_AIN3=16'h748A;        //ADS1118配置数据(模拟通道3)0111_0100_1000_1010*/

  18. parameter ADS_config_AIN0=16'hC2E3;        //ADS1118配置数据(模拟通道0)1100_0010_1110_0011
  19. parameter ADS_config_AIN1=16'hC2E3;        //ADS1118配置数据(模拟通道1)0101_0100_1000_1010
  20. parameter ADS_config_AIN2=16'hE2E3;        //ADS1118配置数据(模拟通道2)1110_0010_1110_0011
  21. parameter ADS_config_AIN3=16'hE2E3;        //ADS1118配置数据(模拟通道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. //--        内部端口声明
  34. //---------------------------------------------------------------------------
  35. wire                                         DIN;                                        //AD串行数据输入
  36. reg                                        DIN_N;                                //DIN的下一个状态
  37. reg                                        CS;                                        //AD片选信号
  38. reg                                        CS_N;                                        //CS的下一个状态
  39. reg                                        SCLK;                                        //AD时钟,最大不超过4MHz,最小为35.71Hz,这里设置为2.5MHz
  40. reg                                        SCLK_N;                                //SCLK的下一个状态

  41. reg                [ 2:0]        fsm_cs;                                //状态机的当前状态
  42. reg                [ 2:0]        fsm_ns;                                //状态机的下一个状态


  43. reg                [ 11:0]        time_cnt;                        //用于记录一个时钟所用时间的定时器
  44. reg                [ 11:0]        time_cnt_n;                        //time_cnt的下一个状态
  45. reg                [ 4:0]        bit_cnt;                                //用来记录时钟周期个数的计数器
  46. reg                [ 4:0]        bit_cnt_n;                        //bit_cnt的下一个状态

  47. reg                 [ 1:0]        flag;                                        //用来标记四个通道采样的顺序
  48. reg                 [ 1:0]        flag_n;                                //flag的下一个状态

  49. reg                [15:0]        ADC_DATA;                        //用来保存稳定的16bit AD数据
  50. reg                [15:0]        ADC_DATA_n;                        //ADC_DATA的下一个状态
  51. reg                [15:0]        ad_data_reg;                //用于保存数据的移位寄存器
  52. reg                [15:0]        ad_data_reg_n;                //ad_data_reg的下一个状态

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

  54. reg                                        wfifo_clk_n1;                //fifo_wclk_n的下一个状态
  55. reg                                        wfifo_clk_n2;                //fifo_wclk_n的下一个状态
  56. reg                [15:0]        wfifo_clk_cnt;                //用于计数ADC_DATA的脉宽
  57. reg                [15:0]        wfifo_clk_cnt_n;        //wfifo_clk_cnt的下一个状态

  58. reg                                        data_flag;                        //16bit ADC数据拆分为8bit的标志
  59.                                                                                                 //1:发送低8位
  60.                                                                                                 //0:发送高八位
  61. reg                [ 7:0]        ADC_result;                        //拆分ADS芯片16bit的采样结果(便于串口传输)

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

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

  65. parameter        FSM_IDLE                        = 3'h0;        //状态机的初始状态
  66. parameter        FSM_CS0                        = 3'h1;        //CS下降沿到第一个SCK上升沿的等待状态,最小为值100ns
  67. parameter        FSM_DATA                        = 3'h2;        //读取16个数据状态
  68. parameter        FSM_CS1                        = 3'h3;        //最后一个SCK下降沿到CS上升沿的等待状态,最小为值100ns
  69. parameter        FSM_END                        = 3'h4;        //结束的状态

  70. //---------------------------------------------------------------------------
  71. //--        逻辑功能实现       
  72. //---------------------------------------------------------------------------
  73. //时序电路,用来给fsm_cs寄存器赋值
  74. always @ (posedge CLK_50M or negedge RST)
  75. begin
  76.         if(!RST)                                                                        //判断复位
  77.                 fsm_cs <= 1'b0;                                        //初始化ad_fsm_cs值
  78.         else
  79.                 fsm_cs <= fsm_ns;                                        //用来给ad_fsm_ns赋值
  80. end

  81. //组合电路,用来实现状态机
  82. always @ (*)
  83. begin
  84.         case(fsm_cs)                                                        //判断状态机的当前状态
  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;                        //完成就进入CS下降沿到第一个SCK上升沿的等待状态
  91.                         else
  92.                                 fsm_ns = fsm_cs;                        //否则保持原状态不变
  93.         //---------------------------------------------------------------------//
  94.                 FSM_CS0:
  95.                                                                                                 //2 x SCLK_TIME 用于等待延时
  96.                         if((bit_cnt == 5'd1 ) && (time_cnt == `SCLK_TIME))
  97.                                 fsm_ns = FSM_DATA;                //完成就进入读取数据状态
  98.                         else
  99.                                 fsm_ns = fsm_cs;                  //否则保持原状态不变

  100.         //---------------------------------------------------------------------//
  101.                 FSM_DATA:
  102.                                                                                                 //读取数据16位,1~16个时钟脉冲
  103.                         if((bit_cnt == 5'd16 ) && (time_cnt == `SCLK_TIME))
  104.                                 fsm_ns = FSM_CS1;                        //如果读取数据状态完成就进入结束状态
  105.                         else
  106.                                 fsm_ns = fsm_cs;                        //否则保持原状态不变               
  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;                        //完成就进入结束状态
  113.                         else
  114.                                 fsm_ns = fsm_cs;                  //否则保持原状态不变
  115.         //---------------------------------------------------------------------//
  116.                 FSM_END:                                                               
  117.                                 fsm_ns = FSM_IDLE;                //完成一次数据转换,进入下一次转换
  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)                                                                        //判断复位
  126.                 time_cnt <= 12'h0;                                        //初始化time_cnt值
  127.         else
  128.                 time_cnt <= time_cnt_n;                        //用来给time_cnt赋值
  129. end

  130. //组合电路,实现SCLK_TIME的定时计数器
  131. always @ (*)
  132. begin
  133.         if(time_cnt == `SCLK_TIME)                        //判断SCLK_TIME时间
  134.                 time_cnt_n = 12'h0;                                //如果到达SCLK_TIME,定时器清零
  135.         else
  136.                 time_cnt_n = time_cnt + 12'h1;        //如果未到SCLK_TIME,定时器继续加1
  137. end

  138. //时序电路,用来给bit_cnt寄存器赋值
  139. always @ (posedge CLK_50M or negedge RST)
  140. begin
  141.         if(!RST)                                                                        //判断复位
  142.                 bit_cnt <= 5'h0;                                        //初始化bit_cnt值
  143.         else
  144.                 bit_cnt <= bit_cnt_n;                        //用来给bit_cnt赋值
  145. end

  146. //组合电路,用来记录时钟周期个数的计数器
  147. always @ (*)
  148. begin
  149.         if(fsm_cs != fsm_ns)                                        //判断状态机的当前状态
  150.                 bit_cnt_n = 5'h0;                                        //如果当前的状态不等于下一个状态,计时器就清零
  151.         else if(time_cnt == `SCLK_TIME_HALF)//判断SCLK_TIME_HALF时间
  152.                 bit_cnt_n = bit_cnt + 5'b1;        //如果到达SCLK_TIME_HALF,计数器就加1
  153.         else
  154.                 bit_cnt_n = bit_cnt;                                //否则计数器保持不变
  155. end

  156. //时序电路,用来给AD_CLK寄存器赋值
  157. always @ (posedge CLK_50M or negedge RST)
  158. begin
  159.         if(!RST)                                                                        //判断复位
  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;                                                //如果当前的状态不等于读取数据状态,SCLK_N就置0
  169.         else if(time_cnt == `SCLK_TIME_HALF)//判断SCLK_TIME_HALF时间
  170.                 SCLK_N = 1'h1;                                                //如果到达SCLK_TIME_HALF,SCLK_N就置1
  171.         else if(time_cnt == `SCLK_TIME)        //判断SCLK_TIME时间
  172.                 SCLK_N = 1'h0;                                                //如果到达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)                                                                        //判断复位
  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的状态
  189.         else
  190.                 CS_N = 1'h1;                                                //CS置0的状态
  191. end

  192. //时序电路,用来给ad_data_reg寄存器赋值
  193. always @ (posedge CLK_50M or negedge RST)
  194. begin
  195.         if(!RST)                                                                        //判断复位
  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线上的数据保存到移位寄存器中
  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.                                                                                                 //将数据存入移位寄存器中,高位优先
  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)                                                                        //判断复位
  214.                 ADC_DATA <= 0;                                                //初始化data_out值
  215.         else
  216.                 ADC_DATA <= ADC_DATA_n;                        //用来给data_out赋值
  217. end

  218. //组合电路,将移位寄存器中的数据存入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)                                                                        //判断复位
  267.                 flag <= 2'b0;                                        //初始化bit_cnt值
  268.         else
  269.                 flag <= flag_n;                                //用来给bit_cnt赋值
  270. end

  271. //组合电路,用来记录时钟周期个数的计数器
  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
复制代码

所有资料51hei提供下载:
ADS1118_FIFO_MODULE.zip (6.65 MB, 下载次数: 80)
回复

使用道具 举报

ID:234676 发表于 2017-12-21 21:52 | 显示全部楼层
学习一波
回复

使用道具 举报

ID:360598 发表于 2018-6-27 21:22 | 显示全部楼层
希望对我有用,谢谢
回复

使用道具 举报

ID:360598 发表于 2018-7-4 06:30 | 显示全部楼层
解释很详细,正好是我需要的,谢谢
回复

使用道具 举报

ID:818590 发表于 2020-9-13 19:44 | 显示全部楼层
正好要学习ADS1118,解释很到位!
回复

使用道具 举报

ID:1042417 发表于 2023-8-30 14:04 | 显示全部楼层
可以实现多通道一块采集吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表