打印
[STM32]

使用24LC64遇到的问题,求帮助

[复制链接]
4779|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我用IO模拟I2C存数据,单次存储的话读出数据不变,但是如果在第一次存储后面加上第二次存储,然后读取第一次存储的数据就会出错,感觉像是产生移位,如果第二次的存储地址距第一次较远(第一次0x0000,第二次0x01ff)又不会出现问题;我怀疑是芯片的问题,可是我用了两块24LC64都是这样,然后我微调了程序用24C02,完美显示两次存储,求求各位大神帮忙!PS:两次写之间有延时

相关帖子

沙发
ayb_ice| | 2015-4-25 15:49 | 只看该作者
还是怀疑程序的问题靠谱些

使用特权

评论回复
板凳
秋水水天|  楼主 | 2015-4-25 15:52 | 只看该作者
那我再搞会程序,这一次可以,为什么两次就不可以呢!!!

使用特权

评论回复
地板
秋水水天|  楼主 | 2015-4-25 15:52 | 只看该作者
ayb_ice 发表于 2015-4-25 15:49
还是怀疑程序的问题靠谱些


那我再搞会程序,这一次可以,为什么两次就不可以呢!!!

使用特权

评论回复
5
ayb_ice| | 2015-4-25 16:28 | 只看该作者
秋水水天 发表于 2015-4-25 15:52
那我再搞会程序,这一次可以,为什么两次就不可以呢!!!

应该是你的程序本身有BUG,随机性较强,我估计是没有搞明白应答与非应答的区别

什么时候用应答信号,什么时候用非应答信号,还有是发送应答还是接收应答。。。

使用特权

评论回复
6
秋水水天|  楼主 | 2015-4-25 17:32 | 只看该作者
ayb_ice 发表于 2015-4-25 16:28
应该是你的程序本身有BUG,随机性较强,我估计是没有搞明白应答与非应答的区别

什么时候用应答信号,什 ...

我查了一下时序,应该没问题,因为我用24C02试过,一点问题都没有,还有我使用Protues模拟也是一点问题没有,太苦恼了,问题到底在哪里!

使用特权

评论回复
7
秋水水天|  楼主 | 2015-4-25 17:40 | 只看该作者
如果可能的话帮我看看这个文件,我是根据原子的程序改的,AT24CXX_WriteTwoByte(0x0000,11256);
AT24CXX_WriteTwoByte(0x0002,11222);
temp1=AT24CXX_ReadTwoByte(0x0000);
temp2=AT24CXX_ReadTwoByte(0x0002);
Number_display1(200, 200, temp1);
Number_display1(200, 300, temp2);

这个是如何使用的,写的第二个显示正常,第一个不会显示11256,而是根据写入地址的不同而改变,如果我把写入的地址二改成0x01ff或者更大地址的话那两个数据都可以正确显示。

Desktop.rar

2.2 KB

24LC64

使用特权

评论回复
8
ayb_ice| | 2015-4-25 19:48 | 只看该作者
简单的看了一下

使用特权

评论回复
9
ayb_ice| | 2015-4-25 19:53 | 只看该作者
秋水水天 发表于 2015-4-25 17:40
如果可能的话帮我看看这个文件,我是根据原子的程序改的,AT24CXX_WriteTwoByte(0x0000,11256);
AT24CXX_Wr ...

简单的看了一下
至少有两个问题
1 如果时序中间出错,根本没有相应处理,还是在往下处理
2 GPIO转换为输出前,应该有明确的输出值,而不是转换后再输出值,否则时序可能已经出错了,这点很重要的

手机不方便没有仔细看

使用特权

评论回复
10
ayb_ice| | 2015-4-25 19:59 | 只看该作者
另外还有个问题要注意,连续写不能直接跨页的,

使用特权

评论回复
11
秋水水天|  楼主 | 2015-4-25 21:17 | 只看该作者
ayb_ice 发表于 2015-4-25 19:53
简单的看了一下
至少有两个问题
1 如果时序中间出错,根本没有相应处理,还是在往下处理

