OpenEdv-开源电子网

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

IIC与外接EEPROM通信

[复制链接]

80

主题

188

帖子

0

精华

高级会员

Rank: 4

积分
681
金钱
681
注册时间
2013-8-16
在线时间
37 小时
发表于 2013-8-26 11:21:37 | 显示全部楼层 |阅读模式
您好,原子哥。我现在遇到了一个棘手的问题,我使用的是STM32f103VCT6上的IIC与外接的EEPROM通信,可是在通信过程中,有些时候写入的数据的值会变成其他值(在大量写入数据的时候这个问题尤为突出),我的程序里面有外部中断和定时器中断,串口中断,是不是中断大致他的数据不稳定的,还是有其他的因素,怎么修改?,希望原子哥可以指点指点小弟,谢谢。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

20

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
187
金钱
187
注册时间
2013-8-14
在线时间
8 小时
发表于 2013-8-26 14:49:45 | 显示全部楼层
这个问题 我以前在用51的时候经常遇到,其实问题无外乎两个 1 直接插播  2接触不良 当然你必须的保证你代码没问题的情况下 呵呵
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-26 15:04:33 | 显示全部楼层
把所有中断屏蔽掉,在测试下试试。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

80

主题

188

帖子

0

精华

高级会员

Rank: 4

积分
681
金钱
681
注册时间
2013-8-16
在线时间
37 小时
 楼主| 发表于 2013-8-26 16:55:04 | 显示全部楼层
我将中断全部屏蔽掉情况也与之前的情况一样。所以我单独做了一段测试程序其具体情况是(以在地址EEPROM的 0x05地址写入数据为例子,IIC的初始化、IIC的读写函数参照官网例子书写):
#include "stm32f10x.h"

int main(void)
{
  SystemInit();
  IIC_INIT();
 I2c_Buf_Write[0]=0xa0;
 I2C_EE_BufferWrite( I2c_Buf_Write, 0x05, 1); 
 p_delay(10);延时
 I2C_EE_BufferRead(I2c_Buf_Read, 0x05, 2);
 if(I2c_Buf_Read[0]==0xa0)
{
    GPIO_SetBits(GPIOC,GPIO_Pin_9);//测试灯亮
}
dis_1000(I2c_Buf_Read[0],2,6);//显示10000以内的数值的函数,第一个参数是显示的内容,后两个参数分别是行号、列号。

p_delay(10);延时

I2c_Buf_Write[0]=0xb0;
 I2C_EE_BufferWrite( I2c_Buf_Write, 0x05, 1); 
 p_delay(10);延时
 I2C_EE_BufferRead(I2c_Buf_Read,0x05, 2);
 if(I2c_Buf_Read[0]==0xb0)
{
    GPIO_ResetBits(GPIOC,GPIO_Pin_9);//测试灯熄灭
}
dis_1000(I2c_Buf_Read[0],5,6);//显示10000以内的数值的函数,第一个参数是显示的内容,后两个参数分别是行号、列号。
while(1);
}

这段测试代码在向地址0x05写入数据0xa0,读出地址0x05的数据是0xa0,测试灯亮;但是紧接着写入的数据0xb0的数据就发生了问题,写入的与读出的不一定相等,等于0xa0或0xb0或两者都不是的其他的值。
回复 支持 反对

使用道具 举报

80

主题

188

帖子

0

精华

高级会员

Rank: 4

积分
681
金钱
681
注册时间
2013-8-16
在线时间
37 小时
 楼主| 发表于 2013-8-26 16:56:38 | 显示全部楼层
回复【2楼】NT06:
---------------------------------
你好,我想问问你说的情况一:直接插播是什么?谢谢
回复 支持 反对

使用道具 举报

20

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
187
金钱
187
注册时间
2013-8-14
在线时间
8 小时
发表于 2013-8-27 18:58:03 | 显示全部楼层
回复【5楼】星空:
---------------------------------
很明显 你说的现象不应该是硬件问题,问题出在程序上,第一次写时你有个I2C初始化  第二次写的时候加上试试,会不会是第二次写入的数据的时候 总线都被拉低了 ,借助仪器看看吧  还有种可能 I2c_Buf_Write 第一次你操作过了首地址会不会发生+1导致读到的数据其实是2c_Buf_Write【1】 试着改改,没用过库函数 程序没有仔细读 请见谅哈
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-27 19:14:21 | 显示全部楼层
回复【4楼】星空:
---------------------------------
你不会是用的硬件IIC吧?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

80

主题

188

帖子

0

