找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机+ADS1115读数据异常,求助高手帮忙解决

[复制链接]
跳转到指定楼层
楼主
本帖最后由 七彩的梦想 于 2025-6-5 23:44 编辑

最近心血来潮买了几个ADS1115模块,想找个时间测验证一下。发现模块配送的资料是Arduino平台,手头没有Arduino硬件,只有STC8G1K08单片机,于是在本论坛找了个现成的51系列的ADS1115代码修修改改发现基本能用,但是读数据有点问题,15位数据的低4位无法正常读取,一直为0,用逻辑分析仪看了数据波形是正常的没发现问题在哪。折腾了好几天还是没能解决。我已经排除过硬件是没有问题的,问题应该还是出在软件上,望论坛里的高手帮忙看看指点我一下。谢谢!
ADS1115配置为:单端输入, A0端口输入0---5V   满量程配置为4.096V  正常转换范围0---32767现在异常转换值范围是这样的:0,16,32,48,64,80,96,112,,,,,,,,32752。随着电压增加 AD转换值以每16个LSB跳跃累加。

问题重点:低4位数据读回来一直为0


以下是用逻辑分析仪采集的波形图

异常波形图

波形图1



波形图2



波形图3



波形图4



波形图5



大于0的第一个值




对应波形图5数据显示



最大值




最小值




硬件连接


