打印

请教个单片机模拟I2C主机,从设备无应答问题

[复制链接]
6029|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gexish|  楼主 | 2011-4-27 16:14 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
沙发
gexish|  楼主 | 2011-4-27 18:06 | 只看该作者
已经确认SDASCL线无接错且都有上拉电阻(10K),单片机到芯片间引线无断路和短路。但就是没应答,搞了好半天了~~~

使用特权

评论回复
板凳
来与君| | 2011-4-28 08:35 | 只看该作者
看似没大错,SCL/SDA硬件连接没反吧?

如果1波形是时钟的话,高低电平不够均匀。不过10uS的高电平应该也够了。

器件地址没错?器件没坏?

使用特权

评论回复
地板
来与君| | 2011-4-28 08:53 | 只看该作者
粗看了一下芯片手册,它有一个SRAD引脚。该引脚接高电平时,芯片地址为0x6A,接低电平时为0x68。

你的硬件连接可正确?

使用特权

评论回复
5
joyme| | 2011-4-28 12:43 | 只看该作者
1. 用的什么单片机?SDA发送完第8位后置SDA脚位input再读取ACK信号,有些单片机从ouput改为input需要设置DDR寄存器

使用特权

评论回复
6
gexish|  楼主 | 2011-4-28 16:34 | 只看该作者
SRAD是接地的,所以器件地址是0X68没错。通过硬件调试该芯片的V5脚能正常输出1.8V默认电压,可以确认芯片没故障(而且换了两块芯片来调试结果都一样)。

我用的单片机是STC89C53RC,应答函数如下:
void i2c_slave_ack()
{//检查被控器件应答信号

SDA=1;//释放sda
_nop_();_nop_();_nop_();_nop_();_nop_();
SCL=1;//在scl为1的时候等待sda值的变化,在器件接受到数据后会把sda拉低。
_nop_();_nop_();_nop_();_nop_();_nop_();
if(SDA==1)
SDA=1;//接受失败
else
SDA=0;//接受成功
SCL=0;
_nop_();_nop_();_nop_();

使用特权

评论回复
7
ayb_ice| | 2011-4-28 16:43 | 只看该作者
没有应答很可能是地址错了

使用特权

评论回复
8
joyme| | 2011-4-28 16:54 | 只看该作者
地址位发送顺序有没有试过反过来发送(一般是高位先发,也有可能地位先发,从设备的datasheet上应该有)

使用特权

评论回复
9
ayb_ice| | 2011-4-28 16:58 | 只看该作者
地址位发送顺序有没有试过反过来发送(一般是高位先发,也有可能地位先发,从设备的datasheet上应该有)
joyme 发表于 2011-4-28 16:54

都不知道你是怎么看资料的
读地址: 0b01101011 = 0x6b
写地址: 0b01101010 = 0x6a

使用特权

评论回复
10
gexish|  楼主 | 2011-4-28 17:05 | 只看该作者
如下图:

1.JPG (27.03 KB )

1.JPG

使用特权

评论回复
11
来与君| | 2011-4-28 17:29 | 只看该作者
有个示波器,I2C总线这种很容易调试的。

模拟就是仿,你把输出波形做的和手册上的差不多,基本上问题就解决了。

使用特权

评论回复
12
joyme| | 2011-4-28 17:40 | 只看该作者
这就是说要高位先发,下面是我做产品时写的,你试试看

send(BYTE data)
{
    BYTE i = 8;
    while(i)
    {
          if(data & (1<<(i-1)))
              SDA = 1;
          else
              SDA = 0;
          delayus(2);
          SCL = 1;
          delayus(5);
          SCL = 0;
          i--;
    }
    SDA = 1;
    CLK = 1;
    while(i<5)
    {
          if(SDA)
             break;
          i++;
          delayus(3);
    }
}

使用特权

评论回复
13
gexish|  楼主 | 2011-4-28 18:13 | 只看该作者
12# joyme


while(i<5)
    {
          if(SDA)
             break;
          i++;
          delayus(3);
    }
请问这段函数是什么意思呢?

使用特权

评论回复
14
gexish|  楼主 | 2011-4-28 18:17 | 只看该作者
我就是看不出实际波形与手册上的有什么区别才头痛~~~
搞了两天了一点进展也没,愁死人。 11# 来与君

使用特权

评论回复
15
joyme| | 2011-4-28 18:19 | 只看该作者
其实就是等ACK,但时间控制在10几个us左右

使用特权

评论回复
16
ayb_ice| | 2011-4-29 08:27 | 只看该作者
不是地址错了,就是程序其它地方有问题
可能基本的开始,停止都有问题

使用特权

评论回复
17
gexish|  楼主 | 2011-4-29 08:31 | 只看该作者
回16楼:
今天我拿了一块EPROM来测试程序可以产生应答,证明程序是没问题的了。

使用特权

评论回复
18
ayb_ice| | 2011-4-29 08:40 | 只看该作者
void i2c_slave_ack()程序有问题,可能其它程序还有问题

修改如下
#define IIC_TRUE 0
#define IIC_FALSE (!IIC_TRUE)
#define uchar unsigned char

uchar i2c_slave_ack(void)
{
uchar r;

SDA = 1;
_nop_();_nop_();_nop_();_nop_();_nop_();

SCL = 1;
_nop_();_nop_();_nop_();_nop_();_nop_();

r = IIC_TRUE;
if(SDA){
  r = IIC_FALSE;
}

SCL = 0;
}

使用特权

评论回复
19
gexish|  楼主 | 2011-4-29 14:11 | 只看该作者
问题找出来了:
该芯片的复位脚需拉高!!

谢谢各位的热心帮忙。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

14

帖子

1

粉丝