关于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. Solution Set -「CF 1539」

    我是傻逼. 「CF 1539A」Contest Start Link. 答案是 \(\sum_{i=1}^{n-1}\min\{i,\lfloor\frac{t}{x}\rfloor\}\),等差数列 ...

  2. linux下查找文件中某字符串出现的行以及该行前后n行

    linux下查找文件中某字符串出现的行以及该行前后n行 查找指定字符串的前后n行 grep -A 100 -B 100 "要查找的字符串" 被查找的文件 -A after 后面 - ...

  3. 小米手机抓取Log教程

    当小米手机遇到任何系统下的较为严重的故障时(即此时系统还是基本正常运行的,只是某些功能实现出了问题),例如软件自动退出,SD卡自动卸载,电话无法拨出等等.可以请用户协助抓取log即系统运行日志,来发送 ...

  4. 关于C++拷贝控制

    通常来说,对于类内动态分配资源的类需要进行拷贝控制:要在拷贝构造函数.拷贝赋值运算符.析构函数中实现安全高效的操作来管理内存.但是资源管理并不是一个类需要定义自己的拷贝控制成员的唯一原因.C++ Pr ...

  5. 基于 Angular和Material autocomplete组件再封装的可双向绑定key-value的可输入下拉框

    GitHub: https://github.com/Xinzheng-Li/AngularCustomerComponent 效果图:为了方便使用,把许多比如ADD的功能去了,可以在使用后自行实现. ...

  6. WSL2 中访问 Windows 的代理的最简易方案

    前言 学校的网卡不允许运行虚拟机,所以必须将 WSL 的流量变成主机的流量,但从百度查的方案都是设置 Windows 主机的 IP,都忽视了 Windows 的默认功能,即 mdns 或 Window ...

  7. buu pwn wp(持续更新)

    1.warmup_csaw_2016 main函数如下 __int64 __fastcall main(int a1, char **a2, char **a3) { char s[64]; // [ ...

  8. .net core中你的MD5用对了吗?

    本文的项目环境为 .net 6.0 (.net 5.0 以上都支持) 在 .net 中获取字符串的 MD5 相信是非常容易的事情吧, 但是随便在网上搜一搜发现流传的版本还不少呢,比如: StringB ...

  9. P8816 [CSP-J 2022] 上升点列

    Problem 考察算法:\(DP\). 题目简述 给你 \(n\) 个点,每个点有一个坐标 \((x_i,y_i)\),还可以添加 \(k\) 个点. 添加之后,求:最长的上升点列的长度. 上升点列 ...

  10. html考点

    编程: 1.放大镜不考 2.购物不考 广告 html html必不可少的标签 <meta charset="utf-8"/> 引入css jis 外部 注释html , ...