代码部分:
  1. /*******************************************************************************************************************************************************************
  2. /*ADS1115+TM1637例程
  3. /*本示例在STC8G1K08A验证暂不OK
  4. /*工作频率11.0592MHz
  5. /*编辑日期:2025/05/26,星期一,00:10
  6. *********************************************************************************************************************************************************************/
  7.   #include<AI8G.h>//STC8G系列头文件
  8.   #define uchar unsigned char  //0---255
  9.   #define uint  unsigned int   //0---65535      
  10.   #define ulong unsigned long  //0---4294967295  
  11.                
  12. ///==================================================================================================================================================================
  13.    bit  Bit0,Bit1,Bit2,Bit3,Bit4,Bit5,Bit6,Bit7,K1_flag,K2_flag,K3_flag,K4_flag,switch_CHN;//8个位变量,对应LED1---LED8 ,5个按键标志位
  14.         sbit  SCL=P3^2;//ADS1115时钟线
  15.   sbit  SDA=P3^3;//ADS1115数据线
  16.   sbit  clk = P5^4;//TM1637时钟端口
  17.   sbit  dio = P5^5;//TM1637数据端口
  18.   uchar buf[6];//6个数码管缓存区
  19.         int D_ADS;   //转换的数字量
  20.   uint Config;//
  21.   uint Result[2];//
  22.   uchar Writebuff[4],Readbuff[3];//
  23.         
  24. ///==================================================================================================================================================================        
  25. #define TRUE        1    //真
  26. #define FALSE       0    //假
  27. #define ADDRESS_0  0x90  //ADDR PIN ->GND
  28. #define ADDRESS_1  0x92  //ADDR PIN ->VDD
  29. #define ADDRESS_2  0x94  //ADDR PIN ->SDA
  30. #define ADDRESS_3  0x96  //ADDR PIN ->SCL

  31. /************POINTERREGISTER*****************/
  32. #define Pointer_0  0x00  //Convertion register
  33. #define Pointer_1  0x01  //Config register
  34. #define Pointer_2  0x02  //Lo_thresh register
  35. #define Pointer_3  0x03  //Hi_thresh register

  36. /************CONFIG REGISTER*****************/
  37. #define OS_0   0x0000
  38. #define OS_1   0x8000
  39. #define MUX_0  0x0000 //AINp=AIN0, AINn=AIN1
  40. #define MUX_1  0x1000 //AINp=AIN0, AINn=AIN3
  41. #define MUX_2  0x2000 //AINp=AIN1, AINn=AIN3
  42. #define MUX_3  0x3000 //AINp=AIN2, AINn=AIN3
  43. #define MUX_4  0x4000 //AINp=AIN0, AINn=GND
  44. #define MUX_5  0x5000 //AINp=AIN1, AINn=GND
  45. #define MUX_6  0x6000 //AINp=AIN2, AINn=GND
  46. #define MUX_7  0x7000 //AINp=AIN3, AINn=GND

  47. #define PGA_0  0x0000  //FS=6.144V
  48. #define PGA_1  0x0200  //FS=4.096V
  49. #define PGA_2  0x0400  //FS=2.048V
  50. #define PGA_3  0x0600  //FS=1.024V
  51. #define PGA_4  0x0800  //FS=0.512V
  52. #define PGA_5  0x0A00  //FS=0.256V
  53. #define PGA_6  0x0C00  //FS=0.256V
  54. #define PGA_7  0x0E00  //FS=0.256V

  55. #define MODE_0 0x0000  //
  56. #define MODE_1 0x0100  //

  57. #define DR_0   0x0000  //Data Rate = 8
  58. #define DR_1   0x0020  //Data Rate = 16
  59. #define DR_2   0x0040  //Data Rate = 32
  60. #define DR_3   0x0060  //Data Rate = 64
  61. #define DR_4   0x0080  //Data Rate = 128
  62. #define DR_5   0x00A0  //Data Rate = 250
  63. #define DR_6   0x00C0  //Data Rate = 475
  64. #define DR_7   0x00E0  //Data Rate = 860

  65. #define COMP_MODE_0  0x0000
  66. #define COMP_MODE_1  0x0010
  67. #define COMP_POL_0   0x0000
  68. #define COMP_POL_1   0x0008
  69. #define COMP_LAT_0   0x0000
  70. #define COMP_LAT_1   0x0040
  71. #define COMP_QUE_0   0x0000
  72. #define COMP_QUE_1   0x0001
  73. #define COMP_QUE_2   0x0002
  74. #define COMP_QUE_3   0x0003

  75. //*************ADDRInitial********************/
  76. #define ADDRESS    ADDRESS_0    //ADDR PIN ->GND
  77. #define ADDRESS_W  ADDRESS|0x00 //写地址
  78. #define ADDRESS_R  ADDRESS|0x01 //读地址

  79. /*************ConfigInitial*********************/
  80. #define OS         OS_1
  81. #define MUX_A0     MUX_4     //AINp=AIN0, AINn=GND
  82. #define MUX_A1     MUX_5     //AINp=AIN1, AINn=GND
  83. #define MUX_A2     MUX_6     //AINp=AIN2, AINn=GND
  84. #define MUX_A3     MUX_7     //AINp=AIN3, AINn=GND
  85. #define PGA        PGA_1     //FS=4.096V分辨率
  86. #define MODE       MODE_1    //Continuous conversion mode
  87. #define DR         DR_0      //Data Rate = 8 转换速率
  88. #define COMP_QUE   COMP_QUE_3
  89. ///==================================================================================================================================================================
  90. void Delay_us(unsigned int i) //N_us 微秒延时
  91. {
  92.   for(;i>0;i--);
  93. }        

  94. ///==================================================================================================================================================================
  95. void Start(void)//IIC开始
  96. {
  97.    SDA=1;
  98.    SCL=1;
  99.          Delay_us (1);
  100.    SDA=0;
  101.          Delay_us (5);
  102.    SCL=0;
  103.    _nop_();  _nop_();
  104.          _nop_();  _nop_();
  105.          _nop_();  _nop_();
  106.          _nop_();  _nop_();
  107. }

  108. ///==================================================================================================================================================================
  109. void Stop(void)//IIC停止
  110. {
  111.         //Delay_us (1);
  112.    SCL=1;
  113.    Delay_us (2);
  114.    SDA=1;
  115. //        Delay_us (5);
  116. //   SCL=0;
  117. //   Delay_us (5);//00&91中间波形
  118. //         SDA=0;
  119. }

  120. ///==================================================================================================================================================================
  121. void ACK(void)//IIC应答 7F&F0中间波形
  122. {
  123.    _nop_();
  124.          _nop_();
  125.    SDA=0;
  126.    _nop_();
  127.          _nop_();
  128.    SCL=1;
  129.    Delay_us (4);
  130.    SCL=0;
  131.    SDA=1;
  132. }

  133. ///==================================================================================================================================================================
  134. void NACK(void)//IIC无应答
  135. {
  136.    unsigned int x;
  137.    for(x=1;x>0;x--);
  138.    SDA=1;
  139.    _nop_();
  140.          _nop_();
  141.    SCL=1;
  142.    Delay_us (4);
  143.    SCL=0;
  144.    _nop_();
  145.          _nop_();
  146.    SDA=0;   
  147.    Delay_us (2);      
  148. }

  149. ///==================================================================================================================================================================
  150. unsigned char Check(void)//检查从机是否有应答:1--有,0--无
  151. {
  152.    unsigned char slaveack;
  153.    SDA=1;
  154.    _nop_();
  155.           _nop_();
  156.   _nop_();
  157.    SCL=1;
  158.    slaveack = SDA;   //读入SDA数值
  159.          Delay_us (5);//90&01中间波形
  160.    SCL=0;
  161.    //Delay_us (1);
  162.    if(slaveack)  
  163.          return FALSE;
  164.    else            
  165.          return TRUE;
  166. }

  167. ///==================================================================================================================================================================
  168. void Write_1_Byte(unsigned char DataByte)//写一字节
  169. {
  170.    int i;
  171.          SCL=0;
  172.         
  173.     for(i=0;i<8;i++)
  174.     {
  175.       if(DataByte&0x80)  //if((DataByte<<i)&0x80)
  176.       SDA=1;
  177.       else
  178.                         SDA=0;
  179.                         DataByte <<= 1;
  180.       SCL=1;
  181.       Delay_us (5);//
  182.       SCL=0;
  183.       Delay_us (3);//
  184.     }
  185.       SDA=1;
  186.                
  187. }

  188. ///==================================================================================================================================================================
  189. unsigned char Write_N_Byte(unsigned char*writebuffer,unsigned char n)//写多字节
  190. {
  191.     int i;
  192.     for(i=0;i<n;i++)
  193.     {
  194.       Write_1_Byte(*writebuffer);
  195.       if(Check())
  196.       {
  197.         writebuffer++;
  198.       }
  199.       else
  200.       {
  201.         Stop();
  202.                                 return FALSE;
  203.       }
  204.     }
  205.                 Delay_us (1);//
  206.         Stop();
  207.         return TRUE;
  208. }

  209. ///==================================================================================================================================================================
  210. unsigned char Read_1_Byte(void)//读一字节
  211. {
  212.    unsigned char data_Value = 0, FLAG, i;  
  213.         for(i=0;i<8;i++)
  214.    {     
  215.      SDA=1;
  216.      Delay_us (3);
  217.      SCL=1;
  218.      Delay_us (3);
  219.      FLAG=SDA;
  220.      data_Value <<= 1;
  221.      if(FLAG)
  222.      data_Value |= 0x01;
  223.      SCL=0;
  224.                  _nop_();_nop_();
  225.                  _nop_();_nop_();
  226.                  _nop_();_nop_();
  227.     }

  228.    return data_Value;
  229. }

  230. ///==================================================================================================================================================================
  231. void Read_N_Byte(unsigned int*readbuff,unsigned char n)//读多字节
  232. {
  233.     unsigned char i;
  234.     for(i=0;i<n;i++)
  235.     {
  236.       readbuff[i]=Read_1_Byte();
  237.       if(i==n-1)
  238.       NACK();  //不连续读字节
  239.       else                        
  240.       ACK();//连续读字节
  241.     }
  242.       Stop();
  243. }

  244. ///==================================================================================================================================================================
  245. void WriteWord(void)//写一个Word
  246. {
  247.     int t;
  248.     Start();   //写入4个字节
  249.     do
  250.     {
  251.       t=Write_N_Byte(Writebuff,4);
  252.     }
  253.                 while(t==0);
  254.                 Stop();
  255. }

  256. ///==================================================================================================================================================================
  257. void ReadWord(void)//读Word
  258. {
  259.    int t;
  260.         
  261.    Start();  //写入2个字节
  262.    do
  263.    {
  264.      t=Write_N_Byte(Readbuff,2);
  265.    }
  266.                  while(t==0);
  267.      Start();   //写入2个字节
  268.    do
  269.    {
  270.      t=Write_N_Byte(&Readbuff[2],1);
  271.    }
  272.                  while(t==0);
  273.          
  274.      Read_N_Byte(Result,2);  //读出2个字节
  275. }

  276. ///==================================================================================================================================================================
  277. void InitADS1115(bit S_MUX_0, bit S_MUX_1)//ADS1115初始化
  278. {      
  279.    if(S_MUX_0 == 0 && S_MUX_1 == 0)         //AIN0
  280.    Config= OS+MUX_A0+PGA+DR+COMP_QUE+MODE;//【OS=1开始ADC转换】+【MUX_A0通道0】+【PGA 电压量程FS=4.096】+【DR总线数据速率】+【COMP_QUE ALERT引脚输出配置】+【MODE=0x0000 连续转换 MODE=0x0100单次转换】;

  281.    if(S_MUX_0 == 0 && S_MUX_1 == 1)         //AIN1
  282.    Config= OS+MUX_A1+PGA+DR+COMP_QUE+MODE;//【OS=1开始ADC转换】+【MUX_A0通道0】+【PGA 电压量程FS=4.096】+【DR总线数据速率】+【COMP_QUE ALERT引脚输出配置】+【MODE=0x0000 连续转换 MODE=0x0100单次转换】;

  283.    if(S_MUX_0 == 1 && S_MUX_1 == 0)         //AIN2
  284.    Config= OS+MUX_A2+PGA+DR+COMP_QUE+MODE;//【OS=1开始ADC转换】+【MUX_A0通道0】+【PGA 电压量程FS=4.096】+【DR总线数据速率】+【COMP_QUE ALERT引脚输出配置】+【MODE=0x0000 连续转换 MODE=0x0100单次转换】;

  285.    if(S_MUX_0 == 1 && S_MUX_1 == 1)         //AIN3
  286.    Config= OS+MUX_A3+PGA+DR+COMP_QUE+MODE;//【OS=1开始ADC转换】+【MUX_A0通道0】+【PGA 电压量程FS=4.096】+【DR总线数据速率】+【COMP_QUE ALERT引脚输出配置】+【MODE=0x0000 连续转换 MODE=0x0100单次转换】;

  287.    Writebuff[0]=ADDRESS_W;//写数据,从机地址0x90(最低位bit0决定读写操作R/W 0读 1写)
  288.    Writebuff[1]=Pointer_1;//数据要写入的寄存器地址(地址指针,0x01)
  289.    Writebuff[2]=Config/256;//参数配置寄存器高8位【对应OS,MUX,PGA,MODE】
  290.    Writebuff[3]=Config%256;//参数配置寄存器低8位【对应DR,COMP_MODE,COMP_POL,COMP_LAT,COMP_QUE】
  291.      
  292.    Readbuff[0]=ADDRESS_W;//写数据,从机地址0x90(最低位bit0决定读写操作R/W 0读 1写)
  293.    Readbuff[1]=Pointer_0;//数据要写入的寄存器地址(地址指针,0x00)  
  294.    Readbuff[2]=ADDRESS_R;//读数据,从机地址0x91(最低位bit0决定读写操作R/W 0读 1写)
  295. }

  296. ///==================================================================================================================================================================
  297. unsigned int ADS1115(bit S_MUX_0, bit S_MUX_1)//从指定AD输入通道读取AD转换值
  298. {
  299.    InitADS1115(S_MUX_0, S_MUX_1);
  300.    WriteWord();
  301.    ReadWord();      
  302.    D_ADS=Result[0]*256+Result[1];   //转换的数字量
  303.    return D_ADS;
  304. }        

  305. ///==================================================================================================================================================================        
  306.   uint ADC_operation()//ADC数据运算处理
  307.   {
  308.                 static unsigned char count = 0;//ADC采样次数,计数
  309.     static unsigned long sum   = 0;//ADC采样总数,“和”
  310.     static unsigned int AD_Value = 0;//处理好的平均值
  311.                 static unsigned int AD_temp  = 0;//未处理的AD值
  312.                
  313.                 AD_Value=ADS1115(0,0);    //ADS1115取值_AIN0
  314.         //AD_temp=ADS1115(0,0);    //ADS1115取值_AIN0
  315.         //AD_Value=Result[0];//调试用
  316.          //AD_Value=Result[1];//调试用
  317. //                Delay_us (5);
  318.                
  319. //    if(count < 100)//如果采集次数小于100
  320. //                {
  321. //      sum += AD_temp;//AD值累计
  322. //      count++;//采样计数加一
  323. //    }
  324. //               
  325. //    if(count >= 100)//如果采集次数大于等于100
  326. //                {
  327. //      AD_Value = sum / 100;//总数“和”除100,虑除波动值
  328. //      count = 0;//采集次数清零
  329. //      sum   = 0;//总数“和”变量清零
  330. //    }        
  331.                         return AD_Value;//返回处理好的AD值
  332.         }

  333. ///==================================================================================================================================================================        
  334.                                                        /* 往下是TM1637代码区域 */
  335. ///==================================================================================================================================================================        

  336.   uchar key_data,key_value;//按键处理过程变量
  337.   uint  Display;//待显示数据
  338.   uchar code SMG_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};//0-F编码表
  339. //uchar code key_table[]={0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef};//key1--key16按键倒序识别码
  340.   uchar code key_table[]={0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0,0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8};//key1--key16按键顺序识别码
  341.         
  342. ///==================================================================================================================================================================
  343.         void init() //初始化函数
  344.         {
  345.           P3M0 = 0x0c; P3M1 = 0x0c;
  346.                 //P3M0 = 0x00; P3M1 = 0x00;//IO口模式配置【准双向口】
  347.     P5M0 = 0x00; P5M1 = 0x00;//IO口模式配置【准双向口】
  348.     switch_CHN=1;//指定显示内容               
  349.         }
  350.         
  351. ///==================================================================================================================================================================        
  352. //  void Delay_us(unsigned int i) //N_us 微秒延时
  353. //  {
  354. //                unsigned char j;
  355. //    for(;i>0;i--)
  356. //    for(j=10;j>0;j--);
  357. //  }        

  358. ///==================================================================================================================================================================
  359.   void I2CStart(void)//TM1637 开始
  360.   {
  361.     clk = 1;
  362.     dio = 1;
  363.     Delay_us(2);
  364.     dio = 0;
  365.   }
  366.         
  367. ///==================================================================================================================================================================
  368.   void I2Cask(void)//TM1637 应答
  369.   {
  370.     clk = 0;
  371.     Delay_us(5);//在第八个时钟下降沿之后延时 5us,开始判断 ACK 信号
  372.     while(dio);
  373.     clk = 1;
  374.     Delay_us(2);
  375.     clk=0;
  376.   }
  377.         
  378. ///==================================================================================================================================================================
  379.   void I2CStop(void)//TM1637 停止
  380.   {
  381.     clk = 0;
  382.     Delay_us(2);
  383.     dio = 0;
  384.     Delay_us(2);
  385.     clk = 1;
  386.     Delay_us(2);
  387.     dio = 1;
  388.   }
  389.         
  390. ///==================================================================================================================================================================
  391.   void I2CWrByte(unsigned char oneByte)//TM1637 写一个字节
  392.   {
  393.     unsigned char i;
  394.     for(i=0;i<8;i++)
  395.     {  
  396.                   clk = 0;
  397.       if(oneByte&0x01)//低位在前
  398.       {dio = 1;}
  399.       else
  400.       {dio = 0;}
  401.       Delay_us(3);
  402.       oneByte=oneByte>>1;
  403.       clk=1;
  404.       Delay_us(3);
  405.     }
  406.   }
  407.         
  408. ///==================================================================================================================================================================
  409.   unsigned char Scankey(void)//TM1637 读按键
  410.   {
  411.     unsigned char rekey,i;
  412.     I2CStart();
  413.     I2CWrByte(0x42);//读按键命令
  414.     I2Cask();
  415.     dio=1; //在读按键前拉高数据线
  416.     for(i=0;i<8;i++)//从低位开始读
  417.     {  
  418.                   clk=0;
  419.       rekey=rekey>>1;
  420.       Delay_us(30);
  421.       clk=1;
  422.       if(dio)
  423.       {rekey=rekey|0x80;}
  424.       else
  425.       {rekey=rekey|0x00;}
  426.       Delay_us(30);
  427.     }
  428.       I2Cask();
  429.       I2CStop();
  430.       return (rekey);
  431.   }
  432.         
  433. ///==================================================================================================================================================================
  434.   void SMG_Display(void)//TM1637 写显示寄存器
  435.   {
  436.     unsigned char i;
  437.     I2CStart();
  438.     I2CWrByte(0x40); // 40H 地址自动加 1 模式,44H 固定地址模式,本程序采用自加 1 模式
  439.     I2Cask();
  440.     I2CStop();
  441.     I2CStart();
  442.     I2CWrByte(0xc0);//设置首地址,
  443.     I2Cask();
  444.     for(i=0;i<6;i++)//地址自加,不必每次都写地址
  445.     {
  446.       if(i<5)
  447.       {I2CWrByte(SMG_table[buf[i]]);}//送数据
  448.       else
  449.       {I2CWrByte(buf[5]);}//送数据        
  450.       I2Cask();
  451.     }
  452.     I2CStop();
  453.     I2CStart();
  454.     I2CWrByte(0x8f);//开显示 ,最大亮度
  455.     I2Cask();
  456.     I2CStop();
  457.   }
  458.         
  459. ///==================================================================================================================================================================
  460.   void key_inquiry(unsigned char key_data)//TM1637 按键ID查询,识别按键
  461.   {
  462.     uchar i;
  463.     for(i=0;i<16;i++)
  464.     {if(key_data==key_table[i])break;}
  465.     key_value=i;//查询到的ID号
  466.   }
  467.         
  468. ///==================================================================================================================================================================
  469.   unsigned char set_led()//合并8个二进制位成一个字节
  470.   {
  471.           unsigned char Byte = 0;
  472.     unsigned char Temp;

  473.     Temp = (unsigned char)Bit0;
  474.     Byte |= (Temp & 1) << 0;

  475.     Temp = (unsigned char)Bit1;
  476.     Byte |= (Temp & 1) << 1;

  477.     Temp = (unsigned char)Bit2;
  478.     Byte |= (Temp & 1) << 2;

  479.     Temp = (unsigned char)Bit3;
  480.     Byte |= (Temp & 1) << 3;

  481.     Temp = (unsigned char)Bit4;
  482.     Byte |= (Temp & 1) << 4;

  483.     Temp = (unsigned char)Bit5;
  484.     Byte |= (Temp & 1) << 5;

  485.     Temp = (unsigned char)Bit6;
  486.     Byte |= (Temp & 1) << 6;

  487.     Temp = (unsigned char)Bit7;
  488.     Byte |= (Temp & 1) << 7;

  489.     return Byte;
  490.   }
  491.         
  492. ///==================================================================================================================================================================               
  493.   void main(void)//主函数
  494.   {
  495.     init();//初始化

  496.    while(1)//循环体
  497.    {         

  498.            Bit0=1;//Mot    (LED1)对应set_led()函数里面的Bit0
  499.      Bit1=0;//Ch4    (LED2)对应set_led()函数里面的Bit1
  500.      Bit2=0;//Valley (LED3)对应set_led()函数里面的Bit2
  501.      Bit3=0;//Ch3    (LED4)对应set_led()函数里面的Bit3
  502.      Bit4=0;//Peak   (LED5)对应set_led()函数里面的Bit4
  503.      Bit5=0;//Ch2    (LED6)对应set_led()函数里面的Bit5
  504.      Bit6=0;//Net    (LED7)对应set_led()函数里面的Bit6
  505.      Bit7=0;//Ch1    (LED8)对应set_led()函数里面的Bit7
  506.                  
  507.                  if(switch_CHN==1){Display=ADC_operation();}//显示ADC值
  508.                  if(switch_CHN==0){if(key_value==0){if(K1_flag==0){K1_flag=1;Display=12345;}}else{K1_flag=0;}}//KEY1按键事件处理
  509.                  if(switch_CHN==0){if(key_value==1){if(K2_flag==0){K2_flag=1;if(Display>0){Display--;}}}else{K2_flag=0;}}//KEY2按键事件处理
  510.                  if(key_value==2){if(K3_flag==0){K3_flag=1;switch_CHN=~switch_CHN;}}else{K3_flag=0;}//KEY3按键事件处理
  511.                  if(switch_CHN==0){if(key_value==3){if(K4_flag==0){K4_flag=1;if(Display<65535){Display++;}}}else{K4_flag=0;}}//KEY4按键事件处理
  512.                           
  513.      key_data=Scankey();//读出的按键值不作处理。
  514.      key_inquiry(key_data);//按键ID号查询函数
  515.    //if(key_data!=0xff){key_value=16;}//如果没有按键按下,显示空白(编码表第16个元素,对应不显示)
  516.          //Display=12345;//数码管显示内容
  517.          //buf[4]=key_value;//按键ID号显示
  518.                  
  519.      if(Display>999){buf[0]=Display%100000/10000;}else{buf[0]=16;}//万
  520.      if(Display>999){buf[1]=Display%10000/1000;}else{buf[1]=16;}//千
  521.      if(Display>99){buf[2]=Display%1000/100;}else{buf[2]=16;}//百
  522.      if(Display>9){buf[3]=Display%100/10;}else{buf[3]=16;}//十
  523.      buf[4]=Display%10;//个        
  524.      buf[5]= set_led();//8个LED灯输出控制,通过Bit0---Bit7设置LED状态
  525.                  
  526.      SMG_Display();//数码管显示控制                                                                                                        
  527.    }
  528.          
  529.   }
  530.         
  531.         
  532.       




