STM32的集成电路总线I2C

news2024/11/27 14:48:55

一、I2C简介

1.I2C总线特点

        (1)两线制

                I2C只需要SDA、SCL两根线来完成数据的传输和外围器件的扩展,器件地址采用软件寻址方式。

        (2)多主机总线

                I2C是一个真正的多主机总线,如果2个或多个主机同时初始化数据传输,可以通过冲突检测和仲裁防止数据被破坏。每个连接到总线上的器件都有唯一的地址,任何器件既可以作为主机也可以作为从机,但同一时刻只能有一个主机。

        (3)传输速率

                数据传输速率相对SPI不高,串行的8位双向数据传输速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s。

        (4)传输方式

                是同步半双工通信机制,总线上传输数据的最小单位是1个字节(8bit),高位先行,每传送完1个字节,接收器必须发送一个应答位。

2.I2C总线术语

  • 主机:初始化发送,产生时钟信号和终止发送的器件。
  • 从机:被主机寻址的器件。
  • 多主机:同时有多于一个主机尝试控制总线,但不破坏信息。
  • 仲裁:是在一个有多个主机同时尝试控制总线,但只允许其中一个控制总线并使信息不被破坏的过程。
  • 同步:两个或多个器件同步时钟信号的过程。
  • 地址:主机用于区分不同从机而分配的地址。
  • SDA:I2C通信时用于数据传输的信号线。
  • SCL:I2C通信时用于时钟传输的信号线。

3.I2C硬件构成

         将所有I2C设备的SDA线连在一起、SCL线连在一起,两线均要配置成开漏输出模式,SDA、SCL各接一个上拉电阻,一般为4.7KΩ左右。

4.位传输

        (1)数据有效性

        I2C总线以串行方式传输数据,数据传输是按照时钟节拍进行的。协议标准规定,SCL为高电平时,SDA上的数据必须保持不变;SCL为低电平时,SDA的电平状态才能改变。即SCL为高电平时数据有效。

        (2)起始信号和停止信号

        协议规定,SCL为高电平 时,SDA产生下降沿,表示起始信号,SDA产生上升沿,表示停止信号。

        (3)重复开始信号

        在I2C总线上,由主机产生一个起始信号后,在产生一个停止信号之前,再产生一个起始信号,称为重复起始信号。

        (4)应答信号和非应答信号

        协议规定,发送器每发送一个字节数据,接收器必须产生一个应答信号或非应答信号。实现方法是:发送器发送完8位数据后,在第9个时钟信号将SDA线拉高,接收器将SDA拉低,产生一个应答信号,或者保持SDA为高,产生一个非应答信号。

5.数据传输格式

        一般情况下,一个标准的I2C通信由4部分组成,起始信号从机地址传输数据传输停止信号,每次通信的数据字节数是没有限制的。

        (1)I2C总线寻址约定

                I2C采用软件方法实现从机寻址来简化总线连接,协议规定了起始信号后的第1个字节为寻址字节。I2C总线支持7位寻址模式和10位寻址模式。常用的7位寻址模式中,寻址字节由从机的7位地址位(D7~D1)和1位读写位(D0)组成,D0=1为读,D0=0为写。

        (2)数据传输模式

                主机从从机读N个字节:主机产生一个起始信号,然后发送一个寻址字节,读写位置1表示读,主机拉高SDA。从机检测到与自己相同的地址,产生一个应答信号。之后从机开始发送数据,每发送一个字节数据,主机产生一个应答信号。当数据传输完毕,主机产生一个非应答信号结束数据传输,主机产生一个停止信号结束通信,或者产生一个重复起始信号进入下一次数据传输。

                主机向从机写N个字节:主机产生一个起始信号,然后发送一个寻址字节,读写位置0表示写,主机拉高SDA。从机检测到与自己相同的地址,产生一个应答信号。之后主机开始发送数据,每发送一个字节数据,从机产生一个应答信号。当数据传输完毕,从机产生应答或非应答信号均可,此时主机再产生一个停止信号结束通信,或者产生一个重复起始信号进入下一次数据传输。

                主机指定地址从从机读N个字节:当主机在访问类似存储器器件(如EEPROM,一种掉电后数据不丢失的存储芯片)时,主机除了发送寻址字节来选择从机外,还要发送从机的存储地址来选择读写的位置。实际上很多器件、模块都有多个寄存器,都要指定相应的寄存器才能读取所需的数据。实现方法是先写后读,具体步骤是在上述读的基础上,在读之前先写存储地址,需要用到重复起始信号(本质就是一个起始信号)。具体如图所示:

                主机指定地址向从机写N个字节:类似的,需要指定存储位置再进行写操作,具体如下: 

