【硬件模块】SHT20温湿度传感器

news2024/11/15 19:23:53

SHT20是一个用IIC通信的温湿度传感器。我们知道这个就可以了。

它支持的电压范围是2.1~3.6V,推荐是3V,所以如果我们的MCU是5V的,那么就得转个电压才能用了。

IIC常见的速率有100k,400k,而SHT20是支持400k的(0.4MHz)。

SHT20的命令有上面几个,不放中文的原因是中文翻译的好烂,我直接解释一下这些是什么意思吧。

命令从上到下分别是触发温度测量(hold master),触发湿度测量(hold master),触发温度测量(no hold master),触发湿度测量(no hold master),写用户寄存器,读用户寄存器,软件复位。

其中hold master 和 no hold master 的意思就是,如果是hold,那么在测量过程中SHT20仍会霸占着IIC的总线,IIC总线上的其他设备无法占用,而no hold就是测量过程中SHT20不占用IIC总线了,一般我们用no hold master,但如果IIC总线上就SHT20一个设备,那么其实无所谓用哪一种。

而读写用户寄存器实际上就是读写配置。

一般来说要修改的就是bit0和bit7,这俩是决定我们温湿度的精度的,默认是00,也就是温度的精度是14bit,湿度的精度是12bit。除非是对采样时间有要求,否则一般情况我们是不用修改的。

接着看看时序图。从时序图可以得知SHT20的IIC从机地址是100 000,加上写命令就是0x80,加上读命令就是0x81。

我们要获取温湿度的话,首先先发送从机地址+写,接着我们发送触发测量的命令,等待测量完毕之后再发送从机地址+读,等到SHT20给我们了ACK回应之后,我们接收3个byte,分别是数据的高8位,数据的低8位,CRC校验码。如果不需要CRC校验,那么我们只需要读取前两个byte即可。

SHT20的CRC校验多项式是x8+x5+x4+1。

我们可以使用在线网站帮我们计算(或者需要在运行时校验的话就按照CRC校验的规则自己写个校验函数)。

CRC在线计算crc在线计算,循环冗余校验在线计算icon-default.png?t=O83Ahttps://www.lddgo.net/encrypt/crc

另外在数据的低8位中的最后两位,是状态位,如果是“00”,那么表示这个数据是温度,如果是“10”则表示这个数据是湿度,但是这个其实没啥用,因为读出啥数据取决于我们之前发送的测量命令,我们要做的就是将最后两位清零,因为最大分辨率为14bit。

得到数据之后我们还需要做些处理。

湿度按照上面这个公式进行计算。

温度按照下面这个公司进行计算。

测量读取温湿度的流程就是上面这些。

读取修改用户寄存器(配置)的流程也大差不大。

如果是要读取,那么先发送从机地址+写,发送读取指令,然后再发送从机地址+读,接着接收一个byte即可。

如果是要修改,那么发送从机地址+读,发送写入指令,接着发送我们要修改的内容即可。

下面是ESP32使用ESP-IDF通过硬件I2C操作SHT20的完整示例代码。

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

#include "driver/i2c.h"

#define SHT20_SCL   5
#define SHT20_SDA   6

