FREERTOS简介、移植和系统配置(基于STM32F103)

news2024/9/28 3:28:30

本文基础内容参考的是正点原子的FREERTOS课程。

这是基于HAL库的

正点原子手把手教你学FreeRTOS实时系统

这是基于标准库的

正点原子FreeRTOS手把手教学-基于STM32

基础知识,直接参考正点原子《FreeRTOS开发指南V1.1》基于标准库的,此处不再赘述。

本文主要对不理解的地方进行查缺补漏,并且先用起来,涉及到原理的部分,可以观看上述教学视频或者开发指南。



裸机和RTOS对比

我们知道,裸机系统的实时性比较差,各任务是顺序执行的,如果有紧急任务,就需要放在中断里,可是中断里又不能进行耗时较长的操作,通常是在中断里面置标志位,然后由主循环判断标志位来执行相关动作,可是这样一来,任务的执行又变成了顺序执行,实时性还是比较差。比如:

上面示例中,肚子疼这一任务属于紧急任务,中断里置标志位,然后主循环里判断标志位从而去医院,但是如果此时打游戏时间很长,就一直无法判断标志位,从而没法及时去医院。

因此,裸机的缺陷是很明显的。

如果是RTOS呢,是怎么处理的呢?

RTOS会创建三个任务,其中可以设置去医院的优先级更高,当肚子疼时,就可以立马执行去医院的操作,实时性就比较好了。

有个有意思的地方,就是延时函数,在裸机中,如果有延时函数,那就是CPU死等,但是在RTOS中,如果一个任务中有延时,那么CPU会看有没有其他任务,从而转去执行其他任务,而不会阻塞在延时这里。比如上面的去医院的例子,去医院的路上就类似于一个延时,这期间,我们照样可以玩游戏和发信息,但是裸机没法做到,去医院路上就只能等着去医院,其他什么事情也干不了。

裸机的特点

RTOS的特点

注意:

这里的高中低优先级,都属于软件层面的优先级设定,中断是硬件层面的优先级,永远都是优先于软件优先级来执行的;

每个任务都有自己的栈空间,这就可以用来保存调度之前的数据信息,是实现返回原来任务时继续执行的关键所在;

如果高优先级任务一直运行,低优先级任务就得不到运行,除非高优先级任务进入阻塞态,这是合理的,因为优先级高,所以肯定很紧急,所以必定占用所有的时间片,比如去医院做手术,肯定是全心全意做手术,不可能做手术时还玩游戏回信息,这里的关键是,实际开发时需要合理安排各任务的优先级。

FREERTOS简介

官网首页:

FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions

2024 年官网现在已经更新中文了。

官网参考手册:

官网参考手册:FreeRTOS 内核快速入门指南

注意事项:

官网进入比较慢,API估计都进不去。

这时如果需要查看API,可以查看正点原子给的几个文档

在这几个文档里搜索一下应该就能找到,可以优先看中文文档,没有的话再看英文文档。

freertos特点

由此可见,freertos的代码量并不高,主要是实现的任务调度。

源码简介

首先获取源码,我们可以从官网下载最新版本的源码

我们也可以直接拿正点原子的源码来使用

实际中我们可以直接拿对应MCU移植例程中的源码来用。

下载完成,我们再来看看里面有哪些内容

我们重点关注这里面的FreeRTOS文件夹,也就是我们要移植的源码。如果想了解其他文件夹中的内容,可以直接参考正点的开发手册。

打开FreeRTOS内核文件夹

Demo 文件夹里面就是 FreeRTOS 的相关例程,打开以后如下图所示:

可以看出 FreeRTOS 针对不同的 MCU 提供了非常多的 Demo,其中就有 ST F1F4 和F7 的相关例程。

打开Source文件夹

这里面包含了内核的头文件、移植文件、核心文件,前面说的FreeRTOS的9000多行代码,重点集中在list.c、queue.c、tasks.c这三个文件中。

再来重点来看一下 portable 这个文件夹,我们知道 FreeRTOS 是个系统,归根结底就是个纯软件的东西,它是怎么和硬件 联系在一起的呢?软件到硬件中间必须有一个桥梁,portable 文件夹里面的东西就是 FreeRTOS 系统和具体的硬件之间的连接桥梁!不同的编译环境,不同的 MCU,其桥梁应该是不同的,打 开 portable 文件夹,如下图所示:

从上图中可以看出 FreeRTOS 针对不同的编译环境和 MCU 都有不同的“桥梁”,我们这里就以 MDK 编译环境下的 STM32F103 为例。

MemMang 这个文件夹是跟内存管理相关的, 我们移植的时候是必须的,具体内容我们后面会专门有一章来讲解。里面的内容如下:

这里面有FreeRTOS提供的几种内存管理算法,我们一般使用heap_4.c这个文件。

Keil 文件夹里面的东西肯定也是必须的,但是我们打开Keil文件夹以后里面只有一个文件:See-also-the-RVDS-directory.txt。 这个 txt 文件是什么鬼?别急嘛!看文件名字“See-also-the-RVDS-directory”,意思就是参考 RVDS 文件夹里面的东西!哎,好吧,再打开 RVDS 文件夹,如下图所示:

RVDS 文件夹针对不同的架构的 MCU 做了详细的分类,STM32F103 就参考 ARM_CM3, 打开 ARM_CM3 文件夹,如下图所示:

ARM_CM3 有两个文件,这两个文件就是我们移植的时候所需要的!

开始移植

可以参考正点的移植过程,开发手册第二章 FreeRTOS 移植

我们这里移植过程略有不同。

1

获取源码

我们直接拿正点的移植例程中的源码来使用。

2

向工程分组中添加文件

打开基础工程,新建分组 FreeRTOS_CORE FreeRTOS_PORTABLE,然后向这两个分组中添加文件,如下图所示:

我们把所有的c文件都加入进来,不用的就放着,没关系。

其中,port.c 是 RVDS 文件 夹下的 ARM_CM3 中的文件,因为 STM32F103 是 Cortex-M3 内核的,因此要选择 ARM_CM3 中的 port.c 文件。

heap_4.c 是 MemMang 文件夹中的,前面说了 MemMang 是跟内存管理相关 的,里面有 5 个 c 文件:heap_1.c、heap_2.c、heap_3.c、heap_4.c 和 heap_5.c。这 5 个 c 文件是 五种不同的内存管理方法,就像从北京到上海你可以坐火车、坐飞机,如果心情好的话也可以 走路,反正有很多种方法,只要能到上海就行。这里也一样的,这 5 个文件都可以用来作为 FreeRTOS 的内存管理文件,只是它们的实现原理不同,各有利弊。

这里我们选择 heap_4.c,至 于原因,后面会有一章节专门来讲解 FreeRTOS 的内存管理,到时候大家就知道原因了。这里 就先选择 heap_4.c。

3

添加相应的头文件路径

添加完 FreeRTOS 源码中的 C 文件以后还要添加 FreeRTOS 源码的头文件路径,头文件路 径如下图所示:

4

确认包含FreeRTOSConfig.h文件

我们这里使用的是正点例程中的源码,所以include目录里面已经包含了系统配置文件FreeRTOSConfig.h,此时编译后一般不会有缺文件的问题。

如果没有FreeRTOSConfig.h文件或者FreeRTOSConfig.h文件不适配MCU,我们需要自己去找。比如打开 FreeRTOS目录里的Demo文件夹里的CORTEX_STM32F103_Keil,打开以后如下图所示:

果然!官方的移植工程中有这个文件,我们可以使用这个文件,但是建议大家使用正点例程中的 FreeRTOSConf.h 文件,这个文件是 FreeRTOS 的系统配置文件,不同的平台其配置不同。看名字就知道,他是 FreeRTOS 的配置文件,一般的操作系统都有裁剪、配置功能,而这些裁剪及配置都是通过一个文件来完成的,基本都是通过宏定义来完成对系统的配置和裁剪的,关于FreeRTOS的配置文件FreeRTOSConfig.h后面也会有一 章节来详细讲解。

5

引入FreeRTOSConfig.h配置文件后,编译,会提示以下内容:

这是因为freertos中也定义了SVC 中断服务函数SVC_Handler()和 PendSV 中断服务函数PendSV_Handler(),而我们STM32的中断文件stm32f10x_it.c中也定义了。

所以,需要将STM32定义的这两个空中断处理函数给屏蔽掉。

之后再编译就没有错误了。

5

配置systick时钟

操作系统一般会使用systick时钟来作为时基,也就是freertos的工作心跳,所以需要配置。

