找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索

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

查看数: 186 | 评论数: 4 | 收藏 0
关灯 | 提示:支持键盘翻页<-左 右->
    组图打开中,请稍候......
发布时间: 2025-6-5 00:07

正文摘要:

本帖最后由 七彩的梦想 于 2025-6-5 23:44 编辑 最近心血来潮买了几个ADS1115模块,想找个时间测试验证一下。发现模块配送的资料是Arduino平台,手头没有Arduino硬件,只有STC8G1K08单片机,于是在本论坛找了个现 ...

回复

ID:66862 发表于 2025-6-5 23:41
从波形图上看,读回来的数据就有问题,是满量程的时候对应数据 7F F0
ID:66862 发表于 2025-6-5 23:33
angmall 发表于 2025-6-5 16:42
AI的回复。

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

感谢你的解答与帮助,我抽个时间好好检查一下
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:1121801 发表于 2025-6-5 10:44
感觉很复杂,我进来是标记一下等着学习的,大神快出来

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

Powered by 单片机教程网

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