ESP32开发之路(10)— ESP32的I2C通信读写AT24C02

ESP32开发之路(10)— ESP32的I2C通信读写AT24C02

一、前言

之前我们将ESP32的基本功能—WiFi都差不多试过了,进行了就来使用一下他的其他功能,比如I2C通信,I2C是一种典型的低速硬件通信协议,我想很多人的I2C通信都是从AT24C02开始的,所以我们ESP32的I2C通信也从AT24C02开始。
因为某种原因,我手边没有单独的AT24C02模块,所以就把小熊派E53_SC1扩展板拿来用一下,因为他上面有一个AT24C02,如下所示:
在这里插入图片描述
通过其地址设置引脚的接线我们知道,其地址应该为0xA2(左移后),可实际上,三个地址设置引脚都接到了地,不知道是不是因为改版的原因,所以在使用的时候最好从实际硬件去确认一下其器件地址。

二、参数配置

在使用IIC各种需要使用到一些参数,我们使用宏定义的方式去设置,首先,是IIC的读写控制:

#define WRITE_BIT 0x00          /*!< I2C master write */
#define READ_BIT 0x01           /*!< I2C master read */

然后是IIC的应答机制的设置:

#define ACK_CHECK_EN 0x1                    /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0x0                   /*!< I2C master will not check ack from slave */
#define ACK_VAL 0x0                         /*!< I2C ack value */
#define NACK_VAL 0x1                        /*!< I2C nack value */

接下来是IIC引脚的设置,ESP32由两个IIC控制器,分别对应不同的引脚,我们设置为如下,可以通过定义来选择使用哪一个IIC控制器:

#if 1
#define IIC_CTRL_NUM I2C_NUM_1              /*!< I2C port number */
#define SDA_PIN_NUM 25                      /*!< gpio number for I2C data  */
#define SCL_PIN_NUM 26                      /*!< gpio number for I2C clock */
#else
#define IIC_CTRL_NUM I2C_NUM_0              /*!< I2C port number */
#define SDA_PIN_NUM 18                      /*!< gpio number for I2C data  */
#define SCL_PIN_NUM 19                      /*!< gpio number for I2C clock */
#endif

还有最重要的AT24C02的器件地址

#define AT24C02_DeviceAddr 0xA0             /* AT24C02的器件地址 */

三、编写AT24C02控制函数

首先我们需要初始化IIC控制器,设置为主模式,

/**
 * @brief i2c master initialization
 */
static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = IIC_CTRL_NUM;
    i2c_config_t conf;
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = SDA_PIN_NUM;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_io_num = SCL_PIN_NUM;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf.master.clk_speed = 100000;     /* 标准模式(100 kbit/s) */
    i2c_param_config(i2c_master_port, &conf);
    return i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0);
}

然后是对AT24C02的写入一个字节函数:

/* AT24C02写入一个字节函数,第一个参数为要写入的值,第二个参数为要写入的地址*/
static esp_err_t at24c02_write(uint8_t data_wr, uint16_t WriteAddr)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, AT24C02_DeviceAddr | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, WriteAddr % 256, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, data_wr, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(IIC_CTRL_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}

然后是读取一个字节的函数:

/* AT24C02读取一个字节函数,第一个参数为要读出值的存放指针,第二个参数为要读出的地址*/
static esp_err_t at24c02_read(uint8_t* data_rd, uint16_t ReadAddr)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, AT24C02_DeviceAddr | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, ReadAddr % 256, ACK_CHECK_EN);
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, 0xA0 | READ_BIT, ACK_CHECK_EN);
    i2c_master_read_byte(cmd, data_rd, NACK_VAL);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(IIC_CTRL_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}

四、读写AT24C02

接下来,编写程序对AT24C02进行读取

void app_main(void)
{
    uint8_t data_buf = 0xff;
    /* 打印Hello world! */
    printf("Hello world!\n");

    /* 初始化IIC控制器 */
    ESP_ERROR_CHECK(i2c_master_init());

    /* 读取AT24C02里的数据 */
    if(at24c02_read(&data_buf, 0x02) == ESP_OK)
        printf("Read at24c02 in 0x02, data = 0x%x \n",data_buf);
    else
        printf("Read at24c02 err \n");

    /* 向AT24C02写入数据 */
    if(at24c02_write(0x55, 0x02) == ESP_OK)
        printf("Write 0x55 to at24c02 in 0x02 \n");
    else
        printf("Write at24c02 err \n");

    /* 读取AT24C02里的数据 */
    if(at24c02_read(&data_buf, 0x02) == ESP_OK)
        printf("Read at24c02 in 0x02, data = 0x%x \n",data_buf);
    else
        printf("Read at24c02 err \n");
}

编译下载运行,结果如下,可以看到,读写数据成功
在这里插入图片描述
替换为另一组IIC控制器,
在这里插入图片描述编译下载运行,读写数据依然成功
在这里插入图片描述

