Renesas R7FA8D1BH (Cortex®-M85) 控制DS18B20

news2024/9/26 5:19:16

目录

概述

1 软硬件

1.1 软硬件环境信息

1.2 开发板信息

1.3 调试器信息

2 FSP和KEIL配置

2.1 硬件接口电路

2.2  FSB配置DS18B20的IO

2.3 生成Keil工程文件

3 DS18B20驱动代码

3.1 DS18B20介绍

3.2 DS18B20驱动实现

3.2.1 IO状态定义

3.2.2 读IO状态函数

3.2.3 其他函数

4 测试程序

4.1 应用程序设计

4.2 测试 

5 附件


Renesas R7FA8D1BH (Cortex®-M85) 控制DS18B20和ADC,实现两个页面的跳转功能

概述

本文主要介绍Renesas R7FA8D1BH (Cortex®-M85)设计一个综合的应用案例:应用R7FA8D1BH的IO实现单总线协议,实现驱动ds18b20的功能,其主要完成读取温度值,并将该值格式化显示在OLED屏幕上。还通过串口终端将温度数据发送至串口终端上。

1 软硬件

1.1 软硬件环境信息

软硬件信息版本信息
Renesas MCUR7FA8D1BH
KeilMDK ARM 5.38
FSP 版本5.3.0
调试工具:N32G45XVL-STBDAP-LINK

1.2 开发板信息

笔者选择使用野火耀阳开发板_瑞萨RA8,该板块的主控MCU为R7FA8D1BHECBD,7FA8D1BHECBD的内核为ARM Contex-M85。

1.3 调试器信息

对于R7FA8D1BHECBD芯片,其使用的内核为Cortex®-M85 Core, ST-LINK-V2或者J-LINK-V9不支持下载和调试功能。笔者经过多次尝试,发现N32G45XVL-STB板卡上自带的DAP-LINK可以下载和调试R7FA8D1BHECBD。

下图为N32G45XVL-STB开发板实物图:

2 FSP和KEIL配置

2.1 硬件接口电路

耀阳开发板_瑞萨RA8上已经设计了DS18B20的接口电路,其使用P809接口作为DS18B20的DQ控制信号。

2.2  FSB配置DS18B20的IO

配置P809为普通的IO接口,然后在代码中动态配置该IO的输出或者输出状态

2.3 生成Keil工程文件

 完成FSP的参数配置之后,就可以Generate Project。打开项目文件,其架构如下:

创建ds18b20.c文件,实现驱动代码

3 DS18B20驱动代码

3.1 DS18B20介绍

笔者在之前的文章中,已经详细分析过DS18B20的时序以及实现逻辑,这里不在做介绍。

DS18B20应用笔记_ds18b20读取数据的波形-CSDN博客

3.2 DS18B20驱动实现

3.2.1 IO状态定义

代码第14行:定义us步长延时函数

代码第15行:定义ms步长延时函数

代码第18行:定义DS18B20的IO PIN

代码第21行:输入端口配置

代码第22行:输出端口配置

代码第24行:设置IO低电平

代码第25行:设置IO高电平

3.2.2 读IO状态函数

代码第47行:读取输入模式下IO的状态

 3.2.3 其他函数

函数:ds18b20Init, 检测DS18B20是否在线

函数:ds18b20BlockModeProcess。 读取DS18B20的数值

/**
  * @brief  reset DS18B20
  * @note   if reset ds18b20 sucess, the return value is TRUE
  * @param  None
  * @retval True or Flalse
  */
static uint8_t ds18b20Init( void )
{
    uint16_t tempCnt = 0;
    bsp_io_level_t status;
   
    // Set PIN mode output
    DS_Mode_Out_PP();
    
    // Master pin is high 
    DQ_SET_HIGH;
    timeDelayUS(10);
    
    // Master pin is low 
    DQ_SET_LOW;
    // wait for 600 us 
    timeDelayUS(750);
    
    // Set PIN mode input
    DS_Mode_IN_PUT();
    
    while(1)
    {
        status = DQ_RAD_PIN();
        if( status == 0)
        {
            tempCnt = 0;
            return TRUE;
        }
        else
        {
          timeDelayUS(1);
          tempCnt++;
          if( tempCnt > 480 )
              return FALSE;
        }
    }
}


