你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 12294|回复: 6

解决stm32f10x I2C读写EEPROM芯片死锁问题

[复制链接]

3

主题

28

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
发表于 2012-10-7 11:43:17 | 显示全部楼层 |阅读模式
首先说下编写这个程序的目的和思路:把AT24C02的驱动代码放一个模块里,只对外提供3个API函数-初始化,指定地址写一个字节,指定地址读一个字节。页写页读什么的都不用,这样方便外部调用. 
参考官方的库和神舟的源代码编写了个简单的读写AT24C02一个字节的程序,调试发现了几个问题:
1. 程序第一次调试没问题,第二次修改写入的数据再调试就陷入了死循环,再也跳不出来了
2. 换成神舟1号(目标板是神舟1号开发板)的源代码,重新编译写入调试,还是同样的问题
3. 把仿真器,目标板全部断电,放一段时间再调试,有时候能够正常跑,有时死锁
4. 打开寄存器查看,发现通常I2C模块一旦初始化,SR1的BUSY位自动置位,等多久都没有
上网搜索,发现碰得这问题的人很多,绝大多数意见都认为是这个BUSY问题,有人说是bug官方推荐模拟I2C,有人说是官方例程有问题,其中一位指出是初始话顺序的问题,应该先配置I2C,再配置GPIO的复用功能,这话很有道理,照做,修改自己写的程序调试,第
一次是没问题,reset再运行,还是死锁,问题依旧。
后来隐约想到,官方文档好像说引脚的初始话应该先置高。修改,在初始化的配置GPIO的复用功能之前,先将GPIO配置为输出,且置
高,而且在每次读操作之后执行初始化一次防止BUSY(写操作实测不需要)。测试再也没有发现令人崩溃的BUSY了。
下面是AT24C02.C的代码,
 
#include"stm32f10x.h"
 
       static AT24C02_Delay(){
//延时2ms, 确保写入成功 ;对外隐藏
        uint32_t   i;
         i=72*200*2;  //72对应系统时钟多少兆,2对应要延时多少毫秒
         while(i--);
      }               
 
  void AT24CO2_Init(uint32_t I2C_speed,uint8_t I2C_selfAddr ){
//I2C_speed     : I2C的SCL的频率,通常配置为100000
//I2C_selfAddr : 自身地址,这里可以为任意
        GPIO_InitTypeDef GPIO_InitStructure;
        I2C_InitTypeDef  I2C_InitStructure;
        //第一步:
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
        I2C_DeInit(I2C1);
        I2C_InitStructure.I2C_ClockSpeed         =  I2C_speed;    
        I2C_InitStructure.I2C_Mode               =  I2C_Mode_I2C;
        I2C_InitStructure.I2C_DutyCycle          =  I2C_DutyCycle_2; 
        I2C_InitStructure.I2C_OwnAddress1        =  I2C_selfAddr;
        I2C_InitStructure.I2C_Ack                =  I2C_Ack_Enable;
        I2C_InitStructure.I2C_AcknowledgedAddress=  I2C_AcknowledgedAddress_7bit; 
        I2C_DeInit(I2C1);
        I2C_Init(I2C1,&I2C_InitStructure);
        //第二步:先将Pins配置为通用输出且置高
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
        GPIO_InitStructure.GPIO_Pin   = (GPIO_Pin_6|GPIO_Pin_7);
        GPIO_InitStructure.GPIO_Mode  =  GPIO_Mode_Out_PP ;
        GPIO_InitStructure.GPIO_Speed =  GPIO_Speed_10MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);
        GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);
        //第三步:配置为I2C功能
        GPIO_InitStructure.GPIO_Pin   = (GPIO_Pin_6|GPIO_Pin_7);
        GPIO_InitStructure.GPIO_Mode  =  GPIO_Mode_AF_OD ;
        GPIO_InitStructure.GPIO_Speed =  GPIO_Speed_10MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);       
       }
 
 
