【1】STM32·FreeRTOS·新建工程模板【一步到位】

目录

一、获取FreeRTOS源码

二、FreeRTOS源码简介

2.1、FreeRTOS源码文件内容

2.2、FreeRTOS内核

2.3、Source文件夹

2.4、portable文件夹

三、FreeRTOS手把手移植

3.1、FreeRTOS移植准备

3.2、FreeRTOS移植步骤

3.2.1、将 FreeRTOS 源码添加至基础工程、头文件路径等

3.2.2、添加 FreeRTOSConfig.h 配置文件

3.2.3、修改 SYSTEM 文件中的 sys.c、delay.c、usart.c

3.2.4、修改 Systick 中断、SVC 中断、PendSV 中断

3.2.5、验证移植是否成功


一、获取FreeRTOS源码

方法一:FreeRTOS 官网:freertos.orgfreertos.orgfreertos.org

方法二:正点原子官网获取,软件资料 —> FreeRTOS 学习资料

二、FreeRTOS源码简介

2.1、FreeRTOS源码文件内容

名称描述
FreeRTOSFreeRTOS 内核
FreeRTOS-PlusFreeRTOS 组件
tools工具
GitHub-FreeRTOS-HomeFreeRTOS 的 GitHub 仓库链接
Quick_Start_Guide快速入门指南官方文档链接
Upgrading to FreeRTOS-xxx升级到指定 FreeRTOS 版本官方文档链接
History.txtFreeRTOS 历史更新记录
其他其他

2.2、FreeRTOS内核

名称描述
DemoFreeRTOS 演示例程
LicenseFreeRTOS 相关许可
SourceFreeRTOS 源码
Test公用以及移植层测试代码

2.3、Source文件夹

名称描述
include包含了 FreeRTOS 的头文件
portable包含了 FreeRTOS 的移植文件
croutine.c协程相关文件
event_groups.c事件相关文件
list.c列表相关文件
queue.c队列相关文件
stream_buffer.c流式缓冲区相关文件
tasks.c任务相关文件
timers.c软件定时器相关文件

2.4、portable文件夹

FreeRTOS 操作系统归根到底是一个软件层面的东西,那 FreeRTOS 是如何跟硬件联系在一起的呢?

portable 文件夹里面的东西就是连接桥梁,由于我们使用 MDK 开发,因此这里只重点介绍其中的部分移植文件

名称描述
Keil指向 RVDS 文件夹
RVDS不同内核芯片的移植文件
MemMang内存管理文件

三、FreeRTOS手把手移植

3.1、FreeRTOS移植准备

有了 FreeRTOS 源码之后,还需要一个 HAL 库版本的实验工程作为基础工程进行 FreeRTOS 的移植

这里以正点原子的 HAL 库版本内存管理实验作为基础工程

3.2、FreeRTOS移植步骤

3.2.1、将 FreeRTOS 源码添加至基础工程、头文件路径等

Middlewares文件夹中新建FreeRTOS文件夹

Source文件夹中的FreeRTOS源码复制进去,并删除非源码文件.gitmodules

打开portable文件夹,保留KeilMemMangRVDS文件夹,其余删除

打开项目工程,点击分组管理图标,新建分组名为Middlewares/FreeRTOS_COREMiddlewares/FreeRTOS_PORT,点击OK

选择Middlewares/FreeRTOS_CORE分组,点击 Add Files,回到FreeRTOS目录,添加当前目录下的所有.c文件,点击 Add

选择Middlewares/FreeRTOS_PORT分组,点击 Add Files,回到FreeRTOS目录,打开portable/MemMang文件夹,选择heap_4.c内存管理算法,点击 Add

回到portable目录,打开RVDS文件夹,根据自己的芯片选择对应的连接桥梁,本人使用的是STM32F407的开发板,对应选择ARM_CM4F文件夹中的port.c文件,点击 Add

开发板芯片port.c 所在文件夹
STM32F1ARM_CM3
STM32F4ARM_CM4F
STM32F7ARM_CM7
STM32H7ARM_CM7

完成设置后的分组

打开魔术棒,点击C/C++,设置头文件包含路径如下图

3.2.2、添加 FreeRTOSConfig.h 配置文件

