OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4233|回复: 19

模拟I2C 访问eeprom 读好使 写不好使???

[复制链接]

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
发表于 2014-3-5 11:44:56 | 显示全部楼层 |阅读模式
各位大牛,以前用库一直出问题,找了好久看到大家的帖子,决定还是模拟吧。用的原子哥的代码,现在的问题是读没问题(E2里已经有内容,是24c02),但是写不进去。

尝试过:
1.加一些额外的延时 和相应的延时时间

2.只写一个字节(此函数的中的内容在读里面都用了,按说功能是好使的)

3.换不同地址写

4.IO口方式配置

因此我现在不知道该怎么查了,大家帮帮我,看看有没有遇到过类似的现象,解决方法,如果没遇到,目前的思路是啥,谢谢啦!!!

对了 程序里有200ms的SysTick中断,有影响吗?








正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
 楼主| 发表于 2014-3-5 12:11:36 | 显示全部楼层
贴程序:

//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT();     //sda线输出
SDA_H;      
SCL_H;
delay_nnus(4);
  SDA_L;//START:when CLK is high,DATA change form high to low 
delay_nnus(4);
SCL_L;//钳住I2C总线,准备发送或接收数据
}   
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
SCL_L;
SDA_L;//STOP:when CLK is high DATA change form low to high
  delay_nnus(4);
SCL_H; 
SDA_H;//发送I2C总线结束信号
delay_nnus(4);    
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN();      //SDA设置为输入  
SDA_H;delay_nnus(1);    
SCL_H;delay_nnus(1);  
while(SDA_read)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
SCL_L;//时钟输出0
return 0;  

//产生ACK应答
void IIC_Ack(void)
{
SCL_L;
SDA_OUT();
SDA_L;
delay_nnus(2);
SCL_H;
delay_nnus(2);
SCL_L;
}
//不产生ACK应答     
void IIC_NAck(void)
{
SCL_L;
SDA_OUT();
SDA_H;
delay_nnus(2);
SCL_H;
delay_nnus(2);
SCL_L;
}        
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答   
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
SDA_OUT();      
    SCL_L;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        if(txd&0x80)
SDA_H;
else
SDA_L;
        txd<<=1;    