这里说明下,正点原子教程里说要改system文件夹里的内容,他们是想让systick既能作为延时,又能用于操作系统时基,但是本来很简单的东西,这样一来就会让操作变得很复杂,完全没必要,如果使用操作系统,我们可以不用systick来延时,而是配置额外的定时器。让systick专心为rtos服务即可。

所以我们根据实际情况,配置systick为1ms的定时中断,此配置可参考这篇文章:

STM32实现延时(Systick+Tim)-CSDN博客

然后在stm32f10x_it.c文件里的systick中断服务函数里调用操作系统的时基心跳。

extern void xPortSysTickHandler(void);

//systick 中断服务函数,使用 OS 时用到
void SysTick_Handler(void)
{ 
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
    {
        xPortSysTickHandler();
    }
}

FreeRTOS 的心跳就是由滴答定时器产生的,根据 FreeRTOS 的系统时钟节拍设置好滴答定 时器的周期,这样就会周期触发滴答定时器中断了。在滴答定时器中断服务函数中调用 FreeRTOS 的 API 函数 xPortSysTickHandler()

至此,移植完成,我们可以编写任务来验证是否移植成功,这一块后续再补充。

系统配置文件

FreeRTOSConf.h文件是 FreeRTOS 的系统配置文件,不同的平台其配置不同。看名字就知道,它是 FreeRTOS 的配置文件,一般的操作系统都有裁剪、配置功能,而这些裁剪及配置都是通过一个文件来完成的,基本都是通过宏定义来完成对系统的配置和裁剪的,这个文件可以在FreeRTOS目录里的Demo文件夹里的CORTEX_STM32F103_Keil路径下找到

我们将该文件拿来放到我们的移植目录中。

本文,重点介绍该文件中有哪些内容。

参考正点原子《FreeRTOS开发指南V1.1》“第三章 FreeRTOS 系统配置

正点原子例程中将该文件放在了User目录下

把文件拿过来看看

/***************************************************************************************************************/
/*                                        FreeRTOS基础配置配置选项                                              */
/***************************************************************************************************************/
//1使用抢占式内核,0使用协程
#define configUSE_PREEMPTION					1   

//1使能时间片调度(默认式使能的)                    
#define configUSE_TIME_SLICING					1

//1启用特殊方法来选择下一个要运行的任务
//一般是硬件计算前导零指令,如果所使用的
//MCU没有这些硬件指令的话此宏应该设置为0!						
#define configUSE_PORT_OPTIMISED_TASK_SELECTION	1

//1启用低功耗tickless模式                       
#define configUSE_TICKLESS_IDLE					0 

//为1时启用队列                      
#define configUSE_QUEUE_SETS					1 

//CPU频率                      
#define configCPU_CLOCK_HZ						(SystemCoreClock)

//时钟节拍频率,这里设置为1000,周期就是1ms       
#define configTICK_RATE_HZ						(1000)

//可使用的最大优先级                  
#define configMAX_PRIORITIES					(32)

//空闲任务使用的堆栈大小                    
#define configMINIMAL_STACK_SIZE				((unsigned short)130)

//任务名字字符串长度   
#define configMAX_TASK_NAME_LEN					(16)                    

//系统节拍计数器变量数据类型,
//1表示为16位无符号整形,0表示为32位无符号整形
#define configUSE_16_BIT_TICKS					0                       

//为1时空闲任务放弃CPU使用权给其他同优先级的用户任务                                                                        
#define configIDLE_SHOULD_YIELD					1

//为1时开启任务通知功能,默认开启                       
#define configUSE_TASK_NOTIFICATIONS            1

//为1时使用互斥信号量                       
#define configUSE_MUTEXES						1

//不为0时表示启用队列记录,具体的值是可以
//记录的队列和信号量最大数目。                       
#define configQUEUE_REGISTRY_SIZE				8

//大于0时启用堆栈溢出检测功能,如果使用此功能
//用户必须提供一个栈溢出钩子函数,如果使用的话
//此值可以为1或者2,因为有两种栈溢出检测方法。                       
#define configCHECK_FOR_STACK_OVERFLOW			0

//为1时使用递归互斥信号量                       
#define configUSE_RECURSIVE_MUTEXES				1

//1使用内存申请失败钩子函数                       
#define configUSE_MALLOC_FAILED_HOOK			0
                       
#define configUSE_APPLICATION_TASK_TAG			0