FreeRTOSConfig.h 是FreeRTOS 操作系统的配置文件,FreeRTOS 操作系统是可裁剪的,用户可以根据需求对 FreeRTOS 进行裁剪,裁剪掉不需要用到的 FreeRTOS 功能,以此来节约 MCU 中寸土寸金的内存资源

FreeRTOSConfig.h 文件的获取途径有三种

1、用户自行编写(不建议新手使用)

2、在 FreeRTOS 内核文件中的 Demo 文件夹包含了 FreeRTOS 官方提供的演示工程,在这些演示工程中就包含了每个演示工程对应的 FreeRTOSConfig.h 文件

3、在正点原子 FreeRTOS 移植实验中复制

将获取到的 FreeRTOSConfig.h 文件放在 User 文件夹下

3.2.3、修改 SYSTEM 文件中的 sys.c、delay.c、usart.c

打开 sys.h 文件,将 SYS_SUPPORT_OS 宏定义修改为 1,支持os

打开 usart.c 文件,在中断服务函数中删除 OSIntEnter()OSIntExit() 函数(在 μC/OS中 会使用到,FreeRTOS 中不会)

删除前

/**
 * @brief       串口1中断服务函数
 * @param       无
 * @retval      无
 */
void USART_UX_IRQHandler(void)
{ 
#if SYS_SUPPORT_OS                              /* 使用OS */
    OSIntEnter();    
#endif

    HAL_UART_IRQHandler(&g_uart1_handle);       /* 调用HAL库中断处理公用函数 */

#if SYS_SUPPORT_OS                              /* 使用OS */
    OSIntExit();
#endif
}

删除后

/**
 * @brief       串口1中断服务函数
 * @param       无
 * @retval      无
 */
void USART_UX_IRQHandler(void)
{ 
    HAL_UART_IRQHandler(&g_uart1_handle);       /* 调用HAL库中断处理公用函数 */
}

删除以下代码(在 μC/OS中 会使用到,FreeRTOS 中不会)

打开 delay.c 文件,删除以下代码(在 μC/OS中 会使用到,FreeRTOS 中不会)

/* 定义g_fac_ms变量, 表示ms延时的倍乘数, 代表每个节拍的ms数, (仅在使能os的时候,需要用到) */
static uint16_t g_fac_ms = 0;

/*
 *  当delay_us/delay_ms需要支持OS的时候需要三个与OS相关的宏定义和函数来支持
 *  首先是3个宏定义:
 *      delay_osrunning    :用于表示OS当前是否正在运行,以决定是否可以使用相关函数
 *      delay_ostickspersec:用于表示OS设定的时钟节拍,delay_init将根据这个参数来初始化systick
 *      delay_osintnesting :用于表示OS中断嵌套级别,因为中断里面不可以调度,delay_ms使用该参数来决定如何运行
 *  然后是3个函数:
 *      delay_osschedlock  :用于锁定OS任务调度,禁止调度
 *      delay_osschedunlock:用于解锁OS任务调度,重新开启调度
 *      delay_ostimedly    :用于OS延时,可以引起任务调度.
 *
 *  本例程仅作UCOSII的支持,其他OS,请自行参考着移植
 */

/* 支持UCOSII */
#define delay_osrunning     OSRunning           /* OS是否运行标记,0,不运行;1,在运行 */
#define delay_ostickspersec OS_TICKS_PER_SEC    /* OS时钟节拍,即每秒调度次数 */
#define delay_osintnesting  OSIntNesting        /* 中断嵌套级别,即中断嵌套次数 */


/**
 * @brief     us级延时时,关闭任务调度(防止打断us级延迟)
 * @param     无
 * @retval    无
 */
void delay_osschedlock(void)
{
    OSSchedLock();                      /* UCOSII的方式,禁止调度,防止打断us延时 */
}

/**
 * @brief     us级延时时,恢复任务调度
 * @param     无
 * @retval    无
 */
void delay_osschedunlock(void)
{
    OSSchedUnlock();                    /* UCOSII的方式,恢复调度 */
}

/**
 * @brief     us级延时时,恢复任务调度
 * @param     ticks: 延时的节拍数
 * @retval    无
 */
void delay_ostimedly(uint32_t ticks)
{
    OSTimeDly(ticks);                               /* UCOSII延时 */
}

