STM32F030硬件I2C代码及解析

这篇具有很好参考价值的文章主要介绍了STM32F030硬件I2C代码及解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

刚接触STM32的时候,第一个学习的就是I2C,当时去网上学习别人写得I2C代码,虽然能用,但是当时并不理解为什么要这么配置,特别希望有人把代码掰碎了讲讲看,今天突然想起来,就把以前写的I2C代码拿出来掰碎了捋捋,希望对新手有些帮助。

先说说STM32的I2C:
ST的M3系列还有M4系列的I2C基本上是一致的,但是到M0系列以后,I2C的设计是重新修改过的,所以用起来会比M3和M4系列的好用很多,前面的文章有详细描述过STM32F103的I2C的硬件缺陷,有兴趣的可以看看,接下来讲讲M0系列的硬件I2C。

从我的使用体验上来说,M0系列的I2C用起来比STM32F103的体验感强太多了,少了很多纷繁复杂的EVENT,通信的流程简化了很多,先看看初始化的代码:

void IIC_Init(void)
{
	I2C_InitTypeDef		I2C_InitStructure;
	GPIO_InitTypeDef	GPIO_InitStructure;
	
	//I2C时钟使能
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;	       //复用模式
	GPIO_InitStructure.GPIO_PuPd =  GPIO_PuPd_UP;// GPIO_PuPd_NOPULL
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	GPIO_PinAFConfig(GPIOC,GPIO_PinSource5,GPIO_AF_0);//SDA
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_0);//SCL
		

	
	//IIC配置
	I2C_InitStructure.I2C_Timing=0x00200002;//0x00210507
	I2C_InitStructure.I2C_AnalogFilter=I2C_AnalogFilter_Enable;
	I2C_InitStructure.I2C_DigitalFilter=4;
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;		//I2C模式
	I2C_InitStructure.I2C_OwnAddress1 =0; //指定自己的地址为七位地址,和从器件不同即可
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;//启用应答	 
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//七位地址模式

	I2C_Init(I2C1, &I2C_InitStructure);
	/* 使能 I2C */
	I2C_Cmd(I2C1, ENABLE);  	

}

IO配置

IO配置为开漏输出,选择复用功能。

TIMING配置

I2C外设寄存器的配置,第一个参数I2C_Timing很多新手朋友可能不知道该怎么设置,原来的时候ST官方有个execl的小工具,选择I2C频率,上升时间和下降时间后,点击计算就可以得到一个值,复制过来填进去就行,如下图(可以在官网找到,名字:I2C_Timing_Configuration_V1.0.1)硬件iic代码,单片机外设,STM32,stm32,单片机,嵌入式硬件

后面我发现一个更简单的办法,直接在cubemx上面选择M0的芯片的I2C,配置好对应的设置后会自动生成配置值:硬件iic代码,单片机外设,STM32,stm32,单片机,嵌入式硬件

滤波器配置

timing配置完成后是滤波器的配置,模拟滤波器和数字滤波器的作用:
去除总线上的一些噪声干扰。
开启后对总线的影响:
在总线上没有挂负载时,I2C的速度可以根据时钟源选择,超过I2C协议规定的3.4M/s(如此速度下通信,前提是从机能支持),但是当开启数字滤波和模拟滤波后,速度会下降很多。
其他的配置没什么特别要注意的地方,不详细展开。

读EEPROM流程详述

I2C作为主机读写从机数据,从机是EEPROM,只做了简单的读数据操作,当时为了偷懒没有做翻页读的处理(由于当时有很多种型号的EEPROM,读写函数里做了条件编译来兼容不同系列),
EE_TYPE在头文件中的定义如下:

#define A24C01   0x01
#define A24C02   0x02
#define A24C04   0x03
#define A24C08   0x04
#define A24C16   0x05
#define A24C32   0x06
#define A24C64   0x07
#define A24C128  0x08
#define A24C256  0x09
#define A24C512  0x0a
#define A24C1024 0x0b

#define EE_TYPE A24C02
//IIC读取数据函数
void IIC_Read(uint16_t SalveAddr,uint8_t startaddr,uint8_t *buffer,uint8_t Length)
{
	uint8_t i;
	

	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));//检查总线是否繁忙
	
#if (EE_TYPE > A24C16)
	I2C_TransferHandling(I2C1,SalveAddr,2,I2C_SoftEnd_Mode,I2C_Generate_Start_Write);
	
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS)==RESET);//检查TXDR寄存器是否为空
	
	I2C_SendData(I2C1, startaddr>>8);//向总线发送从器件地址	
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS)==RESET);//检查发送是否完成
	 
	I2C_SendData(I2C1,startaddr);
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TC)==RESET);
	
	
#else
	I2C_TransferHandling(I2C1,SalveAddr,1,I2C_SoftEnd_Mode,I2C_Generate_Start_Write);
	
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS)==RESET);//检查TXDR寄存器是否为空
	
	I2C_SendData(I2C1,startaddr);
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TC)==RESET);
#endif
	I2C_TransferHandling(I2C1,SalveAddr,Length,I2C_AutoEnd_Mode, I2C_Generate_Start_Read);//产生一个读的起始信号
	
	for(i=0;i<Length;i++)
	{
		while(I2C_GetFlagStatus(I2C1,I2C_FLAG_RXNE)==RESET);//等待接收完成
		
		buffer[i]=I2C_ReceiveData(I2C1);	
	}
	
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_STOPF)==RESET);//作为主机检测由硬件自己产生的停止信号	
	I2C_ClearFlag(I2C1,I2C_FLAG_STOPF);
}