float SHT20_getVal(uint8_t command) {
    i2c_cmd_handle_t container = i2c_cmd_link_create();
    i2c_master_start(container);
    i2c_master_write_byte(container, 0x80, true);

    if (command == 'w') i2c_master_write_byte(container, 0xF3, true);
    else    i2c_master_write_byte(container, 0xF5, true);

    i2c_master_stop(container);
    i2c_master_cmd_begin(I2C_NUM_0, container, 100 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(container);

    vTaskDelay(100 / portTICK_PERIOD_MS);

    uint8_t data_H = 0, data_L = 0;
    uint8_t CRC = 0;

    container = i2c_cmd_link_create();
    i2c_master_start(container);
    i2c_master_write_byte(container, 0x81, true);
    i2c_master_read_byte(container, &data_H, I2C_MASTER_ACK);
    i2c_master_read_byte(container, &data_L, I2C_MASTER_ACK);
    i2c_master_read_byte(container, &CRC, I2C_MASTER_NACK);
    i2c_master_stop(container);
    i2c_master_cmd_begin(I2C_NUM_0, container, 100 / portTICK_PERIOD_MS);

    i2c_cmd_link_delete(container);

    double res = ((uint16_t)data_H << 8 | data_L) & 0xFFFC;  // 把最后两位去掉,因为分辨率为14bit

    if (command == 'w')     return (res / 65536.0) * 175.72 - 46.85;
    return (res / 65536.0) * 125.0 - 6;
}

void SHT20_init(void) {
    i2c_config_t i2c_initer = {.clk_flags = 0,           // 默认时钟源
                               .master.clk_speed = 4e5,  // 400k
                               .mode = I2C_MODE_MASTER,  // 主机
                               .scl_io_num = SHT20_SCL,
                               .scl_pullup_en = true,
                               .sda_io_num = SHT20_SDA,
                               .sda_pullup_en = true};
    i2c_param_config(I2C_NUM_0, &i2c_initer);

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

void app_main(void) {
    SHT20_init();
    float w,s;
    while (1) {
        w = SHT20_getVal('w');
        s = SHT20_getVal('s');
        printf("T is %f ℃    RH is %f%%\r\n", w , s);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

下面是GD32使用硬件I2C操作SHT20的完整示例代码。里面涉及串口的部分可以删除,串口只是为了把数据打印出来方便观察,也可以查看我往期的文章了解GD32的串口怎么使用。

【GD32】07 - UART串口通信_gd32 uart自发自收-CSDN博客文章浏览阅读1.4k次,点赞27次,收藏20次。根据之前STM32串口的经验,我们可以将printf重定向到串口上,在STM32中我们直接重写fputc,然后在Keil的设置中勾选Use MicroLlB就行了,但是在GD32F407中勾选Use MicroLlB在编译后会有两个错误。发送数据,注意这边参数的取值范围,发送数据的范围居然是0~0x1FF,类型是uint32_t。今天我用的型号是GD32F407,用其他型号的小伙伴在使用UART的时候注意一下自己手上板子的资源就行,我们使用固件库就算是不同型号其实也是没有什么太大差别的。_gd32 uart自发自收icon-default.png?t=O83Ahttps://blog.csdn.net/m0_63235356/article/details/139904819

#include "board.h"
#include <stdio.h>
#include "Z_UART.h"
 
float SHT20_GetData(uint8_t command){
    uint16_t res = 0;
 
    i2c_start_on_bus(I2C0);                             //起始时序
    while(!i2c_flag_get(I2C0,I2C_FLAG_SBSEND) );        //等待起始位发送完. 这个不用手动清除标志位
    
    i2c_master_addressing(I2C0, 0x80, I2C_TRANSMITTER); //发送从机地址(0x80)+写命令(0)
    while(!i2c_flag_get(I2C0,I2C_FLAG_ADDSEND) );       //等待从机发送完毕之后得到回应(即从机地址正确)
    i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND);              //清除标志位
    
    while(!i2c_flag_get(I2C0,I2C_FLAG_TBE));            //等待发送缓冲区空
    
    if(command == 'w')  i2c_data_transmit(I2C0,0xF3);   //发送数据,发送SHT20的指令,F3为获取温度,F5为获取湿度
    else    i2c_data_transmit(I2C0,0xF5);
    
    while(!i2c_flag_get(I2C0,I2C_FLAG_BTC) );           //等待字节传输完毕
 
    i2c_stop_on_bus(I2C0);                              //发送结束时序
    
    uint8_t count = 0;                                  //计数,因为SHT20采集数据需要时间,我们设置个超时时间
    do{
        i2c_start_on_bus(I2C0);                         //起始时序
        while(!i2c_flag_get(I2C0,I2C_FLAG_SBSEND));     //等待起始位发送完毕
     
        i2c_master_addressing(I2C0, 0x80, I2C_RECEIVER);//发送从机地址(0x80)+读命令(1)
        
        delay_ms(10);                                   //延时10ms
        if(++count >= 10) return 0;                     //超过100ms我们就算读取失败
    }while(!i2c_flag_get(I2C0,I2C_FLAG_ADDSEND));       //等待回应
 
    i2c_flag_clear(I2C0,I2C_FLAG_ADDSEND);              //清除标志位
 
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);               //开启应答
 
    while(!i2c_flag_get(I2C0,I2C_FLAG_RBNE) );          //等待接收缓冲区不为空
 
    res = i2c_data_receive (I2C0);                      //读取SHT传来的数据的高8位
    res <<= 8;
 
    i2c_ack_config(I2C0, I2C_ACK_DISABLE);              //关闭应答,因为我们就获取俩8bit数据
 
    while(!i2c_flag_get(I2C0,I2C_FLAG_RBNE) );          //等待接收缓冲区不为空
 
    res |= i2c_data_receive (I2C0);                     //读取SHT传来的数据的低8位
    
    i2c_stop_on_bus(I2C0);                              //结束时序
 
    res &= 0xFFFC;                                      //清除最后两位,这是SHT20要求的
    
    //根据指令的不同(获取温度/湿度)来计算数据
    if(command == 'w') return ((res / 65536.0) * 175.72 - 46.85);
    return (( res / 65536.0) * 125 - 6);
}
 
int main(void){
    board_init();
    //初始化串口,为了将结果打印到串口助手上,不懂怎么操作的小伙伴可以看看上一篇文章
    Z_UART_Init();
    //开启时钟
    rcu_periph_clock_enable(RCU_I2C0);
    rcu_periph_clock_enable(RCU_GPIOB);
    //初始化硬件IIC的引脚
    gpio_af_set(GPIOB, GPIO_AF_4,GPIO_PIN_8|GPIO_PIN_9);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8|GPIO_PIN_9);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ,GPIO_PIN_8|GPIO_PIN_9);
       
    i2c_deinit(I2C0);                                           //复位IIC0
    i2c_clock_config(I2C0, 100000, I2C_DTCY_2);                 //设置IIC速率为100k
    i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0X80);  //设置SHT20的七位地址
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);                       //使能应答
    i2c_enable(I2C0);                                           //使能IIC
    
    printf("hello world!\r\n");
    while (1){
        printf("%f\t%f\r\n",SHT20_GetData('w'),SHT20_GetData('s'));
        delay_ms(1000);
    }
}

