关于iic原理建议B站自己看视频去,

然后本文主要实现了esp32的初始化, 写地址, 写数据, 读数据的功能, 从机的代码因为展示不需要,没写.

园子里面有个兄弟写了iic的代码.但是里面有点毒,多发了次地址验证,所以才有这篇文章;

代码注释比较多, 愿君少走弯路❀

以下是头文件主要参数代码:

#include "driver/i2c.h"
#include "freertos/portmacro.h"
#define I2C_NUM I2C_NUM_0
#define I2C_MATER_READ (0x1) // 主机进行读操作,从机进行写操作
#define I2C_MATER_WRITE (0x0) // 主机进行写操作,从机进行读操作
#define ACK_VAL (0x0) // 主机读取时的应答信号(应答)
#define NACK_VAL (0x1) // 主机读取时的应答信号(不应答)
#define portTICK_RATE_MS portTICK_PERIOD_MS //防止报错
 
 
以下为iic初始化函数代码:
 
/*
 * @brief 初始化I2C配置;
 * @param I2C_SCL_Frequency 为i2c的时钟频率 ,一般模式为100 000(100k);
 * @param SCL & SDA 为I2C配置的引脚,允许任意IO口,可直接输入对应的IO口序号,如 19 ,20
 * @return err 为esp特有的报错指南?还没搞得很懂,反正是为了方便调试的;
 */
esp_err_t esp32_i2c_init(char SCL , char SDA , int I2C_SCL_Frequency)
{
        // 初始化I2C配置
        i2c_config_t i2c_config = {
                .mode = I2C_MODE_MASTER, // 设置i2c模式
                .sda_io_num = SDA, // 设置SDA引脚
                .scl_io_num = SCL, // 设置SCL引脚
                .sda_pullup_en = GPIO_PULLUP_ENABLE, // 设置上拉使能
                .scl_pullup_en = GPIO_PULLUP_ENABLE, // 设置上拉使能
                .master.clk_speed = I2C_SCL_Frequency, // 设置时钟频率xxxbit
                // .clk_flags = 0,
        };
        // 设置I2C
        i2c_param_config(
                I2C_NUM,
                //配置参数初始化,此函数内部就是将i2c_config 中的相关参数 填入到 "I2c_NUM "对应的结构体中。
                &i2c_config);
        // 注册I2C服务及使能  (安装 I2C 驱动程序后, ESP32 即可与其他 I2C 设备通信。)
        esp_err_t err = i2c_driver_install(
                I2C_NUM, i2c_config.mode, 0, 0,
                0); //初始化配置以外的所有相关参数,将配置写入寄存器
        return err; //可以直接访问esp32_i2c_init的返回值 即可知道,驱动是否安全完成.
}
 
以下是写地址函数::
/*
 * @brief 进行I2C第一个Byte的写操作(指主机在公屏call对应的从机);
 * @param SlaveAddr 为i2c从机的地址,代码未做自动移位处理;
 * @param endbit 为写入的最后一个bit,肩负着告诉从机接下来是发送数据还是接收数据(I2C_MATER_READ || I2C_MATER_WRITE)
 * @return 0; 暂时没想到有什么需要返回的
 * @property 有已经封装好的函数有对应每8bit进行应答的操作,所以后续开发不需要在意iic协议本身
 * @exception vscode 可能会提示portTICK_RATE_MS 为未定义标识符,可以别管能编译通过
 */
char i2c_write_addr(char SlaveAddr, char end_bit)
{
        //创建i2c_cmd_handle_t对象
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
        //添加各种子数据帧
        i2c_master_start(cmd); //向cmd对象添加起始信号
        i2c_master_write_byte(
                cmd, (SlaveAddr) | end_bit,
                true); //向cmd对象添加从机r地址及读写位 ack(true)为检测slave答应
        //i2c_master_write(cmd, bytes, datalen, true);  //向cmd对象添加数据位(数组)
        i2c_master_stop(cmd); //向cmd对象添加终止信号
        //向I2C_NUM 发送这个数据帧cmd,
        i2c_master_cmd_begin(I2C_NUM, cmd, 1000 / portTICK_RATE_MS);
        //删除i2c_cmd_handle_t对象,释放资源
        i2c_cmd_link_delete(cmd);
        return 0;
}

以下是写数据函数(8bits):

