ESP32-硬件IIC读取温湿度传感器SHT30

news2024/9/21 18:43:05

简介

esp32 使用硬件I2C读取温湿度传感器SHT30,例程基于EDP-IDF-4.4.X 的I2C Simple Example 例程修改

工程创建

  1. 打开 VSCODE ,通过 查看-- 命令面板(快捷键Ctrl+Shift+P),打开 ESP-IDF 的例程后,选择 i2c_simple 例程,点击 Create project using example i2c_simple,选择自己要存储的目录。【PS:工程的目录不要有中文路径】
    在这里插入图片描述
  2. 打开刚刚创建的 i2c_simple 例程,该例程是使用 I2C 读取三轴加速度传感器 MPU9250,我们在这个基础上开始修改 ,首先删除 MPU9250 相关的函数,具体如下:
    在这里插入图片描述

在这里插入图片描述
3. 工程添加 SHT3X 温湿度传感器的驱动

创建components/sht3x/src、components/sht3x/include 这两个文件夹,将 i2c_sht3x.c 和i2c_sht3x.h 分别放入 src 和 include 文件夹中;复制CMakeLists.txt、component.mk到components/sht3x下。工程目录结构如下:
在这里插入图片描述

  • i2c_sht3x.c
#include "i2c_sht3x.h"


#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 */

/* 
1. 在使用SHT3X传感器的驱动之前,需要先调用 
esp_err_t 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
2. 在 i2c_sht3x.h 中根据实际使用的I2C总线修改宏定义 SHT3X_I2C_BUS 的值 

*/
/**
 * @brief  I2Cx-写从设备的寄存器值
 *      - 带有写器件寄存器的方式,适用于 MPU6050、ADXL345、HMC5983、MS5611、BMP280等绝大多数I2C设备
 *      - 例:i2c_master_write_slave_reg(I2C_NUM_0, 0x68, 0x75, &test, 1, 100 / portTICK_RATE_MS);
 * 
 * ____________________________________________________________________________________
 * | start | slave_addr + wr_bit + ack | reg_addr + ack | write n bytes + ack  | stop |
 * --------|---------------------------|----------------|----------------------|------|
 * 
 * @param  i2c_num I2C端口号。I2C_NUM_0 / I2C_NUM_1
 * @param  slave_addr I2C写从机的器件地址
 * @param  reg_addr I2C写从机的寄存器地址
 * @param  data_wr 写入的值的指针,存放写入进的数据
 * @param  size 写入的寄存器数目
 * @param  ticks_to_wait 超时等待时间
 * 
 * @return
 *     - esp_err_t
 */
esp_err_t i2c_master_write_slave_reg(i2c_port_t i2c_num, uint8_t slave_addr, uint8_t reg_addr, uint8_t *data_wr, size_t size, TickType_t ticks_to_wait)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN);
    i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, ticks_to_wait);
    i2c_cmd_link_delete(cmd);
    return ret;
}

/**
 * @brief  I2Cx-读从设备的寄存器值(寄存器地址 或 命令 为2字节的器件)
 *      - 带有读器件寄存器的方式,适用于 SHT20、GT911 这种寄存器地址为16位的I2C设备
 *      - 例:i2c_master_read_slave_reg_16bit(I2C_NUM_0, 0x44, 0xE000, &test, 6, 100 / portTICK_RATE_MS);
 * 
 * ____________________________________________________________________________________________________________________________________________________
 * | start | slave_addr + rd_bit + ack | reg_addr(2byte) + ack | start | slave_addr + wr_bit + ack | read n-1 bytes + ack | read 1 byte + nack | stop |
 * --------|---------------------------|-------------------------------|---------------------------|----------------------|--------------------|------|
 * 
 * @param  i2c_num I2C端口号。I2C_NUM_0 / I2C_NUM_1
 * @param  slave_addr I2C读从机的器件地址
 * @param  reg_addr I2C读从机的寄存器地址(2byte)
 * @param  data_rd 读出的值的指针,存放读取出的数据
 * @param  size 读取的寄存器数目
 * @param  ticks_to_wait 超时等待时间
 * 
 * @return
 *     - esp_err_t
 */
esp_err_t i2c_master_read_slave_reg_16bit(i2c_port_t i2c_num, uint8_t slave_addr, uint16_t reg_addr, uint8_t *data_rd, size_t size, TickType_t ticks_to_wait)
{
    if (size == 0) {
        return ESP_OK;
    }
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, reg_addr>>8, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN);
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
    if (size > 1) {
        i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
    }
    i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, ticks_to_wait);
    i2c_cmd_link_delete(cmd);
    return ret;
}