复制代码
下面是满量程的时候对应的波形图



视频展示:

https://v.youku.com/video?vid=XNjQ4NDEwMDYwNA%3D%3D

ADS1115_STC8G1K08A.rar

53.14 KB, 下载次数: 0

工程文件

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

使用道具 举报

沙发
ID:1121801 发表于 2025-6-5 10:44 | 只看该作者
感觉很复杂,我进来是标记一下等着学习的,大神快出来
回复

使用道具 举报

板凳
ID:155507 发表于 2025-6-5 16:42 | 只看该作者
AI的回复。

根据你的描述(“15位数据的低4位无法正常读取,一直为0”),结合你提供的ADS1115驱动代码,这里分析可能的原因和解决方案:

---

## 1. **ADS1115数据格式分析**

ADS1115是16位ADC,但实际有效数据为15位(最高位为符号位,单端输入时符号位为0)。数据寄存器为2字节,结构如下:


15  14   13   12   11   10    9    8    7    6    5     4     3   2    1   0
S   D14 D13 D12 D11 D10 D9  D8  D7  D6  D5  D4  D3  D2  D1  D0

其中,S为符号位(单端输入时为0),D14~D0为数据位。

你代码中的读取方式为:

D_ADS = Result[0] * 256 + Result[1];

这里`Result`和`Result[1]`分别对应高字节和低字节。