delay_nnus(2);   //对TEA5767这三个延时都是必须的
SCL_H;
delay_nnus(2); 
SCL_L;
delay_nnus(2);
    }  
}      
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(u8 ack)
{
u8 i,receive=0;
SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
{
        SCL_L; 
        delay_nnus(2);
SCL_H;
        receive<<=1;
        if(SDA_read)receive++;   
delay_nnus(1); 
    }  
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

//在AT24CXX指定地址读出一个数据
//ReadAddr:开始读数的地址  
//返回值:读到的数据
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{   
u8 temp=0;          
    IIC_Start();  
if(e2prom>16)                  //AT24C16
{
IIC_Send_Byte(0xA0);    //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(ReadAddr>>8);//发送高地址     
}else IIC_Send_Byte(0xA0+((ReadAddr/256)<<1));   //发送器件地址0XA0,写数据     
IIC_Wait_Ack(); 
    IIC_Send_Byte(ReadAddr%256);   //发送低地址
IIC_Wait_Ack();     
IIC_Start();        
IIC_Send_Byte(0xA1);           //进入接收模式    
IIC_Wait_Ack();  
    temp=IIC_Read_Byte(0);    
    IIC_Stop();                    //产生一个停止条件     
return temp;
}

//在AT24CXX指定地址写入一个数据
//WriteAddr:写入数据的目的地址    
//DataToWrite:要写入的数据
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{              
    IIC_Start();  
if(e2prom>16)                   //AT24C16
{
IIC_Send_Byte(0xA0);     //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr>>8);//发送高地址   
}else IIC_Send_Byte(0xA0+((WriteAddr/256)<<1));  //发送器件地址0XA0,写数据   
IIC_Wait_Ack();    
    IIC_Send_Byte(WriteAddr%256);   //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite);     //发送字节    
IIC_Wait_Ack();           
    IIC_Stop();                     //产生一个停止条件 
delay_nnms(50);  
}
回复 支持 反对

使用道具 举报

36

主题

1263

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1612
金钱
1612
注册时间
2012-6-15
在线时间
39 小时
发表于 2014-3-5 12:18:01 | 显示全部楼层
EE, 写的时候 ,每写一个字节,需要延迟一会 2~5ms 否则写入不成功。
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
 楼主| 发表于 2014-3-5 12:54:46 | 显示全部楼层
我现在就调用AT24CXX_WriteOneByte 写一个字节,用断点调,时间应该足够了,但是写不成功,ACK都有。

会是片子的问题吗?

回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2014-3-5 13:01:52 | 显示全部楼层
回复【4楼】youngboy:
---------------------------------
用示波器看下时序什么的对了没
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
 楼主| 发表于 2014-3-5 13:21:34 | 显示全部楼层
嗯,现在没示波器,所以看程序debug,呵呵。
回复 支持 反对

使用道具 举报

60

主题

409

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2814
金钱
2814
注册时间
2012-10-17
在线时间
653 小时
发表于 2014-3-5 13:23:30 | 显示全部楼层
原子大大的程式可以寫啊~我把它複製到F28335 稍微改一下也可以寫,
應該是像2F說的那樣,我之前也卡在那2~3天,主要就2個問題。

1.連續寫入不能跨頁寫(24C08 一頁是16 byte),例如 你一次寫16Byte從位址0x05開始寫,
等寫到0x0F的時候,剩下的資料會又從那頁的位址0x00開始寫入。

2.不管是連續寫或一次寫一Byte,在STOP信號與下一筆START信號之間都要加上延遲(2ms)。
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
 楼主| 发表于 2014-3-5 13:29:14 | 显示全部楼层
写一个字节函数:
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{              
    IIC_Start();  
if(e2prom>16)                   //AT24C16
{
IIC_Send_Byte(0xA0);     //发送写命令
IIC_Wait_Ack();
IIC_Send_Byte(WriteAddr>>8);//发送高地址   
}else IIC_Send_Byte(0xA0+((WriteAddr/256)<<1));  //发送器件地址0XA0,写数据   
IIC_Wait_Ack();    
    IIC_Send_Byte(WriteAddr%256);   //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(DataToWrite);     //发送字节    
IIC_Wait_Ack();           
    IIC_Stop();                     //产生一个停止条件 
delay_nnms(50);  
}

MAIN 调用:
AT24CXX_WriteOneByte(0x00,0x0f); 设断点
temp=AT24CXX_ReadOneByte(0x00);      设断点

目前延时是50ms  同时设断点调,我觉得 IIC_Stop();后的时间等待应该足够了吧。
回复 支持 反对

使用道具 举报

60

主题

409

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2814
金钱
2814
注册时间
2012-10-17
在线时间
653 小时
发表于 2014-3-5 15:21:51 | 显示全部楼层
看起來沒啥問題...
你檢查一下temp=IIC_Wait_Ack(); return 0 還是 1
看有沒有應答...
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
 楼主| 发表于 2014-3-5 15:32:49 | 显示全部楼层
返回的是0 这个我已经检查过了。  55555555555555

大家帮帮我吧!!!!!!!

实在不行啦!!!!!!!

片子刚换了,也不行,应该不是硬件问题,因为用以前库程序是可以写入的,只是不稳定。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2014-3-5 17:03:14 | 显示全部楼层
IO配置是不是有问题?
移植下我们的代码吧,很简单的。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
 楼主| 发表于 2014-3-5 17:12:06 | 显示全部楼层
我是移植的您的程序吧。

void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Configure I2C1 pins: SCL and SDA */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
  GPIO_SetBits(GPIOB,GPIO_Pin_6);
  GPIO_SetBits(GPIOB,GPIO_Pin_7);
}