/**
 * @brief    向SHT3x发送一条指令(16bit)
 * 
 * @param    cmd —— SHT3x指令(在SHT3x_MODE中枚举定义)
 * 
 * @retval    成功返回HAL_OK(ESP_OK)
*/
static uint8_t SHT3X_Send_Cmd(SHT30_CMD cmd)
{
    uint8_t cmd_buffer[2];
    cmd_buffer[0] = cmd >> 8;
    cmd_buffer[1] = cmd;
    return i2c_master_write_slave_reg(SHT3X_I2C_BUS, SHT3X_SLAVE_ADDRESS, cmd_buffer[0], cmd_buffer+1, 1, SHT3X_TICKS_TO_WAIT);
}

/**
 * @brief    复位SHT3X
 * 
 * @param    none
 * 
 * @retval    none
*/
void sht3x_reset(void)
{
    SHT3X_Send_Cmd(SOFT_RESET_CMD);
    vTaskDelay(20 / portTICK_PERIOD_MS);
}

/**
 * @brief    初始化SHT30
 * 
 * @param    none
 * 
 * @retval    成功返回HAL_OK(ESP_OK)
 * 
 * @note    周期测量模式
*/
esp_err_t sht3x_init(void)
{
    return SHT3X_Send_Cmd(MEDIUM_2_CMD);
}


/**
 * @brief    从SHT3X读取一次数据
 * 
 * @param    dat —— 存储读取数据的地址(6个字节数组)
 * 
 * @retval    成功 —— 返回HAL_OK(ESP_OK)
*/
esp_err_t sht3x_read_th_raw_dat(uint8_t* dat)
{
    return i2c_master_read_slave_reg_16bit(SHT3X_I2C_BUS, SHT3X_SLAVE_ADDRESS, READOUT_FOR_PERIODIC_MODE, dat, 6, SHT3X_TICKS_TO_WAIT);
}

#define CRC8_POLYNOMIAL 0x31

static uint8_t SHT3X_CheckCrc8(uint8_t* const message, uint8_t initial_value)
{
    uint8_t  remainder;        //余数
    uint8_t  i = 0, j = 0;  //循环变量

    /* 初始化 */
    remainder = initial_value;

    for(j = 0; j < 2;j++)
    {
        remainder ^= message[j];

        /* 从最高位开始依次计算  */
        for (i = 0; i < 8; i++)
        {
            if (remainder & 0x80)
            {
                remainder = (remainder << 1)^CRC8_POLYNOMIAL;
            }
            else
            {
                remainder = (remainder << 1);
            }
        }
    }

    /* 返回计算的CRC码 */
    return remainder;
}

/**
 * @brief    将SHT30接收的6个字节数据进行CRC校验,并转换为温度值和湿度值
 * 
 * @param    dat  —— 存储接收数据的地址(6个字节数组)
 * 
 * @retval    校验成功  —— 返回0
 *            校验失败  —— 返回1,并设置温度值和湿度值为0
*/
uint8_t sht3x_dat2float(uint8_t* const dat, float* temperature, float* humidity)
{
    uint16_t recv_temperature = 0;
    uint16_t recv_humidity = 0;

    /* 校验温度数据和湿度数据是否接收正确 */
    if(SHT3X_CheckCrc8(dat, 0xFF) != dat[2] || SHT3X_CheckCrc8(&dat[3], 0xFF) != dat[5])
        return 1;

    /* 转换温度数据 */
    recv_temperature = ((uint16_t)dat[0]<<8)|dat[1];
    *temperature = -45 + 175*((float)recv_temperature/65535);

    /* 转换湿度数据 */
    recv_humidity = ((uint16_t)dat[3]<<8)|dat[4];
    *humidity = 100 * ((float)recv_humidity / 65535);

    return 0;
}
  • i2c_sht3x.h
#ifndef __I2C_SHT3X_H__
#define __I2C_SHT3X_H__


#include "driver/i2c.h"
#include "esp_log.h"

#define SHT3X_TICKS_TO_WAIT           (100 / portTICK_RATE_MS)    // I2C读写的超时等待时间

#define SHT3X_I2C_BUS                 I2C_NUM_0 // SHT30所在的I2C总线

#define SHT3X_SLAVE_ADDRESS           0x44    // SHT30在I2C总线上的从机器件地址