二、STM32的I2C外设

        STM32的I2C外设具有4种工作模式:主发送器模式、主接收器模式、从发送器模式、从接收器模式。其重要特征如下:

  • 支持不同的通信速度。标准速度高达100KHz,快速高达400KHz。
  • 完善的通信功能。可由硬件自动执行时钟生成、起始和终止条件生成、应答位收发、数据收发等功能,减轻CPU的负担。
  • 完善的错误监测。主模式时的仲裁丢失,地址/数据传输后的应答错误,检测到错位的起始或停止条件,禁止拉长时钟功能时的上溢或下溢。
  • 具有2个中断向量。一个用于地址/数据通信中断,一个用于通信出错中断。
  • 具有单字节缓冲器的DMA
  • 兼容系统管理总线(SMBus)

        STM32的I2C内部结构如图所示:

三、STM32 I2C外设的通信方式

        1.I2C主模式

                STM32的I2C模块作为主机使用,启动数据传输并产生时钟信号。

         (1)主模式发送

                I2C主模式发送示意图如图所示:

                在使用STM32的I2C外设时,需要遵循上图中的时序逻辑,等待相应事件的发生再执行下一步,各事件的意义说明如下:

  • EV5: 表示已检测到起始条件,可以开始发送寻址字节。
  • EV6:表示已发送从机地址,且已检测到从机的应答。
  • EV8_1:表示数据寄存器为空且上一个数据字节的传输已经完成,这意味着可以发送下一个数据字节。
  • EV8:表示数据寄存器为空,可以发送数据。
  • EV8_2:表示从机成功接收到主机发出的数据字节并发出应答信号,表明从机已准备好接收下一个数据字节。
  • EV9:暂不说明。
        (2)主模式接收 

                I2C主模式接收示意图如图所示:

                同样的,使用STM32的I2C外设时需要遵循上图中的时序逻辑,各事件的说明如下:

  • EV5: 表示已检测到起始条件,可以开始发送寻址字节。
  • EV6:表示已发送从机地址,且已检测到从机的应答。
  • EV7:表示数据寄存器不为空,即接收到了数据。
  • EV8_2:表示从机成功接收到主机发出的数据字节并发出应答信号,表明从机已准备好接收下一个数据字节。

        2.I2C从模式

        该模式即STM32的I2C模块作为从机,这里暂不介绍。 

四、STM32 I2C外设使用流程

        虽然不同器件实现的功能不同,但是只要遵循I2C协议,其通信方式都是一样的,配置流程也基本相同。对于STM32,首先要对I2C进行配置,使其能够正常工作,再结合不同器件的驱动程序,完成STM32与不同器件的数据传输。这里只介绍STM32作为主机的使用流程,从机可以是AT24XX系列EEPROM或MPU6050等器件,使用流程和参考代码如下:

  1. 配置GPIO。
  2. 配置I2C。
  3. 编写读取从机数据的函数。
  4. 编写向从机写数据的函数。
void I2C_Init(void)     //初始化STM32的I2C2模块,使其能够使用
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	

	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;	        //将PB10和PB11引脚初始化为复用
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;//开漏输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);				 
                                                            
	

	I2C_InitTypeDef I2C_InitStructure;						
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;				//模式,选择为I2C模式
	I2C_InitStructure.I2C_ClockSpeed = 50000;				//时钟速度,选择为50KHz
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;		//时钟占空比,选择占空比为1/3
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;				//应答,选择使能
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;	
                                                   //应答地址,选择7位,从机模式下才有效
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;				//自身地址,从机模式下才有效
	I2C_Init(I2C2, &I2C_InitStructure);	
	
	I2C_Cmd(I2C2, ENABLE);									//使能I2C2,开始运行
}



void Write_Byte(uint8_t 存储地址, uint8_t Data)  //向从机写一个字节数据,存储地址不一定为8位
{
	I2C_GenerateSTART(I2C2, ENABLE);										
    //产生起始条件
    
	while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);	
    //等待EV5,即等待检测到起始条件

	I2C_Send7bitAddress(I2C2, 从机地址, I2C_Direction_Transmitter);	
    //发送从机地址

    while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);
	//等待EV6,即等待发送从机地址并受到从机应答信号
	
	I2C_SendData(I2C2, 存储地址);											
    //发送存储地址

    while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);			
    //等待EV8,即等待数据寄存器为空,可以发送数据
	
	I2C_SendData(I2C2, Data);												
    //发送数据

    while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);				
    //等待EV8_2,即等待从机接收到数据并传回应答信号
	
	I2C_GenerateSTOP(I2C2, ENABLE);											
    //产生停止信号
}

