打印

请教一个单片机I2C通信的问题

[复制链接]
2340|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
天隼之翼|  楼主 | 2007-5-6 13:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
现在手头上要用LPC9102做一个I2C的从机,只需要接收指令,由于9102没有自带的I2C功能,需要软件模拟,我写了一个基本的如下:
#include <reg9102.h>
#include <stdio.h>
#include <intrins.h>
#define uchar unsigned char

sbit SDA = P0^7;  //pin6
sbit SCL = P0^5;  //pin8

void delay()
{
 _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}

unsigned char Read_byte(void)
{
    uchar b=0,q;
    for(q=0;q<8;q++)
    { 
        while(SCL!=1);
        delay();
        while(SCL!=1);
        delay();
        while(SCL!=1);
        b<<=1;
        if(SDA==1)
        {
            delay();
            if(SDA==1)
          b|=1;
          else
          b&=0xfe;
        }
        else
        {
            delay();
            if(SDA==1)
            b|=1;
            else
          b&=0xfe;
        }
        while(SCL!=0);
        delay();
        while(SCL!=0);
        delay();
        while(SCL!=0);
    }
      return(b);
      SDA=0;//回应
      delay();
      while(SCL!=1);//第9个时钟的高电平
      SDA=0;//为了确认回应
      while(SCL!=1);
      SDA=0;
      while(SCL!=1);
      SDA=0;
      while(SCL!=0);//第9个时钟的低电平
      delay();
      while(SCL!=0);
      delay();
      while(SCL!=0);
      delay();
      SDA=1;
}

main()
{
   P0M1=0x00;//全部准双向
    P0M2=0x00;
    P1M1=0x00;
    P1M2=0x00;
  delay();
  
  SDA=0;
  SCL=0;
  delay();
  
  while(1)
  {
  while(SCL!=1);
  delay();
  while(SCL!=1);
  delay();
  while(SCL!=1);
  delay();
  while(SDA!=1);
  delay();
  while(SDA!=1);
  delay();
  while(SDA!=1);//双高电平
  while(SDA!=0);
  delay();
  while(SDA!=0);
  delay();
  while(SDA!=0);//SDA下降沿  判定为起始条件
  while(SCL!=0);
  delay();
  while(SCL!=0);//时钟低,SDA改变状态中,准备开始读取数据的第一位
  
  Read_byte();
  Read_byte();
  }
}

简化起见,我只读两个字节数据,其中第一个是地址,但是由于这条总线上只有9102一个,所以我就不加判定是不是我的地址,直接按接收数据的方式给回应就行了。
但是在实际过程中,由示波器看到的I2C总线上的波形,是主机发出了地址,但从机始终不给回应,而如果我主机不停的循环发,那么从机有时能给回应,有时又不行,请教为何?

相关帖子

沙发
ayb_ice| | 2007-5-7 07:38 | 只看该作者

软件模拟从机可能不可靠吧

软件模拟从机可能不可靠吧...
假设SCLK为400KHZ,周期是2.5US,51只能执行几条指令,况且还有其它的任务...

使用特权

评论回复
板凳
天隼之翼|  楼主 | 2007-5-7 07:42 | 只看该作者

我已经将SCL降到很低速率了

我已经将SCL降到很低速率了,10KHZ
就是为了防止速率太高,单片机反应不过来

使用特权

评论回复
地板
yewuyi| | 2007-5-7 08:29 | 只看该作者

软件模拟IIC从机怎么不可靠?

使用特权

评论回复
5
ayb_ice| | 2007-5-7 08:35 | 只看该作者

况且还有其它的任务...怎么解决?

使用特权

评论回复
6
天隼之翼|  楼主 | 2007-5-7 08:45 | 只看该作者

我现在仅仅让它执行收两个字节的任务

我现在仅仅让它执行收两个字节的任务而已
在整个程序中,由于I2C通信的次数和频率不会很多,所以我准备让它在先一次性接收完所有数据后再进行其它的工作,然后再返回I2C的等待状态。

我测试过,我让主机发送的两个数据的第一个是0xc2,而从机的确正确读出了这个0xc2,但就是没有正确给出ACK,这个是关键啊.
也就是在接收完一个8位数据后,从机无法把SDA拉低

使用特权

评论回复
7
ayb_ice| | 2007-5-7 09:04 | 只看该作者

从机接到主机的应答时钟就可以返回ACK了...

使用特权

评论回复
8
天隼之翼|  楼主 | 2007-5-7 09:31 | 只看该作者

楼上可否说得更详细些?

楼上的话我没看明白
我现在的问题是,作为从机的LPC9102在接收完第一个8位数据后无法正确的拉低SDA给出应答,导致主机无法继续发送数据。

使用特权

评论回复
9
天隼之翼|  楼主 | 2007-5-7 10:19 | 只看该作者

关于这个地方

关于这个地方
return(b);
SDA=0;//回应

实际上我两种情况都试过的,把return语句放在中间或者是最后,效果是一样

我拜读一下阁下的程序先

使用特权

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

本版积分规则

7

主题

57

帖子

0

粉丝