// SHT30命令列表
typedef enum
{
    /* 软件复位命令 */

    SOFT_RESET_CMD = 0x30A2,    
    /*
    单次测量模式
    命名格式:Repeatability_CS_CMD
    CS:Clock stretching
    */
    HIGH_ENABLED_CMD    = 0x2C06,
    MEDIUM_ENABLED_CMD  = 0x2C0D,
    LOW_ENABLED_CMD     = 0x2C10,
    HIGH_DISABLED_CMD   = 0x2400,
    MEDIUM_DISABLED_CMD = 0x240B,
    LOW_DISABLED_CMD    = 0x2416,

    /*
    周期测量模式
    命名格式:Repeatability_MPS_CMD
    MPS:measurement per second
    */
    HIGH_0_5_CMD   = 0x2032,
    MEDIUM_0_5_CMD = 0x2024,
    LOW_0_5_CMD    = 0x202F,
    HIGH_1_CMD     = 0x2130,
    MEDIUM_1_CMD   = 0x2126,
    LOW_1_CMD      = 0x212D,
    HIGH_2_CMD     = 0x2236,
    MEDIUM_2_CMD   = 0x2220,
    LOW_2_CMD      = 0x222B,
    HIGH_4_CMD     = 0x2334,
    MEDIUM_4_CMD   = 0x2322,
    LOW_4_CMD      = 0x2329,
    HIGH_10_CMD    = 0x2737,
    MEDIUM_10_CMD  = 0x2721,
    LOW_10_CMD     = 0x272A,
    /* 周期测量模式读取数据命令 */
    READOUT_FOR_PERIODIC_MODE = 0xE000,
} SHT30_CMD;


/**
 * @brief    复位SHT3X
 * 
 * @param    none
 * 
 * @retval    none
*/
void sht3x_reset(void);

/**
 * @brief    初始化SHT3X
 * 
 * @param    none
 * 
 * @retval    成功返回HAL_OK(ESP_OK)
 * 
 * @note    周期测量模式
*/
uint8_t sht3x_init(void);

/**
 * @brief    从SHT3X读取一次数据
 * 
 * @param    dat —— 存储读取数据的地址(6个字节数组)
 * 
 * @retval    成功 —— 返回HAL_OK(ESP_OK)
*/
uint8_t sht3x_read_dat(uint8_t* dat);

/**
 * @brief    将SHT3X接收的6个字节数据进行CRC校验,并转换为温度值和湿度值
 * 
 * @param    dat  —— 存储接收数据的地址(6个字节数组)
 * 
 * @retval    校验成功  —— 返回0
 *            校验失败  —— 返回1,并设置温度值和湿度值为0
*/
uint8_t sht3x_dat2float(uint8_t* const dat, float* temperature, float* humidity);


#endif
  • CMakeLists.txt
set(sht3x_srcs "src/i2c_sht3x.c")

idf_component_register(SRCS "${sht3x_srcs}"
                       INCLUDE_DIRS "include")

在这里插入图片描述

  • component.mk
#
# Component Makefile
#
COMPONENT_ADD_INCLUDEDIRS := include

COMPONENT_SRCDIRS := src

在这里插入图片描述

  1. 删除不需要的代码后,我们根据实际使用的 I2C 引脚,对 I2C 进行配置,并且编写读取 sht30 传感器的函数
/* i2c - Simple example

   Simple I2C example that shows how to initialize I2C
   as well as reading and writing from and to registers for a sensor connected over I2C.

   The sensor used in this example is a MPU9250 inertial measurement unit.

   For other examples please check:
   https://github.com/espressif/esp-idf/tree/master/examples

   See README.md file to get detailed usage of this example.

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
#include "i2c_sht3x.h" 

static const char *TAG = "i2c-sht3x";//"i2c-simple-example";

#define I2C_MASTER_SCL_IO           GPIO_NUM_14//CONFIG_I2C_MASTER_SCL      /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO           GPIO_NUM_4//CONFIG_I2C_MASTER_SDA      /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_NUM              0                          /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ          400000                     /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE   0                          /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS       1000

/**
 * @brief i2c master initialization
 */
static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = I2C_MASTER_NUM;

    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

    i2c_param_config(i2c_master_port, &conf);

    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}