static uint8_t readBit( void )
{
    uint8_t readCnt = 2;
    uint8_t bitVal = 1;

    DQ_SET_LOW;
    timeDelayUS(3);
    DQ_SET_HIGH;
    
    timeDelayUS(5); // 15 us 
    
    while(readCnt-- )
    {
        //read DQ value 
        if( DQ_RAD_PIN() == 0)
        {
           bitVal = 0;
        }
        timeDelayUS(2);  // 15 us 
    }
    
    timeDelayUS(30);      // 15 us 

    return  bitVal;
}

static uint8_t ds18b20ReadByte( void )
{
   uint8_t byteVal = 0;
    
   for ( uint8_t i = 0; i < 8; i++ )
   {
        byteVal >>= 1;
       
        uint8_t bitVal = readBit(); 
        if( bitVal > 0)
        {
            byteVal |= 0x80;
        }
    }
   
    return  byteVal;
}


/**
  * @brief  write one byte to DS18B20
  * @note   
  * @param  byte: the data that is sended to ds18b20
  * @retval None
  */
void ds18b20WriteByte( uint8_t byte)
{
    unsigned char k;
    
    // Set PIN mode output
    DS_Mode_Out_PP();
    
    for ( k = 0; k < 8; k++ )
    {
        if (byte & (1<<k))
        {
            DQ_SET_LOW;
            timeDelayUS(2); 
 
            DQ_SET_HIGH;
            timeDelayUS(65); 
        }
        else
        {
            DQ_SET_LOW;
            timeDelayUS(65); 
 
            DQ_SET_HIGH;
            timeDelayUS(2); 
        }
    }
}

uint8_t ds18b20BlockModeProcess( void )
{
    uint16_t tempValue;
    uint8_t tempL, tempH;

    if (ds18b20Init() == FALSE)
    {
        return FALSE;
    }

    // wait for 600 us 
    timeDelayUS(600);
    
    ds18b20WriteByte(0xcc);
    ds18b20WriteByte(0x44);  // start convert temperature 

    if (ds18b20Init() == FALSE)
    {
        return FALSE;
    }
    // wait for 600 us 
    timeDelayUS(600);

    ds18b20WriteByte(0xcc);
    ds18b20WriteByte(0xbe);  // read temperature data register

    tempL = ds18b20ReadByte();
    tempH = ds18b20ReadByte();
    
    if (tempH > 0x7f) 
    {
        tempL    = ~tempL;
        tempH    = ~tempH+1; 
        st_ds1b20val.sign = 1;
    }

    tempValue = (uint16_t)((tempH << 8) | tempL);

    st_ds1b20val.temperatureVal = (float)(tempValue * 0.0625);
    
    return TRUE;
}


// NO blocking mode operate ds18b20 
uint8_t ds18b20NoBlockingProcess( void )
{
    uint16_t tempValue;
    static uint16_t waitCnt = 0;
    uint8_t tempL, tempH;
    static  uint8_t runState = 0;
    
    switch( runState )
    {
        default:
        case INIT_DQ:
            if (ds18b20Init() == FALSE)
            {
                return FALSE;
            }
            runState = WAIT_READY;
            break;
            
        case WAIT_READY:
            timeDelayUS(2);       // IDEL 
            runState = SKIDROM_CMD;
            break;
           
       case SKIDROM_CMD:
            ds18b20WriteByte(0xcc);
            ds18b20WriteByte(0x44);  // begin to convert temperature data
            waitCnt = 0;
            runState = WAIT_CONVERT;
            break;
       
       case WAIT_CONVERT:
           waitCnt++;
           if( waitCnt > WAIT_CNT_CONVERT)
           {
               waitCnt = 0;
               runState = RESET_CMD;
           }
           break;
        
        case RESET_CMD:
            if (ds18b20Init() == FALSE)
            {
                return FALSE;
            }
            runState = WAIT_DATA_READY;
            break;
            
        case WAIT_DATA_READY: 
            timeDelayUS(2);     // IDEL 
            runState = READ_CMD;
            break;
            
        case READ_CMD:
            ds18b20WriteByte(0xcc);
            ds18b20WriteByte(0xbe);  // read temperature data register
            runState = GET_VALUE;
            break;
            
        case GET_VALUE:

            tempL = ds18b20ReadByte();
            tempH = ds18b20ReadByte();

            if (tempH > 0x7f) 
            {
                tempL    = ~tempL;
                tempH    = ~tempH+1; 
                st_ds1b20val.sign = 1;
            }

            tempValue = (uint16_t)((tempH << 8) | tempL);

            st_ds1b20val.temperatureVal = (float)(tempValue * 0.0625);
            runState = INIT_DQ;
            return TRUE;
    }
    
    return FALSE;
}

