cube与I2C:https://www.cnblogs.com/121792730applllo/p/5044920.html
I2C官网:https://www.i2c-bus.org/standard-mode/
Ⅰ、写在前面
上一篇文章是“STM32F10x_模拟I2C读写EEPROM”,讲述使用IO口模拟I2C总线通信,对EEPROM(AT24Xxx)进行读写操作的过程。
上一篇文章主要内容:I2C协议、模拟I2C底层驱动、EEPROM(AT24Xxx)单字节读写操作。
本文主要内容:STM32硬件I2C详细配置、EEPROM(AT24Xxx)多字节读写操作、ST官方I2C存在问题。
实例实验效果:
1、多字节读写:任意地址(66), 写入任意长度(129)、读取并打印出来
2、单字节读写:任意地址(0),写入1字节数据、 读取并打印出来
实验说明:
1.多字节读写
实验为什么是从66地址写? 为什么是写入129字节?
答案:验证对EEPROM多字节“非标准地址、长度”读写的准确性。
我是使用AT24C128芯片,页大小是64字节,我从66地址,就是验证非标准地址(如:0、64、128等)开始读写; 写入长度129字节也是验证非标准长度(如:64、128、256等)的读写。
2.单字节读写
我这样实验的目的,相信大家都能理解。验证每一次写入字节数据 和读出的数据是都一致。
关于本文的更多详情请往下看。
Ⅱ、实例工程下载
笔者针对于初学者提供的例程都是去掉了许多不必要的功能,精简了官方的代码,对初学者一看就明白,以简单明了的工程供大家学习。
笔者提供的实例工程都是在板子上经过多次测试并没有问题才上传至360云盘,欢迎下载测试、参照学习。
提供下载的软件工程是基于Keil(MDK-ARM) V5版本、STM32F103ZE芯片,但F1其他型号也适用(适用F1其他型号: 关注微信,回复“修改型号”)。
STM32F10x_硬件I2C读写EEPROM(标准外设库版本)实例源代码工程:
http://yunpan.cn/c6b8d4mCTPpCj 访问密码
STM32F107VC_硬件I2C读写EEPROM(标准外设库版本)实例源代码工程:
http://yunpan.cn/c6b8HGnAGG4Mf 访问密码
I2C EEPROM(AT24xx)资料:
https://yunpan.cn/c667rIDPgvwTf 访问密码 1099
STM32F1资料:
https://yunpan.cn/crBUdUGdYKam2 访问密码 ca90
Ⅲ、硬件I2C配置
硬件I2C的配置其实很简单,RCC时钟、GPIO、I2C配置等。笔者以F1标准外设库(同时也建议初学者使用官方的标准外设库)为基础建立的工程,主要以库的方式来讲述(若您的F1芯片与提供工程不一样,可微信回复“修改型号”)。
1.RCC时钟源
该函数位于bsp.c文件下面;
RCC是很多初学者,甚至已经工作的朋友容易遗漏的地方,有很多朋友觉得它使用的外设不正常,很大部分是没有配置RCC导致的。
重点注意:
A.外设RCC时钟的配置要在其外设初始化的前面;
B.匹配对应时钟。
比如:RCC_APB2外设不要配置在RCC_APB1时钟里面
【如:RCC_APB1PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);这样能编译通过,但这是错误的代码】
2. I2C引脚配置
该函数位于i2c_ee.c文件下面;
1.使用硬件I2C:GPIO_Mode_AF_OD复用开漏模式
2.由于使用硬件I2C,不像使用模拟I2C使用IO操作,所以这里引脚定义的比较“死”GPIO_Pin_6 | GPIO_Pin_7。
如果你使用I2C2或者引脚映射,这里的引脚也要跟着改变。
3. I2C配置
该函数位于i2c_ee.c文件下面;
这个函数才是本文的重点:
1.I2C模式:I2C_Mode = I2C_Mode_I2C;
硬件有多种模式:
I2C_Mode_I2C: I2C模式
I2C_Mode_SMBusDevice: SMBus设备(丛机)模式
I2C_Mode_SMBusHost: 主机模式
2.I2C占空比:I2C_DutyCycle = I2C_DutyCycle_2;
这个参数在快速I2C模式下有效,也就是速度大于100KHz。
I2C_DutyCycle_2:2比1占空比
I2C_DutyCycle_16_9:16比9占空比
感兴趣的朋友可以把时钟配置高于100KHz(如:400KHz),用示波器测一下SCL引脚,可以看得出来占空比不一样。
3.I2C设备地址:I2C_OwnAddress1 = EEPROM_DEV_ADDR;
这个参数是第一个设备(从机)的地址,EEPROM_DEV_ADDR是我们自己宏定义的设备地址。
4.I2C应答:I2C_Ack = I2C_Ack_Enable;
这个参数的含义请结合上一篇文章“I2C协议”来理解。
5.地址位数:I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
这个参数就是设备地址位数,需要和后面函数“I2C_Send7bitAddress”一致。
6.I2C速度:I2C_ClockSpeed = I2C_SPEED;
这个参数很好理解,I2C_SPEED是我们宏定义的值“100000”,也就是100KHz的意思。
Ⅳ、硬件I2C读写EEPROM配置
上一篇文章简单提及了一下EEPROM单字节的读写,提供了多字节读写实例,但没有具体描述多字节的具体操作。
下面将详细描述一下单字节读写和多字节读写的操作。请下载“I2C EEPROM资料”和“实例工程”作为参考。
在对EEPROM(AT24Cxx)读写操作之前需要理解两个参数(可见源代码i2c_ee.h文件):
A.“数据字”地址长度:也就是存数据的地址有多少位。具体分类(见数据手册)如下:
8位: AT24C01、AT24C02
16位: AT24C04、AT24C08、AT24C16、AT24C32、AT24C64、AT24C128、AT24C256、AT24C512
B.页长度:在进行连续写的时候,最长可写一页,写完这一页之后需要指定下一页地址才行,否则会在上一页循环写。具体分类(见数据手册)如下:
8字节: AT24C01、AT24C02
16字节: AT24C04、AT24C08、AT24C16
32字节: AT24C32、AT24C64
64字节: AT24C128、AT24C256
128字节: AT24C512
1. 单字节写
时序图:
截图来自“AT24C128C数据手册”,单字节写主要分5个步骤:
1.开始
2.设备地址/写
3.数据地址
4.写一字节数据
5.停止
源程序:
在操作硬件I2之前需要检测I2C是否处于“忙”状态。数据地址根据长度不同而写入的不同。
2. 单字节读(随机)
时序图:
截图来自“AT24C128C数据手册”,单字节读(也是随机读)主要分7个步骤:
1.开始
2.设备地址/写
3.数据地址
4.重新开始
5.设备地址/读
6.读一字节数据
7.停止
源程序:
这里就提醒一点,单字节读和多字节读的应答位,由于不连续读,这里产生非应答。
3. 页写
时序图:
截图来自“AT24C128C数据手册”,页写和单字节写的区别在于“连续写”。
注意:这里页写的意思是在指向地址的页写数据,也就是EEPROM内部“地址指针”指向的地址所在页。每次写之前我们都要将“地址指针”指向一个地址(见下面源程序),写的过程中,一旦写到最后一个字节,将会回到该页首地址继续写下去,因此,写完该页,我们需要重新将“地址指针”指向下一页首地址。
【芯片页的大小根据芯片不同而不同,见本章开头描述】
源程序:
写最后一字节独立出来是有原因的:防止HardFault_Handler。
4. 多字节写
源程序:
“多字节写”是基于“页写”的基础上写的,从上面页写的描述(写到该页最后一字节会回到该页首地址)可以知道多字节写是要考虑很多情况的,否则会破坏其他数据。
上面源程序截取了简单的一部分:开始写的地址刚好位于该页首地址这种情况。在页首地址开始写数据情况下,要判断需要写的数据的大小是否有多页。
【上面这种情况是比较简单的一种,还有其他情况,我不在这里讲述,希望初学的你多去理解一下,这也是参考ST官方的思路,而且有利于你们编程的思想】
5. 多字节读
时序图:
截图来自“AT24C128C数据手册”,多字节读需要注意应答。
在多字节读到最后一位数据之前,必须产生应答位,而最后一位产生非应答位。请结合下面源程序理解。
源程序:
和单字节读比:前面第1步到第5步都是一样的,重点请看第6步,这里产生的应答需要注意。
Ⅴ、ST官方I2C读写问题
说到ST的I2C这个问题,网上有很多人说也存在严重的I2C问题,我个人倒不觉得存在太大问题(或许是我研究的还不够)。
我从开始至今,使用ST芯片I2C也做过几个项目(控制EEPROM、时钟芯片、温度传感器、触摸芯片),项目中也使用多个中断,我至今还没有发现它的问题。我只知道ST提供的标准外设库例程有些地方不严谨或不规范,我也从没使用ST官方的例程(当然,我自己写的例程很多思路是参考ST的)。
我个人观点:有问题比不可怕,可怕的是不知道如何去解决问题。由于我没有真正的发现I2C硬件真实存在的问题,可以参考一下官方提到是资料,可以下载(第二节)我整理的STM32F1资料 “STM32F10xxCDE勘误手册V14(英文)2015-11”查看。
1.官方标准外设库例程介绍
标准库例程关于I2C读写EEPROM0的例程很多都一样或类似(F1、F2、F4等),感兴趣的可以下载查看。但是,都存在不规范的地方。
2.标准库I2C例程介绍
我大概说一下这个标准库I2C例程中读写相关函数吧。
位置位于STM32F10x_StdPeriph_Lib_V3.5.0\Utilities\STM32_EVAL\Common:
stm32_eval_i2c_ee.c
A.sEE_ReadBuffer读函数
A1.同样注释,不同语句,写地址之后的标志处理;(见265行处)
这个地方其实是处理一下标志位,我也测试过,使用两种语句都可以通过的。只是提出来以下是,我个人举得更应该使用“I2C_EVENT_MASTER_BYTE_TRANSMITTED”(在我的例程中也是使用这个)。
A2.读数据之前,发送停止条件;(见316行处)
这个地方经过我反复测试,没有测试通过(也就是在读之前发送停止条件)。 我个人觉得这是程序上的一个BUG.
B.sEE_WriteBuffer写函数
写页函数暂时还没有发现什么问题,但在综合的写函数(多字节写)中发现了一个问题(如下图),这个地方的count永远都不可能等于0,而这里加了一个判断条件。
文章转载自:https://blog.csdn.net/ybhuangfugui/article/details/52175621
(转)stm32硬件IIC的更多相关文章
-
STM32硬件IIC (转)
源: STM32硬件IIC
-
STM32硬件IIC驱动设计(转)
源: STM32硬件IIC驱动设计 参考: STM32—硬件IIC主机通信 STM32’s I2C 硬件BUG引发的血案(qzm) 解决STM32 I2C接口死锁在BUSY状态的方法讨论
-
STM32硬件IIC操作
Stm32具有IIC接口,接口有以下主要特性 多主机功能:该模块既可做主设备也可做从设备 主设备功能 C地址检测 位/10位地址和广播呼叫 支持不同的通讯速度 状态标志: 发送器/接收器模式标志 字节 ...
-
STM32硬件IIC
/** * @brief 写一个字节到I2C设备中 * @param * @arg pBuffer:缓冲区指针 * @arg WriteAddr:写地址 * @retval 正常返回1,异常返回0 * ...
-
STM32 IIC双机通信—— HAL库硬件IIC版
参考传送门 关于IIC的原理这里我就不多说了,网上有很多很好的解析,如果要看我个人对IIC的理解的话,可以点击查看,这里主要讲一下怎样利用STM32CubeMx实现IIC的通讯,经过个人实践,感觉HA ...
-
STM32读取bq33100数据——硬件IIC
背景:拟采用bq33100超级电容管理芯片,实现自动的超级电容组的均压任务.需监控芯片的工作情况,以及电容组的均压情况. 平台: 硬件:STM32F103C8T6 通信:SMBus(低速IIC) 目标 ...
-
【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)
版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 ...
-
STM32 硬件I2C 到底是不是个坑?
/** ****************************************************************************** * @author Maox ...
-
STM32 硬件UART接收超时检测设置
STM32 硬件UART接收超时检测设置 -----------------本文作者"智御电子",期待与电子爱好者交流学习.---------------- 应用场景 在uart应 ...
随机推荐
-
MySQL学习笔记(1/2)
数据库的学习要求:1.为项目设计表:2.使用SQL(Structure Query Language)语句(SQL编程).其他的都可以使用工具完成. SQL: DDL:创建库.创建表 DML:对数据的 ...
-
laravel框架总结(四) -- 服务容器
1.依赖 我们定义两个类:class Supperman 和 class Power,现在我们要使用Supperman ,而Supperman 依赖了Power class Supperman { p ...
-
修改JSONArray里所有key的值
下面举一个代码的列子目的是实现如下功能: [{"userId":1,"userName":"plf"},{"userId" ...
-
Pair Project: Elevator Scheduler [电梯调度算法的实现和测试]:谢勤政-11061197,吴润凡-11061185
一,关于结对编程 结对编程的优点: 1)在开发层次,结对编程能提供更好的设计质量和代码质量,两人合作能有更强的解决问题的能力. 2)对开发人员自身来说,结对工作能带来更多的信心,高质量的产出能带来更高 ...
-
Linux环境下使用JFS文件系统
Linux环境下使用JFS文件系统 JFS是IBM公司为linux系统开发的一个日志文件系统.从IBM的实力及它对Linux的态度来看,JFS应该是未来日志文件系统中最具实力的一个文件系统. JFS提 ...
-
Keil ";RECURSIVE CALL TO SEGMENT";彻底解决
我们在做菜单程序或通过函数指针调用函数时,如果被调用的函数中有包含了常量字符串,那么经常会出现这样的的错误提示:"RECURSIVE CALL TO SEGMENT"意思是&quo ...
-
pthread_setschedprio()函数详解!!!
pthread_setschedprio() Set a thread's priority 用于设置现成的优先级 包含在头文件 #include <pthread.h> 用法:int p ...
-
03.redis与ssm整合(mybatis二级缓存)
SSM+redis整合 ssm框架之前已经搭建过了,这里不再做代码复制工作. 这里主要是利用redis去做mybatis的二级缓存,mybaits映射文件中所有的select都会刷新已有缓存,如果不存 ...
-
为什么虚拟 dom 会提高性能?
虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能.用 JavaScript 对象结构表示 DOM 树的结构:然后 ...
-
Python全栈之路----函数----高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一函数作为参数,这种函数就称之为高阶函数. 只需满足以下任意一个条件,即是高阶函数: 接收一个或多个函数作为输入 def func(x, ...