---

## 2. **低4位为0的可能原因**

### **(1)数据拼接问题**

- **Result和Result[1]的类型是否正确?**
  - 如果`Result`数组定义为`unsigned int`,而你用`Read_N_Byte(Result, 2);`读取数据,那么`Result`和`Result[1]`应该分别对应高字节和低字节。
  - 但`Read_N_Byte`函数原型为`void Read_N_Byte(unsigned int*readbuff,unsigned char n)`,而`Read_1_Byte`返回的是`unsigned char`,所以`readbuff[i] = Read_1_Byte();`会把每个字节存到`unsigned int`数组的一个单元里,而不是连续存两个字节。
  - **正确做法**:`Result`应该定义为`unsigned char Result[2];`,然后`Read_N_Byte(Result, 2);`(此时函数参数类型也要改为`unsigned char*`)。
  - **你目前的实现**:`Result`和`Result[1]`都是`unsigned int`,每个单元只存了一个字节,但拼接时直接相加,低字节可能被高位覆盖或未正确赋值。

### **(2)I2C读取时序问题**

- **I2C读取时,是否完整读取了两个字节?**
  - 确保`Read_N_Byte`函数正确读取了两个字节,且低字节(Result[1])的数据没有被丢弃或覆盖。
  - 检查`Read_1_Byte`函数是否正确返回每个字节。