//为1时使用计数信号量                       
#define configUSE_COUNTING_SEMAPHORES			1                       

/***************************************************************************************************************/
/*                                FreeRTOS与内存申请有关配置选项                                                */
/***************************************************************************************************************/
//支持动态内存申请
#define configSUPPORT_DYNAMIC_ALLOCATION        1

//系统所有总的堆大小                       
#define configTOTAL_HEAP_SIZE					((size_t)(20*1024))     

/***************************************************************************************************************/
/*                                FreeRTOS与钩子函数有关的配置选项                                              */
/***************************************************************************************************************/
//1,使用空闲钩子;0,不使用
#define configUSE_IDLE_HOOK						0

//1,使用时间片钩子;0,不使用                       
#define configUSE_TICK_HOOK						0                       

/***************************************************************************************************************/
/*                                FreeRTOS与运行时间和任务状态收集有关的配置选项                                 */
/***************************************************************************************************************/
//为1时启用运行时间统计功能
#define configGENERATE_RUN_TIME_STATS	        0

//为1启用可视化跟踪调试                       
#define configUSE_TRACE_FACILITY				1

//与宏configUSE_TRACE_FACILITY同时为1时会编译下面3个函数                       
#define configUSE_STATS_FORMATTING_FUNCTIONS	1                       

//prvWriteNameToBuffer(),vTaskList(),
//vTaskGetRunTimeStats()
                                                                        
/***************************************************************************************************************/
/*                                FreeRTOS与协程有关的配置选项                                                  */
/***************************************************************************************************************/
//为1时启用协程,启用协程以后必须添加文件croutine.c
#define configUSE_CO_ROUTINES 			        0

//协程的有效优先级数目                       
#define configMAX_CO_ROUTINE_PRIORITIES         ( 2 )                   

/***************************************************************************************************************/
/*                                FreeRTOS与软件定时器有关的配置选项                                            */
/***************************************************************************************************************/
//为1时启用软件定时器
#define configUSE_TIMERS				        1

//软件定时器优先级                               
#define configTIMER_TASK_PRIORITY		        (configMAX_PRIORITIES-1) 

//软件定时器队列长度       
#define configTIMER_QUEUE_LENGTH		        5

//软件定时器任务堆栈大小                               
#define configTIMER_TASK_STACK_DEPTH	        (configMINIMAL_STACK_SIZE*2)    

/***************************************************************************************************************/
/*                                FreeRTOS可选函数配置选项                                                      */
/***************************************************************************************************************/
#define INCLUDE_xTaskGetSchedulerState          1                       
#define INCLUDE_vTaskPrioritySet		        1
#define INCLUDE_uxTaskPriorityGet		        1
#define INCLUDE_vTaskDelete				        1
#define INCLUDE_vTaskCleanUpResources	        1
#define INCLUDE_vTaskSuspend			        1
#define INCLUDE_vTaskDelayUntil			        1
#define INCLUDE_vTaskDelay				        1
#define INCLUDE_eTaskGetState			        1
#define INCLUDE_xTimerPendFunctionCall	        1

/***************************************************************************************************************/
/*                                FreeRTOS与中断有关的配置选项                                                  */
/***************************************************************************************************************/
#ifdef __NVIC_PRIO_BITS
	#define configPRIO_BITS       		__NVIC_PRIO_BITS
#else
	#define configPRIO_BITS       		4                  
#endif

//中断最低优先级
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			15

//系统可管理的最高中断优先级                      
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5                       
#define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

/***************************************************************************************************************/
/*                                FreeRTOS与中断服务函数有关的配置选项                                          */
/***************************************************************************************************************/
#define xPortPendSVHandler 	PendSV_Handler
#define vPortSVCHandler 	SVC_Handler

/***************************************************************************************************************/
/*                                FreeRTOS断言等有关的配置选项                                          */
/***************************************************************************************************************/
/* 断言 */
#define vAssertCalled(char, int) printf("Error: %s, %d\r\n", char, int)
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )

/* FreeRTOS MPU 特殊定义 */
//#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0
//#define configTOTAL_MPU_REGIONS                                8
//#define configTEX_S_C_B_FLASH                                  0x07UL
//#define configTEX_S_C_B_SRAM                                   0x07UL
//#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY            1
//#define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS             1

/* ARMv8-M 安全侧端口相关定义。 */
//#define secureconfigMAX_SECURE_CONTEXTS         5

