野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 13896|回复: 4

stm32f103+i2c+dma+eeprom busy问题

[复制链接]
发表于 2017-9-2 22:10:33 | 显示全部楼层 |阅读模式

利用STM32F103ZE微控制器I2C总线DMA读EEPROM一点经验


Stm32f103的i2c真是难学,连续学习了两个星期,终于有了一点进展。现将心得总结一下,供大家交流,不当的地方欢迎指正。

一、硬件平台:野火霸道开发板+野火仿真器

二、软件平台:MDK V5.14和野火多功能调试助手

三、利用资源:I2C和DMA,还有配合的USART

四、预期功能:利用stm32f103的硬件I2C1,向板载的AT24C02 EEPROM写入8个字节数据,然后通过I2C1外设的DMA功能将写入的数据读出,比较写入和读出的数据是否一致。

五、实现方法:具体的方法就不细说了,主要是参考野火的USART和I2C例程,实现I2C 轮询方式数据读写(I2C例程有时会出现超时,主要在busy位操作时,没有在意),然后参照STM32F10x固件库的I2C读写EEPROM例程,希望实现预期功能。

六、问题现象:1.仅I2C,不用dma时,不是每次都能够读写成功,进入debug模式,设置断点运行,停在I2C产生开始信号之前,busy=1;2.开启dma和中断时,不能运行,总是总线忙,busy=1,偶尔能够运行但是读出的数据仅有7位正确,8个字节的WD[0]始终无法正确读出。

七、解决过程:一句话,上网,上论坛,通过连续数天的查找,得出一个结论,大家普遍认为stm32f103的硬件I2C存在BUG,大家也进行了分析,推荐应用软件模拟I2C。由于个人水平有限,理解了个大概,但是无从下手。这个过程中,再次阅读了英文参考手册,感觉这里面的信息量太大了,一时半时没法完全吸收。还有就是,英文的表达方式和汉语的表达方式有差别,很多翻译的资料与英文原版的意思还是有一定差别的。于是,想到查找英文论坛资料,看看擅长电子设计的外国人有没有遇到这类问题,毕竟stm32是外国人设计的嘛。打开bing国际版,输入stm32 i2c busy等关键词,果然外国人也遇到了类似问题,见:https://electronics.stackexchange.com/questions/267972/i2c-busy-flag-strange-behaviour/305954。这里面提到了一个关键词,errata sheet,这篇sheet涉及的微控制器为STM32F100X系列,有可能不适用stm32f103。到st官网一查,stm32f10x果然也有相应的errata sheet(en.CD00197763.pdf),而且发布日期为2015年底,两篇文档中对于遇到的问题都有描述,2.14.7中有问题分析及workaround(理解为权宜之计吧),一共有15步。

八、解决例程:参照errata sheet中方法,编写相应解决busy=1的程序

void I2C_ClearBusyFlagErratum(void)

{

       GPIO_InitTypeDefGPIO_InitStructure;

       I2C_InitTypeDefI2C_InitStructure;

       //step 1 Clear PE bit

       I2C_Cmd(I2C1,DISABLE);

       //step 2 configure thescl and sda i/os as gpio output open drain.high level

       GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;

       GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;

       GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

       GPIO_Init(GPIOB,&GPIO_InitStructure);

       GPIO_WriteBit(GPIOB,GPIO_Pin_6,Bit_SET);

       GPIO_WriteBit(GPIOB,GPIO_Pin_7,Bit_SET);

       //step 3 check scl andsda high level in GPIO_IDR Register

       while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)!=Bit_SET);

       while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)!=Bit_SET);

       //step 4 configure thesda io as gpio output open drain low level

       GPIO_WriteBit(GPIOB,GPIO_Pin_6,Bit_RESET);

       //step 5 check sda lowlevel

       while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)!=Bit_RESET);

       //step 6 configure thescl io as gpio output open drain low level

       GPIO_WriteBit(GPIOB,GPIO_Pin_7,Bit_RESET);

       //step 7 check scl lowlevel

       while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)!=Bit_RESET);

       //step 8 configure thescl io as gpio output open drain high  level

       GPIO_WriteBit(GPIOB,GPIO_Pin_7,Bit_SET);

       //step 9 check scl hihtlevel

       while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)!=Bit_SET);

       //step10 configure thesda io as gpio output open drain high level

       GPIO_WriteBit(GPIOB,GPIO_Pin_6,Bit_SET);

       //step11 check sda highlevel

       while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)!=Bit_SET);

       //step12 configure the scland sda ios as alternate function open drain

       GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6|GPIO_Pin_7;

       GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;

       GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_OD;

       GPIO_Init(GPIOB,&GPIO_InitStructure);

       //step13 set SWRST bitin CR1 register

       I2C_SoftwareResetCmd(I2C1,ENABLE);

       //step14 clear SWRST bitin CR1 register

       I2C_SoftwareResetCmd(I2C1,DISABLE);

       //step15 enable i2c bysetting PE

              

       I2C_InitStructure.I2C_Ack=I2C_Ack_Enable;

       I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;

       I2C_InitStructure.I2C_ClockSpeed=200000;

       I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;

       I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;

       I2C_InitStructure.I2C_OwnAddress1=0x5F;//i2c×ÔÉíµØÖ·£»

    I2C_Init(I2C1,&I2C_InitStructure);

       I2C_Cmd(I2C1,ENABLE);

       I2C_DMALastTransferCmd(I2C1,ENABLE);

}

完整例程附后。

关于8个字节数据之后发送7个问题,有待进一步学习,但是通过多次实验,应该是传输速度匹配的问题,在读eeprom之后加一定延迟,居然解决这个问题。

以上为个人的一点总结和心得,不对的地方大家及时纠正。

en.CD00197763.pdf

676.46 KB, 下载次数: 81

回复

使用道具 举报

 楼主| 发表于 2017-9-2 22:13:29 | 显示全部楼层
有关例程。

MiniBalance.rar

290.84 KB, 下载次数: 21

回复

使用道具 举报

 楼主| 发表于 2017-9-2 22:15:09 | 显示全部楼层
自己编写的有关例程

MiniBalance.rar

290.84 KB, 下载次数: 54

回复 支持 反对

使用道具 举报

发表于 2017-9-4 09:40:25 | 显示全部楼层
恭喜楼主解决了问题
回复 支持 反对

使用道具 举报

发表于 2019-7-2 22:12:20 | 显示全部楼层
谢谢题主,今天试了一下用DMA给I2C读写数据,同样发现了这两个问题。busy问题通过你的方法解决了,不过读0的问题用延时也没解决,心累。。。
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-4-19 06:00 , Processed in 0.038108 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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