嗯嗯,谢谢了,我改一下试试

使用特权

评论回复
12
秋水水天|  楼主 | 2015-5-4 12:35 | 只看该作者
ayb_ice 发表于 2015-4-25 19:59
另外还有个问题要注意,连续写不能直接跨页的,

还是没搞定呀,这里的问题是第二次写会影响第一次写的数据,我找不到问题所在了。快崩溃了。

使用特权

评论回复
13
秋水水天|  楼主 | 2015-5-4 12:35 | 只看该作者
ayb_ice 发表于 2015-4-25 19:59
另外还有个问题要注意,连续写不能直接跨页的,

还是没搞定呀,这里的问题是第二次写会影响第一次写的数据,我找不到问题所在了。快崩溃了。

使用特权

评论回复
14
desertsailor| | 2015-5-4 12:51 | 只看该作者
仔细检查一下AT24CXX_WriteTwoByte和AT24CXX_ReadTwoByte这两个函数,可能你的程序适用于AT24C02,但要改到24L64上可能在地址的处理上需要做一些改动。

使用特权

评论回复
15
ningling_21| | 2015-5-4 13:13 | 只看该作者
秋水水天 发表于 2015-5-4 12:35
还是没搞定呀,这里的问题是第二次写会影响第一次写的数据,我找不到问题所在了。快崩溃了。 ...

读第二个数据前为何没有应答信号呢,每次字节处理后都要有应答处理才对

IIC_Wait_Ack();         
                temp1=IIC_Read_Byte(1);
    .......................................
                temp2=IIC_Read_Byte(0);
                IIC_Stop();//产生一个停止条件       

使用特权

评论回复
16
秋水水天|  楼主 | 2015-5-4 13:30 | 只看该作者
ningling_21 发表于 2015-5-4 13:13
读第二个数据前为何没有应答信号呢,每次字节处理后都要有应答处理才对

IIC_Wait_Ack();         

有应答信号,(1)表示应答,(0)表示非应答。

使用特权

评论回复
17
秋水水天|  楼主 | 2015-5-4 13:32 | 只看该作者
desertsailor 发表于 2015-5-4 12:51
仔细检查一下AT24CXX_WriteTwoByte和AT24CXX_ReadTwoByte这两个函数,可能你的程序适用于AT24C02,但要改到 ...

地址我改动过了,无论写单字节双字节,第二次写都会影响第一次。单词读写没有错误,我想问一下这种问题错误会出现在哪里?

使用特权

评论回复
18
ningling_21| | 2015-5-4 14:59 | 只看该作者
秋水水天 发表于 2015-5-4 13:32
地址我改动过了,无论写单字节双字节,第二次写都会影响第一次。单词读写没有错误,我想问一下这种问题错 ...

用示波器看看波形,一般就很容容易发现问题的所在,或楼主把波形拍下来发上来

使用特权

评论回复
19
秋水水天|  楼主 | 2015-5-4 19:10 | 只看该作者
ningling_21 发表于 2015-5-4 14:59
用示波器看看波形,一般就很容容易发现问题的所在,或楼主把波形拍下来发上来 ...

新买来示波器我不怎么会用,鼓捣了一下感觉从波形上没问题,大神看一下吧
地址分别是0x0000写入0x55,地址0x0020,写入0xaa.读出来的话第一个读出来是0(不对),第二个170对应0xaa(对)。

写入11.JPG (1.87 MB )

写入11.JPG

写入12.JPG (1.9 MB )

写入12.JPG

写入21.JPG (1.93 MB )

写入21.JPG

写入22.JPG (1.79 MB )

写入22.JPG

使用特权

评论回复
20
ayb_ice| | 2015-5-5 08:13 | 只看该作者
给个程序你参考一下,只需要关注几个程序即可