#endif /* FREERTOS_CONFIG_H */

大部分配置都有注释,可以先看看。

官方的在线文档中也有详细的说明:

FreeRTOS - The Free RTOS configuration constants and configuration options - FREE Open Source RTOS for small real time embedded systems

FreeRTOS 的配置基本是通过在 FreeRTOSConfig.h 中使用“#define”这样的语句来定义宏定义实现的。

“config”开始的宏是用来完成 FreeRTOS 的配置和裁剪的。

具体参考正点原子的开发手册。

使用“INCLUDE_”开头的宏用来表示使能或除能 FreeRTOS 中相应的 API 函数,作用就是用来配置 FreeRTOS 中的可选 API 函数的。比如当宏 INCLUDE_vTaskPrioritySet 设置为 0 的
时候表示不能使用函数 vTaskPrioritySet() , 当设置为1的时候就表示可 以使用函数vTaskPrioritySet()。这个功能其实就是条件编译,在文件 tasks.c 中有如下图所示的代码。

从图可以看出当满足条 件 : NCLUDE_vTaskPrioritySet == 1 的 时 候 , 函 数vTaskPrioritySet()才会被编译,注意,这里为了缩小篇幅将函数 vTaskPrioritySet()的内容进行了折叠。FreeRTOS 中的裁剪和配置就是这种用条件编译的方法来实现的,不止FreeRTOS这么干,很多的协议栈、RTOS 系统和 GUI 库等都是使用条件编译的方法来完成配置和裁剪的。条件编译的好处就是节省空间,不需要的功能就不用编译,这样就可以根据实际需求来减少系统占用的 ROM 和 RAM 大小,根据自己所使用的MCU来调整系统消耗。

……

更多补充说明

每个任务都有自己的堆栈。设置堆栈大小时,单位是字,也就是四个字节。

任务优先级理论上是无限的,但因为和configUSE_PORT_OPTIMISED_TASK_SELECTION这个宏的功能相关,也就是和硬件相关,所以最大只能设置到32。不过一般也不会用到32个优先级。

关于宏configUSE_16_BIT_TICKS

宏configCHECK_FOR_STACK_OVERFLOW一般只在调试阶段打开。

暂且认为钩子函数就是回调函数吧。

heap4.c中实现了动态内存管理函数。

堆的内存池大小也在heap4.c中有使用。

这里总堆大小的单位是字节,定义的是20K,具体情况具体设置。

这些都是跟调试相关的

补充:三个重要中断

在 FreeRTOS 的移植过程中会这遇到三个重要的中断,分别是 FreeRTOS 系统时基定时器的中断(SysTick 中断)、SVC 中断、PendSV 中断。

SysTick 中断是用来提供系统时基的,很好理解。

那么SVC和PendSV是用来干嘛的呢?

参考:怎样去理解异常SVC和PendSV_pendsv svc-CSDN博客

SVC(系统服务调用)和 PendSV( 可悬挂系统调用 )。
它们多用于在操作系统之上的软件开发中。
SVC用于产生系统函数的调用请求。
例如,操作系统不让用户程序直接访问硬件,而是通过提供一些系统服务函数,用户程序使用 SVC 发出对系统服务函数的呼叫请求,以这种方法调用它们来间接访问硬件。因此,当用户程序想要控制特定的硬件时,它就会产生一个 SVC 异常,然后操作系统提供的 SVC 异常服务例程得到执行,它再调用相关的操作系统函数,后者完成用户程序请求的服务。

获取数据有两条路线:

通过SVC。

绕过SVC(但是不允许)。

由此实现软件硬件分离。 

另一个相关的异常是 PendSV(可悬挂的系统调用),它和 SVC 协同使用。SVC异常是必须立即得到响应的(若因优先级不比当前正处理的高, 或是其它原因使之无法立即响应, 将上访成硬 fault),应用程序执行 SVC 时都是希望所需的请求立即得到响应。PendSV 则不同,它是可以像普通的中断一样被悬起的(不像 SVC 那样会上访)。 OS 可以利用它“缓期执行” 一个异常——直到其它重要的任务完成后才执行动作。

悬起 PendSV 的方法是:手工往 NVIC 的 PendSV 悬起寄存器中写 1。 悬起后, 如果优先级不够高,则将缓期等待执行。PendSV是可悬起异常,如果我们把它配置最低优先级,那么如果同时有多个异常被触发,它会在其他异常执行完毕后再执行,而且任何异常都可以中断它。

