找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4608|回复: 6
打印 上一主题 下一主题
收起左侧

stm32驱动ads1115读数不准问题

[复制链接]
跳转到指定楼层
楼主
ID:377519 发表于 2019-8-3 14:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这几天尝试用stm32驱动ads1115,是直接从淘宝买的模块,驱起来读数时而看起来准(和手持万用表测出来的差不多),时而不准,误差非常大,不知道是为什么。个人感觉程序没什么问题,会不会是硬件问题?因为我是用杜邦线接到开发板上的(正点原子的精英板),供电也用的是开发板上的3.3v,会不会是开发板3.3不稳定导致内部基准不稳导致的?下面贴上程序,希望有大神可以帮忙看看。

STM32单片机源程序如下:
  1. #include "ads1115.h"
  2. #include "delay.h"


  3. u16 Ads1115_Config;                                                        //存放ADS1115配置寄存器的配置
  4. u8 Ads1115_Result[2];                                         //存放ADS1115转换寄存器的数据
  5. u8 Writebuff[4],Readbuff[3];                //写数据的命令和读数据的命令缓存数组

  6. u16 ads1115_average_data[4];                //获取到的4个通道的经过滤波的后的值
  7. u16 filter_ave_buf[4][201];                        //滤波的数据
  8. u32 filter_sum_buf[4];                                        //数据总和
  9. u8 ch_count;                                                                                //通道数


  10. //初始化ADS1115的IO
  11. void ADS1115_Init(void)
  12. {                                             
  13.         GPIO_InitTypeDef GPIO_InitStructure;
  14.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );                //使能PB端口时钟
  15.           
  16.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15;                //PB13 PB15
  17.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;                           //推挽输出
  18.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                        //输出最大速度50MHz
  19.         GPIO_Init(GPIOB, &GPIO_InitStructure);                                                                                //初始化GPIOB

  20.         ADS1115_SCL=1;
  21.         ADS1115_SDA=1;
  22. }

  23. //********************************************
  24. //函数名称:ADS1115_Start
  25. //功    能:完成IIC的起始条件操作
  26. //参    数:无
  27. //返回值  :无
  28. //********************************************/
  29. void ADS1115_Start(void)
  30. {
  31.         ADS1115_SDA_OUT();                //sda线输出
  32.   ADS1115_SDA=1;
  33.   ADS1115_SCL=1;
  34.   delay_us(2);
  35.         ADS1115_SDA=0;                                //START:when CLK is high,DATA change form high to low
  36.   delay_us(2);
  37.         ADS1115_SCL=0;                                //钳住I2C总线,准备发送或接收数据
  38.         delay_us(2);
  39. }

  40. //********************************************
  41. //函数名称:ADS1115_Stop
  42. //功    能:完成IIC的终止条件操作
  43. //参    数:无
  44. //返回值  :无
  45. //********************************************/
  46. void ADS1115_Stop(void)
  47. {
  48.         ADS1115_SDA_OUT();                //sda线输出
  49.         ADS1115_SCL=0;
  50.   ADS1115_SDA=0;                                //STOP:when CLK is high,DATA change form low to high
  51.   delay_us(2);
  52.   ADS1115_SCL=1;
  53.   delay_us(2);
  54.         ADS1115_SDA=1;                                //发送I2C总线结束信号
  55.         delay_us(2);
  56. }

  57. //********************************************
  58. //函数名称:ADS1115_ACK
  59. //功    能:完成IIC的主机应答操作
  60. //参    数:无
  61. //返回值  :无
  62. //********************************************/
  63. void ADS1115_ACK(void)
  64. {
  65.         ADS1115_SCL=0;
  66.         ADS1115_SDA_OUT();                //sda线输出
  67.   ADS1115_SDA=0;
  68.   delay_us(2);
  69.   ADS1115_SCL=1;
  70.   delay_us(2);
  71.   ADS1115_SCL=0;
  72. }

  73. //********************************************
  74. //函数名称:ADS1115_NACK
  75. //功    能:完成IIC的主机无应答操作
  76. //参    数:无
  77. //返回值  :无
  78. //********************************************/
  79. void ADS1115_NACK(void)
  80. {
  81.         ADS1115_SCL=0;
  82.         ADS1115_SDA_OUT();                //sda线输出
  83.         ADS1115_SDA=1;
  84.         delay_us(2);
  85.         ADS1115_SCL=1;
  86.   delay_us(2);
  87.   ADS1115_SCL=0;      
  88. }

  89. //**********检查应答信号函数******************/
  90. ///*如果返回值为1则证明有应答信号,反之没有*/
  91. ///*******************************************
  92. //函数名称:ADS1115_Check
  93. //功    能:检查从机的应答操作
  94. //参    数:无
  95. //返回值  :从机是否有应答:1--有,0--无
  96. //********************************************/
  97. u8 ADS1115_Check(void)
  98. {
  99.         u8 slave_ack;
  100.   ADS1115_SDA_IN();
  101.   ADS1115_SDA=1;
  102.   delay_us(1);
  103.   ADS1115_SCL=1;
  104.   delay_us(1);
  105.   slave_ack = ADS1115_READ_SDA;   //读入SDA数值
  106.   ADS1115_SCL=0;
  107.   delay_us(3);
  108.         if(slave_ack)return FALSE;
  109.         else         return TRUE;
  110. }

  111. /***************Write a Byte****************/
  112. void Write_1_Byte(u8 DataByte)
  113. {
  114.         u8 i;
  115.         ADS1115_SDA_OUT();                //sda线输出
  116.         for(i=0;i<8;i++)
  117.         {
  118.                 if(DataByte&0x80)  
  119.                         ADS1115_SDA=1;
  120.                 else
  121.                         ADS1115_SDA=0;
  122.                 delay_us(3);
  123.                 ADS1115_SCL=1;
  124.                 delay_us(3);
  125.                 ADS1115_SCL=0;
  126.                 delay_us(2);
  127.                 DataByte <<= 1;
  128.         }
  129.         ADS1115_SDA=1;
  130.         delay_us(2);
  131. }

  132. /***************Write N Byte****************/
  133. u8 Write_N_Byte(u8 *writebuffer,u8 n)
  134. {
  135.         u8 i;
  136.         ADS1115_SDA_OUT();                //sda线输出
  137.         for(i=0;i<n;i++)
  138.         {
  139.                 Write_1_Byte(*writebuffer);
  140.                 if(ADS1115_Check())
  141.                         writebuffer++;
  142.                 else
  143.                 {
  144.                         ADS1115_Stop();
  145.                   return FALSE;
  146.                 }
  147.         }
  148.         ADS1115_Stop();
  149.         return TRUE;
  150. }

  151. //***************Read a Byte****************/
  152. u8 Read_1_Byte(void)
  153. {
  154.         u8 data_Value=0,i;
  155.         for(i=0;i<8;i++)
  156.         {
  157.                 ADS1115_SDA_OUT();                //sda线输出
  158.                 ADS1115_SDA=1;
  159.                 delay_us(3);
  160.                 ADS1115_SCL=1;
  161.                 delay_us(3);
  162.                 ADS1115_SDA_IN();
  163.                 data_Value<<= 1;
  164.                 if(ADS1115_READ_SDA)
  165.                         data_Value++;
  166.                 ADS1115_SCL=0;
  167.                 delay_us(2);
  168.         }
  169.         return data_Value;
  170. }

  171. //***************Read N Byte****************/
  172. void Read_N_Byte(u8*readbuff, u8 n)
  173. {
  174.         u8 i;       
  175.         for(i=0;i<n;i++)
  176.         {
  177.                 readbuff[i]=Read_1_Byte();
  178.                 if(i==n-1)
  179.                         ADS1115_NACK();  //不连续读字节
  180.                 else
  181.                         ADS1115_ACK();         //连续读字节
  182.         }
  183.         ADS1115_Stop();
  184. }

  185. //***************Write a Word***********************/
  186. void WriteWord(void)
  187. {
  188.         u8 t;
  189.         ADS1115_Start();   //写入4个字节
  190.         do
  191.         {
  192.                 t=Write_N_Byte(Writebuff,4);
  193.         }while(t==0);
  194. }

  195. //***************Read Word***********************/
  196. void ReadWord(void)
  197. {
  198.         u8 t;
  199.         ADS1115_Start();          //写入2个字节
  200.         do
  201.         {
  202.                 t=Write_N_Byte(Readbuff,2);
  203.         }while(t==0);
  204.         ADS1115_Start();   //写入1个字节
  205.         do
  206.         {
  207.                 t=Write_N_Byte(&Readbuff[2],1);
  208.         }while(t==0);
  209.         Read_N_Byte(Ads1115_Result,2);  //读出2个字节
  210. }

  211. //***************ADS1115********************/
  212. u16 ADS1115_Get_Data(u8 ch)
  213. {
  214.         u16 result;
  215.         if(ch==0)
  216.                 Ads1115_Config = OS+MUX_A0+PGA+DR+COMP_QUE+MODE;
  217.         else if(ch==1)
  218.                 Ads1115_Config = OS+MUX_A1+PGA+DR+COMP_QUE+MODE;
  219.         else if(ch==2)
  220.                 Ads1115_Config = OS+MUX_A2+PGA+DR+COMP_QUE+MODE;
  221.         else if(ch==3)
  222.                 Ads1115_Config = OS+MUX_A3+PGA+DR+COMP_QUE+MODE;   
  223.         Writebuff[0]=ADDRESS_W;                                                        //写地址
  224.         Writebuff[1]=Pointer_1;                                                        //写配置寄存器
  225.         Writebuff[2]=Ads1115_Config/256;                //写配置
  226.         Writebuff[3]=Ads1115_Config%256;
  227.                        
  228.         Readbuff[0]=ADDRESS_W;                                                        //写地址
  229.         Readbuff[1]=Pointer_0;                                                        //读转换寄存器                       
  230.         Readbuff[2]=ADDRESS_R;                                                        //读地址

  231.         WriteWord();
  232.         delay_ms(1);
  233.         ReadWord();
  234.        
  235.   result=Ads1115_Result[0]*256+Ads1115_Result[1];  //转换的数字量
  236.   return result;
  237. }

  238. /*-----------------------------------------------------------------------------------------------
  239.         名称:中位值滤波法       
  240.         方法:连续采样N次(N取奇数),把N次采样值按大小排列,取中间值为本次有效值。
  241.         优点:能有效克服因偶然因素引起的波动干扰,对温度、液体的变化缓慢的被测参数有良好的滤波效果。
  242.         缺点:对流量、速度等快速变化的参数不宜。
  243.         出口参数:filter_buf[50]
  244. ------------------------------------------------------------------------------------------------*/
  245. //void ADS1115_Process(void)                                               
  246. //{       
  247. //        u16 filter_buf[101];
  248. //  u16 i, j;
  249. //  u16 filter_temp;       
  250. //        for(i = 0; i < 101; i++)
  251. //        {
  252. //    filter_buf[i] = ADS1115_Get_Data(1);
  253. //  }
  254. //        for(j = 0; j < 100; j++)
  255. //        {
  256. //    for(i = 0; i < 100 - j; i++)                                 //将 100-j 个数中取最大的放在数组的最后(100-j)
  257. //                {
  258. //      if(filter_buf[i] > filter_buf[i + 1]) //数组右边的小于左边的
  259. //                        {
  260. //        filter_temp = filter_buf[i];
  261. //        filter_buf[i] = filter_buf[i + 1];        //将小的放在左边
  262. //        filter_buf[i + 1] = filter_temp;                //将大的放在右边
  263. //      }
  264. //    }
  265. //  }
  266. //        ads1115_average_data[1] = filter_buf[50];
  267. //}
  268.        
  269. /*-----------------------------------------------------------------------------------------------
  270.         名称:递推平均滤波法(又称滑动平均滤波法)       
  271.         方法:把连续取得的N个采样值看成一个队列,队列的长度固定为N,
  272.                                 每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则),
  273.                                 把队列中的N个数据进行算术平均运算,获得新的滤波结果。
  274.         优点:对周期性干扰有良好的抑制作用,平滑度高,适用于高频震荡的系统。
  275.         缺点:灵敏度低,对偶然出现的脉冲性干扰的抑制作用较差,不易消除由于脉冲干扰所引起的采样值偏差,
  276.                                 不适用于脉冲干扰比较严重的场合,比较浪费RAM。
  277.         出口参数:filter_sum_buf/200
  278. ------------------------------------------------------------------------------------------------*/
  279. void ADS1115_Process(void)       
  280. {
  281.         u8 i;
  282.         filter_ave_buf[ch_count][200]=ADS1115_Get_Data(ch_count);                                                //读出一个数据放在数组最右边
  283.         for(i = 0; i < 200; i++)                                                                                                                                                                                 //200个数据取平均
  284.         {
  285.                 filter_ave_buf[ch_count][i] = filter_ave_buf[ch_count][i + 1];                 //所有数据左移,低位扔掉
  286.                 filter_sum_buf[ch_count] += filter_ave_buf[ch_count][i];                                        //求出200个数据总和
  287.         }       
  288.         ads1115_average_data[ch_count]=filter_sum_buf[ch_count]/200;                                //得到平均值
  289.         filter_sum_buf[ch_count]=0;                //清总和
  290.         ch_count++;                                                                                //切换下个通道,共4通道
  291.         if(ch_count>=4)
  292.                 ch_count=0;
  293. }


  294. void read(u8 ch)
  295. {
  296.        
  297. }
