ESP32C3学习&开发之路——最全的IIC协议_esp32 iic

2.1起始和停止条件

起始(S)和停止(P)条件一般由主机产生,总线在起始条件后被认为处于忙的状态。在停止条件的某段时间后,总线被认为再次处于空闲状态。
起始条件:在 SCL 线是高电平时,SDA 线从高电平向低电平切换
停止条件:当 SCL 是高电平时,SDA 线由低电平向高电平切换
起始(S)和停止(P)条件时序图如下:
在这里插入图片描述
起始条件表示开始交互,停止条件表示交互结束,主机释放总线,在一次交互中主机可以发起多次起始条件(如读数据)。

2.2应答(ACK)和不应答(NACK)

应答:
数据传输必须带响应,相关的响应时钟脉冲由主机产生,在响应的时钟脉冲期间,发送器释放 SDA 线(高),接收器必须将 SDA 线拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平 。
数据的每个字节(包括地址字节)后面跟着一个来自接收端的ACK位。ACK位允许接收端向发送端发送已成功接收的字节和可以发送的另一个字节。
不应答:
当SDA线在ACK/NACK相关的时钟周期内保持高电平时,这被解释为不应答(NACK)。
有以下几种情况会产生不应答(NACK):
当从机不能响应从机地址时(例如它正在执行一些实时函数不能接收或发送)从机必须使数据线保持高电平。主机然后产生一个停止条件终止传输或者产生重复起始条件开始新的传输。
如果从机-接收器响应了从机地址但是在传输了一段时间后不能接收更多数据字节,主机必须再一次终止传输。这个情况用从机在第一个字节后没有产生响应来表示。从机使数据线保持高电平,主机产生一个停止或重复起始条件。
如果传输中有主机接收器,它必须通过在从机不产生时钟的最后一个字节不产生一个响应,向从机发送器通知数据结束。从机-发送器必须释放数据线,允许主机产生一个停止或重复起始条件。
总结为:
(1)从机无法接收或发送,因为它正在执行一些实时功能,并没有准备好开始与主机通信。
(2)在传输过程中,从机无法接收更多的数据字节。
(3)主机机完成了读取数据并通过NACK指示从机。
(4)在传输过程中,主机获取了它不理解的数据或命令。

应答(ACK)和不应答(NACK)时序图:
在这里插入图片描述

2.3写数据

给从机写数据,主机将在总线先发送起始条件,再发送一个带有写标志的从机地址,在最后一个位(R/W位)设置为0,表示写。 在从机发送应答位后,主机将发送它希望写入的寄存器的寄存器地址。 从机会再次应答,让主人知道它准备好了。 在此之后,主机将开始向从机发送寄存器数据,直到主机发送了它需要的所有数据(有时只是一个字节),并且主机将用STOP条件终止传输,如图所示:
在这里插入图片描述

2.4读数据

在第一个字节后,主机立即读从机如图,在第一次响应时,主机——发送器变成主机——接收器,从机——接收器变成从机——发送器。第一次响应仍由从机产生。之前发送了一个不响应信号的主机产生停止条件。
在这里插入图片描述

2.5读/写数据

读/写操作(复合格式)如图。传输改变方向的时侯,起始条件和从机地址都会被重复。但 R/ W 位取反。如果主机接收器发送一个重复起始条件,它之前应该发送了一个不响应信号。
在这里插入图片描述

二、ESP32C3的IIC

1.概述

ESP32-C3 只有一个 I2C 控制器(也称为端口),负责处理在 I2C 总线上的通信。每个控制器都可以设置为主机或从机。使用IIC就是对这个个 I2C 控制器的操作,作为嵌入式开发人员应该知道IIC协议还可以直接用GPIO来模拟。

2.主要特性

• 支持主机模式和从机模式
• 支持多从机通信
• 支持标准模式 (100 Kbit/s)
• 支持快速模式 (400 Kbit/s)
• 支持 7 位以及10位地址寻址
• 支持拉低 SCL时钟实现连续数据传输
• 支持可编程数字噪声滤波功能
• 支持从机地址和从机内存或寄存器地址的双寻址模式

3.架构

I2C 控制器可以工作于主机模式或者从机模式, I2C_MS_MODE 用于模式选择。图 27-1 为 I2C 主机基本架构图,图27-2 为 I2C 从机基本架构图。 I2C 控制器内部包括的模块主要有:
• 接收和发送存储器 TX/RX RAM
• 命令控制器 CMD_Controller
• SCL 时钟控制器 SCL_FSM
• SDA 数据控制器 SCL_MAIN_FSM
• 串并转换器 DATA_Shifter
• SCL 滤波器 SCL_Filter
• SDA 滤波器 SDA_Filter
在这里插入图片描述