精华

高级会员

Rank: 4

积分
681
金钱
681
注册时间
2013-8-16
在线时间
37 小时
 楼主| 发表于 2013-8-30 10:07:22 | 显示全部楼层
我使用的是硬件IIC,难道不能使用?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-30 10:24:08 | 显示全部楼层
能用,就是不稳定而已。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

80

主题

188

帖子

0

精华

高级会员

Rank: 4

积分
681
金钱
681
注册时间
2013-8-16
在线时间
37 小时
 楼主| 发表于 2013-8-30 14:35:40 | 显示全部楼层
哦,我现在马上去模拟一个IIC,谢谢。
回复 支持 反对

使用道具 举报

80

主题

188

帖子

0

精华

高级会员

Rank: 4

积分
681
金钱
681
注册时间
2013-8-16
在线时间
37 小时
 楼主| 发表于 2013-8-31 15:21:57 | 显示全部楼层
原子哥,我模拟了一个IIC来与外接的EEPROM通信,我要存入的数据有600个,从地址0x00开始存储,可是在存入的数据超过255个,也就是存储的地址大于0x100,我就不知道应该如何存数据了。希望能指点我一下,现在急用,我的模拟程序如下:
#include"stm32f10x.h"
#include"at24c02.h"
void  iicstart(void);
void  iicstop(void);
void  ack(void);
void  iicwritebyte(u8 a);
u8    iicreadbyte(void);
void  iicwrite(u8 add,u8 Achar);
u8    iicread(u8 add);
void  iicinit(void);
/////////////////////////////
void delay5us(void)//ums
{
    unsigned short i, j;
 unsigned short time;
 time=5;
 for(; time > 0; time--){
     for(j = 0; j < 5; j++){
      for(i = 0; i < 1; i++);
  }
 }
}
void delayms(unsigned short time)//nms
{
    unsigned short i, j;
 
 for(; time > 0; time--){
     for(j = 0; j < 10; j++){
      for(i = 0; i < 1004; i++);
  }
 }

}  
void iicinit(void)
{       
    GPIO_InitTypeDef  GPIO_InitStructure;
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

 GPIO_Init(GPIOB, &GPIO_InitStructure); 
}


void iicstart(void)
{
   
 GPIO_SetBits(GPIOB,GPIO_Pin_11); //sda=1;
 delay5us();
 GPIO_SetBits(GPIOB,GPIO_Pin_10); //scl=1;
 delay5us();
 GPIO_ResetBits(GPIOB,GPIO_Pin_11); //sda=0;
 delay5us();

}
void iicstop(void)
{
  
 GPIO_ResetBits(GPIOB,GPIO_Pin_11); //sda=0;
 delay5us();
 GPIO_SetBits(GPIOB,GPIO_Pin_10); //scl=1;
 delay5us();
 GPIO_SetBits(GPIOB,GPIO_Pin_11); //sda=1;
 delay5us();

}
void  ack(void)
{      
 u16 i;
 GPIO_SetBits(GPIOB,GPIO_Pin_10);//scl=1;
 delay5us();
 while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)&&(i<0x2b0)) {i++;}
 GPIO_ResetBits(GPIOB,GPIO_Pin_10);//scl=0;
 delay5us();
}
void  iicwritebyte(u8 a)
{
    u16 i;
 GPIO_ResetBits(GPIOB,GPIO_Pin_10);  //scl=0;
 delay5us();
 for(i=0;i<8;i++)
 { 
  if(a&0x80)  
   GPIO_SetBits(GPIOB,GPIO_Pin_11);//sda=1;
  else
   GPIO_ResetBits(GPIOB,GPIO_Pin_11);
  a=a<<1;
  GPIO_SetBits(GPIOB,GPIO_Pin_10);//scl=1;
  delay5us();
  GPIO_ResetBits(GPIOB,GPIO_Pin_10);//scl=0;
  delay5us(); 
   
 }   
    GPIO_SetBits(GPIOB,GPIO_Pin_11);//sda=1; 
 delay5us();

}
u8 iicreadbyte()
{
 u8 i,temp;
 temp=0;
 GPIO_SetBits(GPIOB,GPIO_Pin_11);//sda=1;
 delay5us();
 GPIO_ResetBits(GPIOB,GPIO_Pin_10);      //scl=0;
 delay5us();
 for(i=0;i<8;i++)
 {
     GPIO_SetBits(GPIOB,GPIO_Pin_10);  //scl=1;
     delay5us();
  delay5us();
  temp=(temp<<1)|GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
  delay5us();
  GPIO_ResetBits(GPIOB,GPIO_Pin_10);  //scl=0;
  delay5us();
 }
 GPIO_SetBits(GPIOB,GPIO_Pin_11);//sda=1;
 delay5us();
 GPIO_ResetBits(GPIOB,GPIO_Pin_10);//scl=0;
 delay5us(); 
 return temp;
}