五、代码

下面贴上完整的app_main.c的代码

#include <string.h>
#include <sys/param.h>
#include "driver/i2c.h"

#define GPIO_LED_NUM 2                      /* LED引脚编号 */

#define WRITE_BIT 0x00                      /*!< I2C master write */
#define READ_BIT 0x01                       /*!< I2C master read  */

#define ACK_CHECK_EN 0x1                    /*!< I2C master will check ack from slave     */
#define ACK_CHECK_DIS 0x0                   /*!< I2C master will not check ack from slave */
#define ACK_VAL 0x0                         /*!< I2C ack value  */
#define NACK_VAL 0x1                        /*!< I2C nack value */

#if 0
#define IIC_CTRL_NUM I2C_NUM_1              /*!< I2C port number */
#define SDA_PIN_NUM 25                      /*!< gpio number for I2C data  */
#define SCL_PIN_NUM 26                      /*!< gpio number for I2C clock */
#else
#define IIC_CTRL_NUM I2C_NUM_0              /*!< I2C port number */
#define SDA_PIN_NUM 18                      /*!< gpio number for I2C data  */
#define SCL_PIN_NUM 19                      /*!< gpio number for I2C clock */
#endif

#define AT24C02_DeviceAddr 0xA0             /* AT24C02的器件地址 */

/**
 * @brief i2c master initialization
 */
static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = IIC_CTRL_NUM;
    i2c_config_t conf;
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = SDA_PIN_NUM;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_io_num = SCL_PIN_NUM;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf.master.clk_speed = 100000;     /* 标准模式(100 kbit/s) */
    i2c_param_config(i2c_master_port, &conf);
    return i2c_driver_install(i2c_master_port, conf.mode, 0, 0, 0);
}

/* AT24C02读取一个字节函数,第一个参数为要读出值的存放指针,第二个参数为要读出的地址*/
static esp_err_t at24c02_read(uint8_t* data_rd, uint16_t ReadAddr)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, AT24C02_DeviceAddr | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, ReadAddr % 256, ACK_CHECK_EN);
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, 0xA0 | READ_BIT, ACK_CHECK_EN);
    i2c_master_read_byte(cmd, data_rd, NACK_VAL);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(IIC_CTRL_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}

/* AT24C02写入一个字节函数,第一个参数为要写入的值,第二个参数为要写入的地址*/
static esp_err_t at24c02_write(uint8_t data_wr, uint16_t WriteAddr)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, AT24C02_DeviceAddr | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, WriteAddr % 256, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, data_wr, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(IIC_CTRL_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}

void app_main(void)
{
    uint8_t data_buf = 0x00;
    /* 打印Hello world! */
    printf("Hello world!\n");

    /* 初始化IIC控制器 */
    ESP_ERROR_CHECK(i2c_master_init());

    /* 读取AT24C02里的数据 */
    if(at24c02_read(&data_buf, 0x03) == ESP_OK)
        printf("Read at24c02 in 0x03, data = 0x%x \n",data_buf);
    else
        printf("Read at24c02 err \n");

    /* 向AT24C02写入数据 */
    if(at24c02_write(0x55, 0x03) == ESP_OK)
        printf("Write 0x55 to at24c02 in 0x03 \n");
    else
        printf("Write at24c02 err \n");

    /* 读取AT24C02里的数据 */
    if(at24c02_read(&data_buf, 0x03) == ESP_OK)
        printf("Read at24c02 in 0x03, data = 0x%x \n",data_buf);
    else
        printf("Read at24c02 err \n");

    /* 定义一个gpio配置结构体 初始化LED */
    gpio_config_t gpio_config_structure;

    /* 初始化gpio配置结构体*/
    gpio_config_structure.pin_bit_mask = (1ULL << GPIO_LED_NUM);/* 选择gpio2 */
    gpio_config_structure.mode = GPIO_MODE_OUTPUT;              /* 输出模式 */
    gpio_config_structure.pull_up_en = 0;                       /* 不上拉 */
    gpio_config_structure.pull_down_en = 0;                     /* 不下拉 */
    gpio_config_structure.intr_type = GPIO_PIN_INTR_DISABLE;    /* 禁止中断 */ 

    /* 根据设定参数初始化并使能 */  
	gpio_config(&gpio_config_structure);
    /* 默认熄灭LED */
    gpio_set_level(GPIO_LED_NUM, 0);        /* 熄灭 */

    while(1)
    {
        gpio_set_level(GPIO_LED_NUM, 0);        /* 熄灭 */
        vTaskDelay(500 / portTICK_PERIOD_MS);   /* 延时500ms*/
        gpio_set_level(GPIO_LED_NUM, 1);        /* 点亮 */
        vTaskDelay(500 / portTICK_PERIOD_MS);   /* 延时500ms*/
    }
}
  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值