下面是STM32使用软件I2C操作SHT20的完整示例代码,其中延时函数需要自己准备,OLED的部分可以删除,是用来观察数据的,可以拿串口来代替。也可以查阅我往期的文章了解STM32利用滴答定时器实现的延时函数,以及串口、OLED的使用。

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
 
#define SCL_Pin GPIO_Pin_0
#define SDA_Pin GPIO_Pin_1
 
void Z_I2C_Init(void){
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    GPIO_InitTypeDef itd;
    itd.GPIO_Mode=GPIO_Mode_Out_OD;        
    itd.GPIO_Pin=SCL_Pin|SDA_Pin;    
    itd.GPIO_Speed=GPIO_Speed_50MHz;                   
    GPIO_Init(GPIOA,&itd);
 
    GPIO_WriteBit(GPIOA,SCL_Pin,Bit_SET);       //SCL和SDA默认都是高电平
    GPIO_WriteBit(GPIOA,SDA_Pin,Bit_SET);       //因此初始化后设为高电平
}
    
void Z_I2C_SetSCL(uint8_t signal){
    if(signal==1) GPIO_WriteBit(GPIOA,SCL_Pin,Bit_SET);
    else GPIO_WriteBit(GPIOA,SCL_Pin,Bit_RESET);
    Delay_us(5);                    //防止电平翻转过快,因此加上延时
}
 
void Z_I2C_SetSDA(uint8_t signal){
    if(signal==1) GPIO_WriteBit(GPIOA,SDA_Pin,Bit_SET);
    else GPIO_WriteBit(GPIOA,SDA_Pin,Bit_RESET);
    Delay_us(5);
}
 
uint8_t Z_I2C_GetSDA(void){
    return GPIO_ReadInputDataBit(GPIOA,SDA_Pin);
}
 
