关于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. kubernates的集群安装-kubadm

    kubernates的集群安装-kubadm 环境准备工作(CentOS) 准备三台或以上的虚拟机 停用防火墙 sudo systemctl stop firewalld sudo systemctl ...

  2. 「hdu - 5780」gcd

    link. 钦定 \(i>j\),研究得 \((x^i-1,x^j-1)\rightleftharpoons(x^i-x^j,x^j-1)\rightleftharpoons(x^j(x^{i- ...

  3. 【知识杂谈#2】如何查看Linux的(本地与公网)IP地址与SSH服务的端口号

    1. 本地Ip地址查看 使用查看linux主机是否有net-tools dpkg -l net-tools 显示以下代码就说明已安装成功 ||/ Name Version Architecture D ...

  4. JS逆向实战23 某市wss URL加密+请求头+ws收发

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 本文首发链接为: http ...

  5. 分布式事务:XA和Seata的XA模式

    上一篇内容<从2PC和容错共识算法讨论zookeeper中的Create请求>介绍了保证分布式事务提交的两阶段提交协议,而XA是针对两阶段提交提出的接口实现标准,本文则对XA进行介绍. 1 ...

  6. Docker CE

    3. 安装Docker CE Docker有两个分支版本:Docker CE和Docker EE,即社区版和企业版.本教程基于CentOS 7安装Docker CE. 执行如下命令,安装Docker的 ...

  7. Mac 下使用 ffmpeg 制作 gif

    Mac 下使用 ffmpeg 制作 gif 公众号文章,gif要求  300帧数以内        .以下是从 mp4 转为 gif 的步骤. 步骤 ffmpeg 是著名的视频处理开源软件 brew ...

  8. Trino容错模式深度测评与思考

    本文分享自华为云社区<走向批处理-交互式分析一体化: Trino容错模式深度测评与思考>,作者:HetuEngine九级代言 . 本文系华为云大数据研发团队原创,原创作者:文博,梦月 1 ...

  9. Telegram 正式引入国产小程序技术

    Telegram 宣布为其开发者提供了一项"能够在 App 中运行迷你应用"的新功能( 迷你应用即 Mini App,下文中以"小程序"代替). 在一篇博客文章 ...

  10. Unity - UIWidgets 7. Redux接入(二) 把Redux划分为不同数据模块

    参考QF.UIWidgets 参考Unity官方示例 - ConnectAppCN 前面说过,当时没想明白一个问题,在reducer中每次返回一个new State(), 会造成极大浪费,没想到用什么 ...