SysTick_Handler函数前添加extern void xPortSysTickHandler(void);代码,用于处理 FreeRTOS 系统时钟节拍

extern void xPortSysTickHandler(void);

/**
 * @brief     systick中断服务函数,使用OS时用到
 * @param     ticks : 延时的节拍数  
 * @retval    无
 */  
void SysTick_Handler(void)
{
    /* OS 开始跑了,才执行正常的调度处理 */
    if (delay_osrunning == OS_TRUE)
    {
        /* 调用 uC/OS-II 的 SysTick 中断服务函数 */
        OS_CPU_SysTickHandler();
    }
    HAL_IncTick();
}

修改SysTick_Handler函数如下

/**
 * @brief     systick中断服务函数,使用OS时用到
 * @param     ticks : 延时的节拍数  
 * @retval    无
 */  
void SysTick_Handler(void)
{
    HAL_IncTick();
    /* OS 开始跑了,才执行正常的调度处理 */
    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
    {
        xPortSysTickHandler();
    }
}

修改delay_init函数

修改前

/**
 * @brief     初始化延迟函数
 * @param     sysclk: 系统时钟频率, 即CPU频率(rcc_c_ck), 168MHz
 * @retval    无
 */  
void delay_init(uint16_t sysclk)
{
#if SYS_SUPPORT_OS                                      /* 如果需要支持OS */
    uint32_t reload;
#endif
    g_fac_us = sysclk;                                  /* 由于在HAL_Init中已对systick做了配置,所以这里无需重新配置 */
#if SYS_SUPPORT_OS                                      /* 如果需要支持OS. */
    reload = sysclk;                                    /* 每秒钟的计数次数 单位为M */
    reload *= 1000000 / delay_ostickspersec;            /* 根据delay_ostickspersec设定溢出时间,reload为24位
                                                         * 寄存器,最大值:16777216,在168M下,约合0.09986s左右
                                                         */
    g_fac_ms = 1000 / delay_ostickspersec;              /* 代表OS可以延时的最少单位 */
    SysTick->CTRL |= 1 << 1;                            /* 开启SYSTICK中断 */
    SysTick->LOAD = reload;                             /* 每1/delay_ostickspersec秒中断一次 */
    SysTick->CTRL |= 1 << 0;                            /* 开启SYSTICK */
#endif 
}

修改后

/**
 * @brief     初始化延迟函数
 * @param     sysclk: 系统时钟频率, 即CPU频率(rcc_c_ck), 168MHz
 * @retval    无
 */  
void delay_init(uint16_t sysclk)
{
#if SYS_SUPPORT_OS                                      /* 如果需要支持OS */
    uint32_t reload;
#endif
    g_fac_us = sysclk;                                  /* 由于在HAL_Init中已对systick做了配置,所以这里无需重新配置 */
#if SYS_SUPPORT_OS                                      /* 如果需要支持OS. */
    reload = sysclk;                                    /* 每秒钟的计数次数 单位为M */
    reload *= 1000000 / configTICK_RATE_HZ;            /* 根据delay_ostickspersec设定溢出时间,reload为24位
                                                         * 寄存器,最大值:16777216,在168M下,约合0.09986s左右
                                                         */
    SysTick->CTRL |= 1 << 1;                            /* 开启SYSTICK中断 */
    SysTick->LOAD = reload;                             /* 每1/delay_ostickspersec秒中断一次 */
    SysTick->CTRL |= 1 << 0;                            /* 开启SYSTICK */
#endif 
}

修改delay_us函数

修改前

/**
 * @brief     延时nus
 * @note      无论是否使用OS, 都是用时钟摘取法来做us延时
 * @param     nus: 要延时的us数
 * @note      nus取值范围: 0 ~ (2^32 / fac_us) (fac_us一般等于系统主频, 自行套入计算)
 * @retval    无
 */
