注:使用VSCode中的ESP-IDF插件进行开发,笔记基于B站UP主艾谷科技的视频教程

ESP32S3+ESPIDF入门教程 程序纯手打 手把手教学 中文字幕 持续更新中_哔哩哔哩_bilibili


目录

一、I2C通信简介

二、硬件电路

三、I2C通信

ESP32S3的I2C外设资源

四、I2C外设工作流程

        读写命令的格式需要对照芯片手册并使用下列函数进行编写

五、BH1750模块

六、建立工程项目

    (1).复制工程文件夹

        (2).在VSCode中打开新的工程文件夹

        (3).在components中的CMakeList文件中添加IIC、BH1750文件路径

        (4).编写iic.c文件

        (5).编写iic.h文件

      (6).编写bh1750.c文件

      (7).编写bh1750.h文件

        (8).编写main.c文件

        (9).编译

        (10).连接电路

        (11).下载并运行


一、I2C通信简介

  • I2C/IIC(Inter IC Bus)是由飞利浦公司开发的一种通用数据总线
  • 两根通信线:SCL(Serial Clock)、SDA(Serial Data)
  • 同步、半双工
  • 带数据应答
  • 总线挂载多设备(一主多从、多主多从)

二、硬件电路

  • 所有的I2C设备的SCL连在一起,SDA连在一起
  • 设备的SCL和SDA均要配置为开漏输出模式,该模式可以避免短路的问题
  • SCL、SDA各添加一个上拉电阻,阻值一般为4.7k Ω左右 

三、I2C通信

  • 起始条件:SCL高电平期间,SDA从高电平切换到低电平
  • 终止条件:SCL高电平期间,SDA从低电平切换到高电平

  • 发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,依次循环上述过程8次,即可发送一个字节的数据

  • 发送应答:主机在接收完一个字节的数据后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答
  • 接收应答:主机在接收完一个字节的数据后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA) 

I2C时序

  • 地址字节:当主机想要进行写操作时,地址字节是在从机设备地址末尾+0,即从机设备地址左移一位;当主机想要进行读操作时,地址字节是在从机设备地址末尾+1,即从机设备地址左移一位后+1

ESP32S3的I2C外设资源

  • ESP32S3内部集成两个I2C控制器,负责处理I2C总线上的通信
  • 支持主机模式、从机模式
  • 支持7/位10位地址模式
  • 支持不同的通信速度,标准速度(100kHz)、快速(400kHz)
  • ESP32S3硬件I2C资源:I2C0、I2C1

四、I2C外设工作流程

  

i2c_param_config(i2c_port_t i2c_num, const i2c_config_t *i2c_conf);

  • i2c_num:I2C端口号
  • i2c_conf:结构体指针,创建新的结构体,并引出所有结构体成员

i2c_config_t i2c_structure = {

        .clk_flags = ,        //配置时钟源

        .master.clk_speed = , //配置I2C时钟线通信速度,且为结构体形式需要引出结构体成员,可配置为10000和40000

        .mode = ,          //I2C通信模式,有主机模式和从机模式两种,一般选择主机模式

        .scl_io_num = , //SCL的IO引脚

        .scl_pullup_en = ,  //SCL引脚内部上拉电阻使能,有外部上拉可以不使能,但无外部上拉电阻时必须使能

        .sda_io_num = ,    ///SDA的IO引脚

        .sda_pullup_en = ,  //SDA引脚内部上拉电阻使能

        .slave = ,        //当I2C设置为从机模式时,配置该结构体,配置相应的从机参数

    };

i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_buf_len, size_t slv_tx_buf_len, int intr_alloc_flags);

  • i2c_num:I2C端口号
  • mode:选则I2C模式
  • slv_rx_buf_len:用于从机模式的接收缓存区大小,此处不使用,直接配置为0
  • slv_tx_buf_len:用于从机模式的发送缓存区大小,此处不使用,直接配置为0
  • intr_alloc_flags:中断标志位,此处不使用,直接配置为0

        读写命令的格式需要对照芯片手册并使用下列函数进行编写

       i2c_cmd_link_create(void); 该函数用于返回命令链句柄

        i2c_master_start(i2c_cmd_handle_t cmd_handle)在命令链中存入起始命令

       i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool ack_en)

  • cmd_handle:命令链句柄
  • data:传输的命令
  • ack_en:应答位

        i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t *data, i2c_ack_type_t ack);

  • cmd_handle:命令链句柄
  • data:读取到的数据存放的地址  
  • ack:应答位

        i2c_master_stop(i2c_cmd_handle_t cmd_handle)在命令链中存入停止命令

        i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait)

  • i2c_num:I2C端口号
  • cmd_handle:命令链句柄
  • ticks_to_wait:超时等待时间

        i2c_cmd_link_delete(i2c_cmd_handle_t cmd_handle);用于销毁命令链

