OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 116|回复: 4

PCF8591读取数据出错的问题

[复制链接]

87

主题

210

帖子

0

精华

高级会员

Rank: 4

积分
675
金钱
675
注册时间
2014-10-15
在线时间
159 小时
发表于 前天 17:17 | 显示全部楼层 |阅读模式
1金钱
我用STM32L4R5ZI驱动PCF8591,DAC正常
函数如下:
uchar DACconversion(unsigned char sla,unsigned char c,  unsigned char Val)

{

   Start_I2c();              //启动总线

   SendByte(sla);            //发送器件地址

   if(ack==0)return(0);

   SendByte(c);              //发送控制字节

   if(ack==0)return(0);

   SendByte(Val);            //发送DAC的数值  

   if(ack==0)return(0);

   Stop_I2c();               //结束总线

   return(1);

}

读取AD值一直是0xff
程序如下:
unsigned char PCF8591_ReadADC(unsigned char AINX)
{
        unsigned char ADC_Value;  
        Start_I2c();  // 起始信号
        SendByte(0x90);  // 发送PCF8591地址
        if(ack==0)return(0);  // 响应应答
       
        SendByte(0x40 | AINX); // 选择ADC通道
        if(ack==0)return(0);  // 响应应答
       
        Start_I2c();  // 重新启动
        SendByte( 0x91); // 发送PCF8591读命令
        if(ack==0)return(0);   // 响应应答
       
        RcvByte();      // 第一次读取丢弃(旧数据)
    Ack_I2c(0);    // 发送非应答信号
       
        ADC_Value = RcvByte();  // 读取ADC值
        Ack_I2c(1);    // 接收应答
        Stop_I2c();   // 停止信号
       
        return ADC_Value;
}

请问高手,如何解决?谢谢!

回复

使用道具 举报

0

主题

51

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
235
金钱
235
注册时间
2026-1-29
在线时间
21 小时
发表于 昨天 14:53 | 显示全部楼层
原因        概率        解决
未等待 ADC 转换完成,立即读取        ⭐⭐⭐⭐⭐        在写控制字后加 100μs 延时
Ack_I2c() 函数逻辑反了(0/1 定义错误)        ⭐⭐⭐⭐        检查 Ack_I2c(0) 是否真的发 ACK(拉低 SDA)
软件模拟 I²C 时序不准确(时钟太快/太慢)        ⭐⭐⭐        调整延时,确保 ≥ 100kHz 时序合规
模拟输入悬空,导致读满量程 0xFF        ⭐⭐        给 AIN 接确定电压(如 1.5V)测试
回复

使用道具 举报

87

主题

210

帖子

0

精华

高级会员

Rank: 4

积分
675
金钱
675
注册时间
2014-10-15
在线时间
159 小时
 楼主| 发表于 半小时前 | 显示全部楼层
664929323 发表于 2026-5-13 14:53
原因        概率        解决
未等待 ADC 转换完成,立即读取        ⭐⭐⭐⭐⭐        在写控制字后 ...

Ack_I2c()函数:
void Ack_I2c(uchar a)

{

  

  if(a==0)SDA_0;              /*在此发出应答或非应答信号 */

  else SDA_1;

  delay_us(3);     

  SCL_1;

  delay_us(5);

  SCL_0;                     /*清时钟线,钳住I2C总线以便继续接收*/

  delay_us(2);   

}
回复

使用道具 举报

87

主题

210

帖子

0

精华

高级会员

Rank: 4

积分
675
金钱
675
注册时间
2014-10-15
在线时间
159 小时
 楼主| 发表于 半小时前 | 显示全部楼层
664929323 发表于 2026-5-13 14:53
原因        概率        解决
未等待 ADC 转换完成,立即读取        ⭐⭐⭐⭐⭐        在写控制字后 ...

谢谢!模拟输入不是悬空。
回复

使用道具 举报

87

主题

210

帖子

0

精华

高级会员

Rank: 4

积分
675
金钱
675
注册时间
2014-10-15
在线时间
159 小时
 楼主| 发表于 29 分钟前 | 显示全部楼层
664929323 发表于 2026-5-13 14:53
原因        概率        解决
未等待 ADC 转换完成,立即读取        ⭐⭐⭐⭐⭐        在写控制字后 ...

函数改为如下:
  1. unsigned char PCF8591_ReadADC(unsigned char AINX)
  2. {
  3.         unsigned char ADC_Value;  
  4.         Start_I2c();  // 起始信号
  5.         SendByte(0x90);  // 发送PCF8591地址
  6.         delay_us(100);
  7.         if(ack==0)return(0);  // 响应应答
  8.        
  9.         SendByte(0x40 | AINX); // 选择ADC通道
  10.         delay_us(100);
  11.         if(ack==0)return(0);  // 响应应答
  12.        
  13.         Start_I2c();  // 重新启动
  14.         SendByte( 0x91); // 发送PCF8591读命令
  15.         delay_us(100);
  16.         if(ack==0)return(0);   // 响应应答
  17.        
  18.         RcvByte();      // 第一次读取丢弃(旧数据)
  19.     Ack_I2c(0);    // 发送非应答信号
  20.        
  21.         ADC_Value = RcvByte();  // 读取ADC值
  22.         Ack_I2c(1);    // 接收应答
  23.         Stop_I2c();   // 停止信号
  24.        
  25.         return ADC_Value;
  26. }
复制代码
结果仍是0xff
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

如发现本坛存在违规或侵权内容, 请点击这里发送邮件举报 (或致电020-38271790)。请提供侵权说明和联系方式。我们将及时审核依法处理,感谢配合。

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2026-5-14 18:35

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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