/*
 * @brief 进行I2C第一个Byte的写操作(指主机在公屏call对应的从机);
 * @param SlaveAddr 为i2c从机的地址,代码未做自动移位处理;
 * @param endbit 为写入的最后一个bit,肩负着告诉从机接下来是发送数据还是接收数据(I2C_MATER_READ || I2C_MATER_WRITE)
 * @return 0; 暂时没想到有什么需要返回的
 * @property 有已经封装好的函数有对应每8bit进行应答的操作,所以后续开发不需要在意iic协议本身
 * @exception vscode 可能会提示portTICK_RATE_MS 为未定义标识符,可以别管能编译通过
 */
char i2c_write_to_slave(char SlaveAddr, char endbit, char data)
{
        //创建i2c_cmd_handle_t对象
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
        //添加各种子数据帧
        i2c_master_start(cmd); //向cmd对象添加起始信号
        i2c_master_write_byte(
                cmd, (SlaveAddr) | endbit,
                true); //向cmd对象添加从机r地址及读写位 ack(true)为检测slave答应
        i2c_master_write_byte(cmd, data, true); //向cmd对象添加数据位(数组)
        i2c_master_stop(cmd); //向cmd对象添加终止信号
        //向I2C_NUM 发送这个数据帧cmd,
        i2c_master_cmd_begin(I2C_NUM, cmd, 1000 / portTICK_RATE_MS);
        //删除i2c_cmd_handle_t对象,释放资源
        i2c_cmd_link_delete(cmd);
        return 0;
}
 
以下是读数据函数:
/*
 * @brief 进行I2C两个Byte的读操作;
 * @param SlaveAddr 为i2c从机的地址,代码已做自动移位处理;
 * @param endbit 为写入的最后一个bit,肩负着告诉从机接下来是发送数据还是接收数据(I2C_MATER_READ || I2C_MATER_WRITE)
 * @return readvalue 为读取的16bit数据,(正常顺序)
 * @property 有已经封装好的函数有对应每8bit进行应答的操作,所以后续开发不需要在意iic协议本身
 * @exception vscode 可能会提示portTICK_RATE_MS 为未定义标识符,可以别管能编译通过
 */
uint16_t i2c_read_slave(char SlaveAddr, char endbit)
{
        static uint8_t readvalue1 = 0; //切记搞成static的,不然会灵异读取
        static uint8_t readvalue2 = 0; //切记搞成static的,不然会灵异读取
        static uint16_t readvalue = 0;
        esp_err_t err = ESP_OK;
        //创建i2c_cmd_handle_t对象
        i2c_cmd_handle_t cmd = i2c_cmd_link_create();
        i2c_master_start(cmd); //向cmd对象添加起始信号
        i2c_master_write_byte(
                cmd, (SlaveAddr << 1) | endbit,
                true); //向cmd对象添加从机地址及读写位 ack(true)为检测slave答应
        //******开始读数据操作:总共读16bit*****//
        err = i2c_master_read_byte(cmd, &readvalue1, ACK_VAL);
        err = i2c_master_read_byte(cmd, &readvalue2, NACK_VAL);
        if (err != ESP_OK) {
                goto end;
        }
        i2c_master_stop(cmd); //向cmd对象添加终止信号
        //向I2C_NUM 发送这个数据帧cmd,
        i2c_master_cmd_begin(I2C_NUM, cmd, 1000 / portTICK_RATE_MS);
        //删除i2c_cmd_handle_t对象,释放资源
end:
        i2c_cmd_link_delete(cmd);
        readvalue = readvalue1 << 8 | readvalue2;
        return readvalue;
}
 