/*_____________________________________________________________________________________________
*_____________________________________________________________________________________________
*
*                                优 利 德 科 技(中国)有 限 公 司
*                               UNIT-TREND TECHNOLOGY(CHINA) LIMITED
*                                  http: //www.uni-trend.com.cn
*                            东莞松山湖**技术产业开发区工业北一路6号
*
*_____________________________________________________________________________________________
* 文 件 名: IIC.C
* 创 建 人: 艾艳斌(E-mail:1109706098@qq.com)
* 版    本: V1.00 / 2006-06-02
* 描    述: 通用IIC模拟驱动程序,通过头文件可以进行配置(只包括基本程序)
*_____________________________________________________________________________________________
* 修 改 人: 艾艳斌
* 版    本: V1.01 / 2006-06-25
* 描    述: 增加IIC_RECEIVE_EN定义,快速屏蔽iic_receive函数(有些情况不用,如PCF8576)
*_____________________________________________________________________________________________
* 修 改 人: 艾艳斌
* 版    本: V1.02 / 2006-07-19
* 描    述: 改进IIC延时函数,使之能适应多种速度IIC器件共存(false=0方式效率高)
*_____________________________________________________________________________________________
* 修 改 人: 艾艳斌
* 版    本: V1.03 / 2006-07-20
* 描    述: 增加iic_query函数(更加通用,适用于多IIC器件查询)
*_____________________________________________________________________________________________
* 修 改 人: 艾艳斌
* 版    本: V1.04 / 2006-07-29
* 描    述: 修改延时程序结构,使SCL高低电平周期容易相等,有利于最大限度利用总线频率(基于_nopx),
*   增加iic_query函数另外二个高效代码版本
*_____________________________________________________________________________________________
* 修 改 人: 艾艳斌
* 版    本: V1.04 / 2012-08-23
* 描    述: 只保留一个iic_query函数
*_____________________________________________________________________________________________
*_____________________________________________________________________________________________
*/



#define __I2C_C
#include "HEADER.H"
#include "I2C.H"


/* 改进记录 / abin 2012-09-20
________________________________________________________________
2013-08-22:
2014-04-14:
        -- 完整支持LSB模式,
        -- 增加函数i2c_send_lsb,i2c_receive_lsb,
                适应某些非I2C标准器件.
        -- 优化延时宏(程序)结构,便于维护.
        -- 增加函数i2c_send_repeat_n_bytes.
        -- 增加函数i2c_send_n_bytes,i2c_receive_n_bytes,提高效率.
        -- iic_query_general更名为iic_query,原iic_query函数去掉.
        -- 优化程序,方便移植到不同架构的MCU上.
        -- 返回时总线SDA,SCL总是为高,iic_send程序优化,待测试.
        -- 增加iic_query_general函数,严格按照手册时序图执行.
                用以取代iic_query函数,iic_query针对有些器件有BUG.

        -- 为方便移植,改造程序。
        -- 精确控制IIC时序延时,更优化,更合理。
        -- 优化程序结构,简化配置,原多速度配置是错误的。
        -- 增加函数i2c_receive_ack,i2c_receive_nack
________________________________________________________________
2015-02-04:
        -- 优化i2c_query函数,支持任何时候调用,不会死机。
________________________________________________________________
2015-05-04:
        -- 修正了i2c_query的小BUG。

________________________________________________________________
*/




//______________________________________________________________
// i2c_init();
//______________________________________________________________
//
// IIC总线初始化
//
#if EN_i2c_init > 0
bit i2c_init(void)
{
        GPIO_ON(GPIO_I2C_WP);
        GPIO_OFF(GPIO_I2C_SCL);
        GPIO_OFF(GPIO_I2C_SDA);

        GPIO_OUTPUT(GPIO_I2C_WP);
        GPIO_OUTPUT(GPIO_I2C_SCL);
        GPIO_OUTPUT(GPIO_I2C_SDA);

        GPIO_ON(GPIO_I2C_WP);
        GPIO_OFF(GPIO_I2C_SCL);
        GPIO_OFF(GPIO_I2C_SDA);

        i2c_delay_std();
        i2c_stop();

        return true;
}
#endif