4 测试程序

4.1 应用程序设计

代码113行:读取ds18b20的值

代码130行:获得ds18b20的结果数据

代码131行:格式化显示数据

代码132行:显示数据到OLED上

4.2 测试 

编译代码,并下载代码到板卡中,其运行结果如下:

5 附件

DS18B20的驱动代码

1)创建ds18b20.c文件,编写如下代码

 /*
 FILE NAME  :  ds18b20.c
 Description:  user ds18b20 interface 
 Author     :  tangmingfei2013@126.com
 Date       :  2024/06/03
 */
#include "ds18b20.h" 
#include "hal_data.h"

typedef enum{
  INPUT = 0,
  OUTPUT = 1,
}IO_TYPE;

typedef enum{
  FALSE = 0,
  TRUE = 1,
}RETURN_RESULT;

typedef enum{
   INIT_DQ = 0,
   WAIT_READY,
   SKIDROM_CMD,
    
   WAIT_CONVERT,
   RESET_CMD,
   READ_CMD,

   WAIT_DATA_READY,
   GET_VALUE,
   IDLE_NULL
}RUN_STATE;

ds18b20Struc st_ds1b20val;


ds18b20Struc get_ds18b20_value( void )
{
    return st_ds1b20val;
}

static bsp_io_level_t DQ_RAD_PIN(void)
{
    bsp_io_level_t state;

    // READ io
    R_IOPORT_PinRead(&g_ioport_ctrl, DS_IO_PORT_PIN, &state);
    
    return state;
}

/**
  * @brief  reset DS18B20
  * @note   if reset ds18b20 sucess, the return value is TRUE
  * @param  None
  * @retval True or Flalse
  */
static uint8_t ds18b20Init( void )
{
    uint16_t tempCnt = 0;
    bsp_io_level_t status;
   
    // Set PIN mode output
    DS_Mode_Out_PP();
    
    // Master pin is high 
    DQ_SET_HIGH;
    timeDelayUS(10);
    
    // Master pin is low 
    DQ_SET_LOW;
    // wait for 600 us 
    timeDelayUS(750);
    
    // Set PIN mode input
    DS_Mode_IN_PUT();
    
    while(1)
    {
        status = DQ_RAD_PIN();
        if( status == 0)
        {
            tempCnt = 0;
            return TRUE;
        }
        else
        {
          timeDelayUS(1);
          tempCnt++;
          if( tempCnt > 480 )
              return FALSE;
        }
    }
}


static uint8_t readBit( void )
{
    uint8_t readCnt = 2;
    uint8_t bitVal = 1;

    DQ_SET_LOW;
    timeDelayUS(3);
    DQ_SET_HIGH;
    
    timeDelayUS(5); // 15 us 
    
    while(readCnt-- )
    {
        //read DQ value 
        if( DQ_RAD_PIN() == 0)
        {
           bitVal = 0;
        }
        timeDelayUS(2);  // 15 us 
    }
    
    timeDelayUS(30);      // 15 us 

    return  bitVal;
}

static uint8_t ds18b20ReadByte( void )
{
   uint8_t byteVal = 0;
    
   for ( uint8_t i = 0; i < 8; i++ )
   {
        byteVal >>= 1;
       
        uint8_t bitVal = readBit(); 
        if( bitVal > 0)
        {
            byteVal |= 0x80;
        }
    }
   
    return  byteVal;
}


/**
  * @brief  write one byte to DS18B20
  * @note   
  * @param  byte: the data that is sended to ds18b20
  * @retval None
  */
void ds18b20WriteByte( uint8_t byte)
{
    unsigned char k;
    
    // Set PIN mode output
    DS_Mode_Out_PP();
    
    for ( k = 0; k < 8; k++ )
    {
        if (byte & (1<<k))
        {
            DQ_SET_LOW;
            timeDelayUS(2); 
 
            DQ_SET_HIGH;
            timeDelayUS(65); 
        }
        else
        {
            DQ_SET_LOW;
            timeDelayUS(65); 
 
            DQ_SET_HIGH;
            timeDelayUS(2); 
        }
    }
}