uint8_t Read_Byte(uint8_t 数据所在地址) //从从机读取一个字节数据,数据所在地址不一定为8位
{
	uint8_t Data;
    //用于暂存数据
	
	I2C_GenerateSTART(I2C2, ENABLE);										
    //产生起始条件

    while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);
    //等待EV5,即等待检测到起始条件
	
	I2C_Send7bitAddress(I2C2, 从机地址, I2C_Direction_Transmitter);	
    //发送从机地址

    while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);
    //等待EV6,即等待发送从机地址并受到从机应答信号
	
	I2C_SendData(I2C2, 数据所在地址);											
    //发送从机的数据所在地址

    while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);
    //等待EV8_2,即等待从机接收到数据并传回应答信号
	
	I2C_GenerateSTART(I2C2, ENABLE);										
    //产生重复起始条件

    while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);					
    //等待EV5,即等待检测到起始条件
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver);		
    //发送从机地址

    while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS);
    //等待EV6,即等待发送从机地址并受到从机应答信号
	
	I2C_AcknowledgeConfig(I2C2, DISABLE);									
    //在接收最后一个字节之前提前将应答失能,之后从机不再传输数据

	I2C_GenerateSTOP(I2C2, ENABLE);											
    //在接收最后一个字节之前提前申请停止条件

	while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);			
    //等待EV7,即等待数据寄存器不为空,收到了数据

	Data = I2C_ReceiveData(I2C2);											
    //将接收到的数据存到Data变量中
	
	I2C_AcknowledgeConfig(I2C2, ENABLE);									
    //将应答恢复为使能,为了不影响后续可能产生的读取多字节操作
	
	return Data;
}

代码仅供参考,具体使用需要结合相关从机器件的开发文档。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2189881.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Day01-MySQL数据库介绍及部署

Day01-MySQL数据库介绍及部署 1、数据库服务概述介绍1.1 企业中为什么需要数据库?1.2 数据库服务作用1.3 数据库服务分类 2、数据库服务安装部署2.1 数据库版本应用2.2 数据库服务程序下载2.3 数据库软件安装方式2.3.1 二进制安装步骤 3、数据库服务初始化介绍3.1 安…

《15分钟轻松学 Python》教程目录

为什么要写这个教程呢,主要是因为即使是AI技术突起的时代,想要用好AI做开发,那肯定离不开Python,就算最轻量级的智能体都有代码块要写,所以不一定要掌握完完整整的Python,只要掌握基础就能应对大部分场景。…

react-问卷星项目(6)

实战 React常用UI组件库 Ant Design国内最常用组件库,稳定,强大Material UI国外流行TailWind UI 国外流行,收费 Ant Design 官网地址 这一章基本内容就是使用UI重构页面,也没有什么知识点,直接上代码 下载 npm ins…

git diff 查看到一行变动,但是目测无差异怎么办?

1. 目测无变化 直接用 git diff main.js 提示有一行变动,但是目测看不出来差异。 结果如图:up panel. 2. 大概是空格的问题,使用参数 --ws-error-highlightall $ git diff --ws-error-highlightall main.js结果如图: down panel.

【LeetCode: 19. 删除链表的倒数第 N 个结点 | 链表 + 快慢指针】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

大学生就业桥梁:基于Spring Boot的招聘系统

1系统概述 1.1 研究背景 如今互联网高速发展,网络遍布全球,通过互联网发布的消息能快而方便的传播到世界每个角落,并且互联网上能传播的信息也很广,比如文字、图片、声音、视频等。从而,这种种好处使得互联网成了信息传…

【操作系统】引导(Boot)电脑的奇妙开机过程

🌹😊🌹博客主页:【Hello_shuoCSDN博客】 ✨操作系统详见 【操作系统专项】 ✨C语言知识详见:【C语言专项】 目录 什么是操作系统的引导? 操作系统的引导(开机过程) Windows操作系…

JavaScript-下篇

上篇我们学习了,一些基础语法和函数,现在我们学习下篇,主要包括,对象和事件。而对象又包括,数组Arrays,String字符串,BOM,DOM等 JS对象 Arrays数组 数组是一种特殊的对象,用于存储…