五、BH1750模块

  • BH1750是一款适用于I2C总线接口的数字环境光强传感器
  • 适用于获取环境光数据,用于后续的光强调控
  • 检测光照强度分辨率:1~65535勒克斯
  • 支持标准I2C(100kHz)、快速I2C(400kHz)

六、建立工程项目

    (1).复制工程文件夹

                复制LED的工程文件夹,并改名为IICBH1750,在components文件夹下创建新的文件夹并取名iic、bh1750,在iic、bh1750文件夹中创建相应的.c、.h文件。

        (2).在VSCode中打开新的工程文件夹

                打开工程文件后,先点击垃圾桶按钮清理之前编译程序产生的中间文件,清理完成后再进行编译。

        (3).在components中的CMakeList文件中添加IIC、BH1750文件路径

        (4).编写iic.c文件

#include "iic.h"
#include "driver/gpio.h"
#include "driver/i2c.h"


void iic_init(void)
{
    i2c_config_t i2c_structure = {
        .clk_flags = 0,
        .master.clk_speed = 100000,
        .mode = I2C_MODE_MASTER,
        .scl_io_num = GPIO_NUM_4,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .sda_io_num = GPIO_NUM_5,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
    };
    i2c_param_config(I2C_NUM_0, &i2c_structure);

   i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
}

        (5).编写iic.h文件

#ifndef __MYIIC_H_
#define __MYIIC_H_

void iic_init(void);

#endif 

      (6).编写bh1750.c文件

#include "bh1750.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/i2c.h" 
#include "iic.h"    

void bh1750_send_cmd(uint8_t cmd_data)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();   //创建空的命令链条
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, bh1750_write_addr, true);
    i2c_master_write_byte(cmd, cmd_data, true);
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000);     //该函数为开启控制开关,命令链自动生成数据帧
                                                    // 第三个参数为最大通信时间
    i2c_cmd_link_delete(cmd);                       //使用完成后删除命令链
}

uint16_t bh1750_read_data(void)
{
    uint8_t light_high = 0, light_low = 0;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, bh1750_read_addr, true);
    i2c_master_read_byte(cmd, &light_high, I2C_MASTER_ACK);
    i2c_master_read_byte(cmd, &light_low, I2C_MASTER_NACK);
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000);
    i2c_cmd_link_delete(cmd);
    return light_high<<8 | light_low;
}

void bh1750_init(void)
{
    iic_init();                                         //初始化I2C
    bh1750_send_cmd(PowerOn);                           //将BH1750设置为上电模式
    bh1750_send_cmd(Continuous_HResolutionMode_1);      //将BH1750设置为连续模式
    vTaskDelay(200);                                    //初次切换为连续模式时,需要等待最大180ms
}

      (7).编写bh1750.h文件

  • 根据芯片手册编写
#ifndef __BH1750_H_
#define __BH1750_H_

#include <stdint.h>

#define bh1750_write_addr 0x46
#define bh1750_read_addr  0x47

#define PowerDown                       0x00
#define PowerOn                         0x01
#define Reset                           0x07
#define Continuous_HResolutionMode_1    0x10
#define Continuous_HResolutionMode_2    0x11
#define Continuous_LResolutionMode      0x13
#define OneShot_HResolutionMode_1       0x20
#define OneShot_HResolutionMode_2       0x21                                                  
#define OneShot_LResolutionMode         0x23

void bh1750_send_cmd(uint8_t cmd_data);
uint16_t bh1750_read_data(void);
void bh1750_init(void);

#endif

        (8).编写main.c文件

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "bh1750.h"

float light = 0;

void app_main(void)
{
    lcd_init();
    bh1750_init();

    while(1)
    {
        light = (float)bh1750_read_data() / 1.2;
        printf("light:%f\r\n",light); 
        vTaskDelay(1000);
    }
}

        (9).编译

        (10).连接电路

        (11).下载并运行

     窗口每秒打印一次光照强度信息

    

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