//______________________________________________________________
// i2c_start();
//______________________________________________________________
//
// I2C开始信号,注意结束时GPIO_IIC_SCL=0,GPIO_IIC_SDA=1
//
#if EN_i2c_start > 0
void i2c_start(void)
{
        SCL_0();
        i2c_delay_std();

        SDA_1();
        SDA_OUTPUT();
        SDA_1();
        i2c_delay_std();
        SCL_1();
        i2c_delay_std();

        SDA_0();
        i2c_delay_std();

        SCL_0();        // SCL = 0, SDA = 1
        i2c_delay_std();
        SDA_1();
}
#endif

//______________________________________________________________
// i2c_stop();
//______________________________________________________________
//
// I2C停止信号,结束时SDA=1,SCL=1,确保I2C总线在停止状态
//
#if EN_i2c_stop > 0
void i2c_stop(void)
{
        SCL_0();
        i2c_delay_std();

        SDA_0();
        SDA_OUTPUT();
        SDA_0();
        i2c_delay_std();

        SCL_1();
        i2c_delay_std();

        SDA_1();
        i2c_delay_std();
}
#endif

//______________________________________________________________
// if(true != i2c_send(PCF8576_WRITE))...
//______________________________________________________________
//
// 发送一个字节,失败后会自动停止总线(发送stop)
// byte = 数据
// 返回: false = 失败, true = 成功
//
#if EN_i2c_send > 0
bit i2c_send(U8 byte)
{
        U8 i;

        SDA_OUTPUT();
        for(i=8; i; i--){
                byte <<= 1, SDA_OUT(PSW_CY);        // GPIO_IIC_SDA = CY;
                i2c_delay_da();

                SCL_1();
                i2c_delay_ck1();

                SCL_0();
                i2c_delay_ck0();
        }

        SDA_OUT(1);
        SDA_INPUT();
        i2c_delay_da();
        SCL_1();
        i2c_delay_std();
//___________________________________
// 等待从机应答,超时失败自动退出
        for(i=16; i; i--){
                if(!SDA_IN()){
                        SCL_0();
                        return true;
                }else{
//                        __debug();
                }
        }

//________________
// 失败停止总线
        i2c_stop();

        return false;
}
#endif

//______________________________________________________________
// x = i2c_receive(NACK);
//______________________________________________________________
//
// 接收一个字节
// ack : 应答信号ACK或NACK
// 返回: 接收的字节
// 注: 软件模拟方式无法判断是否成功或失败,所以总是成功
//
#if EN_i2c_receive > 0
U8 i2c_receive(U8 ack)
{
    U8 i;
    U8 temp;

        SDA_1();
    SDA_INPUT();
    temp = 0;
        for(i=8; i; i--){
        temp <<= 1;
        SCL_1();
        i2c_delay_ck1();
        if(SDA_IN()){
                        temp++;
                }
        SCL_0();
        i2c_delay_ck0();
    }
//________________
// 主机应答从机
        SDA_OUTPUT();
        SDA_OUT(ack);
    i2c_delay_da();

    SCL_1();
    i2c_delay_std();

    SCL_0();
        i2c_delay_std();

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

    return temp;
}
#endif

//______________________________________________________________
// x = i2c_receive_ack();
//______________________________________________________________
//
// 接收一个字节,并应答
//
#if EN_i2c_receive_ack > 0
U8 i2c_receive_ack(void)
{
        U8 i;
    U8 temp = 0;

    SDA_INPUT();
        for(i=0; i<8; i++){
        SCL_1();
        i2c_delay_ck1();
                temp <<= 1;
        if(SDA_IN()){
                        temp++;
                }
        SCL_0();
        i2c_delay_ck0();
    }
//________________
// 主机应答从机
        SDA_OUTPUT();
        SDA_OUT(I2C_ACK);        // I2C_NACK
    i2c_delay_da();

    SCL_1();
    i2c_delay_std();

    SCL_0();
        i2c_delay_std();

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

    return temp;
}
#endif