void delay_us(uint32_t nus)
{
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 0;
    uint32_t reload = SysTick->LOAD;        /* LOAD的值 */
    ticks = nus * g_fac_us;                 /* 需要的节拍数 */
    
#if SYS_SUPPORT_OS                          /* 如果需要支持OS */
    delay_osschedlock();                    /* 锁定 OS 的任务调度器 */
#endif

    told = SysTick->VAL;                    /* 刚进入时的计数器值 */
    while (1)
    {
        tnow = SysTick->VAL;
        if (tnow != told)
        {
            if (tnow < told)
            {
                tcnt += told - tnow;        /* 这里注意一下SYSTICK是一个递减的计数器就可以了 */
            }
            else
            {
                tcnt += reload - tnow + told;
            }
            told = tnow;
            if (tcnt >= ticks) 
            {
                break;                      /* 时间超过/等于要延迟的时间,则退出 */
            }
        }
    }

#if SYS_SUPPORT_OS                          /* 如果需要支持OS */
    delay_osschedunlock();                  /* 恢复 OS 的任务调度器 */
#endif 

}

修改后

/**
 * @brief     延时nus
 * @note      无论是否使用OS, 都是用时钟摘取法来做us延时
 * @param     nus: 要延时的us数
 * @note      nus取值范围: 0 ~ (2^32 / fac_us) (fac_us一般等于系统主频, 自行套入计算)
 * @retval    无
 */
void delay_us(uint32_t nus)
{
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 0;
    uint32_t reload = SysTick->LOAD;        /* LOAD的值 */
    ticks = nus * g_fac_us;                 /* 需要的节拍数 */
    told = SysTick->VAL;                    /* 刚进入时的计数器值 */
    while (1)
    {
        tnow = SysTick->VAL;
        if (tnow != told)
        {
            if (tnow < told)
            {
                tcnt += told - tnow;        /* 这里注意一下SYSTICK是一个递减的计数器就可以了 */
            }
            else
            {
                tcnt += reload - tnow + told;
            }
            told = tnow;
            if (tcnt >= ticks) 
            {
                break;                      /* 时间超过/等于要延迟的时间,则退出 */
            }
        }
    }
}

修改delay_ms函数

修改前

/**
 * @brief     延时nms
 * @param     nms: 要延时的ms数 (0< nms <= (2^32 / fac_us / 1000))(fac_us一般等于系统主频, 自行套入计算)
 * @retval    无
 */
void delay_ms(uint16_t nms)
{
    
#if SYS_SUPPORT_OS  /* 如果需要支持OS, 则根据情况调用os延时以释放CPU */
    if (delay_osrunning && delay_osintnesting == 0)     /* 如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度) */
    {
        if (nms >= g_fac_ms)                            /* 延时的时间大于OS的最少时间周期 */
        {
            delay_ostimedly(nms / g_fac_ms);            /* OS延时 */
        }

        nms %= g_fac_ms;                                /* OS已经无法提供这么小的延时了,采用普通方式延时 */
    }
#endif

    delay_us((uint32_t)(nms * 1000));                   /* 普通方式延时 */
}

修改后

/**
 * @brief     延时nms
 * @param     nms: 要延时的ms数 (0< nms <= (2^32 / fac_us / 1000))(fac_us一般等于系统主频, 自行套入计算)
 * @retval    无
 */
void delay_ms(uint16_t nms)
{
    uint32_t i;

    for (i = 0; i < nms; ++i)
    {
        delay_us(1000);
    }
}

修改公共头文件

修改前

/* 添加公共头文件 ( ucos需要用到) */
#include "os.h"

修改后

/* 添加公共头文件 (FreeRTOS 需要用到) */
#include "FreeRTOS.h"
#include "task.h"

3.2.4、修改 Systick 中断、SVC 中断、PendSV 中断

打开stm32f4xx_it.c文件,引入sys.h头文件

采用宏定义的方式屏蔽SystickSVCPendSV函数的定义

/**
  * @brief  This function handles SVCall exception.
  * @param  None
  * @retval None
  */
#if (!SYS_SUPPORT_OS)
void SVC_Handler(void)
{
}
#endif

/**
  * @brief  This function handles Debug Monitor exception.
  * @param  None
  * @retval None
  */
void DebugMon_Handler(void)
{
}

/**
  * @brief  This function handles PendSVC exception.
  * @param  None
  * @retval None
  */
#if (!SYS_SUPPORT_OS)
void PendSV_Handler(void)
{
}
#endif

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
#if (!SYS_SUPPORT_OS)
void SysTick_Handler(void)
{
  HAL_IncTick();
}
#endif