void Z_I2C_Start(void){
    Z_I2C_SetSDA(1);
    Z_I2C_SetSCL(1);
    Z_I2C_SetSDA(0);
    Z_I2C_SetSCL(0);
}
 
void Z_I2C_End(){
    Z_I2C_SetSDA(0);
    Z_I2C_SetSCL(1);
    Z_I2C_SetSDA(1);
}
 
void Z_I2C_SendByte(uint8_t byte){
    Z_I2C_SetSCL(0);
    for(int i=0;i<8;++i){
        if((byte&0x80)==0) Z_I2C_SetSDA(0);
        else Z_I2C_SetSDA(1);
        byte<<=1;
        Z_I2C_SetSCL(1);
        Z_I2C_SetSCL(0);
    }
}
 
uint8_t Z_I2C_ReveiceByte(){
    uint8_t data=0x00;
    Z_I2C_SetSDA(1);
    for(int i=0;i<8;++i){
        Z_I2C_SetSCL(1);
        if(Z_I2C_GetSDA()==1) data|=(0x80>>i);
        Z_I2C_SetSCL(0);
    }
    return data;
}
 
void Z_I2C_SendACK(uint8_t ack){
    if(ack==0) Z_I2C_SetSDA(0);
    else Z_I2C_SetSDA(1);
    Z_I2C_SetSCL(1);
    Z_I2C_SetSCL(0);
}
 
uint8_t Z_I2C_ReveiceACK(){
    Z_I2C_SetSDA(1);
    Z_I2C_SetSCL(1);
    uint8_t ack=Z_I2C_GetSDA();
    Z_I2C_SetSCL(0);
    return ack;
}
 
#define WENDU_COMMAND 0xF3
#define SHIDU_COMMAND 0xF5
 
uint16_t STH20_WData=0;
uint16_t STH20_SData=0;
 
void Z_STH20_GetData(char command){
    Z_I2C_Start();
    Z_I2C_SendByte(0x80);
    
    if(Z_I2C_ReveiceACK()!=0) return;
    
    if(command=='w') Z_I2C_SendByte(WENDU_COMMAND);   //发送命令
    else Z_I2C_SendByte(SHIDU_COMMAND);
    
    if(Z_I2C_ReveiceACK()!=0) return;
    
    int count=0;
    do{
        Z_I2C_Start();
        Z_I2C_SendByte(0x81);
        Delay_ms(10);
        if(++count>=10) return;
    }while(Z_I2C_ReveiceACK()!=0);
    
    if(command=='w'){
        STH20_WData=0;                                  //数据清零
        STH20_WData|=Z_I2C_ReveiceByte();               //获取数据高位
        Z_I2C_SendACK(0);
        STH20_WData<<=8;
        STH20_WData|=Z_I2C_ReveiceByte();               //获取数据低位
        Z_I2C_SendACK(0);
        uint8_t check=Z_I2C_ReveiceByte();              //获取CRC校验位
        Z_I2C_End();
        STH20_WData&=0xFFFC;                            //清除最后两位
        return;
    }else{
        STH20_SData=0;                                  //数据清零
        STH20_SData|=Z_I2C_ReveiceByte();               //获取数据高位
        Z_I2C_SendACK(0);
        STH20_SData<<=8;
        STH20_SData|=Z_I2C_ReveiceByte();               //获取数据低位
        Z_I2C_SendACK(0);
        uint8_t check=Z_I2C_ReveiceByte();              //获取CRC校验位
        Z_I2C_End();
        STH20_SData&=0xFFFC;                            //清除最后两位
        return ;
    }
}
 
 
int main(void){
    OLED_Init();
    Z_I2C_Init();
    
    while(1){
        Z_STH20_GetData('w');
        Z_STH20_GetData('s');
        double wendu=STH20_WData;
        wendu=(wendu/65536.0)*175.72-46.85;
        OLED_ShowNum(1,1,(int)wendu%100,2);
        OLED_ShowChar(1,3,'.');
        OLED_ShowNum(1,4,((int)(wendu*100)%100),2);
        OLED_ShowNum(2,1,STH20_WData,6);
        
        double shidu=STH20_SData;
        shidu=(shidu/65536.0)*125-6;
        OLED_ShowNum(3,1,(int)shidu%100,2);
        OLED_ShowChar(3,3,'.');
        OLED_ShowNum(3,4,((int)(shidu*100)%100),2);
        OLED_ShowNum(4,1,STH20_SData,6);
        Delay_ms(500);
    }
}

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

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