3.功能描述

I2C 控制器涉及的功能比较丰富,朋友们请参阅《esp32-c3_technical_reference_manual_cn》手册(我是去看了很多遍),篇幅有限就不贴上来了,功能描述目录如下图:
在这里插入图片描述

4.ESP32C3 IIC中断

ESP32-C3的IIC可以产生多种中断,可以根据需要开启相应的中断功能。请参阅《esp32-c3_technical_reference_manual_cn》手册中IIC的中断介绍。

三、ESP32C3 IIC驱动MPU6500

1.MPU6500介绍

1.1概述

MPU- 60X0是全球首例9轴运动处理传感器。它集成了3轴MEMS陀螺仪,3轴MEMS加速度计,以及一个可扩展的数字运动处理器DMP(Digital MotionProcessor),可用I²C接口连接一个第三方的数字传感器,比如磁力计。扩展之后就可以通过其I²C或SPI接口输出一个9轴的信号(SPI接口仅在MPU- 6000可用)。MPU- 60X0也可以通过其I²C接口连接非惯性的数字传感器,比如压力传感器。
MPU- 60X0对陀螺仪和加速度计分别用了三个16位的ADC,将其测量的模拟量转化为可输出的数字量。为了精确跟踪快速和慢速的运动,传感器的测量范围都是用户可控的,陀螺仪可测范围为±250,±500,±1000,±2000/秒 (dps),加速度计可测范围为±2,±4,±8,±16g。 一个片上1024字节的FIFO,有助于降低系统功耗。和所有设备寄存器之间的通信采用400kHz的I²C接口或1MHz的SPI接口(SPI仅MPU-6000可用)对于需要高速传输的应用,对寄存器的读取和中断可用20MHz的SPI。另外,片上还内嵌了一个温度传感器和在工作环境下仅有±1%变动的振荡器。

1.2产品参数

供电电源:3-5v (内部低压差稳压)
通信方式:标准IIC/SPI通信协议
芯片内置16bitAD转换器,16位数据输出
陀螺仪范围:±250 500 1000 2000° /s
加速度范围:±2 ±4 ±8 ±16g
引脚间距: 2. 54mm
模块尺寸: 25*15mm

1.3引脚说明

VCC:电源正
GND:地
SCL:I2C串 行时钟线/SPI串行时钟端口
SDA: I2C串行数据线/SPI串行数据输入
EDA:连接其他I2C设备的主机数据口
ECL:给I2C设备 提供主时钟
ADO/SD0:I2C器 件地址选择位/SPI串行数据输出
INT:中断引脚
NCS:片选
FSYNC:数字同步输入帧, 不用请接地
在这里插入图片描述

2.ESP32C3驱动MPU6500

MPU6500地址:
设置为0xD0(主机寻址时要左移一位,最低位用于控制读写)
在这里插入图片描述
在这里插入图片描述
当AD0悬空时为低电平,这里我让该引脚悬空,所以地址为0xD0。

测试读取的寄存器地址:
在这里插入图片描述
设置ESP32C3映射IIC的引脚:
通过meunconfig的Example Configuration进行设置,因为工程有针对IIC配置了Kconfig.projbuild文件,如下图:选择GPIO5、6
在这里插入图片描述
电路连接:
如图:
在这里插入图片描述
在ESP32C3的IIC库文件已经实现了IIC协议操作的API函数我们只要调用和传参即可,如图:
在这里插入图片描述
在这里插入图片描述

代码:

#include <stdio.h>
#include "esp\_log.h"
#include "driver/i2c.h"

static const char \*TAG = "i2c-MPU6500";

#define I2C\_MASTER\_SCL\_IO CONFIG\_I2C\_MASTER\_SCL /\*!< GPIO number used for I2C master clock \*/
#define I2C\_MASTER\_SDA\_IO CONFIG\_I2C\_MASTER\_SDA /\*!< GPIO number used for I2C master data \*/
#define I2C\_MASTER\_NUM 0 /\*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip \*/
#define I2C\_MASTER\_FREQ\_HZ 400000 /\*!< I2C master clock frequency \*/
#define I2C\_MASTER\_TX\_BUF\_DISABLE 0 /\*!< I2C master doesn't need buffer \*/
#define I2C\_MASTER\_RX\_BUF\_DISABLE 0 /\*!< I2C master doesn't need buffer \*/
#define I2C\_MASTER\_TIMEOUT\_MS 1000

