找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 190|回复: 4
收起左侧

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

[复制链接]
ID:66862 发表于 2025-6-5 00:07 | 显示全部楼层 |阅读模式
本帖最后由 七彩的梦想 于 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


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

异常波形图

低4位异常

低4位异常


波形图1
波形图1.png


波形图2

波形图2

波形图2



波形图3
波形图3.png


波形图4

波形图4

波形图4



波形图5

波形图5

波形图5



大于0的第一个值

大于0的第一个值

大于0的第一个值




对应波形图5数据显示

对应波形图5数据显示

对应波形图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

工程文件

回复

使用道具 举报

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]。
回复

使用道具 举报

ID:66862 发表于 2025-6-5 23:33 | 显示全部楼层
angmall 发表于 2025-6-5 16:42
AI的回复。

根据你的描述(“15位数据的低4位无法正常读取,一直为0”),结合你提供的ADS1115驱动代码 ...

感谢你的解答与帮助,我抽个时间好好检查一下
回复

使用道具 举报

ID:66862 发表于 2025-6-5 23:41 | 显示全部楼层
从波形图上看,读回来的数据就有问题,是满量程的时候对应数据 7F F0
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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