编译项目工程(报错不用管),打开 FreeRTOSConfig.h 文件,找到如下宏定义转跳到定义

4U修改成4

3.2.5、验证移植是否成功

点击全编译

编译完成后显示零错误零警告,工程模板创建完毕!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LLaMA 羊驼系大语言模型的前世今生

关于 LLaMA LLaMA是由Meta AI发布的大语言系列模型&#xff0c;完整的名字是Large Language Model Meta AI&#xff0c;直译&#xff1a;大语言模型元AI。Llama这个单词本身是指美洲大羊驼&#xff0c;所以社区也将这个系列的模型昵称为羊驼系模型。 Llama、Llama2 和 Llama3…

修改idea缓存的默认存储位置

打开idea.properties 找到 # idea.config.path${user.home}/.IntelliJIdea/config # idea.system.path${user.home}/.IntelliJIdea/system 将${user.home}替换成你要存储到的路径 再次打开idea时会弹出消息&#xff0c;点击ok即可。

电脑c盘太满了,如何清理 电脑杀毒软件哪个好用又干净免费 电脑预防病毒的软件 cleanmymacX有必要买吗 杀毒软件排行榜第一名

杀毒软件通常集成监控识别、病毒扫描和清除、自动升级、主动防御等功能&#xff0c;有的杀毒软件还带有数据恢复、防范黑客入侵、网络流量控制等功能&#xff0c;是计算机防御系统的重要组成部分。 那么&#xff0c;对于Mac电脑用户来说&#xff0c;哪款电脑杀毒软件更好呢&a…

虚幻引擎5 Gameplay框架(二)

Gameplay重要类及重要功能使用方法&#xff08;一&#xff09; 配置LOG类及PlayerController的网络机制 探索验证GamePlay重要函数、类的执行顺序与含义 我们定义自己的日志&#xff0c;专门建立一个存放自己日志的类&#xff0c;这个类继承自BlueprintFunctionLibrary 然后…

Prometheus 2: 一个专门评估其他语言模型的开源语言模型(续集)

普罗米修斯的续集来了。 专有的语言模型如 GPT-4 经常被用来评估来自各种语言模型的回应品质。然而,透明度、可控制性和可负担性等考虑强烈促使开发专门用于评估的开源语言模型。另一方面,现有的开源评估语言模型表现出关键的缺点:1) 它们给出的分数与人类给出的分数存在显著差…

[Android]四大组件简介

在 Android 开发中&#xff0c;“四大组件”&#xff08;Four Major Components&#xff09;是指构成 Android 应用程序的四种核心组件&#xff0c;它们通过各自的方式与系统交互&#xff0c;实现应用的多样功能。这些组件是&#xff1a;Activity、Service、Broadcast Receiver…

用 node 写一个命令行工具,全局安装可用

现在&#xff0c;不管是前端项目还是 node 项目&#xff0c;一般都会用 npm 做包管理工具&#xff0c;而 package.json 是其相关的配置信息。 对 node 项目而言&#xff0c;模块导出入口文件由 package.json 的 main 字段指定&#xff0c;而如果是要安装到命令行的工具&#x…

28 - 算术运算指令

---- 整理自B站UP主 踌躇月光 的视频 文章目录 1. ALU改进2. CPU 整体电路3. 程序4. 实验结果 1. ALU改进 此前的 ALU&#xff1a; 改进后的 ALU&#xff1a; 2. CPU 整体电路 3. 程序 # pin.pyMSR 1 MAR 2 MDR 3 RAM 4 IR 5 DST 6 SRC 7 A 8 B 9 C 10 D 11 DI 1…

在.NET架构的Winform项目中引入“异步编程”思想和技术

在.NET架构的Winform项目中引入“异步编程”思想和技术 一、异步编程引入&#xff08;1&#xff09;异步编程引入背景&#xff08;2&#xff09;异步编程程序控制流图&#xff08;3&#xff09;异步编程前置知识&#xff1a; 二、异步编程demo步骤1&#xff1a;步骤2&#xff1…

政安晨:【Keras机器学习示例演绎】(三十八)—— 从零开始的文本分类