// i2c_sht3x_task 任务。初始化 SHT3x工作于周期测量模式,获取环境温湿度数据
void i2c_sht3x_task(void* arg)
{
    // 配置I2C0-主机模式,400K,指定 SCL-14,SDA-4
    i2c_master_init();

    uint8_t recv_dat[6] = {0};
    float temperature = 0.0;
    float humidity = 0.0;

    ESP_LOGI(TAG, "esp32 sht3x project starting ……");
    
    sht3x_reset(); // 复位SHT3X
    if(sht3x_init() == ESP_OK) // 初始化SHT3X(周期测量模式)
        ESP_LOGI(TAG, "sht3x init ok.\n");
    else
        ESP_LOGE(TAG, "sht3x init fail.\n");
    vTaskDelay(1000 / portTICK_PERIOD_MS); //延时1s 等待SHT3X传感器内部采样完成

    for (;;)
    {
        if(sht3x_read_th_raw_dat(recv_dat) == ESP_OK) // 从SHT3X读取一次数据(周期测量模式下)
        {
            // 将SHT3X接收的6个字节数据进行CRC校验,并转换为温度值和湿度值
            if(sht3x_dat2float(recv_dat, &temperature, &humidity) == 0)
            {
                ESP_LOGI(TAG, "temperature = %.2f ℃,humidity = %.2f %%RH", temperature, humidity);
            }
            else
            {
                ESP_LOGE(TAG, "crc check fail.\n");
            }
        }
        else
        {
            ESP_LOGE(TAG, "read data from sht3x fail.\n");
        }

        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

void app_main(void)
{
    // 创建 i2c_sht3x_task 任务。初始化 SHT30工作于周期测量模式,获取环境温湿度数据
    xTaskCreate(i2c_sht3x_task, "i2c_sht3x_task", 2048, NULL, 3, NULL);
}

  1. 点击 VSCODE IDF 插件的 编译,下载,数据监测,即可在终端处查看 SHT30 传感器测量到的温湿度的值
    在这里插入图片描述

工程下载

可以点击此处下载工程,工程是不需要积分的,随意下载,如果觉得文章对您有帮助,请关注分享!
PS:该工程需要电脑已经安装了 ESP-IDF 才能编译通过

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/480585.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习卷积神经网络学习小结

————————————————————————————————————————————— 学习小结&#xff1a; 1&#xff09;深度学习综述&#xff1b;&#xff08;2&#xff09;对卷积神经网络&#xff08;CNN&#xff09;的认识&#xff1b;&#xff08;3&#xff0…

C语言中函数宏的三种封装方式详解

目录 ​编辑 1. 函数宏介绍 3. do{...}while(0) 方式 4. ({}) 方式 5. 总结 1. 函数宏介绍 函数宏&#xff0c;即包含多条语句的宏定义&#xff0c;其通常为某一被频繁调用的功能的语句封装&#xff0c;且不想通过函数方式封装来降低额外的弹栈压栈开销。 函数宏本质上为…

Winform从入门到精通(37)—FolderBrowserDialog(史上最全)

文章目录 前言1、Name2、Description3、RootFolder4、SelectedPath5、ShowNewFolderButton前言 当需要获取一个可以通过用户自由选择路径的时候,这时候就需要FolderBrowserDialog控件 1、Name 获取FolderBrowserDialog对象 2、Description 用于指示对话框的描述,如下: …

leetcode刷题(10)二叉树(4)

各位朋友们&#xff0c;大家五一劳动节快乐啊&#xff0c;在这里祝大家假期玩得愉快&#xff01;但是在玩耍的期间不要忘记了敲代码哦。今天我为大家分享的是二叉树的第四篇&#xff0c;废话不多说&#xff0c;我们一起来看看吧。 文章目录 二叉树的最近公共祖先题目要求做题思…

Stable Diffusion Controlnet V1.1 的14种基础标志用法

用于ControlNet和其他基于注入的SD控件的WebUI扩展。 针对 AUTOMATIC1111 的 Stable Diffusion web UI 网络用户界面的扩展&#xff0c;它可以让网络界面在原始的 Stable Diffusion 模型中添加 ControlNet 条件来生成图像。这种添加是实时的&#xff0c;不需要进行合并。 Con…

【openAI】Whisper如何高效语音转文字(详细教程)

文章目录 前言一、准备二、使用Whisper进行语音转文字三.Whisper转换结果分析总结 前言 语音转文字在许多不同领域都有着广泛的应用。以下是一些例子&#xff1a; 1.字幕制作&#xff1a;语音转文字可以帮助视频制作者快速制作字幕&#xff0c;这在影视行业和网络视频领域非常…

【软件下载】换新电脑记录下下载的软件时所需地址

1.idea https://www.jetbrains.com/zh-cn/idea/download/other.html 2.oracle官方&#xff08;下载jdk时找的&#xff09; https://www.oracle.com/ 3.jdk8 https://www.oracle.com/java/technologies/downloads/ 下拉找到jdk8 切换windows &#xff08;需要注册个oracle账…

TabError: inconsistent use of tabs and spaces in indentation

错误原因是tab制表符和空格混用了。从其他地方复制源码容易出现此错误 解决办法&#xff1a;把处于同级缩进的所有缩进修改统一 比较流行的几个编辑器都能标识tab和空格&#xff0c;比如我用的vscode 用鼠标框选不知道是tab还是空格的部分。 若是空格则显示为上图73行所示的点…

自动化运维工具一Ansible Roles实战

目录 一、Ansible Roles概述 1.1.roles官方的目录结构 1.2.Ansible Roles依赖关系 二、Ansible Roles案例实战 2.1.Ansible Roles NFS服务 2.2 Roles Memcached 2.3 Roles-rsync服务 一、Ansible Roles概述 之前介绍了 Playbook 的使用方法&#xff0c;对于批量任务的部…

C++程序设计——常见C++11新特性

一、列表初始化 1.C98中{}的初始化问题 在C98中&#xff0c;允许使用花括号{}对数组元素进行统一的列表初始化值设定&#xff0c;比如&#xff1a; 但是对于一些自定义类型&#xff0c;就无法使用这样的方式进行初始化了&#xff0c;比如&#xff1a; 就无法通过编译&#xff…

HIT-CSAPP实验二gdb和edb的配置

笔者只是根据自己的电脑进行环境的配置&#xff0c;不一定适配所有的电脑&#xff0c;也不是万能的方法&#xff0c;如果读者使用本人的方法没有配置成功本人深表抱歉。 gdb的使用 通过网上查阅一些资料获得 gdb查看内存和寄存器以及中断设置&#xff08;转&#xff09;_gdb…

关于安装PicGo后启动无界面问题

关于安装PicGo后启动无界面问题 其实我遇到的这个也不算是问题&#xff0c;也挺无语的。 最近为了搭建图床&#xff0c;需要使用PicGo&#xff0c;第一次搭建图床也是第一次使用PicGo。在安装了PicGo后发现启动不了&#xff0c;查看后台发现PicGo在运行着&#xff0c;但是没有界…

数据结构与算法九 树进阶

一 平衡树 之前我们学习过二叉查找树&#xff0c;发现它的查询效率比单纯的链表和数组的查询效率要高很多&#xff0c;大部分情况下&#xff0c;确实是这样的&#xff0c;但不幸的是&#xff0c;在最坏情况下&#xff0c;二叉查找树的性能还是很糟糕。 例如我们依次往二叉查找…

User Experience Design and Information Architecture

&#x1f4a5;(1) What is IA (Information Architecture)? Definition of four sentences I. Information Architecture is "The structure design of shared informaiton environments-共享信息环境的结构设计" II. Information Architecture is "The sy…

ChatGPT提示词工程(三):Summarizing概括总结

目录 一、说明二、安装环境三、概括总结&#xff08;Summarizing&#xff09;1. 简单地概括总结&#xff0c;只有字数限制2. 概括总结需要关注的某些点 四、用“提取”代替“总结”&#xff08;Try "extract" instead of "summarize"&#xff09;五、概括总…

Mysql第二章 多表查询的操作

这里写自定义目录标题 一 外连接与内连接的概念sql99语法实现 默认是内连接sql99语法实现左外连接&#xff0c;把没有部门的员工也查出来sql99语法实现右外连接&#xff0c;把没有人的部门查出来sql99语法实现满外连接&#xff0c;mysql不支持这样写mysql中如果要实现满外连接的…

生成对抗网络原理

GAN的原理 GAN是在2014年由Ian Goodfellow等人提出的&#xff0c;发表在论文“Generative Adversarial Networks”中。 GAN的主要灵感来源于博弈论中零和博弈的思想&#xff0c;应用到深度学习神经网络上来说&#xff0c;就是通过生成网络G&#xff08;Generator&#xff09;和…

系统架构设计

高性能 客户端内部缓存客户端到服务器之间缓存&#xff1a;CDN,网络专线数据库前加缓存Sessioin等信息共享NoSQL数据库分片&#xff0c;读写分离web层无关态集群负载均衡GeoDNS 就近原则&#xff0c;边缘计算存储异步&#xff0c;解耦&#xff0c;削峰&#xff1a;消息队列离线…

MySQL学习笔记第五天

第06章多表查询 多表查询概述&#xff1a; 多表查询&#xff0c;也称为关联查询&#xff0c;指两个或更多个表一起完成查询操作。前提条件&#xff1a;这些一起查询的表之间是有关系的&#xff08;一对一、一对多&#xff09;&#xff0c;它们之间一定是有关联字段&#xff0…

第二十章 渲染管线

渲染管线是计算机图形中最基础最核心的部分&#xff0c;它是将3D场景显示到2D平面的技术过程。在DirectX课程中&#xff0c;我们就介绍了渲染管线&#xff0c;分为固定渲染管线和可编程渲染管线&#xff08;Shader&#xff09;。但是在DirectX 10版本之后统一了渲染架构&#x…