### **(3)ADS1115配置问题**

- **是否配置为单端输入、正确通道、正确PGA?**
  - 你的代码中配置为单端输入(MUX_A0~A3),PGA为4.096V,基本没问题。
- **是否配置为连续转换模式?**
  - 你的代码中`MODE = MODE_1`(连续转换),建议改为单次转换(MODE_0),并在每次读取前启动转换。

### **(4)数据对齐问题**

- **如果Result和Result[1]都是unsigned int,且每个单元只存了一个字节,那么低字节的低4位可能被高位覆盖。**
  - 例如,如果`Result = 0x12`,`Result[1] = 0x34`,拼接时`Result * 256 + Result[1]`理论上没问题,但如果`Result[1]`的值不正确(比如被覆盖或未赋值),那么低4位会为0。

---

## 3. **解决方案**

### **(1)修改Result数组类型**


unsigned char Result[2]; // 改为unsigned char


### **(2)修改Read_N_Byte函数**


void Read_N_Byte(unsigned char *readbuff, unsigned char n)
{
    unsigned char i;
    for(i = 0; i < n; i++)
    {
        readbuff[i] = Read_1_Byte();
        if(i == n - 1)
            NACK();  // 不连续读字节
        else
            ACK();   // 连续读字节
    }
    Stop();
}


