打印

请教一个I2C的问题

[复制链接]
2086|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yuangli|  楼主 | 2008-11-20 13:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我写了一个I2C的通讯程序,连续读十个数据,数据是一个一个的读,头两个数据正常读出,从第三个数据开始,发送地址数据后,24c02的芯片没有发出应答信号,因此数据错误,可是奇怪的是从这个数据开始,数据读出的是一个正常,一个错误间隔的出现,为什么会出现这种现象,是软件的问题还是硬件的问题,在此想各位大侠请教了。 

相关帖子

沙发
keyanfeng| | 2008-11-20 13:13 | 只看该作者

可能是软件


IIC发送停止信号后,
要再次启动IIC总线,要延时一段时间.
试下再读两个数据之间增加一个延时函数.

使用特权

评论回复
板凳
yuangli|  楼主 | 2008-11-20 13:45 | 只看该作者

谢谢你的回复

软件问题回去动手再改一改,明天汇报结果。还有个问题上拉电阻网上介绍的从10K到56K都有。以你的经验你看用那种阻值较好。

使用特权

评论回复
地板
isbit| | 2008-11-20 13:54 | 只看该作者

可能还有一个问题,等你汇报结果后再说!

使用特权

评论回复
5
abc996633| | 2008-11-20 14:39 | 只看该作者

是软件问题

另外,上拉电阻与传输速率有关,上拉电阻越大,传输速率越低。

使用特权

评论回复
6
yuangli|  楼主 | 2008-11-20 17:24 | 只看该作者

见鬼了,发送是否成功居然和数据有关。

#include<pic.h>
#define scl     RA0
#define sda     RA1
#define nop     asm("nop")
#define clrwdt  asm("clrwdt")

char a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,i,j,k;

void delay();
void delay_time();
void i2c_start();
void i2c_stop();
void i2c_write_byte(char data);
void i2c_write(char add,char data);
i2c_read_byte();
i2c_read(char add);