假设任务A、任务B。

任务A,2ms执行结束后延迟500ms再次执行,那么OS在这段500ms内寻找下一个要执行的任务B,任务B,2ms执行结束延迟600ms再次执行(如果还有任务C、E等依次类推)。但是现在任务A并没有延迟到500ms所以此时OS执行空闲任务,到达500ms后才会执行任务A。

当空闲任务切换到任务A或者任务B时,此时突然中断产生,PendSV执行。

一时半会儿还不太理解,后续可能需要看这本书:

《ARM Cortex-M3 与 Cortex-M4 权威指南(第三版)》

以后再补充。

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

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

相关文章

SwiftUI的context Menu

SwiftUI的 context Menu 现在来演示一下如何使用 SwiftUI 的 Context Menu 。 代码&#xff1a; import SwiftUIstruct ContextMenuBootCamp: View {State var bgColor: Color .purplevar body: some View {VStack(alignment: .leading, spacing: 10.0) {Image(systemName: …

【LeetCode】升级打怪之路 Day 21:二叉树的最近公共祖先(LCA)问题

今日题目&#xff1a; 236. 二叉树的最近公共祖先1644. 二叉树的最近公共祖先 II235. 二叉搜索树的最近公共祖先 目录 LCA 问题LC 236. 二叉树的最近公共祖先 【classic】LC 1644. 二叉树的最近公共祖先 II 【稍有难度】LC 235. 二叉搜索树的最近公共祖先 ⭐⭐⭐ 今天做了几道有…

电源常用电路—驱动电路详解

数字电源控制核心对输入输出参数进行采集后&#xff0c;利用控制算法进行分析从而产生PWM控制信号&#xff0c;PWM信号将经过驱动电路的进行功率放大和隔离&#xff0c;随后接入功率开关器件从而完成电源的输出控制。本篇将主要针对电源的驱动电路进行讲解。 一、驱动电路概述…

高效Go编程: encoding/csv标准库深度解析

高效Go编程: encoding/csv标准库深度解析 引言了解encoding/csv库CSV文件的基本结构encoding/csv库的核心功能应用场景 读取CSV文件基本步骤代码示例处理不同的分隔符错误处理 处理CSV数据数据解析代码示例处理不规则数据代码示例 写入CSV文件基本步骤代码示例自定义设置错误处…

C语言——详解字符函数和字符串函数(一)

Hi,铁子们好呀&#xff01;今天博主来给大家更一篇C语言的字符函数和字符串函数~ 具体讲的内容如下&#xff1a; 文章目录 &#x1f386;1.字符分类函数&#x1f4af;&#x1f4af;⏩1.1 什么是字符分类函数的&#xff1f;&#x1f4af;&#x1f4af;⏩1.2 字符函数的类型有哪…

DXP软件界面显示“No Hard Devices”【简单的操作问题】加【软件下载】

目录 一&#xff0c;DXP软件界面显示“No Hard Devices” 二&#xff0c;软件下载的百度网盘资源 一&#xff0c;DXP软件界面显示“No Hard Devices” Protel DXP是2004是澳大利亚Altium公司于2002年推出的一款电子设计自动化软件。它的主要功能包括&#xff1a;原理图编辑、印…

北斗卫星推动数智油田建设

北斗卫星推动数智油田建设 中国石油大港油田采油三厂深入推动北斗智能终端在智能巡检、安全监督、油井导航、坐标测绘等多场景应用&#xff0c;实现了人工查井向智能巡检的变革。截至2月下旬&#xff0c;场景覆盖率达100%&#xff0c;高效助推大港南部“双高”老区数智油田建设…

修改vscode的相对路径计算逻辑

vscode的相对路径计算逻辑是&#xff0c;"./"表示当前项目的文件夹&#xff0c;而不是当前文件所在的文件夹 做出如下修改&#xff1a; File-->Preferences-->settings 搜索Execute in File Dir , 然后取消勾选

TikTok新手如何起号?环境因素与内容创新技巧

相信很多刚入行的TikTok玩家都遇到过一个难题&#xff0c;那就是账号权重低&#xff0c;播放量在个位数徘徊&#xff0c;其实都是因为还没起号&#xff01;那么具体如何起号呢&#xff1f;下面小编也给大家分享一下技巧。 一、如何起号 1、明确注册 TikTok 账号的目的 无论是…