### **(3)修改数据拼接方式**


D_ADS = ((unsigned int)Result[0] << 8) | Result[1];


### **(4)检查I2C时序和硬件连接**

- **确保SCL和SDA引脚配置正确,无干扰。**
- **确保ADS1115供电和参考电压正常。**

### **(5)建议改为单次转换模式**


#define MODE MODE_0  // 单次转换

并在每次读取前写入配置寄存器启动转换。

---

## 4. **总结**

- **低4位为0的根本原因很可能是Result数组类型和Read_N_Byte函数实现不匹配,导致低字节数据未正确保存。**
- **建议将Result改为unsigned char数组,并修改Read_N_Byte函数为unsigned char*类型。**
- **数据拼接时使用位操作,确保低字节不被覆盖。**

---

## 5. **示例修正代码片段**


unsigned char Result[2]; // 改为unsigned char

void Read_N_Byte(unsigned char *readbuff, unsigned char n)
{
    unsigned char i;
    for(i = 0; i < n; i++)
    {
        readbuff[i] = Read_1_Byte();
        if(i == n - 1)
            NACK();
        else
            ACK();
    }
    Stop();
}

// 读取数据
Read_N_Byte(Result, 2);
D_ADS = ((unsigned int)Result[0] << 8) | Result[1];


这样修改后,低4位数据应该能正常读取[1]。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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