FreeRTOS源码分析-11 软件定时器

目录

1 软件定时器概念及其应用

1.1 软件定时器定义

1.2 FreeRTOS软件定时器介绍

 1.3 FreeRTOS软件定时器工作原理

2 软件定时器函数应用

2.1 功能需求

2.2 API

2.3 功能实现

3 软件定时器原理源码分析

3.1 软件定时器控制块

3.2 软件定时器任务&软件定时器创建

3.3 软件定时器启动&停止


1 软件定时器概念及其应用

1.1 软件定时器定义

问:为什么要有软件定时器?

因为硬件定时器的数量有限,所以会出现软件定时器这样的辅助功能。

提醒我们什么时间做什么事。

选择时间,重复模式等辅助实用功能。

智能化场景非常常见,使用软件定时器能大大减少cpu使用率。

1.2 FreeRTOS软件定时器介绍

到达时间后通过回调函数提供接口实现功能。

 1.3 FreeRTOS软件定时器工作原理

横坐标是tick值,软件定时器原理即定时器,可单次执行也可周期执行。

2 软件定时器函数应用

2.1 功能需求

  • 使用软件定时器功能完成闹钟功能设计(具体设计闹钟数量、重复模式、RTC)
  • 当闹钟到达时,可根据执行动作,触发相关的led亮灭

2.2 API

自动装载即是否重复闹钟

可以使用一个CallBack通过ID来实现不同ID的实现方法。

内部即消息队列的发送命令。

内部即消息队列的发送命令。

Reset和Start几乎没有区别

重点,修改完后会启动定时器,不需要Start或者Reset

2.3 功能实现

设计

 

实现

 现象

RTC相关CubeMX配置:使能外部低速时钟

 

命令解析、led控制创建两个任务和消息队列

Cmd针对RealTime和AlarmTIme

Led针对4个led灯解析

 软件定时器相关配置,周期性功能

2.3.1实时时钟功能实现 