main()
{
        i2c_write(0x11,0x11);
        i2c_write(0x12,0x22);
        i2c_write(0x13,0x33);
        i2c_write(0x14,0x44);
        i2c_write(0x15,0x55);
        i2c_write(0x16,0x66);
        i2c_write(0x17,0x77);
        i2c_write(0x18,0x88);
        i2c_write(0x19,0x99);
        i2c_write(0x1a,0xaa);
        delay_time();
        delay_time();
    delay_time();
    delay_time();
    delay_time();
    delay_time();
        a1=i2c_read(0x11);
    a2=i2c_read(0x12);
    a3=i2c_read(0x13);
        a4=i2c_read(0x14);
        a5=i2c_read(0x15);
        a6=i2c_read(0x16);
        a7=i2c_read(0x17);
        a8=i2c_read(0x18);
        a9=i2c_read(0x19);
        aa=i2c_read(0x1a);
    while(1)
    {
        nop;    //设置断点,成功可到这
        nop;
        clrwdt;
    }
}
//*************************************
void delay_time()
{
    char i;
    for(i=255;i>0;i--)
    {
        nop;
    }
}
//======================================
void delay()
{
        char k;
        for(k=0xff;k>0;k--)
        {
                nop;
        }
}
//*************************************
//I2C读写
//*************************************
void i2c_start()
{
        
    TRISA=0x00;
        sda=1;                  //发送起始条件的数据信号
    delay();                //起始条件建立时间大于4.7us
        scl=1;
    delay();
    sda=0;                  //发送起始信号
        delay();                //起始条件锁定时间大于4μs                
        scl=0;                  //钳住I2C总线,准备发送或接收数据
        delay();
}
//=====================================
void i2c_stop()
{
        TRISA=0x00;
        nop;nop;
        sda=0;          //发送结束条件的数据信号
        delay();
    scl=1;          //发送结束条件的时钟信号
        delay();        //结束条件建立时间大于4μs
        sda=1;          //发送I2C总线结束信号
        delay();
    scl=0;
    delay();
}
//=====================================
void i2c_write_byte(char temp)
{
        char i;
        TRISA=0B00000000;
        delay();
        for(i=8;i>0;i--)
        {
                
        if(temp&0x80)           
                {sda=1;}
                else
                {sda=0;}
        delay();
        scl=1;          //置时钟线为高,通知被控器开始接收数据位
                delay();        //保证时钟高电平周期大于4μs
                scl=0;
                delay();
        sda=0;
        delay();
        temp<<=1;
        }
    
        sda=1;                  //8位发送完后释放数据线,准备接收应答位
        delay();
        scl=1;
        delay();
        TRISA=0B00000010;
        nop;nop;
        for(i=5;i>0;i--)
        {
                if(sda==0)
                {break;}
                else
                {nop;}      //设置断点,失败断在这里。
        }
        scl=0;
        delay();
    //sda=0;
    //delay();
}
//=====================================
i2c_read_byte()
{
        char i,data=0;
        TRISA=0B00000010;
        delay();
        for(i=8;i>0;i--)
        {
                data<<=1;
        if(sda==1) 
                {data|=0x01;}
                delay();
        scl=1;
                delay();
        scl=0;
                delay();
        //sda=0;
        //delay();
        }
        TRISA=0;
        delay();
        sda=0;
        delay();
        scl=1;
        delay();
        scl=0;
        delay();
    //sda=1;
    //delay();
    return(data);
}
//=====================================
void i2c_write(char add,char temp)
{
        i2c_start();
    delay_time();
        i2c_write_byte(0xa0);
        delay_time();
    i2c_write_byte(add);
        delay_time();
    i2c_write_byte(temp);
        delay_time();
    i2c_stop();
    delay_time();
}
//=====================================
i2c_read(char add)
{
        char temp;
        i2c_start();
    delay_time();
        i2c_write_byte(0xa0);
        delay_time();
    i2c_write_byte(add);
        delay_time();
    i2c_start();
    delay_time();
        i2c_write_byte(0xa1);
        delay_time();
    temp=i2c_read_byte();
        delay_time();
    i2c_stop();
    delay_time();
        return (temp);
}
发送81~8a的数据没有问题,发送现在的数据,第一个成功,以后都失败。
程序中//后部分试过没有影响。

使用特权

评论回复
7
yuangli|  楼主 | 2008-11-20 17:28 | 只看该作者

仿真器用的是高奇的PICMATE-Lite

仿真软件用的是MPLAB-IDE V7.62

使用特权

评论回复
8
yuangli|  楼主 | 2008-11-20 17:30 | 只看该作者

delay的参数设置

低过0x30什么数据都失败。

使用特权

评论回复
9
yuangli|  楼主 | 2008-11-20 17:34 | 只看该作者

delay()的参数设置

大过0x30写什么数据都可以成功,但是读现在的数据,只有第一个是对的,后面的都失败。

使用特权

评论回复
10
ayb_ice| | 2008-11-20 19:57 | 只看该作者

你这应该是NACK的问题

使用特权

评论回复
11
keyanfeng| | 2008-11-20 22:19 | 只看该作者

同意楼上的

i2c_read之后要加上nack,

void IIC_nack()
{
    IIC_sda = 1;               // sda = 1
    delay5us();
    IIC_scl = 1;               // scl = 1
    delay5us();
    IIC_scl = 0;               // scl = 0
    delay5us();
}

而且两个时序之间也不用delay()
过长时间,5~10us就足够了。
        for(k=0xff;k>0;k--)
        {
                nop;
        }
       太长了。

相反,读两个byte之间可以延长ms级别,
或者不用发IIC_stop时序,连续读。

使用特权

评论回复
12
yuangli|  楼主 | 2008-11-21 09:31 | 只看该作者

谢谢诸位的帮助,问题已解决!

原来一直认为i2c_read是ack的,没有认真看书。现改为nack问题解决,谢谢!!

使用特权

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

本版积分规则

2

主题

9

帖子

2

粉丝