嵌入式实时操作系统笔记2:UCOS基础知识_UC/OS-III移植(STM32F4)_编写简单的UC/OS-III任务例程(失败.....)

 今日学习嵌入式实时操作系统RTOS:UC/OS-III实时操作系统

本文只是个人学习笔记备忘用,附图、描述等 部分都是对网上资料的整合......

文章主要研究如何将UC/OS-III 移植到 STM32 F407VET6上,提供测试工程下载

 (2024.5.21 文章未写完,测试有问题,以后再说)

 (2024.5.22 系统移植失败,测试有问题,以后再说)

 附言:网络上的资料真是参差不齐,整整浪费我一天时间......

目录

UCOS基础知识:

任务的五种状态:

 任务五种状态转换图:

UCOS-III的三大列表:

UCOS-III系统配置文件说明:

UC/OS-III移植(STM32F4):

添加 UC/OS-III 源码部分:

修改system_stm32f4xx.s启动文件代码:

修改/确定 系统时钟(SysTick)内核:

修改CONFIG/app_cfg.h:

修改CONFIG/includes.h :

尝试编写简单的 UC/OS-III 任务例程:

先引用头文件:

定义任务栈大小/优先级:

定义任务控制块TCB:

定义任务栈:

定义任务主体函数:

创建任务TASK1-2-3:

CPU_SR_ALLOC();  

OS_CRITICAL_ENTER();  

OS_CRITICAL_EXIT();

启动UCOS III 系统函数:

主函数调用情况展示:

测试效果展示:

整体测试工程下载:

网上学习资料网址贴出:


UCOS基础知识:

任务的五种状态:

 任务五种状态转换图:

1、被创建的任务,初始状态均为就绪态
2、被删除的任务,会转为休眠态
3、仅就绪态和中断态可转变成运行态
4、其他状态的任务想运行,必须先转变成就绪

UCOS-III的三大列表:

UCOS-川主要有三大类列表用来跟踪任务状态:


就绪列表  准备运行的任务将放在就绪列表:OSRdyList[x],其中x代表任务优先级数值
Tick列表   正在等待延时超时或挂起的对象超时的任务,将放在OSTickList
挂起列表   当任务等待信号量、事件时,任务将放置在挂起列表PendList

UCOS-III系统配置文件说明:

以下就是我们接下来需要移植的 部分文件,他们的作用大致各自如下:

UC/OS-III移植(STM32F4):

本次尝试移植UC/OS-III 于立创梁山派天空星开发板上,芯片型号是STM32F407VET6

其中UC/OS-III 的源码可以在整体工程下载中的压缩包内找到

注意:这里的源码是被我阉割过的,削除了官方文件中不必要的文件与目录

其次就是网络上那些所谓提供UC/OS源码或者教程的,如果没有移植成功的工程供下载的案例,基本都是垃圾!浪费时间!不是缺少文件,就是解释不详细,缺步漏步!

本人也是在艰难的学习中掉进太多移植源码方面的坑里了.........

添加 UC/OS-III 源码部分

在工程中新建几个分组:

uC-OS3/CPU

uC-OS3/LIB

uC-OS3/PORT

uC-OS3/SOURCE

uC-OS3/CONFIG
 

点击uC-OS3/CPU–>Add Files

UC-OSIII/CPU添加以下文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/CPU–>Add Files

UCOSIII\bsp添加以下文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/LIB–>Add Files

UCOSIII\uC-LIB添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/PORT–>Add Files

UCOSIII\uCOS-III\Ports添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

点击uC-OS3/SOURCE–>Add Files

UCOSIII\uCOS-III\Source添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

uC-OS3/CONFIG添加文件:

UCOSIII\config添加以下所有文件,如果只查找到一个,请将文件类型(I)选为 ALL files(''.'')

最后别忘记在魔棒中添加各个文件路径:

补:补充添加一条bsp的路径,之前忘记添加了,导致报错......

添加结束,编译看看有无报错缺漏:

这里也是完美无报错的典范了哈哈哈......

修改system_stm32f4xx.s启动文件代码:

打开工程自带的 system_stm32f4xx.s启动文件(这是启动文件,不是UC/OS源码!)

我们需要对其进行一些修改:

1

第80行框出代码修改:

                DCD     OS_CPU_PendSVHandler             ; PendSV Handler
                DCD     OS_CPU_SysTickHandler            ; SysTick Handler