Linux 管道

目录 一、认识管道 二、匿名管道 pipe函数 用法&#xff1a; pipefd&#xff1a; 匿名管道通信&#xff1a; 三、命名管道 概念&#xff1a; 创建&#xff1a; 特性&#xff1a; 用途&#xff1a; 四、命名管道和匿名管道的区别 命名&#xff1a; 持久性&#xff1a;…

MySQL:概念简章

1.SQL通用语法 SQL单行、多行书写&#xff0c;以分号结尾SQL可以以空格有缩进增加代码可读性SQL语句不区分大小写 2.SQL语句分类 2.1 DDL&#xff08;数据定义语言&#xff09; 用于数据库、数据表、字段的定义的语言 create by 表名 &#xff08;表里有什么字段&#xff09;…

力扣经典题:化栈为队

整体思路&#xff1a;入栈然后出栈&#xff0c;操作就和队列相同了 大佬的代码 typedef struct Node {int val;struct Node* next; }Node; Node* newNode(int Val) {Node* n(Node*)malloc(sizeof(Node));n->valVal;n->nextNULL;return n; } void push(Node* Head,int Va…

怎么把mp4转换成amv格式?如何下载amv格式视频?

MP4&#xff08;MPEG-4 Part 14&#xff09;是一种通用的视频文件格式&#xff0c;广泛用于多媒体应用。作为MPEG-4标准的一部分&#xff0c;MP4以其卓越的压缩性能、出色的视频质量和广泛的兼容性成为当前最流行的视频格式之一。 AMV文件格式的介绍 AMV文件格式起源于中国公司…

c语言大小写字母的转换

通过ascll码表我们可以知道大写字母与小写字母相差32个数&#xff08;小写字母比大写字母大&#xff09;。因此&#xff0c;通过相加减32即可转换大小写字母。 #include <stdio.h>int main() {char ch c;char CH A;printf("%c\n", ch - 32);printf("%c…

网工内推 | 上市公司网工,IE认证优先,最高18K*13薪,包吃住

01 深圳市宝腾互联科技有限公司 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1、是整个数据中心的网络技术及安全问题的负责人&#xff0c;确保数据中心业务的正常进行&#xff1b; 2、负责规划、设计、搭建、维护数据中心的网络环境&#xff0c;确保IDC /云平台&a…

【Qt】常用控件或属性(1)

需要云服务器等云产品来学习Linux可以移步/-->腾讯云<--/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;新用户首次下单享超低折扣。 目录 一、QWidget属性一览 二、控件button、属性enabled(可用状态) 三、属性geometry(修改位置和尺寸) 1、QRect类型的结…

第五十五天| 583. 两个字符串的删除操作、72. 编辑距离

Leetcode 583. 两个字符串的删除操作 题目链接&#xff1a;583 两个字符串的删除操作 题干&#xff1a;给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。 思考&#xff1a;动态规划。本题中…

现已修复!微软 SmartScreen 漏洞被用于分发 DarkGate 恶意软件

昨天&#xff08;3月13日&#xff09;&#xff0c;趋势科技分析师报告称有黑客利用Windows SmartScreen 漏洞在目标系统投放DarkGate 恶意软件。 该漏洞被追踪为 CVE-2024-21412 漏洞&#xff0c;是一个 Windows Defender SmartScreen 漏洞&#xff0c;它允许特制的下载文件绕…

Self-supervised Contextual Keyword and Keyphrase Retrieval with Self-Labelling

文章目录 题目摘要方法数据集实验 题目 通过自我标记进行自我监督的上下文关键字和关键词短语检索 论文地址&#xff1a;https://www.preprints.org/manuscript/201908.0073/v1 项目地址&#xff1a;https://github.com/naister/Keyword-OpenSource-Data 摘要 在本文中&#x…

SE园区综合实验(未补齐版)

实验要求&#xff1a; 1.局域网存在vlan10和vlan20两个业务vlan&#xff0c;ip网段分别对应192.168.1.0/24和192.168.2.0/24 2.业务vlan可以在所有链路上传输数据 3.sw1和sw2之间的直连链路上配置静态链路聚合实现链路冗余&#xff0c;并提高链路带宽 4.sw3为某接入点二次交…