//______________________________________________________________
// x = i2c_receive_nack();
//______________________________________________________________
//
// 接收一个字节,并非应答
//
#if EN_i2c_receive_nack > 0
U8 i2c_receive_nack(void)
{
        U8 i;
    U8 temp = 0;

    SDA_INPUT();
        for(i=0; i<8; i++){
        SCL_1();
        i2c_delay_ck1();
                temp <<= 1;
        if(SDA_IN()){
                        temp++;
                }
        SCL_0();
        i2c_delay_ck0();
    }
//________________
// 主机应答从机
        SDA_OUTPUT();
        SDA_OUT(I2C_NACK);        // I2C_ACK
    i2c_delay_da();

    SCL_1();
    i2c_delay_std();

    SCL_0();
        i2c_delay_std();

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

    return temp;
}
#endif

//______________________________________________________________
// i2c_send_repeat_n_bytes
//______________________________________________________________
//
// 发送多个重复的字节(主要用于初始化).
//
#if EN_i2c_send_repeat_n_bytes > 0
bit i2c_send_repeat_n_bytes(const U8 d, U8 n)
{
        for(__null; n; n--){
                if(i2c_send(d) == false){
                        return false;
                }
        }

        return true;
}
#endif

//______________________________________________________________
// i2c_send_n_bytes
//______________________________________________________________
//
// 发送多个字节
//
#if EN_i2c_send_n_bytes > 0
bit i2c_send_n_bytes(void* p, U8 n)
{
        U8* p2;

        p2 = (U8*)p;
        for(__null; n; n--,p2++){
                if(i2c_send(p2[0]) == false){
                        return false;
                }
        }

        return true;

}
#endif

//______________________________________________________________
// i2c_receive_n_bytes
//______________________________________________________________
//
// 接收多个字节
//
#if EN_i2c_receive_n_bytes > 0
bit i2c_receive_n_bytes(void* p, U8 n)
{
        U8* p2;

        p2 = (U8*)p;
        for(__null; n; n--,p2++){
                if(n == 1){
                        p2[0] = i2c_receive(I2C_NACK);
                }else{
                        p2[0] = i2c_receive(I2C_ACK);
                }
        }

        return true;

}
#endif

//______________________________________________________________
// if(true != i2c_query(PCF8576_WRITE, 10ms))...
//______________________________________________________________
//
// 查询IIC器件操作是否完成
// device = 器件选择(建议写操作,主机主动)
// timeout = 超时间
// 返回: false = 未完成, true = 完成
//
// 注意: 可能不同的设备需要定制查询程序
//
#if EN_iic_query > 0
bit i2c_query(U8 device, U8 timeout)
{
        U8 t0;
//________________
// 简化算法
//        sys_delay(timeout);
//        return true;

//________________
// 正常算法
        if(IEN0_EAL && TCON_TR0){
                t0 = ayb_isr_inc_get();
                for(;;){
                        i2c_start();        // !!!

                        if(i2c_send(device) == true){
                                i2c_stop();
                                return true;
                        }
                        if(ayb_isr_inc_get() - t0 >= timeout){        // timeout
//                                i2c_stop();
                                return false;
                        }
                }
        }else{
                for(;;){
                        i2c_start();        // !!!
                        if(i2c_send(device) == true){
                                i2c_stop();
                                return true;
                        }
                        ayb_delay(1ms);
                        if(--timeout == 0){
//                                i2c_stop();
                                return false;
                        }
                }
        }
}
#endif



/*
//______________________________________________________________
// 完整的LSB方式
//______________________________________________________________
*/