第220行框出代码修改:

OS_CPU_PendSVHandler\
                PROC
                EXPORT  OS_CPU_PendSVHandler       [WEAK]
                B       .
                ENDP
OS_CPU_SysTickHandler\
                PROC
                EXPORT  OS_CPU_SysTickHandler      [WEAK]
                B       .
                ENDP

最后编译检查无问题:

修改/确定 系统时钟(SysTick)内核:

这里我还特意出去学习了一下系统内核时钟的初始化等知识:并附文:

STM32F407VET6 学习笔记3:内核定时器SystemTick(SysTick)初始化中断-CSDN博客

/**
 * This function will initial stm32 board.
 */
void board_init(void)
{
    /* NVIC Configuration */
#define NVIC_VTOR_MASK              0x3FFFFF80
#ifdef  VECT_TAB_RAM
    /* Set the Vector Table base location at 0x10000000 */
    SCB->VTOR  = (0x10000000 & NVIC_VTOR_MASK);
#else  /* VECT_TAB_FLASH  */
    /* Set the Vector Table base location at 0x08000000 */
    SCB->VTOR  = (0x08000000 & NVIC_VTOR_MASK);
#endif

	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //Systick 时钟源频率168M
	
	  // 计算SysTick重装载值(SystemCoreClock为168MHz,希望SysTick中断频率为1ms(1000 Hz))
		//SysTick_LOAD = (SystemCoreClock / TickRate) - 1
    uint32_t reload = SystemCoreClock / 1000 - 1; // 1ms中断频率  
    SysTick->LOAD = reload;  

    // 清除SysTick当前值并启动SysTick,同时使能中断
    SysTick->VAL  = 0; // 清空当前值  
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;  

    /* 设置NVIC优先级分组 */  
    // 4位抢占优先级和0位子优先级  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);   
    /* 设置SysTick中断的优先级 */  
    // 设置SysTick的抢占优先级为3(最低),没有子优先级(因为分组4没有子优先级位)  
    NVIC_SetPriority(SysTick_IRQn, 3); // 注意:优先级值根据分组设置可能有所不同 
		
}
// 声明SysTick中断处理函数  
void SysTick_Handler(void)
{
	  OSIntEnter();		      //进入中断
    OSTimeTick();       //调用ucos的时钟服务程序               
    OSIntExit();        //触发任务切换软中断
}

修改CONFIG/app_cfg.h:

#define APP_CFG_SERIAL_EN        DEF_ENABLED ------>

#define APP_CFG_SERIAL_EN        DEF_DISABLED

改后如下:

#define APP_TRACE BSP_Ser_Printf --------> #define APP_TRACE (void)

修改CONFIG/includes.h :

尝试编写简单的 UC/OS-III 任务例程:

先引用头文件:

/*****************UC/OS头文件***************/
#include "os.h"
#include "os_cpu_bsp.h"
#include <app_cfg.h>
#include <cpu_core.h>
#include <os_app_hooks.h>
#include <cpu.h>
/* USER CODE END Includes */

定义任务栈大小/优先级:


//任务栈大小定义
#define  START_STK_SIZE                     128
#define  TASK1_STK_SIZE                     128
#define  TASK2_STK_SIZE                     128
#define  TASK3_STK_SIZE                     128
//任务优先级定义
#define  APP_TASK_START_PRIO                     4
#define  APP_TASK_1_PRIO                         5
#define  APP_TASK_2_PRIO                         6
#define  APP_TASK_3_PRIO                         7

定义任务控制块TCB:

//创建任务控制块
static OS_TCB Start_Task_TCB;
static OS_TCB Task1_TCB;
static OS_TCB Task2_TCB;
static OS_TCB Task3_TCB;

定义任务栈:

//任务堆栈	
CPU_STK START_TASK_STK[START_STK_SIZE];
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
CPU_STK TASK3_TASK_STK[TASK3_STK_SIZE];

定义任务主体函数:

这个放置在主函数下面吧就:

任务里面一定要有阻塞延时,如果这个任务的优先级最高且没有阻塞延时,那么操作系统就只会执行这一个任务,其他的任务就得不到执行。

注意:这里的    OSTimeDly ( 2000, OS_OPT_TIME_DLY, & err ); 对应的延时 不仅与 内传的参数 有关 还与 内核定时器SystemTick 有关:

创建任务TASK1-2-3:

各个TASK的任务如下描述:

//TASK_1 报告自己执行次数(2s),并在执行8次后删除 TASK_2

//TASK_2 串口报告自己执行的次数 (4s)

//这里的 TASK_3 会每隔 17S 恢复TASK_2 (全新的开始)
/*
    创建一个全新的任务实例,而不是简单地“恢复”一个已经被删除的任务。
  这意味着新的任务实例将拥有自己独立的堆栈(stack)和其他资源,而原来的任务实例(如果已经被删除)的资源将被释放
*/

//TASK_1 报告自己执行次数(2s),并在执行8次后删除 TASK_2
void TASK_1(void)
{
	OS_ERR  err;			// 定义一个“错误” 变量用来存放一些错误的类型
	int TASK1_num=0;  //记录任务TASK_1执行次数

	
	//在某些嵌入式系统中,进入和退出关键区域可能需要禁用中断,以防止在关键代码执行过程中被中断打断。	
  CPU_SR_ALLOC();   //为保存和恢复CPU的状态寄存器(Status Register)或中断状态做准备工作。
	OS_CRITICAL_ENTER();
	/* 此处添加不希望被打断的硬件初始化代码等......*/
	OS_CRITICAL_EXIT();
	
	while(1)
	{
		TASK1_num++;	//任务TASK_1执行次数加1
		
		if(TASK1_num%8==0)
		{
			OSTaskDel((OS_TCB*)&Task2_TCB,&err);	        //任务1每执行8次后(即16s时) 删除掉任务2
			printf("TASK_1 has Deleted the TASK_2 !\r\n");//打印报告	任务1 删除了 任务2
		}
	  UsartPrintf(USART1,"TASK_1 has Carred out %d times! \r\n",TASK1_num);	//打印测试字符串(并报告TASK_1执行次数)
		OSTimeDly ( 2000, OS_OPT_TIME_DLY, & err ); //使当前任务延迟指定的时间(2s):  (让当前任务放弃CPU一段时间,CPU让给其余任务)
	}
}

//TASK_2 串口报告自己执行的次数 (4s)
void TASK_2(void)
{
	OS_ERR  err;			// 定义一个“错误” 变量用来存放一些错误的类型
	int TASK2_num=0;  //记录任务TASK_2执行次数
		
	while(1)
	{
	  UsartPrintf(USART1,"TASK_2 has Carred out %d times! \r\n",TASK2_num);	//打印测试字符串(并报告TASK_2执行次数)
		OSTimeDly ( 4000, OS_OPT_TIME_DLY, & err );//使当前任务延迟指定的时间(4S):  (让当前任务放弃CPU一段时间,CPU让给其余任务) 
	}
}

//这里的 TASK_3 会每隔 17S 恢复TASK_2 (全新的开始)
/*
	创建一个全新的任务实例,而不是简单地“恢复”一个已经被删除的任务。
  这意味着新的任务实例将拥有自己独立的堆栈(stack)和其他资源,而原来的任务实例(如果已经被删除)的资源将被释放
*/
void TASK_3(void)
{
	OS_ERR  err;			// 定义一个“错误” 变量用来存放一些错误的类型
	int TASK3_num=0;  //记录任务TASK_3执行次数
	CPU_SR_ALLOC();
	
	OS_CRITICAL_ENTER();	//进入临界区			 
	 //重新创建TASK2任务
			OSTaskCreate((OS_TCB 	* )&Task2_TCB,		
				 (CPU_CHAR	* )"TASK_2", 		
                 (OS_TASK_PTR )TASK_2, 			
                 (void		* )0,					
                 (OS_PRIO	  )TASK2_PRIO,     	
                 (CPU_STK   * )&TASK2_TASK_STK[0],	
                 (CPU_STK_SIZE)TASK2_STK_SIZE/10,	
                 (CPU_STK_SIZE)TASK2_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, 
                 (OS_ERR 	* )&err);	
	OS_CRITICAL_EXIT();	//退出临界区	 		
								 
	while(1)
	{
	    UsartPrintf(USART1,"TASK_3 has Resume the TASK_2 %d times! \r\n",TASK3_num);	//打印测试字符串(并报告TASK_3执行次数)							 
			OSTimeDly ( 17000, OS_OPT_TIME_DLY, & err );//使当前任务延迟指定的时间(17S):  (让当前任务放弃CPU一段时间,CPU让给其余任务) 
		
	}
}

