打印

AT24C08读写正常,但连续向两个地址写,读到的数据不对

[复制链接]
714|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
橘子阿小|  楼主 | 2022-1-5 09:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
AT24C08读写正常,但连续向两个地址写,读到的数据不对
中间加延时也不好使

使用特权

评论回复
沙发
xch| | 2022-1-5 09:46 | 只看该作者
没检测ACK/NACK 位状态吗?

使用特权

评论回复
板凳
橘子阿小|  楼主 | 2022-1-5 10:13 | 只看该作者
xch 发表于 2022-1-5 09:46
没检测ACK/NACK 位状态吗?

没有,不会,你能不能帮我看看程序有没有什么问题

使用特权

评论回复
地板
橘子阿小|  楼主 | 2022-1-5 10:15 | 只看该作者
#include <pic.h>
//__CONFIG(INTIO&WDTEN&PWRTEN&MCLRDIS);
__CONFIG(0x3b34);
#define uchar unsigned char
#define uint unsigned int
#define scl RC4
#define sda RC5
uchar sec;
//uchar table[]={0x48,0x3d,0x6d,0x4b,0x67,0x77,0x4c,0x7f,0x6f};
void delay()
{ ;;;;;;;;;;;;;}
void delay1ms(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
void start()  //开始信号
{       
        sda=1;
        delay();
        scl=1;
        delay();
        sda=0;
        delay();
}
void stop()   //停止
{
        sda=0;
        delay();
        scl=1;
        delay();
        sda=1;
        delay();
}
void respons()  //应答
{
        uchar i=0;
        TRISC5=1;
        scl=1;
        delay();
        while((sda==1)&&(i<250))i++;
        scl=0;
        delay();
        TRISC5=0;
}
void init()
{
        sda=1;
        delay();
        scl=1;
        delay();
}
void write_byte(uchar date)
{
        uchar bit_count,a;
        for (bit_count=0;bit_count<8;bit_count++)
        {
                if ((date<<bit_count)&0x80) {a=1;}
                else {a=0;}
                scl=0;
                delay();
                sda=a;
                delay();
                scl=1;
                delay();
        }
        scl=0;
        delay();
        sda=1;
        delay();
}
uchar read_byte()
{
        uchar i,k;
        scl=0;
        delay();
        sda=1;
        delay();
        TRISC5=1;
        for(i=0;i<8;i++)
        {
                scl=1;
                delay();       
                k=(k<<1)|sda;
                scl=0;
                delay();       
        }
        TRISC5=0;
        return k;
}

void write_add(uint address,uchar date)
{
        uchar address_h,address_l;
        address_h=address/256;
        address_l=address%256;
        start();
        write_byte(0xa0);
        respons();
        write_byte(address_h);
        respons();
        write_byte(address_l);
        respons();
        write_byte(date);
        respons();
        stop();
}

uchar read_add(uint address)
{
        uchar date;
        uchar address_h,address_l;
        address_h=address/256;
        address_l=address%256;
        start();
        write_byte(0xa0);
        respons();
        write_byte(address_h);
        respons();
        write_byte(address_l);
        respons();
        start();
        write_byte(0xa1);
        respons();
        date=read_byte();
        stop();
        return date;
}

void usart_init()
{
        TRISB=0xff;
        TXSTA=0x24;
        RCSTA=0x90;
        SPBRG=25;
        GIE=1;
        PEIE=1;
        RCIE=1;
        WPUB5=0;        //禁止RB5弱上拉
}

void main()
{
        OSCCON=0B01100110;//4MHz;器件运行在内部振荡器之下;高频稳定;低频稳定;时钟源由FOSC<2:0>决定
        ANSEL                                =        0X00;       
        ANSELH                                =        0X00;
        usart_init();
        TRISC4=0;
        TRISC5=0;
        init();
        sec=0xcc;
        write_add(0x00a0,sec);  //写入数据
        delay1ms(500);
        sec=read_add(0x00a0);        //读出所写的数据
        while(1)
        {
                TXREG=sec;          //将读出的数据通过串口发送给串口调试助手
                while(!TRMT);
                delay1ms(1000);
        }
}

使用特权

评论回复
5
ayb_ice| | 2022-1-5 11:01 | 只看该作者
写完要延时20MS,等待内部操作完成再读

使用特权

评论回复
6
ayb_ice| | 2022-1-5 11:07 | 只看该作者
write_byte发了9个脉冲,多了一个

使用特权

评论回复
7
橘子阿小|  楼主 | 2022-1-5 11:19 | 只看该作者
ayb_ice 发表于 2022-1-5 11:07
write_byte发了9个脉冲,多了一个

能说再明白些吗?

使用特权

评论回复
8
ayb_ice| | 2022-1-5 11:27 | 只看该作者
橘子阿小 发表于 2022-1-5 11:19
能说再明白些吗?

谁发数据谁收对方应答(每个字节都需要接收或发送应答),应答需要一个脉冲,所有时钟均由主机发出

使用特权

评论回复
9
ayb_ice| | 2022-1-5 11:30 | 只看该作者
接收最后一个字节需要发送非应答字节,以便对方释放总线(对方收到一个非应答后认为出错,自动释放总线,方便后续操作,否则可能导致死锁)

使用特权

评论回复
10
橘子阿小|  楼主 | 2022-1-5 11:36 | 只看该作者
ayb_ice 发表于 2022-1-5 11:30
接收最后一个字节需要发送非应答字节,以便对方释放总线(对方收到一个非应答后认为出错,自动释放总线,方 ...

不好意思,麻烦您能不能在程序中指出错误

使用特权

评论回复
11
ayb_ice| | 2022-1-5 11:38 | 只看该作者
给个参考你

//______________________________________________________________
// IIC_Init
//______________________________________________________________
//
// IIC总线初始化
//
bit IIC_Init(void)
{
        //调用之前需要初始化GPIO
        //IIC_GpioInit();

        //________________
        // GPIO
        //TICK_Delay(20);

        //________________
        // STD
        SDA_1();
        SDA_OUTPUT();

        SCL_1();
        IIC_DelayStd();

        IIC_Stop();

        if (1)
        {
                if (!AT24X_Init())
                {
                        return 0;
                }
        }

        return 1;
}

//______________________________________________________________
// IIC_Start
//______________________________________________________________
//
// I2C开始信号,注意结束时GPIO_I2C_SCL=0,GPIO_I2C_SDA=1
//
void IIC_Start(void)
{
        SCL_0();
        IIC_DelayStd();

        SDA_1();
        SDA_OUTPUT();
        IIC_DelayStd();
        SCL_1();
        IIC_DelayStd();

        SDA_0();
        IIC_DelayStd();

        SCL_0();        // SCL = 0, SDA = 1
        IIC_DelayStd();
        SDA_1();
}

//______________________________________________________________
// IIC_Stop
//______________________________________________________________
//
// I2C停止信号,结束时SDA=1,SCL=1,确保I2C总线在停止状态
//
void IIC_Stop(void)
{
        SCL_0();
        IIC_DelayStd();

        SDA_0();
        SDA_OUTPUT();
        IIC_DelayStd();

        SCL_1();
        IIC_DelayStd();

        SDA_1();
        IIC_DelayStd();
}

//______________________________________________________________
// IIC_Send
//______________________________________________________________
//
// 发送一个字节,失败后会自动停止总线(发送stop)
// byte = 数据
// 返回: 0 = 失败, 1 = 成功
//
bit IIC_Send(u8 ucData)
{
        SDA_OUTPUT();

        u32 uiTmp = ucData;
        for (u32 i=0; i<8; i++)
        {
                if (uiTmp & BIT7)
                {
                        SDA_1();
                }
                else
                {
                        SDA_0();
                }
                uiTmp <<= 1;
                IIC_DelaySda();

                SCL_1();
                IIC_DelaySclHigh();

                SCL_0();
                //IIC_DelaySclLow();
        }

        SDA_INPUT();
        IIC_DelaySda();
        SCL_1();
        IIC_DelayStd();

        if (!SDA_VALUE)
        {
                SCL_0();
                return 1;
        }
        else
        {
                __DEBUG();
        }

//___________________________________
// 失败停止总线
        IIC_Stop();

        return 0;
}

//______________________________________________________________
// IIC_Receive
//______________________________________________________________
//
// 接收一个字节
// ack : 应答信号ACK或NACK
// 返回: 接收的字节
// 注: 软件模拟方式无法判断是否成功或失败,所以总是成功
//
u8 IIC_Receive(bit bAck)
{
    SDA_INPUT();
    u32 uiTmp = 0;
        for (u32 i=0; i<8; i++)
        {
                uiTmp <<= 1;
        SCL_1();
        IIC_DelaySclHigh();
                vu32 uiSda = SDA_VALUE;
        SCL_0();
                if (uiSda)
                {
                        uiTmp++;
                }
        IIC_DelaySclLow();
    }
//___________________________________
// 主机应答从机
        SDA_OUTPUT();
        SDA_OUT(bAck);
    IIC_DelaySda();

    SCL_1();
    IIC_DelayStd();

    SCL_0();
        IIC_DelayStd();

        SDA_1();            // 接收结束时GPIO_I2C_SDA=1

    return uiTmp;
}

//______________________________________________________________
// IIC_SendSame
//______________________________________________________________
//
// 发送多个重复的字节(主要用于初始化).
//
bit IIC_SendSame(const u8 ucData, u32 uiNumber)
{
        while (uiNumber--)
        {
                if (IIC_Send(ucData) == 0)
                {
                        return 0;
                }
        }

        IIC_Stop();

        return 1;
}

//______________________________________________________________
// IIC_SendBuffer
//______________________________________________________________
//
// 发送多个字节
//
bit IIC_SendBuffer(void* pVoid, u32 uiNumber)
{
        u8* pSrc = (u8*)pVoid;

        while (uiNumber--)
        {
                if (IIC_Send(*pSrc++) == 0)
                {
                        return 0;
                }
        }

        IIC_Stop();

        return 1;
}

//______________________________________________________________
// IIC_ReceiveBuffer
//______________________________________________________________
//
// 接收多个字节
//
bit IIC_ReceiveBuffer(void* pVoid, u32 uiNumber)
{
        u8* pSrc = (u8*)pVoid;

        u32 uiTmp = uiNumber -1;
        while (uiTmp--)
        {
                *pSrc++ = IIC_Receive(I2C_ACK);
        }
        *pSrc = IIC_Receive(I2C_NACK);

        IIC_Stop();

        return 1;
}

//______________________________________________________________
// IIC_Query
//______________________________________________________________
//
// 查询IIC器件操作是否完成
// ucDevice = 器件选择(建议写操作,主机主动)
// uiTimeout = 超时间
// 返回: 0 = 未完成, 1 = 完成
//
// 注意: 可能不同的设备需要定制查询程序
//
bit IIC_Query(u8 ucDevice, const u32 uiTimeout)
{
        //_______________________
        // 简化算法
        if (0)
        {
                TICK_Delay(uiTimeout);
                return 1;
        }
        else
        {
        //_______________________
        // 正常算法
                u32 uiTmp = INT_GetTick();

                while (1)
                {
                        IIC_Start();        // !!!

                        if (IIC_Send(ucDevice) == 1)
                        {
                                IIC_Stop();
                                return 1;
                        }
                        else
                        {
                                //TICK_Delay(1ms);
                                if (TICK_IfTimeOut(uiTmp, uiTimeout))
                                {
                                        return 0;
                                }
                                else
                                {
                                        __DEBUG();
                                }
                        }
                }
        }
}


/*
//______________________________________________________________
// 函数延时方式
//______________________________________________________________
*/

#if cfg_I2C_DELAY_MODE != 0

//______________________________________________________________
// IIC_Delay
// IIC_DelayStd
// IIC_DelaySda
// IIC_DelaySclHigh
// IIC_DelaySclLow
//______________________________________________________________
//
// iic延时函数
//
static void IIC_Delay(void)
{
        TVS_BasicDelay(1.25vs-10);
}

static void IIC_DelayStd(void)
{
        IIC_Delay();
}

static void IIC_DelaySda(void)
{
        TVS_BasicDelay(0.5vs);
}

static void IIC_DelaySclHigh(void)
{
        IIC_Delay();
}

static void IIC_DelaySclLow(void)
{
        IIC_Delay();
}

#endif

使用特权

评论回复
12
橘子阿小|  楼主 | 2022-1-5 11:41 | 只看该作者
ayb_ice 发表于 2022-1-5 11:38
给个参考你

//______________________________________________________________

感谢,问题已解决,我没有看参考,我明白您说的无应答了

使用特权

评论回复
13
橘子阿小|  楼主 | 2022-1-5 11:52 | 只看该作者
ayb_ice 发表于 2022-1-5 11:38
给个参考你

//______________________________________________________________

不好意思,刚才恍惚了,还是那样,连续写,中间加延时,还是不行,您能不能在我的程序上指导一下

使用特权

评论回复
14
ayb_ice| | 2022-1-5 14:53 | 只看该作者
橘子阿小 发表于 2022-1-5 11:52
不好意思,刚才恍惚了,还是那样,连续写,中间加延时,还是不行,您能不能在我的程序上指导一下 ...

程序需要调试,无法保证一定正确
#include <pic.h>
//__CONFIG(INTIO&WDTEN&PWRTEN&MCLRDIS);
__CONFIG(0x3b34);
#define uchar unsigned char
#define uint unsigned int
#define SCL RC4
#define SDA RC5

#define IIC_ACK                (0)
#define IIC_NACK        (1)

uchar sec;
//uchar table[]={0x48,0x3d,0x6d,0x4b,0x67,0x77,0x4c,0x7f,0x6f};
void delay()
{ ;;;;;;;;;;;;;}
void delay1ms(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
void start()  //开始信号
{
        SDA=1;
        delay();
        SCL=1;
        delay();
        SDA=0;
        delay();

                SCL=0;
                delay();
}
void stop()   //停止
{
        SDA=0;
        delay();
        SCL=1;
        delay();
        SDA=1;
        delay();

                SCL=0;
                delay();
}

void respons()  //应答
{
        uchar i=0;
        TRISC5=1;
        SCL=1;
        delay();
        while((SDA==1)&&(i<250))i++;
        SCL=0;
        delay();
        TRISC5=0;
}
void init()
{
        SDA=1;
        delay();
        SCL=1;
        delay();
}
void write_byte(uchar date)
{
        uchar bit_count,a;
                TRISC5=0;
        for (bit_count=0;bit_count<8;bit_count++)
        {
                if ((date<<bit_count)&0x80) {SDA=1;}
                else {SDA=0;}
                SCL=1;
                delay();
                SCL=0;
                delay();
        }
}
uchar read_byte(bit bAck)
{
        uchar i,k;
        TRISC5=1;
                delay();
        for(i=0;i<8;i++)
        {
                SCL=1;
                delay();
                                k <<= 1;
                if(SDA)
                                {
                                        k++;
                                }
                SCL=0;
                delay();
        }

                TRISC5=0;
                if (bAck == IIC_NACK)
                {
                        SDA = 1;
                }
                else
                {
                        SDA = 0;
                }
                SCL=1;
        delay();
                SCL=0;
        delay();

        return k;
}

void write_add(uint address,uchar date)
{
        uchar address_h,address_l;
        address_h=address/256;
        address_l=address%256;
        start();
        write_byte(0xa0);
        respons();
        write_byte(address_h);
        respons();
        write_byte(address_l);
        respons();
        write_byte(date);
        respons();
        stop();
}

uchar read_add(uint address)
{
        uchar date;
        uchar address_h,address_l;
        address_h=address/256;
        address_l=address%256;
        start();
        write_byte(0xa0);
        respons();
        write_byte(address_h);
        respons();
        write_byte(address_l);
        respons();
        start();
        write_byte(0xa1);
        respons();
        date=read_byte(IIC_NACK);
        stop();
        return date;
}

void usart_init()
{
        TRISB=0xff;
        TXSTA=0x24;
        RCSTA=0x90;
        SPBRG=25;
        GIE=1;
        PEIE=1;
        RCIE=1;
        WPUB5=0;        //禁止RB5弱上拉
}

void main()
{
        OSCCON=0B01100110;//4MHz;器件运行在内部振荡器之下;高频稳定;低频稳定;时钟源由FOSC<2:0>决定
        ANSEL                                =        0X00;
        ANSELH                                =        0X00;
        usart_init();
        TRISC4=0;
        TRISC5=0;
        init();
        sec=0xcc;
        write_add(0x00a0,sec);  //写入数据
        delay1ms(500);
        sec=read_add(0x00a0);        //读出所写的数据
        while(1)
        {
                TXREG=sec;          //将读出的数据通过串口发送给串口调试助手
                while(!TRMT);
                delay1ms(1000);
        }
}

使用特权

评论回复
15
xch| | 2022-1-5 18:21 | 只看该作者
橘子阿小 发表于 2022-1-5 10:15
#include  
//__CONFIG(INTIO&WDTEN&PWRTEN&MCLRDIS);
__CONFIG(0x3b34);

晚上帮你看看

使用特权

评论回复
16
coody| | 2022-1-5 20:48 | 只看该作者
每写一个字节就停止的话,要等10ms再写下一个字节,否则就连续写入再发停止信号,最多写入一个页的字节数。

使用特权

评论回复
17
xch| | 2022-1-5 22:03 | 只看该作者
本帖最后由 xch 于 2022-1-6 01:20 编辑
橘子阿小 发表于 2022-1-5 10:15
#include  
//__CONFIG(INTIO&WDTEN&PWRTEN&MCLRDIS);
__CONFIG(0x3b34);

#include <pic.h>
//__CONFIG(INTIO&WDTEN&PWRTEN&MCLRDIS);
__CONFIG(0x3b34);
#define uchar unsigned char
#define uint unsigned int
#define scl RC4
#define sda RC5
#define faile 1
#define success 0
uchar sec;
uchar readbackdata;
void start(void);
void stop(void);
//uchar table[]={0x48,0x3d,0x6d,0x4b,0x67,0x77,0x4c,0x7f,0x6f};
void delay()    //假设延时符合要求
{ ;;;;;;;;;;;;;}
void delay1ms(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--); //看样子一拍延时9us;
}

void HizSDA(void)
{
    TRISC5 =1;
    sda = 1;
}
void PullDownSDA(void)
{
   sda =0;
   TRISC5 =0;
}

void stop()   //停止
{   PullDownSDA();
    delay();
    scl=1;
    delay();
    HizSDA();
    delay();
}

void start()  //开始信号
{
    PullDownSDA();
        delay();
    scl = 0;
        delay();
}
void restart(void)
{
    stop();
    start();
}

uchar GetAck(void)
{
    uchar ackbit;
        HizSDA();
        scl=1;
        delay();
        ackbit  = sda;
        scl=0;
        PullDownSDA();
        delay();
        return ackbit;
}

void EchoAck(uchar ackbit )
{
    if ( ackbit )
        HizSDA();
    else
        PullDownSDA();
    delay();
    scl=1;
    delay();
    scl =0;
    PullDownSDA();
    delay();
}

void init()
{
    start();
    stop();
}

void write_byte(uchar date)
{
    uchar i=8;
    for (;i;i--)
    {
          if( date&0x80)
            HizSDA();
          else
            PullDownSDA();
          date <<=1;
          delay();//bypass??
          scl =1;
          delay();
          scl = 0;
          delay();
    }
}

uchar read_byte(void)
{
    uchar result = 0,i = 8;
    HizSDA();
    for(;i;i--)
    {
        result <<=1;
        scl =1;
        delay();
        if (sda == 1)
            result |=1;
       scl = 0;
       delay();
    }
    return result;
}

uchar write_add(uint address,uchar date)
{
        uchar address_h,address_l;
        address_h=address/256;
        address_l=address%256;

        start();
        write_byte(0xa0);
        if ( GetAck())
        {
           stop();
           return faile;
        }
        write_byte(address_h);
        if ( GetAck())
        {
           stop();
           return faile;
        };
        write_byte(address_l);
        if ( GetAck())
        {
           stop();
           return faile;
        }
        write_byte(date);
        if ( GetAck())
        {
           stop();
           return faile;
        }
        stop();
        return success;
}
//uchar readbackdata;
uchar read_add(uint address)
{
        uchar date;
        uchar address_h,address_l;
        address_h=address/256;
        address_l=address%256;
        start();
        write_byte(0xa0);
        if ( GetAck())
        {
           stop();
           return faile;
        }
        write_byte(address_h);
        if ( GetAck())
        {
           stop();
           return faile;
        }
        write_byte(address_l);
        if ( GetAck())
        {
           stop();
           return faile;
        }
        restart();
        write_byte(0xa1);
        if ( GetAck())
        {
           stop();
           return faile;
        }
        readbackdata = read_byte();
        EchoAck(1);
        stop();
        return success;
}
uchar polling(void)
{
    uchar ackbit =0;
    start();
    write_byte(0xa0);
    ackbit = GetAck();
    stop();
    return ackbit;
}
void usart_init()
{
        TRISB=0xff;
        TXSTA=0x24;
        RCSTA=0x90;
        SPBRG=25;
        GIE=1;
        PEIE=1;
        RCIE=1;
        WPUB5=0;        //禁止RB5弱上拉
}

void main()
{
        OSCCON=0B01100110;//4MHz;器件运行在内部振荡器之下;高频稳定;低频稳定;时钟源由FOSC<2:0>决定
        ANSEL                                =        0X00;
        ANSELH                                =        0X00;
        usart_init();
        TRISC4=0;
        TRISC5=0;
        init();
        sec=0xcc;
        write_add(0x00a0,sec);  //写入数据
        //delay1ms(500);
        while(polling());   //等待就绪
        if(  success == read_add(0x00a0) )
            sec = readbackdata;        //复制数据
        else
            while(1);
        while(1)
        {
                TXREG=sec;          //将读出的数据通过串口发送给串口调试助手
                while(!TRMT);
                delay1ms(1000);
        }
}

使用特权

评论回复
18
xch| | 2022-1-5 22:05 | 只看该作者
橘子阿小 发表于 2022-1-5 10:15
#include  
//__CONFIG(INTIO&WDTEN&PWRTEN&MCLRDIS);
__CONFIG(0x3b34);

没看到你写两次eeprom

使用特权

评论回复
19
xch| | 2022-1-6 01:18 | 只看该作者
void stop()   //停止
{
   PullDownSDA();
  delay();
    scl=1;
    delay();
    HizSDA();
    delay();
}
补充修改。

使用特权

评论回复
20
昨天| | 2022-1-6 10:38 | 只看该作者
这个比较头疼,烧脑壳。

使用特权

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

本版积分规则

65

主题

152

帖子

1

粉丝