![]() |
从波形图上看,读回来的数据就有问题,是满量程的时候对应数据 7F F0 |
angmall 发表于 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]。 |
感觉很复杂,我进来是标记一下等着学习的,大神快出来![]() |