读数据前先对总线进行BUSY判断,总线电平有变化时,说明处于busy状态,暂时无法操作。
如果总线处于空闲状态,就可以接手总线的控制权,调用I2C_TransferHandling函数向总线上的器件发起寻址,参数中需要确定从器件地址,发送字节数,及达到发送字节数后的结束方式,是否生成起始条件及读写方向。
其中结束方式有三个选项:
软件结束模式:在既定传输字节完成后,TC标志将置位且SCL线低电平将被延展,此时可以执行的操作有两个,一是不放弃总线控制权重新发起start信号,二是通过软件操作手动发送停止位。
自动结束模式:在既定传输字节完成后,硬件自动发送停止位。
重加载模式:当要传输的字节数大于255时,可以选择重加载模式,完成既定传输字节数后,TCR标志将置1,SCL会被延长,向NBYTES中写入一个非0值可以继续传输数据,但是在向NBYTES中写入最后一次传输的字节数之前,必须关闭重加载模式。

由于从器件是EEPROM,在器件地址发送完成后还要发送一次读写地址,此时如果用的从机器件是24c16以下的型号,从机的读写地址就是8位的,如果是24c32以上的,就要发送16位读写地址。读写地址发送完成后判断TC标志表示发送完成,16位地址时,需要在高8位地址发送完成后判断TXIS标志,我理解的TXIS标志置起状态是TXDR寄存器中数据传输到移位寄存器中(此寄存器没有公开到用户手册),并未转化成高低电平到总线时的状态(TC标志未置位),TXIS置起后,可以继续发送低八位地址。

到这里为止,如果通信过程顺利,接下来的操作就是对eeprom具体区域读数,由于上一次调用I2C_TransferHandling选择软件结束模式,且并未发送停止信号,接下来的操作就是调用I2C_TransferHandling,再次发起起始信号,发送从器件地址,将传输方向从写改为读,且确定传输字节数,接下来就是根据既定字节数,由硬件自动发送时钟出去读取数据,根据RXNE标志来接收数据,如果想读取的字节数小于255,可以选择自动结束模式,在传输完成后,自动发出停止信号,也可以选择软件结束(需要在传输完成后配置寄存器发出停止信号),如果接收数据大于255,选择重加载模式,操作方法上文有描述。
接收完成后,需要读取状态寄存器判断主机是否已经发送停止位,此时,一次完整的I2C作为主机读取EEPROM数据的通信过程结束。

写EEPROM流程详述

void IIC_Write(uint16_t SalveAddr,uint8_t startaddr,uint8_t *buffer, uint8_t Length)
{
	uint8_t i;
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));

#if (EE_TYPE > A24C16)	
	I2C_TransferHandling(I2C1,SalveAddr,2,I2C_Reload_Mode,I2C_Generate_Start_Write);
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS)==RESET);//检查TXDR寄存器是否为空
	
	I2C_SendData(I2C1, startaddr>>8);
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS)==RESET);//该位在Reload=1时NBYTES个数数据发送完成后被置1,向NBYTES写入非0数值时被清0
	I2C_SendData(I2C1,startaddr);
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TCR)==RESET);

#else 
	I2C_TransferHandling(I2C1,SalveAddr,1,I2C_Reload_Mode,I2C_Generate_Start_Write);
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS)==RESET);//检查TXDR寄存器是否为空
	
	I2C_SendData(I2C1,startaddr);
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TCR)==RESET);
#endif 
	
	I2C_TransferHandling(I2C1,SalveAddr,Length,I2C_AutoEnd_Mode,I2C_No_StartStop);
	
	for(i=0;i<Length;i++)
	{
		while(I2C_GetFlagStatus(I2C1,I2C_FLAG_TXIS)==RESET);//等待发送寄存器为空
		
		I2C_SendData(I2C1,buffer[i]);	
	}
	
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_STOPF)==RESET);//作为主机检测由硬件自己产生的停止信号
	
	I2C_ClearFlag(I2C1,I2C_FLAG_STOPF);
}

作为主机写EEPROM的操作流程类似,但是不需要修改传输方向,所以在第一次寻址时使用重加载模式,在8位或16位读写地址发送完成后,不重新生成起始信号,直接再次写入NBYTES,开始写入数据操作,由于该函数中我既定的传输字节数小于255,所以在该次传输开始前将模式修改成自动结束模式。
然后就是开始发送数据,后续结束流程和读EEPROM操作时类似。文章来源地址https://www.toymoban.com/news/detail-716187.html