//开始任务任务函数
void start_task(void *p_arg)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;

	CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
  OSStatTaskCPUUsageInit(&err);  	//统计任务                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了测量中断关闭时间
  CPU_IntDisMeasMaxCurReset();	
#endif
	
#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //当使用时间片轮转的时候
	 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif	
	
	OS_CRITICAL_ENTER();	//进入临界区
	//创建TASK1任务
	OSTaskCreate((OS_TCB 	* )&Task1_TCB,				          //任务控制块
				 (CPU_CHAR	* )"TASK_1", 	 		                  //任务名字	
                 (OS_TASK_PTR )TASK_1, 			            //任务函数
                 (void		* )0,					                //传递给任务函数的参数					
                 (OS_PRIO	  )TASK1_PRIO,     
                 (CPU_STK   * )&TASK1_TASK_STK[0],	
                 (CPU_STK_SIZE)TASK1_STK_SIZE/10,	
                 (CPU_STK_SIZE)TASK1_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);				
				 
	//创建TASK2任务
	OSTaskCreate((OS_TCB 	* )&Task2_TCB,		
				 (CPU_CHAR	* )"TASK_2", 		
                 (OS_TASK_PTR )TASK_2, 			
                 (void		* )0,					
                 (OS_PRIO	  )TASK2_PRIO,     	
                 (CPU_STK   * )&TASK2_TASK_STK[0],	
                 (CPU_STK_SIZE)TASK2_STK_SIZE/10,	
                 (CPU_STK_SIZE)TASK2_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, 
                 (OS_ERR 	* )&err);		

	//创建TASK3任务
	OSTaskCreate((OS_TCB 	* )&Task3_TCB,		
				 (CPU_CHAR	* )"TASK_3", 		
                 (OS_TASK_PTR )TASK_3, 			
                 (void		* )0,					
                 (OS_PRIO	  )TASK3_PRIO,     	
                 (CPU_STK   * )&TASK3_TASK_STK[0],	
                 (CPU_STK_SIZE)TASK3_STK_SIZE/10,	
                 (CPU_STK_SIZE)TASK3_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,					
                 (void   	* )0,				
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, 
                 (OS_ERR 	* )&err);	
								 
	OS_CRITICAL_EXIT();	//退出临界区
	OSTaskDel((OS_TCB*)0,&err);	//删除start_task任务自身
}

CPU_SR_ALLOC();  

OS_CRITICAL_ENTER();  

OS_CRITICAL_EXIT();

	//在某些嵌入式系统中,进入和退出关键区域可能需要禁用中断,以防止在关键代码执行过程中被中断打断。	
  CPU_SR_ALLOC();   //为保存和恢复CPU的状态寄存器(Status Register)或中断状态做准备工作。
	
	/*
		OS_CRITICAL_ENTER();
    这个函数通常用于进入一个关键区域。在进入关键区域之前,
		它可能会禁用中断(如果之前通过CPU_SR_ALLOC();已经做了相关准备),
	  或者通过其他机制(如锁)来确保没有其他线程或中断可以访问当前线程正在使用的共享资源。
    通过禁用中断或获得锁,OS_CRITICAL_ENTER();
	  确保了代码的关键部分在执行时不会被其他任务或中断打断,
	  从而保证了数据的一致性和操作的原子性。

	*/
	OS_CRITICAL_ENTER();
	/*
		OS_CRITICAL_EXIT();
		这个函数用于退出之前由OS_CRITICAL_ENTER();进入的关键区域。
		在退出关键区域时,它可能会重新启用之前被禁用的中断,或者释放之前获得的锁。
		这样做允许其他任务或中断再次访问之前被保护的共享资源
	*/
	OS_CRITICAL_EXIT();

启动UCOS III 系统函数:

//启动UCOS III 系统 !
void UCOS_III_init(void)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	
	OSInit(&err);		      //初始化UCOSIII
	OS_CRITICAL_ENTER();	//进入临界区			 
	//创建开始任务
	OSTaskCreate((OS_TCB 	* )&Start_Task_TCB,		      //任务控制块
				 (CPU_CHAR	* )"start_task", 		            //任务名字
                 (OS_TASK_PTR )start_task, 			    //任务函数
                 (void		* )0,					            //传递给任务函数的参数
                 (OS_PRIO	  )START_TASK_PRIO,       //任务优先级
                 (CPU_STK   * )&START_TASK_STK[0],	//任务堆栈基地址
                 (CPU_STK_SIZE)START_STK_SIZE/10,	  //任务堆栈深度限位
                 (CPU_STK_SIZE)START_STK_SIZE,		  //任务堆栈大小
                 (OS_MSG_QTY  )0,				//任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
                 (OS_TICK	  )0,					//当使能时间片轮转时的时间片长度,为0时为默认长度,
                 (void   	* )0,					//用户补充的存储区
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
                 (OS_ERR 	* )&err);			//存放该函数错误时的返回值
	OS_CRITICAL_EXIT();	//退出临界区	 
	OSStart(&err);      //开启UCOSIII	 
}

主函数调用情况展示:

网上学习资料网址贴出:

第3讲 UCOS基础知识_哔哩哔哩_bilibili

uCosII移植STM32F407教程_stm32f407 ucos-CSDN博客

基于stm32cubemx移植uC/OS-III操作系统_cubemx ucos-CSDN博客

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

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

相关文章

数据结构--顺序表

目录 1.顺序表 1.1顺序表的概念及结构 线性表 2、顺序表分类 2.1顺序表和数组的区别 静态顺序表 动态顺序表 3.顺序表的实现 3.1初始化 随后便可对顺序表初始化 3.2插入数据 尾插 头插 在指定位置插入数据 顺序表的查找 头删、尾删及指定位置删除 实现代码&#x…

pycharm找不到conda可执行文件解决办法

解决办法 1、第一种 按照以下步骤&#xff0c;找到condabin文件下面&#xff0c;conda.bat 文件&#xff0c;把路径给复制下来&#xff0c;粘贴到 Conda 可执行文件&#xff0c;即可。 然后再点击加载环境&#xff0c;我这里是已经汉化了 pycharm &#xff0c;如何汉化&…

P451 try-Catch异常处理

//基本使用演示代码 public static void main(String[] args) { int num1 10; int num2 0; try { int res num1 / num2; }catch (Exception e) { System.out.println(e.getMessage()); } } public class TryCatchDetail { public static void main(String[] args) { //1. 如…

Excel工作簿/表的合并/拆分全集(一文通关)

概述 在工作中&#xff0c;我们常会用到到Excel拆分/合并为多个工作表/簿&#xff0c;如全国的订单表&#xff0c;需要根据省份列拆分下发至对应的省、各省份数据需要汇总、...... 应该如何操作呢&#xff1f; 1. 传统方法&#xff08;借助透视表、Power Query编辑器、VBA实现…

【启程Golang之旅】运算符与流程控制讲解

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

java -spring 15 配置类 ConfigurationClassPostProcessor

01Spring中定义的配置类 ConfigurationClassPostProcessor是一个BeanFactory的后置处理器&#xff0c;因此它的主要功能是参与BeanFactory的建造&#xff0c;在这个类中&#xff0c;会解析加了Configuration的配置类&#xff0c;还会解析ComponentScan、ComponentScans注解扫描…

【全开源】知识库文档系统源码(ThinkPHP+FastAdmin)

知识库文档系统源码&#xff1a;构建智慧知识库的基石 引言 在当今信息爆炸的时代&#xff0c;知识的有效管理和利用对于企业和个人来说至关重要。知识库文档系统源码正是为了满足这一需求而诞生的&#xff0c;它提供了一个高效、便捷的平台&#xff0c;帮助用户构建、管理、…

全金属狂潮!金银铜齐飞

在纽约铜史诗级逼空的影响下&#xff0c;全球金属市场迎来了一波“全金属狂潮”。 全金属狂潮 本周&#xff0c;纽约、上海交易所铜价纷纷创下新高。周五&#xff0c;伦敦金属交易所的铜价也录得2.8%涨幅&#xff0c;逼近2022年3月的历史最高点。 与此同时&#xff0c;白银价…

Ardupilot开源代码之Rover上路 - 后续3