uint8_t ds18b20BlockModeProcess( void )
{
    uint16_t tempValue;
    uint8_t tempL, tempH;

    if (ds18b20Init() == FALSE)
    {
        return FALSE;
    }

    // wait for 600 us 
    timeDelayUS(600);
    
    ds18b20WriteByte(0xcc);
    ds18b20WriteByte(0x44);  // start convert temperature 

    if (ds18b20Init() == FALSE)
    {
        return FALSE;
    }
    // wait for 600 us 
    timeDelayUS(600);

    ds18b20WriteByte(0xcc);
    ds18b20WriteByte(0xbe);  // read temperature data register

    tempL = ds18b20ReadByte();
    tempH = ds18b20ReadByte();
    
    if (tempH > 0x7f) 
    {
        tempL    = ~tempL;
        tempH    = ~tempH+1; 
        st_ds1b20val.sign = 1;
    }

    tempValue = (uint16_t)((tempH << 8) | tempL);

    st_ds1b20val.temperatureVal = (float)(tempValue * 0.0625);
    
    return TRUE;
}


// NO blocking mode operate ds18b20 
uint8_t ds18b20NoBlockingProcess( void )
{
    uint16_t tempValue;
    static uint16_t waitCnt = 0;
    uint8_t tempL, tempH;
    static  uint8_t runState = 0;
    
    switch( runState )
    {
        default:
        case INIT_DQ:
            if (ds18b20Init() == FALSE)
            {
                return FALSE;
            }
            runState = WAIT_READY;
            break;
            
        case WAIT_READY:
            timeDelayUS(2);       // IDEL 
            runState = SKIDROM_CMD;
            break;
           
       case SKIDROM_CMD:
            ds18b20WriteByte(0xcc);
            ds18b20WriteByte(0x44);  // begin to convert temperature data
            waitCnt = 0;
            runState = WAIT_CONVERT;
            break;
       
       case WAIT_CONVERT:
           waitCnt++;
           if( waitCnt > WAIT_CNT_CONVERT)
           {
               waitCnt = 0;
               runState = RESET_CMD;
           }
           break;
        
        case RESET_CMD:
            if (ds18b20Init() == FALSE)
            {
                return FALSE;
            }
            runState = WAIT_DATA_READY;
            break;
            
        case WAIT_DATA_READY: 
            timeDelayUS(2);     // IDEL 
            runState = READ_CMD;
            break;
            
        case READ_CMD:
            ds18b20WriteByte(0xcc);
            ds18b20WriteByte(0xbe);  // read temperature data register
            runState = GET_VALUE;
            break;
            
        case GET_VALUE:

            tempL = ds18b20ReadByte();
            tempH = ds18b20ReadByte();

            if (tempH > 0x7f) 
            {
                tempL    = ~tempL;
                tempH    = ~tempH+1; 
                st_ds1b20val.sign = 1;
            }

            tempValue = (uint16_t)((tempH << 8) | tempL);

            st_ds1b20val.temperatureVal = (float)(tempValue * 0.0625);
            runState = INIT_DQ;
            return TRUE;
    }
    
    return FALSE;
}



/* End of this file */

2)创建ds18b20.h文件,编写如下代码

/*
    FILE NAME  :  ds18b20.h
    Description:  user ds18b20 interface 
    Author     :  tangmingfei2013@126.com
    Date       :  2024/06/03
*/
#ifndef DS18B20_H
#define DS18B20_H
#include "hal_data.h"
 
 
#define WAIT_CNT_CONVERT     500 

#define timeDelayUS(us)      R_BSP_SoftwareDelay(us, BSP_DELAY_UNITS_MICROSECONDS);
#define DS_DELAY_MS(ms)      R_BSP_SoftwareDelay(ms, BSP_DELAY_UNITS_MILLISECONDS);


#define DS_IO_PORT_PIN       BSP_IO_PORT_08_PIN_09