到了这里,关于STM32F030硬件I2C代码及解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 HAL FreeRTOS 硬件I2C 使用

    因为某个项目想要颜色识别,去识别球的颜色,但是又不想多来个摄像头,所以想尝试一下颜色传感器的方案。但是经过尝试,HAL库生成的 FreeRTOS 硬件 I2C 读写一直在报错。 刚好手头上有九轴陀螺仪的例程代码。最后用FreeRTOS 硬件 I2C 读取数据。 这里提到了阻塞式 HAL 函数(

    2024年02月20日
    浏览(52)
  • STM32 SHT40驱动源码(使用硬件I2C)

    目录 简介: SHT40.c: SHT40.h 测试结果:         SHT40是瑞士Sensirion公司推出的第四代温湿度传感器,内部集成加热器用于去除表面微小液滴。集成I2C接口,典型的相对湿度精度1.8%RH,典型温度精度0.2℃,运行在0-100%RH和-40-125℃的环境中。 主控:STM32H7B0VBT6 平台:STM32CubeIDE SHT4

    2024年03月19日
    浏览(74)
  • 【STM32】STM32学习笔记-硬件I2C读写MPU6050(35)

    I2C(Inter-Integrated Circuit)总线是一种由NXP(原PHILIPS)公司开发的两线式串行总线,用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。 串行的 8 位双向数据传输位速率在标准模式下可

    2024年01月25日
    浏览(63)
  • 【STM32学习】——STM32-I2C外设&硬件读写MPU6050&软硬件读写波形对比

    目录 前言 一、I2C外设 二、硬件I2C操作流程 1.主机发送时序 3.其他时序

    2024年02月10日
    浏览(49)
  • STM32 硬件IIC 控制OLED I2C卡死问题

    #更新通知:2023-09-06 STM32L151 固件库 使用I2C 太难了,又宕机了,建议不要在固件库版本上尝试硬件IIC 了,一般人真用不了,直接使用软件模拟的,或者不要使用固件库了,用HAL 库吧,据说HAL 库没这么多问题,不死心的我还是死心了,等有空再研究吧 3.1 I2C模式,我这里选的

    2024年02月09日
    浏览(50)
  • STM32配合cubeMX硬件I2C驱动0.96寸OLED

    目录 一、简单介绍 1.1   OLED 1.2   I2C协议 二、实战 2.1 工程配置 2.2 测试工程 2.3 波形分析 三、驱动OLED 3.1 初始化代码 3.2 清屏函数 3.3 设置坐标函数 3.4 显示字符函数 3.5 显示字符串函数 3.6 显示图片函数 附录 驱动代码文件 oled.c oled.h f6x8.h 有机发光二极管 (英语:Organic

    2024年02月08日
    浏览(64)
  • 01_STM32软件+硬件I2C读取MPU6050(HAL库)

    目录 1、I2C简介 2、I2C时序单元 2.1 起始条件 2.2 终止条件 2.3 发送一个字节 2.4 接收一个字节 2.5 发送应答 2.6 接收应答 3、I2C完整时序 3.1 指定地址写一个字节 3.2 当前地址读一个字节 3.2 指定地址读一个字节 4、简单软件I2C代码(HAL) 4.1 软件I2C 4.2 软件I2C读MPU6050寄存器 5、ST

    2024年04月17日
    浏览(49)
  • 4针0.96寸OLED的HAL库代码(硬件I2C/全代码/stm32f1/CubeMX配置/包含有正负浮点数/100%一次点亮)

    一、HC-SR04超声波模块的使用 二、4针OLED的HAL库代码介绍及使用(本篇) 三、7针OLED的HAL库代码介绍及使用 四、编码电机以及双电机驱动 更多有意思的文章点击“我的主页” --------😐 更多有意思的视频 ----- B站 @想要亿只独角兽 --------😐 之前在做一些小项目时用到了OLED,到

    2024年02月10日
    浏览(40)
  • RT-Thread在STM32硬件I2C的踩坑记录

    参考文章: 1.将硬件I2C巧妙地将“嫁接”到RTT原生的模拟I2C驱动框架 2.基于STM32F4平台的硬件I2C驱动实现笔记 3.《rt-thread驱动框架分析》- i2c驱动   最近打算用RT-Thread做一个小demo玩玩,其中需要用I2C通信驱动一个oled屏幕,但是找了一圈也没找到RTT中对硬件I2C的支持方式以及

    2024年02月11日
    浏览(74)
  • 【STM32】AT24C256硬件I2C读写,基于HAL库

    目录 一、简单介绍 二、配置工程 打开CubeMX,配置时钟,调试接口,工程名,目录等 配置iic 配置串口用于显示信息 三、硬件连接 四、代码编写 一、随机写入一个字节 测试代码 波形如下 代码编写 二、连续写入 代码如下 三、随机读取 测试代码 波形如下 代码编写 四、连续

    2024年02月03日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包