//IO方向设置
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(unsigned int)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(unsigned int)3<<28;}

//IO操作函数  
#define SCL_H         GPIOB->BSRR = GPIO_Pin_6
#define SCL_L         GPIOB->BRR  = GPIO_Pin_6        
#define SDA_H         GPIOB->BSRR = GPIO_Pin_7
#define SDA_L         GPIOB->BRR  = GPIO_Pin_7
#define SCL_read      GPIOB->IDR  & GPIO_Pin_6
#define SDA_read      GPIOB->IDR  & GPIO_Pin_7
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2014-3-5 17:51:28 | 显示全部楼层
回复【12楼】youngboy:
---------------------------------
CLK设置为推挽输出试试吧。
其他的貌似没问题。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
 楼主| 发表于 2014-3-5 18:20:40 | 显示全部楼层
找了个示波器看了一下,确实有问题,sda下不来,低电平在逐渐往下落,即在以一个往下降的低电平上叠加的脉冲,读写都这样,但是读好使。

看了用库写好使的程序,波形差不过,只不过库是50K  模拟的这个是250k

上拉4.7K

大家说是什么问题?
回复 支持 反对

使用道具 举报

24

主题

66

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
342
金钱
342
注册时间
2012-6-27
在线时间
44 小时
发表于 2014-3-5 21:57:15 | 显示全部楼层
回复【14楼】youngboy:
---------------------------------
看你用什么芯片,430的我验证过原子的程序不行,不管IO上拉还是串
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
 楼主| 发表于 2014-3-5 22:11:36 | 显示全部楼层
stm32呀   st的24c02w3   SCL信号很好  SDA不好,输出0的时候电平下不来  用的4.7K电阻  是不是换小点的 让速度快点? 现在是250K
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
 楼主| 发表于 2014-3-6 15:29:07 | 显示全部楼层
终于好了!首先谢谢大家的帮助!!!

波形的问题是示波器一个表笔坏了  555555555

最终解决:
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
SCL_L;
SDA_L;//STOP:when CLK is high DATA change form low to high
  delay_nnus(4);
SCL_H;
delay_nnus(4);   //******************************************************************
SDA_H;//发送I2C总线结束信号
delay_nnus(4);    
}

stop函数中,加了个延时,注意上边打星的那行,从示波器上看最后停止的波形,感觉时钟置高以后的时间太短,怀疑是不是e2没认为这是个停止信号,所以加上延时试了一下,好使了,嘿嘿

另外:延时函数用示波器标了一下,现在1us比较准:   目前的波特率142k 即时钟一位7us
void delay_us(void)
{
//72MHZ时钟
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();
}
回复 支持 反对

使用道具 举报

30

主题

705

帖子

1

精华

新手上路

积分
21
金钱
21
注册时间
2013-3-14
在线时间
52 小时
发表于 2014-3-6 18:00:04 | 显示全部楼层
回复【楼主位】youngboy:
---------------------------------
http://www.openedv.com/posts/list/19827.htm
原子哥是不是又要出黑科技了呀。^_^...
回复 支持 反对

使用道具 举报

1

主题

11

帖子

0

精华

新手上路

积分
35
金钱
35
注册时间
2014-3-5
在线时间
0 小时
 楼主| 发表于 2014-3-6 18:21:12 | 显示全部楼层
17楼兄弟什么意思?呵呵
回复 支持 反对

使用道具 举报

1

主题

83

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3556
金钱
3556
注册时间
2017-7-10
在线时间
390 小时
发表于 2018-2-27 10:36:57 | 显示全部楼层
这个stop的时序有些问题
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
SCL_L;
SDA_L;//STOP:when CLK is high DATA change form low to high
        delay_nnus(4);
SCL_H;  
        delay_nnus(4);  //需加这个延时!
SDA_H;//发送I2C总线结束信号
delay_nnus(4);                  
}
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-8 18:04

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表