ESP32 IDF iic通信( 已验证) C语言的更多相关文章

  1. 破圈法求解最小生成树c语言实现(已验证)

    破圈法求解最小生成树c语言实现(已验证) 下面是算法伪代码,每一个算法都取一个图作为输入,并返回一个边集T. 对该算法,证明T是一棵最小生成树,或者证明T不是一棵最小生成树.此外,对于每个算法,无论它 ...

  2. STM32—IIC通信(软件实现底层函数)

    使用GPIO引脚模拟SDA和SCL总线实现软件模拟IIC通信,IIC的具体通信协议层和物理层链接:IIC #ifndef __BSP_IIC_H #define __BSP_IIC_H #includ ...

  3. 单片机modebus RTU通信实现,采用C语言,可适用于单片机,VC,安卓等(转)

    源:单片机modebus RTU通信实现,采用C语言,可适用于单片机,VC,安卓等 //modebus_rtu.c /***************************************** ...

  4. 基于51单片机IIC通信的PCF8591学习笔记

    引言 PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入.一个输出和一个串行I2C 总线接口.3 个地址引脚A0.A1 和A2 用于编程硬件地址,允许将最多8 个器件连接 ...

  5. 基于51单片机IIC通信的AT24C02学习笔记

    引言 最近在学习几种串行通信协议,感觉收获很多,这篇文章是学习IIC总线协议的第一篇文章,以后还会再写一篇关于PCF8591 IIC通信的ADDA转换芯片的文章. 关于IIC总线 IIC 即Inter ...

  6. 基于esp32的IIC通讯

    本文源码地址在:http://download.csdn.net/download/noticeable/9962029 IIC 通讯应该是当代比较常用的几种通讯方式之一,其无需特殊的IO接口,连线方 ...

  7. C语言风格的 for 循环(SHELL的循环写法 已验证20200517)

    C语言风格的 for 循环 C语言风格的 for 循环的用法如下: for((exp1; exp2; exp3))do    statementsdone 几点说明: exp1.exp2.exp3 是 ...

  8. 搭建Hadoop的HA高可用架构(超详细步骤+已验证)

    一.集群的规划 Zookeeper集群: 192.168.182.12 (bigdata12)192.168.182.13 (bigdata13)192.168.182.14 (bigdata14) ...

  9. Laravel中的信息验证 和 语言包

    首先,谈下语言包的问题 1.安装语言包,通过composer进行安装 composer require "overtrue/laravel-lang:dev-master" 2.成 ...

  10. Asp.net MVC 服务端验证多语言错误

    服务端验证用户提交信息时为了实现多语言使用了资源文件,如: using System.ComponentModel.DataAnnotations; public class UserModel { ...

随机推荐

  1. 一文弄懂TypeScript中的混合

    1.前言 由于TypeScrip中的类不支持多继承,所以引入了混合(Mixin)的特性,可以间接实现继承的效果. 2.正文 // 声明一个汽车类Vehicle,它有drive方法 class Vehi ...

  2. OPPO主题组件开发 - 调试与预览

    本篇作为 OPPO主题组件调试与预览 文档的补充,因为它真的很简单而且太老,一些命令已发生变化 1. 调试前准备 1. PC 端下载 adb命令工具 下载 https://adbdownload.co ...

  3. 爬虫系列——selenium

    文章目录 一 介绍 二 安装 三 基本使用 四 选择器 五 等待元素被加载 六 元素交互操作 七 其他 八 项目练习 一 介绍 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决r ...

  4. 【Unity3D】消融特效

    1 前言 ​ 选中物体消融特效中基于 Shader 实现了消融特效,本文将基于 Shader Graph 实现消融特效,两者原理一样,只是表达方式不同,另外,选中物体消融特效中通过 discard 丢 ...

  5. ts 终于搞懂TS中的泛型啦! | typescript 入门指南 04

    大家好,我是王天~ 这篇文章是 ts入门指南系列中第四篇,主要讲解ts中的泛型应用,泛型在ts中是比较重要的概念,我花挺长时间才搞明白的,希望能帮助到大家 ~ ** ts 入门指南系列 ** Ts和J ...

  6. 再学Blazor——组件

    Blazor 应用基于组件,组件可以复用和嵌套.本文内容如下: 组件类 组件嵌套 组件参数 组件对象 1. 组件类 所有组件都是继承 ComponentBase 组件基类,razor 文件默认继承 C ...

  7. Util应用框架快速入门(4) - 集成测试开发入门

    本文演示Util应用框架开发的项目中如何编写集成测试. 准备 完成 Web Api 快速入门,本文将在之前生成的示例项目上讲解集成测试的开发. 测试概述 自动化测试对于Util应用框架的开发非常重要, ...

  8. logback java动态配置【动态修改日志级别,动态修改appender】(转)

    logback 动态配置 写在前面在做java日志之前,强烈建议大家读一下这篇java日志的前世今生,对理清java日志框架很有帮助!1奉上地址: 一个著名的日志系统是怎么设计出来的 然后说一下,为啥 ...

  9. JUC并发编程学习笔记(九)阻塞队列

    阻塞队列 阻塞 队列 队列的特性:FIFO(fist inpupt fist output)先进先出 不得不阻塞的情况 什么情况下会使用阻塞队列:多线程并发处理.线程池 学会使用队列 添加.移除 四组 ...

  10. 题解 AGC054D

    前言 因为本人尚菜,所以本篇文章没有什么数学符号,请大家放心食用. 题目分析 先吐槽一嘴,这个 o 表示 (),这个 x 表示 )(,十分形象. 好,我们先观察原序列,容易得出第一条性质: ox 的加 ...