Ardupilot开源代码之Rover上路 - 后续3 1. 源由2. 深度配置2.1 编码器2.2 WS2812B LED灯带2.3 4GLTE超视距2.3.1 摄像头2.3.2 QGC OSD虚拟遥控2.3.3 QGC外接JoyStick遥控 2.4 伴机电脑供电 3. 实测效果4. 遗留&后续4.1 设置倒车按钮4.2 MP无法连接ESP82664.3 高精度编码器问…

FFMPEG 解码过程初步学习

1. 视频文件解码过程 解码过程 步骤如下&#xff1a; 视频文件&#xff08;封装格式&#xff0c;MP4/FLV/AVI 等&#xff09;获取视频格式信息等解复用为Stream 流&#xff0c; 准备解码用的Codec将Stream 流 使用解码器解为Raw 格式针 1.1 音视频格式填充&#xff1a; int…

神秘山洞惊现AI绘画至宝Stable Diffusion残卷

最近听到不少大宗门纷纷发声&#xff1a;随着AI神器的现世“程序员职业将不复存在”&#xff0c;“设计图将要失业”。 至此&#xff0c;不少修士开始担忧起来&#xff0c;现出世的AI神器会不会取代掉我辈修士。 其实&#xff0c;至女娲天神创造人类以来&#xff0c;在这漫漫…

接口测试流程详解

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 在讲接口测试流程之前&#xff0c;首先需要给大家申明下&#xff1a;接口测试对于测试人员而言&a…

STM32H743的FDCAN使用方法(1):STM32CubeMX初始化代码生成

0 工具准备 1.STM32CubeMX1 前言 本文介绍基于STM32CubeMX&#xff0c;使用stm32h743xi的对FDCAN2进行配置的方法。 2 初始化代码生成 2.1 选择FDCAN引脚 本例选择PB5、PB6作为FDCAN2的RX、TX引脚。 2.2 选择FDCAN时钟源 本例选择PLL2Q作为FDCAN时钟源&#xff0c;频率…

深度学习中的优化算法二(Pytorch 19)

一 梯度下降 尽管梯度下降&#xff08;gradient descent&#xff09;很少直接用于深度学习&#xff0c;但了解它是理解下一节 随机梯度下降算法 的关键。例如&#xff0c;由于学习率过大&#xff0c;优化问题可能会发散&#xff0c;这种现象早已在梯度下降中出现。同样地&…

YOLOV10实时端到端目标检测

代码地址&#xff1a;GitHub - THU-MIG/yolov10: YOLOv10: Real-Time End-to-End Object Detection 论文地址&#xff1a;https://arxiv.org/pdf/2405.14458 本文介绍了YOLO系列目标检测器在实时和高效方面的优势&#xff0c;但是仍然存在一些缺陷&#xff0c;包括依赖非极大值…

Linux修炼之路之冯系结构,操作系统

目录 一&#xff1a;冯诺依曼体系结构 1.五大组件 2.存储器存在的意义 3.几个问题 二&#xff1a;操作系统 接下来的日子会顺顺利利&#xff0c;万事胜意&#xff0c;生活明朗-----------林辞忧 一&#xff1a;冯诺依曼体系结构 我们当代的计算机的基本构成都是由冯诺依曼…

【Tools】微服务工程中的通用功能模块抽取

Catalog 通用功能模块抽取一、需求二、步骤三、细节 通用功能模块抽取 一、需求 在微服务工程中&#xff0c;可能有一些工具类、实体类是多个微服务通用的&#xff0c;如果在每个微服务中都复制粘贴这些工具类&#xff0c;会产生很多重复性的代码&#xff0c;对开发来说也很繁…

git revert 和 git reset

文章目录 工作区 暂存区 本地仓库 远程仓库需求&#xff1a;已推送到远程仓库&#xff0c;想要撤销操作git revert &#xff08;添加新的提交来“反做”之前的更改&#xff0c;云端会残留上次的提交记录&#xff09;git reset&#xff08;相当于覆盖上次的提交&#xff09;1.--…

Convolutional Occupancy Networks【ECCV】

论文&#xff1a;https://arxiv.org/pdf/2003.04618 代码&#xff1a;GitHub - autonomousvision/convolutional_occupancy_networks: [ECCV20] Convolutional Occupancy Networks 图 1&#xff1a;卷积占据网络。传统的隐式模型 (a) 由于其全连接网络结构&#xff0c;表现能力…