复制代码

所有资料51hei提供下载:
F1-ADS1115例程.7z (231.58 KB, 下载次数: 83)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:388197 发表于 2019-8-4 02:07 | 只看该作者
没记错的话,ADS1115的基准电压好像是内部的.并不是以电源电压为基准电压的.好像有4.096V 2.048V之类的可选,具体怎么设置不太记得了,你找个例程对照手册看看就知道了.
回复

使用道具 举报

板凳
ID:377519 发表于 2019-8-4 10:18 | 只看该作者
cjm82 发表于 2019-8-4 02:07
没记错的话,ADS1115的基准电压好像是内部的.并不是以电源电压为基准电压的.好像有4.096V 2.048V之类的可选, ...

我找了很久都没找到好使的例程,要么数都读不到,要么也是和我一样的问题,我换了一个模块还这样
回复

使用道具 举报

地板
ID:388197 发表于 2019-8-4 12:31 | 只看该作者
基佬霍夫 发表于 2019-8-4 10:18
我找了很久都没找到好使的例程,要么数都读不到,要么也是和我一样的问题,我换了一个模块还这样

怎么会呢,本论坛应该就有ADS1115的例程了
回复

使用道具 举报

5#
ID:273656 发表于 2019-9-26 16:51 | 只看该作者
请问楼主最后怎么解决的?我也遇到了类似问题,时钟采不到数,谢谢啦
回复

使用道具 举报

6#
ID:273656 发表于 2019-9-26 17:01 | 只看该作者
请问解决了吗
回复

使用道具 举报

7#
ID:273656 发表于 2019-10-11 17:42 | 只看该作者
采样3.3V电压误差约0.07V,若AD输入接地,误差最大有0.16V,楼主问题解决了吗。谢谢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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