void AT24C02_WriteByte(uint8_t AT24C02_MemAddr, uint8_t data){
//向指定地址写一个数据,1个字节
//AT24C02_MemAddr: 存储地址,范围为0x00~0xFF
// data                           : 8位数据,范围为0x00~0xFF           
                I2C_GenerateSTART(I2C1,  ENABLE);
                 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
                 I2C_Send7bitAddress(I2C1, 0xA0,I2C_Direction_Transmitter);
                 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
                 I2C_SendData(I2C1,  AT24C02_MemAddr);
                 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
                 I2C_SendData(I2C1,data);
                 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
                 I2C_GenerateSTOP(I2C1,  ENABLE);
                 AT24C02_Delay();   //延时2毫秒,确保写入成功
}
 
 
uint8_t AT24C02_ReadByte(uint8_t AT24C02_MemAddr){
//随机读取一个字节的数据
//从指定地址读出一个字节       
//AT24C02_MemAddr: 存储地址,范围为0x00~0xFF 
                 uint8_t I2cReceiveData;
                 I2C_GenerateSTART(I2C1,  ENABLE);
                 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
                 I2C_Send7bitAddress(I2C1, 0xA0,I2C_Direction_Transmitter);
                 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
                 I2C_SendData(I2C1, AT24C02_MemAddr );
                 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));       
                 I2C_GenerateSTART(I2C1,  ENABLE);
                 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
                 I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Receiver);
                while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));               
                 while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));       
                 I2cReceiveData=I2C_ReceiveData(I2C1);
                 I2C_AcknowledgeConfig(I2C1,  DISABLE);
                 I2C_GenerateSTOP(I2C1,  ENABLE);
                 I2C_AcknowledgeConfig(I2C1,  ENABLE);
                 AT24CO2_Init( 100000, 0xDD );  //这里跟main函数中的初始设置保持一致
                 return I2cReceiveData ;
}
 
<
回复

使用道具 举报

3

主题

28

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
 楼主| 发表于 2012-10-7 11:51:52 | 显示全部楼层

回复:解决stm32f10x I2C读写EEPROM芯片死锁问题

 怎么排版老不对,无解了。欢迎大家拍砖
回复 支持 反对

使用道具 举报

0

主题

3

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
发表于 2012-12-3 17:37:57 | 显示全部楼层

RE:解决stm32f10x I2C读写EEPROM芯片死锁问题

I2C_InitStructure.I2C_AcknowledgedAddress=  I2C_AcknowledgedAddress_7bit;
I2C_DeInit(I2C1);
回复 支持 反对

使用道具 举报

0

主题

3

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
发表于 2012-12-4 06:44:10 | 显示全部楼层

回复:解决stm32f10x I2C读写EEPROM芯片死锁问题

检查下这两行里面设了什么
     RCC_APB1PeriphClockCmd(?????
                           , ENABLE );
         RCC_APB2PeriphClockCmd( ????| RCC_APB2Periph_GPIOA  |RCC_APB2Periph_AFIO
                       , ENABLE );     
如有该设的时脉未设到,及不该出现同时启动了的,皆无法正常运行
回复 支持 反对

使用道具 举报

3

主题

28

回帖

0

蝴蝶豆

新手上路

最后登录
1970-1-1
 楼主| 发表于 2012-12-21 22:52:27 | 显示全部楼层

回复:解决stm32f10x I2C读写EEPROM芯片死锁问题

&lt;div style=&quot;padding:5px;border:1px dashed #ccc;&quot;&gt;
回复第 3 楼 于2012-12-03 17:37:57发表:
I2C_InitStructure.I2C_AcknowledgedAddress=  I2C_AcknowledgedAddress_7bit;
I2C_DeInit(I2C1);
回复 支持 反对

使用道具 举报

0

主题

2

回帖

0

蝴蝶豆

新手上路

最后登录
2017-9-8
发表于 2017-9-8 09:45:59 | 显示全部楼层
楼主,你好!这个问题困扰我很久了,你说“后来隐约想到,官方文档好像说引脚的初始话应该先置高”,请问你这是在哪里看到的,是参考手册吗,我怎么没看到有这个,麻烦指点一二,谢谢!
回复 支持 反对

使用道具 举报

0

主题

1

回帖

0

蝴蝶豆

新手上路

最后登录
2018-4-29
发表于 2018-4-29 22:09:13 | 显示全部楼层
猜测一下,是不是eeprom没有识别到非应答,或mcu给出了应答信号
回复 支持 反对

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版