目录 简介 设置 加载数据IMDB 电影评论情感分类 准备数据 数据矢量化的两种选择 建立模型 训练模型 在测试集上评估模型 制作端到端模型 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨…

在Linux上使用Selenium驱动Chrome浏览器无头模式

大家好&#xff0c;我们平时在做UI自动化测试的时候&#xff0c;经常会用到Chrome浏览器的无头模式&#xff08;无界面模式&#xff09;&#xff0c;并且将测试代码部署到Linux系统中执行&#xff0c;或者平时我们写个爬虫爬取网站的数据也会使用到&#xff0c;接下来和大家分享…

软考中级-软件设计师(九)数据库技术基础 考点最精简

一、基本概念 1.1数据库与数据库系统 数据&#xff1a;是数据库中存储的基本对象&#xff0c;是描述事物的符号记录 数据库&#xff08;DataBase&#xff0c;DB&#xff09;&#xff1a;是长期存储在计算机内、有组织、可共享的大量数据集合 数据库系统&#xff08;DataBas…

python基础---面向对象相关知识

面向对象 可以把数据以及功能打包为一个整体 类: 名称属性(数据)方法 class Person:def __init__(self, name, age):self.age ageself.name namedef print_info:print(self.name, self.age)定义 #经典类 class Dog1:pass# 新式类 class Dog2(object):pass在python3里面这…

LeetCode-741. 摘樱桃【数组 动态规划 矩阵】

LeetCode-741. 摘樱桃【数组 动态规划 矩阵】 题目描述&#xff1a;解题思路一&#xff1a;动态规划&#xff0c;定推初遍举。解题思路二&#xff1a;倒序循环解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个 n x n 的网格 grid &#xff0c;代表一块樱桃地&#xff0…

VMware虚拟机中Linux系统奔溃,怎么办?

一大早启动虚拟机准备开始工作&#xff0c;却遭遇到Linux系统崩溃&#xff0c;屏幕上显示以下错误提示&#xff1a; 这段文本看起来是来自系统引导时的日志信息&#xff0c;提到了一些关于文件系统的问题和建议。根据这段信息&#xff0c;似乎 /dev/sda1 分区中的文件系统存在一…

红日靶场ATTCK 1通关攻略

环境 拓扑图 VM1 web服务器 win7&#xff08;192.168.22.129&#xff0c;10.10.10.140&#xff09; VM2 win2003&#xff08;10.10.10.135&#xff09; VM3 DC win2008&#xff08;10.10.10.138&#xff09; 环境搭建 win7&#xff1a; 设置内网两张网卡&#xff0c;开启…

SeetaFace6人脸检测C++代码实现Demo

SeetaFace6包含人脸识别的基本能力&#xff1a;人脸检测、关键点定位、人脸识别&#xff0c;同时增加了活体检测、质量评估、年龄性别估计&#xff0c;并且顺应实际应用需求&#xff0c;开放口罩检测以及口罩佩戴场景下的人脸识别模型。 官网地址&#xff1a;https://github.co…

dockerk8s常用知识点

1、什么是docker 容器化和虚拟化对比 ▪开源的应用容器引擎&#xff0c;基于 Go 语言开发 ▪容器是完全使用沙箱机制,容器开销极低 ▪Docker就是容器化技术的代名词 ▪Docker也具备一定虚拟化职能 docker三大核心&#xff1a; Docker Engine: 提供了一个可以用来运行和管…

代码+视频,R语言绘制生存分析模型的时间依赖(相关)性roc曲线和时间依赖(相关)性cindex曲线

ROC曲线分析是用于评估一个因素预测能力的手段&#xff0c;是可以用于连续型变量分组的方法。在生存分析中&#xff0c;疾病状态和因素取值均会随时间发生变化。而标准的ROC曲线分析将个体的疾病状态和因素取值视作固定值&#xff0c;未将时间因素考虑在分析之中。在这种情况下…

edge使用心得

1. **性能提升**&#xff1a;基于Chromium的Edge浏览器在速度和响应方面有显著提升&#xff0c;特别是在处理复杂的网页结构和执行JavaScript代码时。这意味着无论是日常浏览还是运行Web应用程序&#xff0c;都能享受流畅的用户体验。 2. **更好的兼容性**&#xff1a;由于与G…