void  iicwrite(u8 add,u8 Achar)
{
    iicstart();
    iicwritebyte(0xa0);
    ack();
    iicwritebyte(add);
    ack();
    iicwritebyte(Achar);
    ack();
    iicstop();
    delayms(20);
}
u8  iicread(u8 add)
{
 u8 temp;
 iicstart();
 iicwritebyte(0xa0);
 ack();
 iicwritebyte(add);
 ack();
 iicstart();
 iicwritebyte(0xa1);
 ack();
 temp=iicreadbyte();
 ack();
 iicstop();
 return temp;
}
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-31 17:04:27 | 显示全部楼层
存储的地址大于0x100,我就不知道应该如何存数据了??
这个,你小于256的时候,怎么存储的?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

80

主题

188

帖子

0

精华

高级会员

Rank: 4

积分
681
金钱
681
注册时间
2013-8-16
在线时间
37 小时
 楼主| 发表于 2013-9-2 10:19:25 | 显示全部楼层
我的模拟IIC的程序就是前面那段代码,小于256的时候,我是为每一个变量在外接的EEPROM中指定一个对应的地址,再利用收纳柜面那段代码中的读写函数,实现对数据的读写操作。
回复 支持 反对

使用道具 举报

80

主题

188

帖子

0

精华

高级会员

Rank: 4

积分
681
金钱
681
注册时间
2013-8-16
在线时间
37 小时
 楼主| 发表于 2013-9-2 10:35:08 | 显示全部楼层
以下是我最新的IIC模拟程序,他能实现在16位地址下进行8位数据的读写操作,不过里面存在一个问题,就是对16位的数据不能实现连续的读写操作。我现在测试的结果是:在8位地址或者16位地址中写如8位的数据可以成功,不论是连续读写数据还是分开读写数据都不会发生问题,而对于16位的数据就有问题了。
例如:u8 value0,value_0;u8 value,value2;u16 q=2000;
       value=q>>8;
       value2=q&0x00FF;
       ……;//IIC的起始操作和应答
       IIC_Write(0x11,value);
       value0=IIC_Read(0x11);

       IIC_Write(0x12,value2);
       value_0=IIC_ReadIIC(0x12);

      value_0=value0*256+value_0;//等价于(value<<8)|value_0;
      像这样操作来将q的值写入,写入的和从对应地址中读出来的相等。
    但是如果是这样写
     u8 value0,value_0; 
       u8 value,value2;
       u16 q=2000;
       value=q>>8;
       value2=q&0x00FF;
       ……;
       IIC_Write(0x11,value);
       IIC_Write(0x12,value2);
       value0=IIC_Read(0x11);
       value_0=IIC_Read(0x12);
       value_0=value0*256+value_0;
      //结果与写入的不匹配,我现在都没有弄明白,在连续读写间加入延时依旧没有效果.为什么八位的数据可以在16位或者8位的地址上实现连续读或写操作,其结果正确,而十六位的数据都能这样做,我每次写入的和读入的数据不都是8位的数据吗?这有什么区别阿?还请原子哥指点指点,谢谢。
回复 支持 反对

使用道具 举报

80

主题

188

帖子

0

精华

高级会员

Rank: 4

积分
681
金钱
681
注册时间
2013-8-16
在线时间
37 小时
 楼主| 发表于 2013-9-2 10:35:38 | 显示全部楼层
#include"stm32f10x.h"
#include"at24c02.h"
void  iicstart(void);
void  iicstop(void);
void  ack(void);
void  iicwritebyte(u8 a);
u8    iicreadbyte(void);
void  iicwrite(u8 add,u8 Achar);
u8    iicread(u8 add);
void  iicinit(void);
/////////////////////////////
void delay5us(void)//ums
{
    unsigned short i, j;
 unsigned short time;
 time=5;
 for(; time > 0; time--){
     for(j = 0; j < 5; j++){
      for(i = 0; i < 1; i++);
  }
 }
}
void delayms(unsigned short time)//nms
{
    unsigned short i, j;
 
 for(; time > 0; time--){
     for(j = 0; j < 10; j++){
      for(i = 0; i < 1004; i++);
  }
 }

}  
void iicinit(void)
{       
    GPIO_InitTypeDef  GPIO_InitStructure;
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
 
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;

 GPIO_Init(GPIOB, &GPIO_InitStructure); 
}