#define DS_Mode_IN_PUT()     R_IOPORT_PinCfg(&g_ioport_ctrl, DS_IO_PORT_PIN, IOPORT_CFG_PORT_DIRECTION_INPUT)
#define DS_Mode_Out_PP()     R_IOPORT_PinCfg(&g_ioport_ctrl, DS_IO_PORT_PIN, IOPORT_CFG_PORT_DIRECTION_OUTPUT)

#define DQ_SET_LOW           R_IOPORT_PinWrite(&g_ioport_ctrl, DS_IO_PORT_PIN, BSP_IO_LEVEL_LOW)
#define DQ_SET_HIGH          R_IOPORT_PinWrite(&g_ioport_ctrl, DS_IO_PORT_PIN, BSP_IO_LEVEL_HIGH)


typedef struct{
    float  temperatureVal; 
    bool sign;
}ds18b20Struc;

uint8_t ds18b20BlockModeProcess( void );
ds18b20Struc get_ds18b20_value( void );


#endif   /* DS18B20_H */


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

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

相关文章

谷粒商城实战笔记-27-分布式组件-SpringCloud-Gateway-创建测试API网关

本节的主要内容是创建网关模块&#xff0c;将网关注册到Nacos&#xff0c;并配置路由进行测试。 一&#xff0c;创建网关模块 右键工程New->Module&#xff0c;创建新模块&#xff0c;模块名称 gulimall-gateway。 填充各种信息。 选中Gateway依赖。 点击Create创建模块。…

uni-app iOS上架相关App store App store connect 云打包有次数限制

相册权限 uni-app云打包免费有次数 切换一个账号继续

C语言 | Leetcode C语言题解之第230题二叉搜索树中第K小的元素

题目&#xff1a; 题解&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/int search_num(struct TreeNode* root, int k, int *result, int num) {if(num k 1){retu…

JAVA之(static关键字、final关键字、抽象类、接口)

JAVA之&#xff08;static关键字、final关键字&#xff09; 一、 static关键字1、静态变量2、静态方法3、 静态代码块4、例子 二、final关键字1、final修饰类2、 final修饰方法3、修饰变量 三、抽象类1、 抽象类 四、接口 一、 static关键字 1、静态变量 private static Stri…

Java异常体系、UncaughtExceptionHandler、Spring MVC统一异常处理、Spring Boot统一异常处理

概述 所有异常都是继承自java.lang.Throwable类&#xff0c;Throwable有两个直接子类&#xff0c;Error和Exception。 Error用来表示程序底层或硬件有关的错误&#xff0c;这种错误和程序本身无关&#xff0c;如常见的NoClassDefFoundError。这种异常和程序本身无关&#xff0…

学习大数据DAY14 PLSQL基础语法3

目录 二重循环 三种循环随便嵌套 exit continue return 作业 数据提取 游标 隐式游标 显示游标 动态游标 游标使用流程 游标属性 游标配合循环使用示例 作业2 参数游标 current of 语句 作业3 PLSQL基础语法&#xff08;三&#xff09; 二重循环 三种循环随便嵌…

threadLocal详细认识(使用场景与局限性)与样例测试

Threadlocal的介绍与使用 1&#xff0c;是什么&#xff1f; ThreadLocal 是 Java 提供的一个工具类&#xff0c;用于在多线程环境中为每个线程提供独立的变量副本。它是 Java 标准库中的一部分&#xff0c;提供了线程局部存储的功能&#xff0c;这意味着每个线程都有自己独立…

【安全设备】APT攻击预警平台

一、什么是APT 高级持续性威胁&#xff08;APT&#xff09;是一种高度复杂和长期的网络攻击&#xff0c;旨在通过持续监视和访问特定目标来窃取敏感信息或进行其他恶意活动。这种攻击结合了多种先进的技术手段和社会工程学方法&#xff0c;以极高的隐蔽性实现长期潜伏和信息窃…

2 文件

2 文件 1、文件系统1.1 文件系统的逻辑结构1.2 文件的访问流程 2、文件类型3、文件的打开与关闭4、文件的内核结构5、文件的读写4.1 顺序与随机读写4.2 文件描述符的复制4.3 访问测试4.4 修改文件大小 5、文件锁5.1 读写冲突5.2 文件锁5.3 文件锁的内核结构 6、文件的元数据7、…

