STM32第二十课:FreeRTOS任务管理和信号量

目录

  • 一、任务管理方式
  • 二、任务堆栈溢出检测
  • 三、二值信号量(任务同步)
  • 四、计数信号量
  • 五、互斥信号量
  • 六、队列


一、任务管理方式

在这里插入图片描述
1.任务创建成功后会添加到就绪链表中,开启调度器,此时任务调度器会去就绪链表中找优先级最高的任务执行。若优先级一样则按照创建任务的先后来执行。
2.任务被执行时就会变为运行态时,该任务就会从就绪链表删除,若此时执行到任务中的vTaskDelay等函数时,该任务就会被挪到阻塞链表中。调度器此时会去执行其他任务。
3.当阻塞解除时,该任务会从阻塞链表中删掉,移动到就绪链表中。若解除任务的优先级很高,那么此时该任务会直接打断cpu正在执行的任务,抢占位置去执行自己。

二、任务堆栈溢出检测

详情见FreeRTOS中的任务堆栈溢出检测机制
主要作用就是方便调试,工程做完之后没问题了就关掉
写检测函数之前需要更改宏定义,我们采用的是第二种堆栈检测方法。
![

void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf("任务:%s->栈溢出\r\n",pcTaskName);printf("任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}

本质上就是一个钩子函数,在任务上下文切换的时候做检测,具有一定的滞后性,需要在任务发生上下文切换时才会进行,任务堆栈溢出时并不能马上检测到问题。
但大多常见情况下这种检测机制依然是非常实用的功能,可以帮助用户减少代码中的错误并提高应用程序代码的质量。

三、二值信号量(任务同步)

任务同步:任务B需要等待任务A执行完再去执行。
二值信号量也一样,谁拥有谁执行,比如任务B需要获得信号量才能执行,那么他就要等待A给他一个信号量然后再去执行。

1.添加头文件

#include "semphr.h"

2.创建一个SemaphoreHandle_t 类型的二值信号量句柄

SemaphoreHandle_t Binary;

3.主函数创建二值信号量,返回值为该信号量的句柄

	//创建一个二值信号量Binary = xSemaphoreCreateBinary();

4.使用函数xSemaphoreGive给出二值信号量,参数为二值信号量的句柄

xSemaphoreGive(Binary)

5.使用xSemaphoreTake函数接收二值信号量,参数为句柄和超时时间(也可填写portMAX_DELAY,表示死等)
若返回值为pdTRUE,则表示获取到该信号量。

if(xSemaphoreTake(Binary,1000) == pdTRUE) {printf("按键按下,获取到信号量\r\n");}

完整代码

//包含支持stm32f1系列的头文件
#include  "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include "adc.h"
#include "kqm.h"
#include "dht11.h"//使用FreeRTOS相关头文件之前先包含FreeRTOS.h
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/********************信号量句柄***********************/
SemaphoreHandle_t Binary;//传感器任务
TaskHandle_t Sensor_TaskHandle;
void Sensor_Task(void *p)
{while(1){taskENTER_CRITICAL();//进入临界区Dht11ReadData();//DHT11读取函数不能被打断taskEXIT_CRITICAL();//退出临界区KQMDealData();//该函数的调用时间小于等于1秒ADC_DataFliter();//ADC均值滤波vTaskDelay(1000);//阻塞1秒}
}//任务本体 闪灯任务
TaskHandle_t LED_TaskHandle;
void LED_Task(void *p)
{uint8_t i=0;while(1){if(xSemaphoreTake(Binary,1000) == pdTRUE) {printf("按键按下,获取到信号量\r\n");}else{printf("获取到信号量等待超时\r\n");}i++;printf("i=%d\r\n",i);Led_Toggle(1);//printf("LED任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(NULL));
//		Delay_nms(200);//也能延时,但是会一直占用CPU//也是延时200ms,但是FreeRTOS提供的函数,有阻塞机制,能够让任务从运行态变为阻塞态vTaskDelay(200);}
}
//任务本体 按键任务
TaskHandle_t KEY_TaskHandle;
void KEY_Task(void *p)
{while(1){switch(key_getvalue()){case 1:vTaskSuspend(LED_TaskHandle);break;case 2:vTaskResume(LED_TaskHandle);break;case 3:xSemaphoreGive(Binary);break;case 4:break;}vTaskDelay(10);//MS级别的延时,带有阻塞性质,任务会从运行态变为阻塞态}
}	int main()
{Led_Init();//初始化LEDKey_init();//初始化按键Usart1_Config();//初始化串口1ADC_Config();//初始化ADCKqm_U4Config();//初始化KQMDHT11_Mode();//初始化DHT11BaseType_t Ret = pdPASS;//创建一个二值信号量Binary = xSemaphoreCreateBinary();//1,如何创建一个任务?Ret = xTaskCreate(Sensor_Task,"Sensor_Task",200,NULL,1,&Sensor_TaskHandle);Ret = xTaskCreate(LED_Task, //创建任务的任务函数名"LED1_Toggle",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL3,//任务优先级&LED_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("LED_Task创建完成\r\n");}Ret = xTaskCreate(KEY_Task, //创建任务的任务函数名"KEY_Task",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL2,//任务优先级&KEY_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("KEY_Task创建完成\r\n");}printf("开启FreeRTOS调度器\r\n");//调度器启动完成之后,FreeRTOS会获取CPU控制权,会按照任务优先级执行创建的任务vTaskStartScheduler();while(1){	}
}void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf("任务:%s->栈溢出\r\n",pcTaskName);printf("任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}

四、计数信号量

一般在资源有限的情况下使用,如:停车场,坐位,传感器的访问等。
计数信号量测试:按键和灯,按键按下几次,灯翻转几次。
1.创建计数信号量的句柄

SemaphoreHandle_t Count_Handle;//计数信号量句柄

2.创建计数信号量
返回值为该信号量的句柄,参数为最大信号量为多少和初始信号量有几个。

Count_Handle = xSemaphoreCreateCounting(10,5);//创建计数信号量

3.给出信号量
参数为计数信号量的句柄

xSemaphoreGive(Count_Handle);

4.消耗信号量
参数和二值信号量一样,一个是对应的句柄,一个是超时。
成功返回pdTRUE。

if(xSemaphoreTake(Count_Handle,portMAX_DELAY) == pdTRUE) 

完整代码

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "delay.h"
#include "string.h"
#include "pwm.h"
#include "adc.h"
#include "su03t.h"
#include "dht11.h"
#include "kqm.h"
#include "usart.h"
#include "key.h"//使用FreeRtos相关头文件之前,一定要先包含这个#include "FreeRtos.h"
#include "FreeRtos.h"
#include "task.h"
#include "semphr.h"
#include "queue.h"TaskHandle_t Deal_TaskHandle;//数据处理
SemaphoreHandle_t Binary;//二值信号量句柄
SemaphoreHandle_t Count_Handle;//计数信号量句柄
TaskHandle_t LED_TaskHandle;//任务本体 闪灯任务
TaskHandle_t KEY_TaskHandle;//任务本体 按键任务
void Data_Task(void *p)
{while(1){Get_Smoke_Light_MidValue();DHT11_ReadData();vTaskDelay(300);KQM_DealData();Su03tDealData();}
}void KEY_Task(void *p)
{while(1){switch(key_getvalue()){case 1:vTaskSuspend(LED_TaskHandle);break;case 2:vTaskResume(LED_TaskHandle);break;case 3:xSemaphoreGive(Count_Handle);printf("给一个计数信号量\r\n");break;case 4:break;}vTaskDelay(10);//MS级别的延时,带有阻塞性质,任务会从运行态变为阻塞态}
}	
void LED_Task(void *p)
{uint8_t i=0;while(1){if(xSemaphoreTake(Count_Handle,portMAX_DELAY) == pdTRUE) {printf("消耗计数信号量\r\n");i++;printf("i=%d\r\n",i);Led_Toggle(1);vTaskDelay(1000);}}
}int main()
{RGBpwm_Config();Kqm_U4Config();Su03t_U5Config();DHT11_Config();	 Adc_Config();Led_Init();key_Init();Usart1_Config();BaseType_t Ret = pdPASS;
//	Ret = xTaskCreate(Data_Task,"DealData",300,NULL,2,&Deal_TaskHandle);
//	if(Ret==pdPASS)
//	{
//		printf("数据创建成功!\r\n");
//	}Binary = xSemaphoreCreateBinary();//计数信号量最大值   初始时有多少个信号量可用Count_Handle = xSemaphoreCreateCounting(10,5);//创建计数信号量Ret = xTaskCreate(LED_Task, //创建任务的任务函数名"LED1_Toggle",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL3,//任务优先级&LED_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("LED_Task创建完成\r\n");}Ret = xTaskCreate(KEY_Task, //创建任务的任务函数名"KEY_Task",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL2,//任务优先级&KEY_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("KEY_Task创建完成\r\n");}printf("开启FreeRTOS调度器成功\r\n");vTaskStartScheduler();while(1){}
}void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf("任务:%s->栈溢出\r\n",pcTaskName);printf("任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}

五、互斥信号量

用于共享资源的保护
资源A是共享资源,此时如果被任务1使用,那么就不能被其他任务使用。
(任务1:小A,你让我使用了,可就不能让别人使用了哦 ~)
1.创建句柄

SemaphoreHandle_t Mutex_Handle=NULL;

2.创建互斥信号量
返回值为互斥信号量的句柄

Mutex_Handle = xSemaphoreCreateMutex();//创建互斥信号量

3.获取信号,给出信号
保护printf,使printf能够完整打印。

void MyPrintf(char *p)
{xSemaphoreTake(Mutex_Handle,portMAX_DELAY);//获取信号量printf("%s",p);xSemaphoreGive(Mutex_Handle);//还回去
}

完整代码:

#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "usart.h"
#include "stdio.h"
#include "led.h"
#include "key.h"
#include "dht.h"
#include "adc.h"
#include "kqm.h"/*******************信号量句柄*********************/
SemaphoreHandle_t Binary_Handle=NULL;
SemaphoreHandle_t Count_Handle=NULL;
SemaphoreHandle_t Mutex_Handle=NULL;
/*******************互斥信号量保护资源*********************/
void MyPrintf(char *p)
{xSemaphoreTake(Mutex_Handle,portMAX_DELAY);//获取信号量printf("%s",p);xSemaphoreGive(Mutex_Handle);//还回去
}/*******************LED任务*********************/
TaskHandle_t LEDtask_Handle = NULL;
//任务函数本身
void LED_Task(void * p)
{MyPrintf("LED任务创建成功\r\n");LED_Config();BEEP_Config();while(1){	if(xSemaphoreTake(Count_Handle,portMAX_DELAY) == pdTRUE){MyPrintf("LED反转\r\n");LED1_Toggle();}else{MyPrintf("超时结束\r\n");}vTaskDelay(500);//控制任务的执行周期}
}
/*******************按键任务*********************/
TaskHandle_t KEYtask_Handle = NULL;
//任务函数本身
void KEY_Task(void * p)
{MyPrintf("按键任务创建成功\r\n");KEY_Config();while(1){	switch(KEY_Scan()){case 1:BEEP_Toggle(); break;case 2:
//				xSemaphoreGive(Binary_Handle);//给出二值信号量if(xSemaphoreGive(Count_Handle) == pdTRUE)//给出计数信号量{MyPrintf("成功给出计数信号量\r\n");}else{MyPrintf("信号量已满\r\n");}break;case 3: break;case 4:vTaskDelete(LEDtask_Handle);break;}vTaskDelay(10);}
}
/*******************传感器任务*********************/
TaskHandle_t Senortask_Handle = NULL;
//任务函数本身
void Senor_Task(void * p)
{MyPrintf("传感器任务创建成功\r\n");uint8_t cnt = 0;ADC_Config();//初始化ADCUART4_Config();//初始化KQM传感器while(1){	cnt++;if(KQM_Anlyze() == 0){printf("CO2:%d\r\n",kqmdata.CO2);}else{MyPrintf("KQM数据错误\r\n");}if(cnt>=3){cnt = 0;taskENTER_CRITICAL();//进入临界区if(DHT11_ReadData()== 0){printf("温度数据:%.2f 湿度数据:%d\r\n",TEM,HUM);}else{MyPrintf("温湿度数据获取失败\r\n");}taskEXIT_CRITICAL();//退出临界区			}vTaskDelay(1000);}
}
int main(void)
{USART_Config();BaseType_t Ret = pdPASS;Binary_Handle = xSemaphoreCreateBinary();//创建二值信号量//                       计数信号量最大值   初始时有多少个信号量可用Count_Handle = xSemaphoreCreateCounting(10,5);//创建计数信号量Mutex_Handle = xSemaphoreCreateMutex();//创建互斥信号量//动态创建任务Ret =  xTaskCreate(LED_Task,//任务函数的入口,也就是函数名"LED_Task",//任务别名,方便FreeRTOS管理100,//任务分配的堆栈空间 32单片机就是50*4 = 200字节NULL,//任务函数的参数,无参数就写NULL1,//任务优先级&LEDtask_Handle);//任务的句柄(指针),可以用来管理任务if(Ret == pdPASS){printf("LED任务创建成功\r\n");}//动态创建任务Ret =  xTaskCreate(KEY_Task,//任务函数的入口,也就是函数名"KEY_Task",//任务别名,方便FreeRTOS管理100,//任务分配的堆栈空间 32单片机就是50*4 = 200字节NULL,//任务函数的参数,无参数就写NULL1,//任务优先级&KEYtask_Handle);//任务的句柄(指针),可以用来管理任务if(Ret == pdPASS){printf("按键任务创建成功\r\n");}Ret =  xTaskCreate(Senor_Task,//任务函数的入口,也就是函数名"Senor_Task",//任务别名,方便FreeRTOS管理100,//任务分配的堆栈空间 32单片机就是50*4 = 200字节NULL,//任务函数的参数,无参数就写NULL2,//任务优先级&Senortask_Handle);//任务的句柄(指针),可以用来管理任务if(Ret == pdPASS){printf("传感器任务创建成功\r\n");}vTaskStartScheduler();//启动调度器printf("调度器启动失败\r\n");while (1){}
}//函 数 功 能:任务栈溢出钩子函数,调试阶段用
void vApplicationStackOverflowHook(TaskHandle_t xTask,signed char *pcTaskName)
{printf("任务:#%s #栈溢出\r\n",pcTaskName);printf("任务栈空间剩余:%d\r\n",uxTaskGetStackHighWaterMark(xTask));while(1){}
}

六、队列

  主要用于任务间数据传输,采用FIFO(先进先出)模式,新数据通常发到队列后面,但也可以发到队列前面。
1.创建句柄

QueueHandle_t Queue;

2.创建队列

//创建队列 长度为10 ,队列中每个数据的大小2字节Queue = xQueueCreate(10,2);

3.接收数据
参数1:要发送数据的目标队列的句柄。
参数2:指向要发送数据的指针。
参数3:发送数据时等待的最长时间
返回值:
pdPASS:数据成功发送到队列。
errQUEUE_FULL:队列已满,无法发送数据。

if(xQueueReceive(Queue,buff2,100)==pdTRUE)

4.发送数据

if(xQueueSend(Queue,buff,100) == pdTRUE)

完整代码:

//包含支持stm32f1系列的头文件
#include  "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include "adc.h"
#include "kqm.h"
#include "dht11.h"//使用FreeRTOS相关头文件之前先包含FreeRTOS.h
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/********************信号量句柄***********************/
SemaphoreHandle_t Binary;
SemaphoreHandle_t Count;
SemaphoreHandle_t Mutex;
/********************队列句柄***********************/
QueueHandle_t Queue;
QueueHandle_t KqmQueue;
/*********************互斥锁保护Printf****************/
void MyPrintf(char *p)
{xSemaphoreTake(Mutex,portMAX_DELAY);printf("%s",p);xSemaphoreGive(Mutex);
}//传感器任务
TaskHandle_t Sensor_TaskHandle;
void Sensor_Task(void *p)
{uint8_t recv[8] = {0};MyPrintf("Sensor Task Begin\r\n");while(1){if(xQueueReceive(KqmQueue,recv,100)==pdTRUE){printf("接受数据:%x %x %x %x %x %x %x %x\r\n",recv[0],recv[1],\recv[2],recv[3],recv[4],recv[5],recv[6],recv[7]);}else{printf("队列为空,接收失败\r\n");}taskENTER_CRITICAL();//进入临界区Dht11ReadData();//DHT11读取函数不能被打断ADC_DataFliter();//ADC均值滤波taskEXIT_CRITICAL();//退出临界区vTaskDelay(1000);//阻塞1秒}
}//任务本体 闪灯任务
TaskHandle_t LED_TaskHandle;
void LED_Task(void *p)
{uint8_t i=0;MyPrintf("LED_Task Begin\r\n");while(1){if(xSemaphoreTake(Count,portMAX_DELAY) == pdTRUE) {MyPrintf("按键按下,获取到信号量\r\n");}else{MyPrintf("获取到信号量等待超时\r\n");}printf("i=%d\r\n",i++);Led_Toggle(1);//printf("LED任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(NULL));
//	Delay_nms(200);//也能延时,但是会一直占用CPU//也是延时200ms,但是FreeRTOS提供的函数,有阻塞机制,能够让任务从运行态变为阻塞态vTaskDelay(1000);}
}
//任务本体 按键任务
TaskHandle_t KEY_TaskHandle;
void KEY_Task(void *p)
{uint8_t buff[2] = {0xAA,0x55};uint8_t buff2[2] = {0};MyPrintf("KEY_Task Begin\r\n");while(1){switch(key_getvalue()){case 1:if(xQueueSend(Queue,buff,100) == pdTRUE){printf("发送成功\r\n");}else{printf("队列已满,发送失败\r\n");}break;case 2:if(xQueueReceive(Queue,buff2,100)==pdTRUE){printf("接受数据:%x %x\r\n",buff2[0],buff2[1]);}else{printf("队列为空,接收失败\r\n");}break;case 3:xSemaphoreGive(Count);break;case 4: break;}vTaskDelay(10);//MS级别的延时,带有阻塞性质,任务会从运行态变为阻塞态}
}	int main()
{Led_Init();//初始化LEDKey_init();//初始化按键Usart1_Config();//初始化串口1ADC_Config();//初始化ADCKqm_U4Config();//初始化KQMDHT11_Mode();//初始化DHT11BaseType_t Ret = pdPASS;//创建一个二值信号量Binary = xSemaphoreCreateBinary();//创建一个计数信号量Count = xSemaphoreCreateCounting(10,5);//创建互斥锁Mutex = xSemaphoreCreateMutex();//创建队列 长度为10 ,队列中每个数据的大小2字节Queue = xQueueCreate(10,2);KqmQueue = xQueueCreate(1,8);//1,如何创建一个任务?Ret = xTaskCreate(Sensor_Task,"Sensor_Task",200,NULL,1,&Sensor_TaskHandle);
//	Ret = xTaskCreate(LED_Task, //创建任务的任务函数名
//                    "LED1_Toggle",//任务名字
//                    100,//任务栈深度。32位单片机*4
//                    NULL,//创建任务时传递参数,没有就给NULL
//                    1,//任务优先级
//										&LED_TaskHandle);//任务的句柄,用于后边删除,挂起任务
//	if(Ret == pdPASS){
//		printf("LED_Task创建完成\r\n");
//	}Ret = xTaskCreate(KEY_Task, //创建任务的任务函数名"KEY_Task",//任务名字100,//任务栈深度。32位单片机*4NULL,//创建任务时传递参数,没有就给NULL1,//任务优先级&KEY_TaskHandle);//任务的句柄,用于后边删除,挂起任务if(Ret == pdPASS){printf("KEY_Task创建完成\r\n");}printf("开启FreeRTOS调度器\r\n");//调度器启动完成之后,FreeRTOS会获取CPU控制权,会按照任务优先级执行创建的任务vTaskStartScheduler();printf("开启FreeRTOS调度器成功\r\n");while(1){	}
}void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{printf("任务:%s->栈溢出\r\n",pcTaskName);printf("任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(xTask));while(1)//栈溢出时卡死到钩子函数中{}
}

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

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

相关文章

二叉树 —— OJ题目详解

1.二叉树的前序遍历 二叉树的前序遍历比较简单,但是在力扣上写这个接口需要注意几个点: int* preorderTraversal(struct TreeNode* root, int* returnSize) {} preorderTraversal 的返回值是动态开辟的数组,里面存放的是前序遍历的顺序int*…

【Linux取经之路】Linux常见指令

目录 基本指令 常见指令 1)ls —— 对于目录,列出该目录下的所有子目录和文件;对于文件,将列出文件名及其他信息 2)pwd —— 显示当前所在的目录 ​编辑 3)cd —— 切换到指定路径下 4)t…

itextpdf字体选择

itextpdf 版本7.2.5 itextpdf-html2pdf 版本4.0.5 这里讲的是通过html转pdf,在html2pdf中是通过html中font-family样式来确定字体的,那已知font-family的情况,怎么确定pdf中实际用的字体,大致分为两步: 1、通过font…

识别 TON 生态系统中前10种加密资产,以bitget 钱包为例

元描述:想要找到下一个 100 倍加密货币投资?请密切关注这篇文章;它揭示了所有可能很快变得非常有价值的 TON 网络宝石。 由 Telegram 提供支持的 TON(开放网络)生态系统正在蓬勃发展!这是一个充满激动人心的…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【25】【分布式事务】

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【25】【分布式事务】 本地事务事务的基本性质事务的隔离级别(下面四个越往下,隔离级 别越高,并发能力越差)事务的传播行为(是否…

【Hive SQL 每日一题】找出各个商品销售额的中位数

文章目录 测试数据需求说明需求实现方法1 —— 升序计算法方法2 —— 正反排序法 补充 测试数据 -- 创建 orders 表 DROP TABLE IF EXISTS orders; CREATE TABLE orders (order_id INT,product_id INT,order_date STRING,amount DOUBLE );-- 插入 orders 数据 INSERT INTO ord…

软件工程课设——成绩管理系统

软件工程课设——成绩管理系统 该文档是软件工程课程设计,成绩管理子系统的开发模块仓库。 功能分析 从面向的用户分,成绩管理子系统主要面向三类用户,即至少需要满足这三类用户的需求: 学生:学生是成绩管理系统的…

深入理解 Git Reset 的三种模式及其使用场景

🍎个人博客:个人主页 🏆个人专栏:Android ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 1. --soft 模式 2. --mixed 模式(默认) 3. --hard 模式 总结 结语 我的其他博客 前言 在日常的开发…

机器学习-1:人工智能、机器学习和深度学习的关系

人工智能(AI) 简单理解,任何一种事物只要具备了一定的智能就可以把它归类为人工智能。 官方定义:"AI is the field that sdudies the synthesis and analysis of computational agents that act intelligently." 其中&a…

安卓学习中遇到的问题【bug】

安卓学习中遇到的问题 1Gradle下载慢怎么办? Gradle下载慢怎么办? distributionUrlhttps://mirrors.cloud.tencent.com/gradle/gradle-7.5-bin.zip 2 Could not resolve all files for configuration ‘:classpath‘. > Could not resolv…

uniapp-vue3-vite 搭建小程序、H5 项目模板

uniapp-vue3-vite 搭建小程序、H5 项目模板 特色准备拉取默认UniApp模板安装依赖启动项目测试结果 配置自动化导入安装依赖在vite.config.js中配置 引入 prerttier eslint stylelint.editorconfig.prettierrc.cjs.eslintrc.cjs.stylelintrc.cjs 引入 husky lint-staged com…

处理在 electron 中使用开启了懒加载的 el-image 后,窗口最大化或窗口尺寸变化后图片无法显示的问题

文章目录 1、问题描述2、详情动图3、解决思路4、解决方案5、效果展示 1、问题描述 在 electron 中使用 el-image 时,开启了懒加载后,发现只有当窗口滚动后,图片才会显示,即便图片已经处于窗口的可视区域。当拖动窗口使其尺寸变大…

基于JAVA+SpringBoot+Vue+uniapp+协同过滤算法+爬虫+AI的减肥小程序

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍: 小程序用户登录&#…

前端开发体系+html文件详解

目录 html骨架 body主体内基本元素 基本元素 超文本(超链接跳转) 锚点 图片标签 列表标签 表格标签 框架标签(窗口标签) 音频标签 视频标签 VScode编译器 输入框 字体样式 实例展示: 首先简要介绍前端的整…

在VS2017下FFmpeg+SDL编写最简单的视频播放器

1.下载ShiftMediaProject/FFmpeg 2.下载SDL2 3.新建VC控制台应用 3.配置include和lib 4.把FFmpeg和SDL的dll 复制到工程Debug目录下,并设置调试命令 5.复制一下mp4视频到工程Debug目录下(复制一份到*.vcxproj同一目录,用于调试) 6…

python中的re模块--正则表达式

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科 学的一个概念。正则表达式通常被用来检索、替换那些符合某个模 式(规则)的文本 re模块作用 通过使用…

JVM 内存介绍

本文主要介绍: JVM 内存分哪几个区,每个区的作用是什么 备注: 橙色:堆 和 方法区 ,属于jvm公有部分,可以进行调优 灰色:java栈,本地方法栈和计数器 属于jvm的私有部分,不可进行调优 一个对象从创建到被回收的过程是怎样的? Personpnew Perso…

【HarmonyOS】HarmonyOS NEXT学习日记:一、创建和运行一个页面

【HarmonyOS】HarmonyOS NEXT学习日记:一 DevEco Studio下载与安装 直接到官网的下载地址下载即可 正常下载、解压、安装完成后 正常来说不会有项目,并且是英文界面。 需要汉化的话可以按照下面的步骤设置插件 选择customize里的 all setting 进入…

macOS Sequoia 15(Macos15系统)v15.0 Beta 3发布 macOS Sequoia 15 功能预览

macOS Sequoia 15 功能预览 犀利一如 Mac macOS Sequoia 15(Macos15系统)v15.0 Beta 3测试版本下载安装 连续互通 你的 Mac 上,iPhone 用起来。 有了 iPhone 镜像功能,在 Mac 上就能看到 iPhone 屏幕画面,还能直接进行操控,不拿…

uniapp 实现上传文件的功能

上传单个文件 <script setup>const handleUploadClick () > {console.log("上传文件")uni.chooseImage({success: (chooseImageRes) > {const tempFilePaths chooseImageRes.tempFilePaths;console.log("用户选择的图片&#xff1a;", temp…