使用24LC64遇到的问题,求帮助
我用IO模拟I2C存数据,单次存储的话读出数据不变,但是如果在第一次存储后面加上第二次存储,然后读取第一次存储的数据就会出错,感觉像是产生移位,如果第二次的存储地址距第一次较远(第一次0x0000,第二次0x01ff)又不会出现问题;我怀疑是芯片的问题,可是我用了两块24LC64都是这样,然后我微调了程序用24C02,完美显示两次存储,求求各位大神帮忙!PS:两次写之间有延时还是怀疑程序的问题靠谱些 那我再搞会程序,这一次可以,为什么两次就不可以呢!!! ayb_ice 发表于 2015-4-25 15:49
还是怀疑程序的问题靠谱些
那我再搞会程序,这一次可以,为什么两次就不可以呢!!! 秋水水天 发表于 2015-4-25 15:52
那我再搞会程序,这一次可以,为什么两次就不可以呢!!!
应该是你的程序本身有BUG,随机性较强,我估计是没有搞明白应答与非应答的区别
什么时候用应答信号,什么时候用非应答信号,还有是发送应答还是接收应答。。。 ayb_ice 发表于 2015-4-25 16:28
应该是你的程序本身有BUG,随机性较强,我估计是没有搞明白应答与非应答的区别
什么时候用应答信号,什 ...
我查了一下时序,应该没问题,因为我用24C02试过,一点问题都没有,还有我使用Protues模拟也是一点问题没有,太苦恼了,问题到底在哪里! 如果可能的话帮我看看这个文件,我是根据原子的程序改的,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或者更大地址的话那两个数据都可以正确显示。
简单的看了一下 秋水水天 发表于 2015-4-25 17:40
如果可能的话帮我看看这个文件,我是根据原子的程序改的,AT24CXX_WriteTwoByte(0x0000,11256);
AT24CXX_Wr ...
简单的看了一下
至少有两个问题
1 如果时序中间出错,根本没有相应处理,还是在往下处理
2 GPIO转换为输出前,应该有明确的输出值,而不是转换后再输出值,否则时序可能已经出错了,这点很重要的
手机不方便没有仔细看 另外还有个问题要注意,连续写不能直接跨页的, ayb_ice 发表于 2015-4-25 19:53
简单的看了一下
至少有两个问题
1 如果时序中间出错,根本没有相应处理,还是在往下处理
嗯嗯,谢谢了,我改一下试试 ayb_ice 发表于 2015-4-25 19:59
另外还有个问题要注意,连续写不能直接跨页的,
还是没搞定呀,这里的问题是第二次写会影响第一次写的数据,我找不到问题所在了。快崩溃了。 ayb_ice 发表于 2015-4-25 19:59
另外还有个问题要注意,连续写不能直接跨页的,
还是没搞定呀,这里的问题是第二次写会影响第一次写的数据,我找不到问题所在了。快崩溃了。 仔细检查一下AT24CXX_WriteTwoByte和AT24CXX_ReadTwoByte这两个函数,可能你的程序适用于AT24C02,但要改到24L64上可能在地址的处理上需要做一些改动。 秋水水天 发表于 2015-5-4 12:35
还是没搞定呀,这里的问题是第二次写会影响第一次写的数据,我找不到问题所在了。快崩溃了。 ...
读第二个数据前为何没有应答信号呢,每次字节处理后都要有应答处理才对
IIC_Wait_Ack();
temp1=IIC_Read_Byte(1);
.......................................
temp2=IIC_Read_Byte(0);
IIC_Stop();//产生一个停止条件 ningling_21 发表于 2015-5-4 13:13
读第二个数据前为何没有应答信号呢,每次字节处理后都要有应答处理才对
IIC_Wait_Ack();
有应答信号,(1)表示应答,(0)表示非应答。 desertsailor 发表于 2015-5-4 12:51
仔细检查一下AT24CXX_WriteTwoByte和AT24CXX_ReadTwoByte这两个函数,可能你的程序适用于AT24C02,但要改到 ...
地址我改动过了,无论写单字节双字节,第二次写都会影响第一次。单词读写没有错误,我想问一下这种问题错误会出现在哪里? 秋水水天 发表于 2015-5-4 13:32
地址我改动过了,无论写单字节双字节,第二次写都会影响第一次。单词读写没有错误,我想问一下这种问题错 ...
用示波器看看波形,一般就很容容易发现问题的所在,或楼主把波形拍下来发上来 ningling_21 发表于 2015-5-4 14:59
用示波器看看波形,一般就很容容易发现问题的所在,或楼主把波形拍下来发上来 ...
新买来示波器我不怎么会用,鼓捣了一下感觉从波形上没问题,大神看一下吧
地址分别是0x0000写入0x55,地址0x0020,写入0xaa.读出来的话第一个读出来是0(不对),第二个170对应0xaa(对)。
给个程序你参考一下,只需要关注几个程序即可
/*_____________________________________________________________________________________________
*_____________________________________________________________________________________________
*
* 优 利 德 科 技(中国)有 限 公 司
* 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) == 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 = i2c_receive(I2C_NACK);
}else{
p2 = 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) == 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 = i2c_receive_lsb(I2C_NACK);
}else{
p2 = 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
//______________________________________________________________
页:
[1]
2