相关文章

Parallels Desktop 20破解版(Mac虚拟机) v20.0.0 for Mac 最新商业版(支持M系列)

Parallels Desktop 20是一款目前功能最强大灵活度最高的虚拟机软件&#xff0c;可运行数千种 Windows 应用程序&#xff0c;如 Microsoft Office、Internet Explorer、Access、Quicken、QuickBooks、Visual Studio&#xff0c;甚至支持对图像要求较高的游戏和 CAD 项目&#xf…

[产品管理-17]:NPDP新产品开发 - 15 - 产品设计与开发工具 - 工欲善其事,必先利其器 - 创意工具:借助各种工具和方法,完成产品的创意

目录 前言&#xff1a; 一、创意&#xff08;用户问题 -》产品想法&#xff09;的生成 1.1 创意 1.2 先发散后收敛 1.3 创意工具集 二、创意工具概述 2.1 SCAMPER - 按照数据处理逻辑运算的方式发散 SCAMPER创意工具详解&#xff1a;对数据/产品的各种运算、变换&…

如何用SQL Server和Oracle进行数据同步?

数据同步是大数据应用中非常重要的环节&#xff0c;它可以保证数据的实时性和一致性&#xff0c;为数据分析和决策提供重要依据。常见的数据同步方式包括ETL实时同步和实时ETL工具&#xff0c;其中实时ETL工具又可以分为基于日志追踪和基于触发器两种。 针对不同的数据库系统&…

Hqst 品牌 H81801D 千兆 DIP 网络变压器在光猫收发器机顶盒中的应用

Hqst 牌 H81801D 千兆 DIP 网络变压器在光猫收发器机顶盒中的应用主要包括以下几个方面&#xff1a; 1. 信号匹配和转换&#xff1a; H81801D 网络变压器能够匹配光猫收发器与以太网电缆之间的阻抗差&#xff0c;确保信号在传输过程中的完整性&#xff0c;同时它还能将光信号转…

量化交易backtrader实践(一)_数据获取篇(3)_爬取数据

这一节实践其实是在上一节之前进行的&#xff0c;背景原因是因为tushare.pro的积分不够高&#xff0c;当时还没有接触到使用akshare等其他接口&#xff0c;因此对于全股票列表用的是去网页上爬的方式获得的&#xff0c;也就借此机会&#xff0c;再复习了一遍爬虫的相关知识。 …

WPS生成目录

导航窗格&#xff1a;视图->导航窗格 可修改标题的样式&#xff0c;之后的标题直接套用即可 修改其他标题样式也是这样 添加编号&#xff1a;可以选上面的模版 也可自定义编号 生成目录&#xff1a;引用->目录->选用一个 但是我想把目录插到另一页 当我添加几个标题…

IDEA-调用Restful接口

告别Swagger3/Apifox/Postman Swagger3&#xff08;丝袜哥&#xff09; 地址&#xff1a;REST API Documentation Tool | Swagger UI简介&#xff1a;在java代码里面增加注解生成接口文档 在代码里面增加注解 RestController RequestMapping("api/v1/user") Api(ta…

移动UI案例:工具类app整套案例

工具类App是指提供各种实用工具和功能的手机应用程序。这些工具可以包括但不限于日历、闹钟、备忘录、翻译、计算器、单位转换、天气预报、地图导航、音乐播放器、相机、视频编辑等。这些工具类App能够帮助用户解决日常生活和工作中的各种问题&#xff0c;提高效率和便利性。 …

浅谈Spring Cloud:认识微服务