#define MPU6500\_SENSOR\_ADDR 0xD0 /\*!< Slave address of the MPU6500 sensor \*/
#define MPU6500\_WHO\_AM\_I\_REG\_ADDR 0x75 /\*!< Register addresses of the "who am I" register \*/

#define MPU6500\_PWR\_MGMT\_1\_REG\_ADDR 0x6B /\*!< Register addresses of the power managment register \*/
#define MPU6500\_RESET\_BIT 7

/\*\*
 \* @brief Read a sequence of bytes from a MPU6500 sensor registers
 \*/
static esp\_err\_t mpu6500\_register\_read(uint8\_t reg_addr, uint8\_t \*data, size\_t len)
{
    return i2c\_master\_write\_read\_device(I2C_MASTER_NUM, MPU6500_SENSOR_ADDR, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
}

/\*\*
 \* @brief Write a byte to a MPU6500 sensor register
 \*/
static esp\_err\_t mpu6500\_register\_write\_byte(uint8\_t reg_addr, uint8\_t data)
{
    int ret;
    uint8\_t write_buf[2] = {reg_addr, data};

    ret = i2c\_master\_write\_to\_device(I2C_MASTER_NUM, MPU6500_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);

    return ret;
}

/\*\*
 \* @brief i2c master initialization
 \*/
static esp\_err\_t i2c\_master\_init(void)
{
    int i2c_master_port = I2C_MASTER_NUM;

    i2c\_config\_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

    i2c\_param\_config(i2c_master_port, &conf);

    return i2c\_driver\_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}


void app\_main(void)
{
    uint8\_t data[2];
    ESP\_ERROR\_CHECK(i2c\_master\_init());
    ESP\_LOGI(TAG, "I2C initialized successfully");

    /\* Read the MPU6500 WHO\_AM\_I register, on power up the register should have the value 0x71 \*/
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/eebc7c03cf2cf1b8fa80ac9c596c2e1e.png)

![img](https://img-blog.csdnimg.cn/img_convert/e2cf519aab91e6b1d5654f50d17c665a.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/2f08f81dceb5f296095a59936cb8a4fd.png)

 ![img](https://img-blog.csdnimg.cn/img_convert/cd0a6de8ca55445ada58353e27aaa155.png)

![img](https://img-blog.csdnimg.cn/img_convert/1c39188cd3953c7ae36adf6c5ea88533.png)

![img](https://img-blog.csdnimg.cn/img_convert/13706115281113777305711d5b996a49.png)

![](https://img-blog.csdnimg.cn/img_convert/126ee1570e77a6f3b72d6331e6ba618a.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


g-7eGiSdWl-1715556136489)]

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ESP32-C3是一款高度集成的低功耗Wi-Fi和蓝牙SoC,是ESP32系列的最新成员。ESP32-C3的硬件支持I2C总线,可以实现多个设备之间的通信。ESP32-C3的I2C实现使用硬件I2C接口,可以实现高速、稳定的数据传输。以下是ESP32-C3 I2C的基本使用方法: 1. 配置I2C总线参数: ```c i2c_config_t conf; conf.mode = I2C_MODE_MASTER; conf.sda_io_num = I2C_SDA_PIN; conf.scl_io_num = I2C_SCL_PIN; conf.sda_pullup_en = GPIO_PULLUP_ENABLE; conf.scl_pullup_en = GPIO_PULLUP_ENABLE; conf.master.clk_speed = I2C_FREQ_HZ; i2c_param_config(I2C_NUM_0, &amp;conf); ``` 其中,I2C_SDA_PIN和I2C_SCL_PIN是SDA和SCL信号线的GPIO引脚号,I2C_FREQ_HZ是I2C总线的时钟频率。 2. 初始化I2C总线: ```c i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0); ``` 3. 发送I2C数据: ```c i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, SLAVE_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN); i2c_master_write_byte(cmd, data, ACK_CHECK_EN); i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS); i2c_cmd_link_delete(cmd); ``` 其中,SLAVE_ADDR是从设备的I2C地址,WRITE_BIT是写操作标志位,data是要发送的数据。 4. 接收I2C数据: ```c i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, SLAVE_ADDR << 1 | READ_BIT, ACK_CHECK_EN); i2c_master_read_byte(cmd, &amp;data, ACK_CHECK_EN); i2c_master_stop(cmd); esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS); i2c_cmd_link_delete(cmd); ``` 其中,READ_BIT是读操作标志位,data是接收数据的变量。 以上代码仅供参考,具体实现要根据实际应用场景进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值