MTK Camera 冷启动、前后摄切换性能优化分析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、背景二、问题分解三、工具分析四、 traceView教程五、surface create优化六、systrace的教程七、优化方案八、前后切换速度优化九、优化方案十、热…

旷野之间4 - 100 个 Kubernetes 面试问题及答案

100 个 Kubernetes 面试问题及答案 Kubernetes 简介 什么是 Kubernetes&#xff1f; Kubernetes 是一个开源容器编排平台&#xff0c;可自动部署、扩展和管理容器化应用程序。 什么是容器&#xff1f; 容器是一个轻量级、独立的、可执行软件包&#xff0c;其中包含运行应用…

学习笔记——动态路由——IS-IS中间系统到中间系统(特性之路由撤销)

6、路由撤销 ISIS路由协议的路由信息是封装在LSP报文中的TLV中的&#xff0c;但是它对撤销路由的处理和OSPF的处理方式类似。 在ISIS中撤销一条路由实则是将接口下的ISIS关闭&#xff1a; 撤销内部路由&#xff1a; 在ISIS中路由信息是由IP接口TLV和IP内部可达性TLV共同来描…

游戏AI的创造思路-技术基础-决策树(2)

上一篇写了决策树的基础概念和一些简单例子&#xff0c;本篇将着重在实际案例上进行说明 目录 8. 决策树应用的实际例子 8.1. 方法和过程 8.1.1. 定义行为 8.1.2. 确定属性 8.1.3. 构建决策树 8.1.4. 实施行为 8.1.5. 实时更新 8.2. Python代码 8. 决策树应用的实际例子…

hudi数据湖万字全方位教程+应用示例

1、时间轴&#xff08;TimeLine&#xff09; Hudi的核心是维护表上在不同的即时时间&#xff08;instants&#xff09;执行的所有操作的时间轴&#xff08;timeline&#xff09;&#xff0c;这有助于提供表的即时视图 一个instant由以下三个部分组成&#xff1a; 1&#xff09;…

YOLOv10改进 | Conv篇 | RCS-OSA替换C2f实现暴力涨点(减少通道的空间对象注意力机制)

一、本文介绍 本文给大家带来的改进机制是RCS-YOLO提出的RCS-OSA模块&#xff0c;其全称是"Reduced Channel Spatial Object Attention"&#xff0c;意即"减少通道的空间对象注意力"。这个模块的主要功能是通过减少特征图的通道数量&#xff0c;同时关注空…

Android使用AndServer在安卓设备上搭建服务端(Java)(Kotlin)两种写法

一直都是通过OkHttp远程服务端进行数据交互&#xff0c;突发奇想能不能也通过OkHttp在局域网的情况下对两个安卓设备或者手机进行数据交互呢&#xff1f; 这样一方安卓设备要当做服务端与另一个安卓设备通过OkHttp进行数据交互即可 当然还可以通过 socket 和 ServerSocket 通…

IC后端设计中的shrink系数设置方法

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 在一些成熟的工艺节点通过shrink的方式(光照过程中缩小特征尺寸比例)得到了半节点,比如40nm从45nm shrink得到,28nm从32nm shrink得到,由于半节点的性能更优异,成本又低,漏电等不利因素也可以…

旷野之间5 - AI基础代理决策的范式转变

介绍 让我们来谈谈最近在人工智能领域引起轰动的一件事——基础代理及其彻底改变我们所知的决策的潜力。现在,我知道你可能会想,“另一天,又一个人工智能突破,乏味无趣。”但相信我,这是一个改变游戏规则的突破,值得你关注。 如果您一直在关注人工智能和人工智能代理的…

JupyterNotebook中导出当前环境,并存储为requirements.txt

​使用Anaconda管理Python环境时&#xff0c;可以轻松地导出环境配置&#xff0c;以便在其他机器或环境中重新创建相同的环境。可以通过生成一个environment.yml文件实现的&#xff0c;该文件包含了环境中安装的所有包及其版本。但是&#xff0c;常常在一些课程中JupyterNotebo…

synchronized关键字详解(全面分析)

目录 synchronized关键字详解1、synchronized关键字简介2、synchronized作用和使用场景作用使用场景①、用在代码块上(类级别同步)②、用在代码块上(对象级别同步)③、用在普通方法上(对象级别同步)④、用在静态方法上(类级别同步)总结&#xff1a; 3、synchronized底层原理&am…