//______________________________________________________________
// if(true != i2c_send_lsb(PCF8576_WRITE))...
//______________________________________________________________
//
// 发送一个字节,失败后会自动停止总线(发送stop)
// byte = 数据
// 返回: false = 失败, true = 成功
//
#if EN_i2c_send_lsb > 0
bit i2c_send_lsb(U8 byte)
{
        U8 i;

        SDA_OUTPUT();
        for(i=8; i; i--){
                byte >>= 1, SDA_OUT(PSW_CY);        // GPIO_IIC_SDA = CY;
                i2c_delay_da();

                SCL_1();
                i2c_delay_ck1();

                SCL_0();
                i2c_delay_ck0();
        }

        SDA_INPUT();
        i2c_delay_da();
        SCL_1();
        i2c_delay_std();
//___________________________________
// 等待从机应答,超时失败自动退出
        for(i=16; i; i--){
                if(!SDA_IN() == 1){
                        SCL_0();
                        return true;
                }else{
//                        __debug();
                }
        }

//________________
// 失败停止总线
        i2c_stop();

        return false;
}
#endif

//______________________________________________________________
// x = i2c_receive_lsb(NACK);
//______________________________________________________________
//
// 接收一个字节
// ack : 应答信号ACK或NACK
// 返回: 接收的字节
// 注: 软件模拟方式无法判断是否成功或失败,所以总是成功
//
#if EN_i2c_receive_lsb > 0
U8 i2c_receive_lsb(U8 ack)
{
    U8 i;
    U8 temp;

    SDA_INPUT();
    temp = 0;
        for(i=8; i; i--){
        temp >>= 1;
        SCL_1();
        i2c_delay_ck1();
        if(SDA_IN() == 1){
                        temp |= BIT7;
                }
        SCL_0();
        i2c_delay_ck0();
    }
//________________
// 主机应答从机
        SDA_OUTPUT();
        SDA_OUT(ack);
    i2c_delay_da();

    SCL_1();
    i2c_delay_std();

    SCL_0();
        i2c_delay_std();

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

    return temp;
}
#endif

//______________________________________________________________
// i2c_send_lsb_n_bytes
//______________________________________________________________
//
// 发送多个字节
//
#if EN_i2c_send_lsb_n_bytes > 0
bit i2c_send_lsb_n_bytes(void* p, U8 n)
{
        U8* p2;

        p2 = (U8*)p;
        for(__null; n; n--,p2++){
                if(i2c_send_lsb(p2[0]) == false){
                        return false;
                }
        }

        return true;

}
#endif

//______________________________________________________________
// i2c_receive_lsb_n_bytes
//______________________________________________________________
//
// 接收多个字节
//
#if EN_i2c_receive_lsb_n_bytes > 0
bit i2c_receive_lsb_n_bytes(void* p, U8 n)
{
        U8* p2;

        p2 = (U8*)p;
        for(__null; n; n--,p2++){
                if(n == 1){
                        p2[0] = i2c_receive_lsb(I2C_NACK);
                }else{
                        p2[0] = i2c_receive_lsb(I2C_ACK);
                }
        }

        return true;

}
#endif




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

#if I2C_DELAY_MODE != 0

//______________________________________________________________
// i2c_delay_ss,i2c_delay_da,i2c_delay_ck1,i2c_delay_ck0
//______________________________________________________________
//
// iic延时函数
//
static void i2c_delay_std(void)
{
        __nops(NOPS_i2c_delay_std);
}

static void i2c_delay_da(void)
{
        __nops(NOPS_i2c_delay_da);
}

static void i2c_delay_ck1(void)
{
        __nops(NOPS_i2c_delay_ck1);
}

static void i2c_delay_ck0(void)
{
        __nops(NOPS_i2c_delay_ck0);
}

#endif        // #if IIC_DELAY_MODE != 0





//______________________________________________________________
// @End
//______________________________________________________________

使用特权

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

本版积分规则

36

主题

227

帖子

0

粉丝