//参考初始化代码void MX_RTC_Init改写void SetRTC(RTCTimeDates *pRTCTimeDate){if (HAL_RTC_SetTime(&hrtc, &pRTCTimeDate->RtcTime, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}if (HAL_RTC_SetDate(&hrtc, &pRTCTimeDate->RtcDate, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}
}RTCTimeDates GetRTC(void)
{RTCTimeDates	RTCTimeDate;if (HAL_RTC_GetTime(&hrtc, &RTCTimeDate.RtcTime, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}if (HAL_RTC_GetDate(&hrtc, &RTCTimeDate.RtcDate, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}printf("Real Time:%d-%d-%d %d:%d:%d\n",RTCTimeDate.RtcDate.Year + 2000,RTCTimeDate.RtcDate.Month,RTCTimeDate.RtcDate.Date,RTCTimeDate.RtcTime.Hours,RTCTimeDate.RtcTime.Minutes,RTCTimeDate.RtcTime.Seconds);return RTCTimeDate;}

 串口接收

void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 */uint8_t u8Data;//判断接收标志置位if(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE) == SET){//读取接收寄存器u8Data = huart1.Instance->DR;//进行入队操作xQueueSendFromISR(CmdQueueHandle,&u8Data,NULL);}/* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 *//* USER CODE END USART1_IRQn 1 */
}void Usart_Task(void const * argument)
{/* USER CODE BEGIN Usart_Task */uint8_t u8Index;/* Infinite loop */for(;;){//每次读取消息之前,把索引初始化为0u8Index = 0;//1、一直等待接收消息,第一个消息应该放在消息缓冲区的第一个元素上if(xQueueReceive(CmdQueueHandle,&u8CmdBuff[u8Index++],portMAX_DELAY)==pdPASS){while(xQueueReceive(CmdQueueHandle,&u8CmdBuff[u8Index++],50)){}u8CmdBuff[u8Index] = '\0';//保证一包完整字符串信息vCmdParseString(u8CmdBuff);//完成解析以后,要清空接收缓冲区,不然会出现问题memset(u8CmdBuff,0,MESSAGE_BUFF_SIZE);}}/* USER CODE END Usart_Task */
}

解析字符串

//解析串口命令字符串
void vCmdParseString(uint8_t *buff){//判断是否为实时时钟设置if(strncmp((char const*)buff,REALTIME,strlen(REALTIME)) == 0){ParseRealTimeString(buff);}//判断是否为闹钟设置else if(strncmp((char const*)buff,ALARMTIME,strlen(ALARMTIME)) == 0){ParseAlarmTimeString(buff);}}

解析实时时钟和闹钟

//计算闹钟与实时时钟之前的间隔时间,返回ms
uint32_t CountAlarmInterval(sAlarmTime AlarmTime){int32_t AlarmTimeTick,RealTimeTick;RTCTimeDates RTCTimeDate;//获取实时时钟RTCTimeDate = GetRTC();//计算闹钟ms计数AlarmTimeTick = AlarmTime.Hours*HT0MS+AlarmTime.Minutes*MT0MS+AlarmTime.Seconds*ST0MS;//计算实时时钟ms计数RealTimeTick = RTCTimeDate.RtcTime.Hours*HT0MS+RTCTimeDate.RtcTime.Minutes*MT0MS+RTCTimeDate.RtcTime.Seconds*ST0MS;printf("AlarmTimeTick = %lu\r\n",AlarmTimeTick);printf("RealTimeTick = %lu\r\n",RealTimeTick);//判断闹钟是否大于等于当前实时时钟//大于->返回闹钟-实时时钟if((AlarmTimeTick-RealTimeTick) >= 0){return AlarmTimeTick-RealTimeTick;}else{//小于->一天的ms值+实时时钟-返回闹钟return DT0MS+RealTimeTick-AlarmTimeTick;}}void ParseAlarmTimeString(uint8_t *buff){char *pbufftime;char *pbufftimeindex;char *pbuffparm;char *pbuffparmindex;uint32_t AlarmTick;TimerHandle_t xTimer;sAlarmTime AlarmTime;void SetRTC(RTCTimeDates *pRTCTimeDate);//获取闹钟时间字符串指针pbufftime = strstr((char const *)buff, ":");//获取闹钟参数字符串指针pbuffparm = strstr((char const *)buff, ",");if (pbufftime != NULL){//指针加1 取出正确的头指针pbufftime++;//取出正确的尾指针pbufftime = strtok(pbufftime, ",");//取出小时pbufftimeindex = strtok(pbufftime, ":");memcpy(AlarmTimeString.Hours, pbufftimeindex, strlen(pbufftimeindex));//取出分钟pbufftimeindex = strtok(NULL, ":");memcpy(AlarmTimeString.Minutes, pbufftimeindex, strlen(pbufftimeindex));//取出秒pbufftimeindex = strtok(NULL, ":");memcpy(AlarmTimeString.Seconds, pbufftimeindex, strlen(pbufftimeindex));}if (pbuffparm != NULL){//指针加1 取出正确的头指针pbuffparm++;//取出工作模式pbuffparmindex = strtok(pbuffparm, ",");memcpy(AlarmTimeString.Mode, pbuffparmindex, strlen(pbuffparmindex));//取出执行动作pbuffparmindex = strtok(NULL, ",");memcpy(AlarmTimeString.Action, pbuffparmindex, strlen(pbuffparmindex));}printf("设置闹钟系统时间为:%s:%s:%s\r\n",AlarmTimeString.Hours,AlarmTimeString.Minutes,AlarmTimeString.Seconds);    printf("设置闹钟工作模式为:%s\r\n",AlarmTimeString.Mode);   printf("设置闹钟执行动作为:%s\r\n",AlarmTimeString.Action); //转换字符串格式的闹钟参数为整型值AlarmTime.Hours = atoi((char const *)AlarmTimeString.Hours);AlarmTime.Minutes = atoi((char const *)AlarmTimeString.Minutes);AlarmTime.Seconds = atoi((char const *)AlarmTimeString.Seconds);AlarmTime.Mode = atoi((char const *)AlarmTimeString.Mode);AlarmTime.Action = atoi((char const *)AlarmTimeString.Action);//计数周期间隔AlarmTick = CountAlarmInterval(AlarmTime);printf("当前闹钟间隔为:%lu\r\n",AlarmTick);//创建定时器,传入间隔、工作模式、触发动作xTimer = xTimerCreate("timer",AlarmTick,AlarmTime.Mode,(void*)AlarmTime.Action,vTimerCallback);//判断定时器是否创建成功if(xTimer != NULL){//启动定时器xTimerStart(xTimer,0);printf("启动定时器成功!\r\n");}}//解析实时时钟字符串
void ParseRealTimeString(uint8_t *buff)
{char *pbuffdate;char *pbuffdateindex;char *pbufftime;char *pbufftimeindex;RTCTimeDates RTCTimeDate;//获取日期字符串指针pbuffdate = strstr((char const *)buff, ":");//获取时间字符串指针pbufftime = strstr((char const *)buff, ",");if (pbuffdate != NULL){//指针加1 取出正确的头指针pbuffdate++;//取出正确的尾指针pbuffdate = strtok(pbuffdate, ",");//取出年pbuffdateindex = strtok(pbuffdate, "-");memcpy(RealTimeString.Year, pbuffdateindex, strlen(pbuffdateindex));//取出月pbuffdateindex = strtok(NULL, "-");memcpy(RealTimeString.Month, pbuffdateindex, strlen(pbuffdateindex));//取出天pbuffdateindex = strtok(NULL, "-");memcpy(RealTimeString.Date, pbuffdateindex, strlen(pbuffdateindex));}if (pbufftime != NULL){//指针加1 取出正确的头指针pbufftime++;//取出小时pbufftimeindex = strtok(pbufftime, ":");memcpy(RealTimeString.Hours, pbufftimeindex, strlen(pbufftimeindex));//取出分钟pbufftimeindex = strtok(NULL, ":");memcpy(RealTimeString.Minutes, pbufftimeindex, strlen(pbufftimeindex));//取出秒pbufftimeindex = strtok(NULL, ":");memcpy(RealTimeString.Seconds, pbufftimeindex, strlen(pbufftimeindex));}printf("设置当前系统时间为:%s-%s-%s,%s:%s:%s\r\n",RealTimeString.Year,RealTimeString.Month,RealTimeString.Date,RealTimeString.Hours,RealTimeString.Minutes,RealTimeString.Seconds);//字符串转换为实时时钟值RTCTimeDate.RtcDate.Year = atoi((char const *)RealTimeString.Year) - 2000;RTCTimeDate.RtcDate.Month = atoi((char const *)RealTimeString.Month);RTCTimeDate.RtcDate.Date = atoi((char const *)RealTimeString.Date);RTCTimeDate.RtcTime.Hours = atoi((char const *)RealTimeString.Hours);RTCTimeDate.RtcTime.Minutes = atoi((char const *)RealTimeString.Minutes);RTCTimeDate.RtcTime.Seconds = atoi((char const *)RealTimeString.Seconds);//设置当前实时时钟SetRTC(&RTCTimeDate);
}

闹钟触发回调函数

//这个定义再Timer.c中,要再freertos.c中使用必须重新再定义
//主要因为需要针对控制块,进行重新装载if(((xTIMER*)pxTimer)->uxAutoReload){
typedef struct tmrTimerControl
{const char				*pcTimerName;		/*<< Text name.  This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ListItem_t				xTimerListItem;		/*<< Standard linked list item as used by all kernel features for event management. */TickType_t				xTimerPeriodInTicks;/*<< How quickly and often the timer expires. */UBaseType_t				uxAutoReload;		/*<< Set to pdTRUE if the timer should be automatically restarted once expired.  Set to pdFALSE if the timer is, in effect, a one-shot timer. */void 					*pvTimerID;			/*<< An ID to identify the timer.  This allows the timer to be identified when the same callback is used for multiple timers. */TimerCallbackFunction_t	pxCallbackFunction;	/*<< The function that will be called when the timer expires. */#if( configUSE_TRACE_FACILITY == 1 )UBaseType_t			uxTimerNumber;		/*<< An ID assigned by trace tools such as FreeRTOS+Trace */#endif#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )uint8_t 			ucStaticallyAllocated; /*<< Set to pdTRUE if the timer was created statically so no attempt is made to free the memory again if the timer is later deleted. */#endif
} xTIMER;//闹钟触发的软件定时器,回调函数
void vTimerCallback(xTimerHandle pxTimer){uint32_t ulTimerID;uint8_t i;//获取当前定时器IDulTimerID = (uint32_t)pvTimerGetTimerID(pxTimer);//判断定时器工作模式,如果自动重载,则更新软件定时器周期if(((xTIMER*)pxTimer)->uxAutoReload){xTimerChangePeriodFromISR(pxTimer,DT0MS,NULL);printf("明天继续触发动作!!!\r\n");}printf("ulTimerID = %d\r\n",ulTimerID);//根据软件定时器ID号, 发送到led消息队列中for(i=0;i<strlen((char const*)LedCmdString[ulTimerID]);i++){xQueueSend(LedQueueHandle,&LedCmdString[ulTimerID][i],1);}}

问:如果不自动重载,直接更新软件定时器周期行不行?

不行,因为更新软件定时器周期,相当于重启定时器,本来只执行1次的,会重复执行。

LED接收任务

void vLedParseString(uint8_t *buff){uint8_t i;for(i=0;i<LED_NUM;i++){if(strcmp((char const*)buff,(char const*)OpenString[i]) == 0){HAL_GPIO_WritePin(LedPort[i], LedPin[i], GPIO_PIN_RESET);printf("Cmd is %s\n",OpenString[i]);return;}}for(i=0;i<LED_NUM;i++){if(strcmp((char const*)buff,(char const*)CloseString[i]) == 0){HAL_GPIO_WritePin(LedPort[i], LedPin[i], GPIO_PIN_SET);printf("Cmd is %s\n",CloseString[i]);return;}}}
/*** @brief  Function implementing the LedTask thread.* @param  argument: Not used * @retval None*/
/* USER CODE END Header_Led_Task */
void Led_Task(void const * argument)
{/* USER CODE BEGIN Led_Task */uint8_t u8Index;osTimerStart(RrcTimerHandle,1000);/* Infinite loop */for(;;){//每次读取消息之前,把索引初始化为0u8Index = 0;//1、一直等待接收消息,第一个消息应该放在消息缓冲区的第一个元素上if(xQueueReceive(LedQueueHandle,&u8LedMessageBuff[u8Index++],portMAX_DELAY)==pdPASS){while(xQueueReceive(LedQueueHandle,&u8LedMessageBuff[u8Index++],50)){}u8LedMessageBuff[u8Index] = '\0';//保证一包完整字符串信息vLedParseString(u8LedMessageBuff);//完成解析以后,要清空接收缓冲区,不然会出现问题memset(u8LedMessageBuff,0,MESSAGE_BUFF_SIZE);}	}/* USER CODE END Led_Task */
}

3 软件定时器原理源码分析

3.1 软件定时器控制块

typedef struct tmrTimerQueueMessage
{BaseType_t			xMessageID;			union{TimerParameter_t xTimerParameters;#if ( INCLUDE_xTimerPendFunctionCall == 1 )CallbackParameters_t xCallbackParameters;#endif /* INCLUDE_xTimerPendFunctionCall */} u;
} DaemonTaskMessage_t;typedef struct tmrTimerParameters
{TickType_t			xMessageValue;		/*一个可选值,例如,传入更改计时器的周期*/Timer_t *			pxTimer;			/*<< The timer to which the command will be applied. */
} TimerParameter_t;typedef struct tmrCallbackParameters
{PendedFunction_t	pxCallbackFunction;	/* << The callback function to execute. */void *pvParameter1;						// 如事件标志组句柄uint32_t ulParameter2;					// 如事件标志组位信息 
} CallbackParameters_t;typedef struct tmrTimerControl
{const char				*pcTimerName;		//名称而已ListItem_t				xTimerListItem;		//列表项TickType_t				xTimerPeriodInTicks;//计时周期UBaseType_t				uxAutoReload;		//pdTRUE:自动装载pdFALSE:单次计时void 					*pvTimerID;			//ID号,方便回调识别TimerCallbackFunction_t	pxCallbackFunction;	//计时器到期时将被调用的函数} xTIMER;

3.2 软件定时器任务&软件定时器创建

 问:为什么创建两个列表

在systick中,tick值时u32,在不断累加到一定程度会溢出。那么之前活动列表就会出现错误,所以每当溢出得时候,就要进行列表得切换,所以创建了2个列表,防止程序出错。

BaseType_t xTimerCreateTimerTask( void )
{
BaseType_t xReturn = pdFAIL;/* 1、检查 软件定时器列表和队列2、如果没有创建内存空间,需要新建*/prvCheckForValidListAndQueue();if( xTimerQueue != NULL ){#else{//为了满足软件定时器的实时性,软件定时器任务的优先级最高,其实就是最大值xReturn = xTaskCreate(	prvTimerTask,"Tmr Svc",configTIMER_TASK_STACK_DEPTH,NULL,( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,&xTimerTaskHandle );}#endif /* configSUPPORT_STATIC_ALLOCATION */}else{mtCOVERAGE_TEST_MARKER();}configASSERT( xReturn );return xReturn;
}static void prvCheckForValidListAndQueue( void )
{taskENTER_CRITICAL();{//如果队列为空,则进行列表的初始化和队列的创建if( xTimerQueue == NULL ){vListInitialise( &xActiveTimerList1 );vListInitialise( &xActiveTimerList2 );pxCurrentTimerList = &xActiveTimerList1;pxOverflowTimerList = &xActiveTimerList2;//创建消息队列/*消息队列参数:1、configTIMER_QUEUE_LENGTH ------软件定时器 队列长度  102、DaemonTaskMessage_t   ------整个软件定时器消息的大小*/{xTimerQueue = xQueueCreate( ( UBaseType_t ) configTIMER_QUEUE_LENGTH, sizeof( DaemonTaskMessage_t ) );}#endif}else{mtCOVERAGE_TEST_MARKER();}}taskEXIT_CRITICAL();
}

即初始化值

	TimerHandle_t xTimerCreate(	const char * const pcTimerName,const TickType_t xTimerPeriodInTicks,const UBaseType_t uxAutoReload,void * const pvTimerID,TimerCallbackFunction_t pxCallbackFunction ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */{Timer_t *pxNewTimer;//动态分配 软件定时器控制块内存空间pxNewTimer = ( Timer_t * ) pvPortMalloc( sizeof( Timer_t ) );if( pxNewTimer != NULL ){//进入控制初始化prvInitialiseNewTimer( pcTimerName, xTimerPeriodInTicks, uxAutoReload, pvTimerID, pxCallbackFunction, pxNewTimer );}return pxNewTimer;}static void prvInitialiseNewTimer(	const char * const pcTimerName,const TickType_t xTimerPeriodInTicks,const UBaseType_t uxAutoReload,void * const pvTimerID,TimerCallbackFunction_t pxCallbackFunction,Timer_t *pxNewTimer ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
{/* 0 is not a valid value for xTimerPeriodInTicks. */configASSERT( ( xTimerPeriodInTicks > 0 ) );if( pxNewTimer != NULL ){/* 再次判断是否已经创建 队列 初始化了列表 */prvCheckForValidListAndQueue();/*1、进行软件定时器控制块信息的赋值2、把当前软件定时器列表项初始化,便于以后使用*/pxNewTimer->pcTimerName = pcTimerName;pxNewTimer->xTimerPeriodInTicks = xTimerPeriodInTicks;pxNewTimer->uxAutoReload = uxAutoReload;pxNewTimer->pvTimerID = pvTimerID;pxNewTimer->pxCallbackFunction = pxCallbackFunction;vListInitialiseItem( &( pxNewTimer->xTimerListItem ) );traceTIMER_CREATE( pxNewTimer );}
}

3.3 软件定时器启动&停止

#define xTimerStart( xTimer, xTicksToWait ) 
/*参数:1、软件定时器句柄2、定义Start编号3、当前的系统的Tick值4、null5、阻塞等待时间
*/
xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )#define xTimerStop( xTimer, xTicksToWait )
/*参数:1、软件定时器句柄2、定义Stop编号3、0 不需要传入消息4、null5、阻塞等待时间
*/
xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) )#define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) 
/*参数:1、软件定时器句柄2、定义CHANGE编号3、xNewPeriod 用于改变新的周期4、null5、阻塞等待时间
*/
xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) )BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait )
{
BaseType_t xReturn = pdFAIL;
DaemonTaskMessage_t xMessage;if( xTimerQueue != NULL ){/* 1、xCommandID  用于标识 触发的类型 比如start2、xOptionalValue = xTaskGetTickCount在start时,才是软件定时器的真正启动,内部参考systick,这个时候要传入一个初值,才能计算3、xTimer  要操作的软件定时器的句柄*/xMessage.xMessageID = xCommandID;xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer;//判断命令类型if( xCommandID < tmrFIRST_FROM_ISR_COMMAND ){//判断调度器状态if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING ){xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );}else{xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY );}}else{xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );}traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn );}else{mtCOVERAGE_TEST_MARKER();}return xReturn;
}

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

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

相关文章

EIK+Filebeat+Kafka

目录 一、Kafka 概述 1&#xff09;为什么需要消息队列&#xff08;MQ&#xff09; 2&#xff09;使用消息队列的好处 &#xff08;1&#xff09;解耦 &#xff08;2&#xff09;可恢复性 &#xff08;3&#xff09;缓冲 &#xff08;4&#xff09;灵活性 & 峰值处理…

C++笔记之回调函数的演变

C笔记之回调函数的演变 code review! 文章目录 C笔记之回调函数的演变1.使用函数指针2.使用typedef加函数指针3.使用std::using加函数指针4.使用typedef加std::function5.使用std::using加std::function6.使用回调和不使用回调对比 1.使用函数指针 代码 #include <iostre…

【笔试训练】统计回文

一、单选 1、以下代码结果是什么&#xff08;&#xff09; public class foo {public static void main(String sgf[]) {StringBuffer anew StringBuffer("A");StringBuffer bnew StringBuffer("B");operate(a,b);System.out.println(a"."b);}st…

ffmpeg+intel核显实现硬解码

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、前言二、检查方法1.图形法2.nvidia-smi3.intel-gpu-tools 三、安装使用1.libva-dev2.libva-utils3.编译安装4.测试1.vainfo2.ffmpeg测试解码 总结 前言 之…

nuxt.js框架使用

1、这种框架只要页面有一个地方错&#xff0c;都会出现404或者吓人的报错界面。 如表单的prop属性&#xff0c;在data函数return对象里面该字段找不到或者不一致&#xff0c;就会报404。 2、使用字典&#xff0c;对字典进行翻译。 在plugins/methods.js文件里面&#xff0c;加…

电脑连接安卓设备显示offline

The Android is offline. This can be resolved by physically disconnecting and...用USB线连接手机和电脑&#xff0c;打开cmd&#xff0c;输入adb devices -l, adb devices -l结果显示可以识别手机&#xff0c;但是状态为offline 打开另外一个终端&#xff0c;输入 adb k…

Spring MVC程序开发

目录 1. 什么是Spring MVC? 1.1 什么是MVC 1.2 MVC和Spring MVC 的关系 1.3 为什么要学Spring MVC? 2. Spring MVC的使用 2.1 Spring MVC的创建和连接 2.1.1 项目创建 2.1.2 项目连接 2.1.2.1 连接 2.1.2.2 RequestMapping注解介绍 2.1.2.3 GetMapping和 PostMapping 2.2 获取…

EFLFK——ELK日志分析系统+kafka+filebeat架构

环境准备 node1节点192.168.40.16elasticsearch2c/4Gnode2节点192.168.40.17elasticsearch2c/4GApache节点192.168.40.170logstash/Apache/kibana2c/4Gfilebeat节点192.168.40.20filebeat2c/4G https://blog.csdn.net/m0_57554344/article/details/132059066?spm1001.2014.30…

【生成式AI】ProlificDreamer论文阅读

ProlificDreamer 论文阅读 Project指路&#xff1a;https://ml.cs.tsinghua.edu.cn/prolificdreamer/ 论文简介&#xff1a;截止2023/8/10&#xff0c;text-to-3D的baseline SOTA&#xff0c;提出了VSD优化方法 前置芝士:text-to-3D任务简介 text-to-3D Problem text-to-3D…

实例035 动画形式的程序界面

实例说明 在很多的程序界面中&#xff0c;都是以菜单或工具栏的形式显示窗体界面&#xff0c;这种显示方式是以静止状态显示的&#xff0c;界面不够生动。下面介绍一个以动画显示窗体界面的设计方法。运行本例&#xff0c;效果如图1.35所示。 技术要点 在该实例中用到了Micr…

配置nginx服务端口时-在同一个页面中打开多个地址端口-查看服务情况

1&#xff1a;把代码保存到xxx.html文件中 2&#xff1a;因为一个个端口打开查看&#xff0c;实在太麻烦了 3&#xff1a;在一个页面中查看多页的响应才能提高测试效率 <html><head><title>本地连接列表</title> </head><body><cente…

Java课题笔记~ HTTP协议(请求和响应)

Servlet最主要的作用就是处理客户端请求&#xff0c;并向客户端做出响应。为此&#xff0c;针对Servlet的每次请求&#xff0c;Web服务器在调用service()方法之前&#xff0c;都会创建两个对象 分别是HttpServletRequest和HttpServletResponse。 其中HttpServletRequest用于封…

shapely库的用法,高效处理点、线、面的几何关系和相关延申(GeoPandas 库)python

1、shapely库的基本用法 Shapely 是一个用于处理几何对象的 Python 库&#xff0c;它提供了各种函数和方法来进行空间分析和几何计算。下面是一些 Shapely 库的常见用法示例&#xff1a; 1. 创建几何对象&#xff1a; from shapely.geometry import Point, LineString, Poly…

【Flutter】【基础】CustomPaint 绘画功能,绘制各种图形(二)

CustomPaint 使用实例和代码&#xff1a; 1.canvas.drawColor 绘制背景颜色 class MyPainter1 extends CustomPainter {overridevoid paint(Canvas canvas, Size size) {//绘制背景颜色&#xff0c;整个UI 现在就是红色的canvas.drawColor(Colors.red, BlendMode.srcATop);}…

Maven安装与配置

目录 一、Maven简介1.1 概述1.2 作用1.3 仓库 二、安装三、配置3.1 配置环境变量3.2 环境变量测试3.3 配置仓库 一、Maven简介 1.1 概述 Maven是一个开源的项目管理工具&#xff0c;用于构建和管理Java项目&#xff0c;基于项目对象模型&#xff08;POM&#xff09;的概念。它…

数据库优化脚本执行报错

目录 一、执行数据库优化脚本 报错... 3 解决方法&#xff1a;... 4 1、直接注释掉RECYCLE_POOLS 赋值sql语句块... 4 2、手动修改脚本... 5 附录... 6 一、执行数据库优化脚本 报错 AutoParaAdj3.5_dm8.sql 1&#xff09;manager中报错 -20001: 执行失败, -7065 数据未…

青大数据结构【2015】

一、单选 二、简答 5.如果一组关键字&#xff0c;以不同的次序输入后建立起来的二叉排序树是否相同&#xff1f;当中序遍历这些二叉排序树时&#xff0c;其遍历的结果是否相同&#xff1f;为什么&#xff1f; 不同&#xff0c;因为输入次序不同&#xff0c;所放置的位置与上一…

Stable Diffusion - 俯视 (from below) 拍摄的人物图像 LoRA 与配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132192139 图像来自 哥特风格 LoRA 俯视 LoRA&#xff0c;提升视觉冲击力&#xff0c;核心配置 <lora:view_from_below:0.6>,(from below,…

时间复杂度与空间复杂度的详解

目录 1.时间复杂度 2.时间复杂度计算例题 3.空间复杂度 1.时间复杂度 算法中的基本操作的执行次数&#xff0c;为算法的时间复杂度。 如何表达 时间复杂度&#xff1f; 大O的渐进表示法 实际中我们计算时间复杂度时&#xff0c;我们其实并不一定要计算精确的执行次数&#xf…

nginx基于源码安装的方式对静态页面、虚拟主机(IP、端口、域名)和日志文件进行配置

一.静态页面 1.更改页面内容 2.更改配置文件 3.测试 二.虚拟主机配置 1.基于IP &#xff08;1&#xff09;在html目录下新建目录存放测试文件 &#xff08;2&#xff09;修改nginx.conf文件&#xff0c;在htttp模块中配置两个server模块分别对应两个IP &#xff08;3&am…