void iicstart(void)
{
   
 GPIO_SetBits(GPIOB,GPIO_Pin_11); //sda=1;
 delay5us();
 GPIO_SetBits(GPIOB,GPIO_Pin_10); //scl=1;
 delay5us();
 GPIO_ResetBits(GPIOB,GPIO_Pin_11); //sda=0;
 delay5us();

}
void iicstop(void)
{
  
 GPIO_ResetBits(GPIOB,GPIO_Pin_11); //sda=0;
 delay5us();
 GPIO_SetBits(GPIOB,GPIO_Pin_10); //scl=1;
 delay5us();
 GPIO_SetBits(GPIOB,GPIO_Pin_11); //sda=1;
 delay5us();

}
void  ack(void)
{      
 u16 i;
 GPIO_SetBits(GPIOB,GPIO_Pin_10);//scl=1;
 delay5us();
 while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)&&(i<0x2b0)) {i++;}
 GPIO_ResetBits(GPIOB,GPIO_Pin_10);//scl=0;
 delay5us();
}
void  iicwritebyte(u8 a)
{
    u16 i;
 GPIO_ResetBits(GPIOB,GPIO_Pin_10);  //scl=0;
 delay5us();
 for(i=0;i<8;i++)
 { 
  if(a&0x80)  
   GPIO_SetBits(GPIOB,GPIO_Pin_11);//sda=1;
  else
   GPIO_ResetBits(GPIOB,GPIO_Pin_11);;
  a=a<<1;
  GPIO_SetBits(GPIOB,GPIO_Pin_10);//scl=1;
  delay5us();
  GPIO_ResetBits(GPIOB,GPIO_Pin_10);//scl=0;
  delay5us(); 
   
 }   
    GPIO_SetBits(GPIOB,GPIO_Pin_11);//sda=1; 
 delay5us();

}
u8 iicreadbyte()
{
 u8 i,temp;
 temp=0;
 GPIO_SetBits(GPIOB,GPIO_Pin_11);//sda=1;
 delay5us();
 GPIO_ResetBits(GPIOB,GPIO_Pin_10);      //scl=0;
 delay5us();
 for(i=0;i<8;i++)
 {
     GPIO_SetBits(GPIOB,GPIO_Pin_10);  //scl=1;
     delay5us();
  delay5us();
  temp=(temp<<1)|GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
  delay5us();
  GPIO_ResetBits(GPIOB,GPIO_Pin_10);  //scl=0;
  delay5us();
 }
 GPIO_SetBits(GPIOB,GPIO_Pin_11);//sda=1;
 delay5us();
 GPIO_ResetBits(GPIOB,GPIO_Pin_10);//scl=0;
 delay5us(); 
 return temp;
}

void  iicwrite(u16 add,u8 Achar)
{
   u8 add1,add2;
   

    add1=add>>8;//获取地址高八位
    add2=add&0x00FF;//获取地址的低八位
    iicstart();
    iicwritebyte(0xa0);//写函数指令
    ack();//应答
    iicwritebyte(add1);//写地址的高八位
    ack();
    iicwritebyte(add2);//写地址的低八位
    ack();
    iicwritebyte(Achar);//写入数据
    ack();
    iicstop();
    delayms(20);
}
u8  iicread(u16 add)
{
 u8 add1,add2;
 u8 temp;

 add1=add>>8;
 add2=add&0x00FF;
 iicstart();
 iicwritebyte(0xa0);//读指令
 ack();
 iicwritebyte(add1);
 ack();
 iicwritebyte(add2);
 ack();
 iicstart();
 iicwritebyte(0xa1);//写指令
 ack();
 temp=iicreadbyte();
 ack();
 iicstop();
 return temp;
}
回复 支持 反对

使用道具 举报

80

主题

188

帖子

0

精华

高级会员

Rank: 4

积分
681
金钱
681
注册时间
2013-8-16
在线时间
37 小时
 楼主| 发表于 2013-10-26 18:38:38 | 显示全部楼层
原子哥,我使用模拟的IIC与16K大小的EEPROM通信成功了。现在我需要用64K的EEPROM存储,不知道需要改动先前的程序的哪些地方,还请指点指点,谢谢。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-10-26 19:45:18 | 显示全部楼层
直接改.h里面的宏就可以了。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-9 22:00

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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