【多线程】多线程(8):单例模式:阻塞队列

【阻塞队列】 阻塞队列是在普通的“先进先出”队列的基础上,做出了扩充,可以组成「生产者消费者模型」 1.线程安全性 标准库是原有的队列Queue和其子类,默认都是“线程不安全的”,而阻塞队列是“线程安全的” 2.具有阻塞特性 …

【pytorch】张量求导3

再接上文,补一下作者未补完的矩阵运算的坑。 首先贴一下原作者的图,将其转化为如下代码: import torch import torch.nn as nn import torch.optim as optim# 定义一个简单的两层神经网络 class TwoLayerNet(nn.Module):def __init__(self):super(TwoLayerNet, self).__in…

Markdown 语法详解大全(超级版)(二)

Markdown 语法详解大全(超级版)(二) Markdown 语法详解大全(超级版)(一) Markdown 语法详解大全(超级版)(二) Markdown 语法详解大全(超级版)(三) (歌词节选&#xff09…

Ubuntu 中 Redis ,MySQL 基本使用

1、Redis (1)启动Redis 服务端客户端命令 服务端 ps aux | grep redis 查看redis服务器进程 sudo kill -9 pid 杀死redis服务器 sudo redis-server /etc/redis/redis.conf 指定加载的配置文件客户端 连接redis: redis-cli运⾏测试命令&am…

C++结构体定义和创建

// // Created by 徐昌真 on 2024/10/5. // #include <iostream> using namespace std;int main() {//结构体的定义 struct 结构体名字 { 结构体成员名字 }struct Book{string name;double price;int value;}java; //java是创建的结构体//创建结构体//这是第一种方式Boo…

目标检测 DAB-DETR(2022)

文章目录 前言Query是什么&#xff0c;Detr收敛速度慢的原因是什么&#xff1f;改进策略位置先验和模型框架设置温度系数 前言 本文认为原始的Detr系列论文中&#xff1a;可学习的object queries仅仅是给model预测box提供了锚点&#xff08;中心点&#xff09;信息&#xff0c…

SpringBoot环境下古典舞交流平台的快速开发

第三章 系统分析 3.1 可行性分析 需要使用大部分精力开发的古典舞在线交流平台为了充分降低开发风险&#xff0c;特意在开发之前进行可行性分析这个验证系统开发是否可行的步骤。本文就会从技术角度&#xff0c;经济角度&#xff0c;还有操作角度等进行综合阐述。 3.1.1技术可行…

Python案例--三数排序

一、引言 在信息爆炸的时代&#xff0c;我们每天都会接触到大量的数据。无论是工作中的报表、学习中的数据集&#xff0c;还是日常生活中的购物清单&#xff0c;数据的有序性对于提高效率和决策质量都至关重要。排序算法作为数据处理的基础工具&#xff0c;其重要性不言而喻。…

日记学习小迪安全27

感觉复制粘贴没有意思&#xff0c;而且还有点浪费时间&#xff0c;主要是学习&#xff0c;不是复制&#xff0c;那就复制别人的吧 第27关就参考这篇文章吧&#xff0c;以下大部分内容都是参考以下文章&#xff08;侵权删除&#xff09; 第27天&#xff1a;WEB攻防-通用漏洞&a…

芯片录-低压差线性稳压器AZ1084D-ADJE1失效记录与原理分析

背景 最近主板坏了&#xff0c;现象是主机不停重启&#xff0c;USB设备LED灯一会儿亮&#xff0c;一会儿灭。经过一些分析和定位&#xff0c;通过测温发现主板上AZ1084D-ADJE1芯片高达91摄氏度&#xff0c;进一步测量该芯片的输出引脚和接地引脚短路&#xff0c;初步推测某些原…

Shell-使用函数

在 Shell 脚本中&#xff0c;函数是由一段代码定义的&#xff0c;可以被重复调用。Shell 函数的定义和调用相对简单&#xff0c;并且它支持参数传递和返回值。错误处理在 Shell 中也非常重要&#xff0c;通常通过检查返回的状态码来判断是否有错误发生。 1.Shell 函数的定义和…

构建高效招聘流程:Spring Boot大学生就业系统

1系统概述 1.1 研究背景 如今互联网高速发展&#xff0c;网络遍布全球&#xff0c;通过互联网发布的消息能快而方便的传播到世界每个角落&#xff0c;并且互联网上能传播的信息也很广&#xff0c;比如文字、图片、声音、视频等。从而&#xff0c;这种种好处使得互联网成了信息传…