SpringCloud就是分布式微服务架构的一站式解决方案&#xff0c;是微服务架构落地的多种技术的集合。 目录 微服务远程调用 Eureka注册中心 搭建Eureka Server 注册组件 服务拉取 当各种各样的服务越来越多&#xff0c;拆分的也越来越细&#xff0c;此时就会出现一个服务集…

Ubuntu 22.04.5 LTS 发布下载 - 现代化的企业与开源 Linux

Ubuntu 22.04.5 LTS (Jammy Jellyfish) - 现代化的企业与开源 Linux Ubuntu 22.04.5 发布&#xff0c;配备 Linux 内核 6.8 请访问原文链接&#xff1a;https://sysin.org/blog/ubuntu-2204/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xf…

Spring Boot与gRPC的完美融合:构建高效用户服务与订单服务通信

gRPC 是一种由 Google 开发的高性能、开源的远程过程调用&#xff08;Remote Procedure Call, RPC&#xff09;框架。它允许在不同的计算机系统或进程之间进行通信&#xff0c;使得分布式系统和微服务架构中的服务之间能够轻松地相互调用方法。gRPC 基于 HTTP/2 协议&#xff0…

21章 规则集和映射

1.同20章 线性表、栈、队列和优先队列的第10题。 2.同20章 线性表、栈、队列和优先队列的第1题。 3.修改程序清单21-7中的程序。如果关键字在注释或者字符串中&#xff0c;则不进行统计。将Java文件名从命令行传递。 import java.io.*; import java.util.Arrays; import jav…

轨道列车舱门检测系统源码分享

轨道列车舱门检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

【Android 13源码分析】WindowContainer窗口层级-3-实例分析

在安卓源码的设计中&#xff0c;将将屏幕分为了37层&#xff0c;不同的窗口将在不同的层级中显示。 对这一块的概念以及相关源码做了详细分析&#xff0c;整理出以下几篇。 【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树 【Android 13源码分析】WindowCon…

Redis的AOF持久化、重写机制、RDB持久化、混合持久化

1、AOF持久化 1.1.AOF持久化大致过程 概括&#xff1a;命令追加&#xff08;append&#xff09;、文件写入、文件同步&#xff08;sync&#xff09; Redis 每执行一条写操作命令&#xff0c;就把该命令以追加的方式写入到一个文件里&#xff0c;然后重启 Redis 的时候&#…

Pytest配置文件pytest.ini如何编写生成日志文件?

1、新建pytest.ini文件 [pytest] log_clitrue log_leveLNOTSET log_format %(asctime)s %(levelname)s %(message)s %(filename)s %(funcName)s %(lineno)d log_date_format %Y-%m-%d %H:%M:%Slog_file ./logdata/log.log log_file_level info log_file_format %(asctime…

实时(按帧)处理的低通滤波C语言实现

写在前面&#xff1a; 低通滤波采用一般的FIR滤波器&#xff0c;因为本次任务&#xff0c;允许的延迟较多&#xff0c;或者说前面损失的信号可以较多&#xff0c;因此&#xff0c;涉及一个很高阶的FIR滤波器&#xff0c;信号起始段的信号点可以不处理&#xff0c;以及&#xf…

召回01 基于物品是协同过滤 ItemCF

相似度&#xff0c;类似机器学习里面常用的cosine相似度

python AssertionError: Torch not compiled with CUDA enabled

查看&#xff1a;torch import torch# 输出带CPU&#xff0c;表示torch是CPU版本的 print(ftorch的版本是&#xff1a;{torch.__version__}) # print(ftorch是否能使用cuda&#xff1a;{torch.cuda.is_available()}) 修改一下代码&#xff0c;将cuda改成cpu 最后运行正常&…

【React源码解析】深入理解react时间切片和fiber架构

时间切片 假如React一个更新需要耗时200ms&#xff0c;我们可以将其拆分为40个5ms的更新&#xff08;后续会讲到如何拆分&#xff09;&#xff0c;然后每一帧里只花5ms来执行更新。那么&#xff0c;每一帧里不就剩余16.7 - 5 11.7ms的时间可以进行用户事件&#xff0c;渲染等…