FreeRTOS记录(八、用软件定时器?还是硬件定时器?)

2023-10-27

FreeRTOS软件定时器,相对前面的内容来说,软件定时器还是比较简单的,我们简单测试一下
因为是简单介绍,所以原理和源码的分析不会那么详细,具体可以根据文中API查看源码
使用起来记住创建,启动,回调函数核心步骤即可
..增加测试Demo,再次遇到溢出问题说明,定时器数量问题说明				  2021/12/2

问:什么时候使用软件定时器,什么时候使用硬件定时器?

软件定时器可以解决硬件定时器数量不够的问题,理论上软件定时器可以很多,每个芯片的定时器外设是有限的,如果硬件定时器不够用,可以使用软件定时器。

但是,软件定时器相对硬件定时器来说,精度没有那么高(为什么不高?因为它以系统时钟为基准,系统时钟中断优先级又是最低,容易被打断)。 对于需要高精度要求的场合,不建议使用软件定时器。

同时软件定时器 是需要占用一部分内存空间的,用到的软件定时器数量越多,内存占用越大。 如果RAM空间不够用,不能使用软件定时器。

当然,使用软件定时器的程序还有一个好处就是方便移植,不同芯片的硬件定时器的设置代码是不一样的,在条件允许的情况下使用软件定时器,那么不同平台之间的的代码移植起来相对方便一点。

一、FreeRTOS软件定时器基础

1.1 时钟来源

系统的时钟周期,对于FreeRTOS而言,就是 TICK_RATE_HZ 对应的值。在以上的测试我们使用都是设置为默认的1000,那么系统的时钟节拍周期就为 1ms(1s 跳动 1000 下,每一下就为 1ms)。

1.2 运行原理

FreeRTOS 所创建的软件定时器共用一个任务prvTimerTask(也叫守护任务 Daemon)和队列,定时器处理API函数最终都是通过给队列发送信息,在任务中接收处理。

创建prvTimerTask任务:
在这里插入图片描述

在文章 FreeRTOS记录(六、FreeRTOS消息队列—Enocean模块串口通讯、RAM空间不足问题分析) 中的 第 5小结:5 、RAM空间不足问题 中讲到过只要使能了使用定时器,系统就会自动产生一个任务,占用内存空间,说的就是这个任务:
在这里插入图片描述

prvTimerTask任务:

  • 优先级为我们定时器的配置 configTIMER_TASK_PRIORITY

  • 任务的堆栈大小为 configTIMER_TASK_STACK_DEPTH

队列:

  • 队列的长度由配置 configTIMER_QUEUE_LENGTH 决定

prvTimerTask任务会在其执行期间检查用户启动的时间周期溢出的定时器,并调用其回调函数。在任务中最后会调用prvProcessReceivedCommands();函数:
在这里插入图片描述
定时器消息队列的命令在这个函数中进行处理:
在这里插入图片描述

在定时器创建好了以后,定时器并不会运行。在prvTimerTask任务中,如果暂时没有运行中的定时器,任务会进入阻塞态等待命令。 使用xTimerStart才会开始定时器的运行,启动函数通过“定时器命令队列” 向定时器任务发送一个启动命令,这个命令最终就在prvProcessReceivedCommands();函数中解析,定时器任务获得命令就解除阻塞,然后执行启动软件定时器命令。

1.3 使用注意事项

  • 软件定时器的定时时间必须是系统时钟周期的整数倍,如果我们定义的 TICK_RATE_HZ 为100,系统的时钟周期为10ms,必须为10的整数倍。那么5ms,15ms的延时是无法实现的。

  • 软件定时器使用了系统的一个队列和一个任务资源,软件定时器任务的优先级默认为configTIMER_TASK_PRIORITY,为了更好响应,该优先级应设置为所有任务中最高的优先级

  • 软件定时器的回调函数中应快进快出,切不可在定时器回调函数中调用任何将定时器任务挂起的函数,比如vTaskDelay(), vTaskDelayUntil()以及非零延迟的消息队列和信号量相关的函数,也绝对不允许出现死循环。

二、API介绍

FreeRTOS软件定时器的API所有的都可以在FreeRTOS驱动文件timers.h文件中找到,这里介绍常用的基本的几个:

2.1 创建定时器

  • xTimerCreate()xTimerCreateStatic()

创建以 xTimerCreate()为例介绍:

TimerHandle_t xTimerCreate
				 ( const char * const pcTimerName, /* 定时器名字,方便识别不同的定时器 */
				 const TickType_t xTimerPeriod, /* 定时器周期,单位系统时钟节拍 */
				 const UBaseType_t uxAutoReload, /* 若参数为 pdTRUE,则表示选择周期模式,
				 									若参数为pdFALSE,则表示选择单次模式 */
				 void * const pvTimerID, /* 创建不同的定时器,但使用相同的回调函数时,
				 							在回调函数中通过不同的ID 号来区分不同的定时器。 */
				 TimerCallbackFunction_t pxCallbackFunction ); /* 定时器回调函数 */

...
void pxCallbackFunction (xTimerHandle pxTimer){...}

在CubeMX中封装后的函数为osTimerCreate
在这里插入图片描述

2.2 开始定时器(为什么开启定时器还需要等待时间)

  • xTimerStart()xTimerStartFromISR()

xTimerStart():

BaseType_t xTimerStart( TimerHandle_t xTimer, /* 定时器句柄 */
									 TickType_t xBlockTime ); /* 成功启动定时器前的最大等待时间设置,单位系统时钟节拍 
									 						 如果在 FreeRTOS 调度器开启之前调用 xTimerStart(),该形参将不起作用*/

说明:为什么开启定时器还需要等待时间?

前面 运行原理 已经介绍过,FreeRTOS的软件定时器是通过消息队列给定时器任务发消息来实现的,此参数设置的等待时间就是当消息队列已经满的情况下,等待消息队列有空间时的最大等待时间。

定时器任务实际执行消息队列发来的命令依赖于定时器任务的优先级,如果定时器任务是高优先级会及时得到执行,如果是低优先级,就要等待其余高优先级任务释放 CPU 权才可以得到执行。

对于已经被激活的定时器,即调用过函数 xTimerStart进行启动,再次调用此函数相当于调用了函数xTimerReset对定时器时间进行了复位。

如果在启动 FreeRTOS 调度器前调用了此函数,定时器是不会立即执行的,需要等到启动了 FreeRTOS调度器才会得到执行,即从此刻开始计时,达到xTimerCreate 中设置的单次或者周期性延迟时间才 会执行相应的回调函数。

xTimerStartFromISR():

/*******************************************************************************************************
  *@ 函数功能:在中断中启动一个软件定时器。
  
  *@ 函数参数:xTimer:软件定时器句柄  
  		pxHigherPriorityTaskWoken:定时器守护任务的大部分时间都在阻塞态等待定时器命令队列的命令。 
     调用函数 xTimerStartFromISR()将会往定时器的命令队列发送一个启动命令,这很有可能会将定时器任务从阻塞除。 
     如果调用函数xTimerStartFromISR()让定时器任务脱离阻塞态, 
     且定时器守护任务的优先级大于或者等于当前被中断的任务的优先级,
     那么 pxHigherPriorityTaskWoken 的值会在函数xTimerStartFromISR()内部设置为 pdTRUE,
     然后在中断退出之前执行一次上下文切换。
		pxHigherPriorityTaskWoken:pxHigherPriorityTaskWoken 在使用之前必须初始化成pdFALSE。
	调用xEventGroupSetBitsFromISR()会给守护任务发送一个消息,
	如果守护任务的优先级高于当前被中断的任务的优先级的话
	(一般情况下都需要将守护任务的优先级设置为所有任务中最高优先级),
	pxHigherPriorityTaskWoken 会被置为 pdTRUE, 然后在中断退出前执行一次上下文切换。
	
  *@ 返回值:如果启动命令无法成功地发送到定时器命令队列则返回 pdFAILE,成功发送则返回pdPASS。
			 软件定时器成功发送的命令是否真正的被执行也还要看定时器守护任务的优先级,
			 其优先级由宏 configTIMER_TASK_PRIORITY 定义。
*******************************************************************************************************/
#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken )    xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR,( xTaskGetTickCountFromISR() ),( pxHigherPriorityTaskWoken ), 0U )

2.3 获取定时器ID

  • pvTimerGetTimerID
void *pvTimerGetTimerID( const TimerHandle_t xTimer ) /* 定时器句柄 */

2.4 停止/删除定时器

  • xTimerStop()xTimerStopFromISR()

xTimerStop():

/*******************************************************************************************************
  *@ 函数功能:停止一个软件定时器, 让其进入休眠态。
  *@ 函数参数:xTimer:软件定时器句柄
               xBlockTime:用户指定超时时间, 单位为系统节拍周期(即 tick)。 
               如果在 FreeRTOS 调度器开启之前调用 xTimerStart(),形参将不起作用。
  *@ 返回值:
  如果启动命令在超时时间之前无法成功地发送到定时器命令队列则返回 pdFAILE,成功发送则返回 pdPASS。
  软件定时器成功发送的命令是否真正的被执行也还要看定时器守护任务的优先级,
  其优先级由宏 configTIMER_TASK_PRIORITY 定义。
*******************************************************************************************************/
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xBlockTime );

xTimerStopFromISR():

/*******************************************************************************************************
  *@ 函数功能:在中断中停止一个软件定时器, 让其进入休眠态。
  *@ 函数参数:xTimer:软件定时器句柄
       pxHigherPriorityTaskWoken:定时器守护任务的大部分时间都在阻塞态等待定时器命令队列的命令。
       调用函数 xTimerStopFromISR()将会往定时器的命令队列发送一个停止命令,
       这很有可能会将定时器任务从阻塞态移除 。 
       如果调用函数xTimerStopFromISR()让定时器任务脱离阻塞态,
       且定时器守护任务的优先级大于或者等于当前被中断的任务的优先级,
       那么 pxHigherPriorityTaskWoken 的值会在函数xTimerStopFromISR()内部设置为 pdTRUE, 
       然后在中断退出之前执行一次上下文切换。
  *@ 返回值:
 	 如果停止命令在超时时间之前无法成功地发送到定时器命令队列则返回pdFAILE,成功发送则返回 pdPASS。 
	 软件定时器成功发送的命令是否真正的被执行也还要看定时器守护任务的优先级,
	 其优先级由宏 configTIMER_TASK_PRIORITY 定义。
*******************************************************************************************************/
BaseType_t xTimerStopFromISR(TimerHandle_t xTimer,BaseType_t *pxHigherPriorityTaskWoken);
  • xTimerDelete()
/*******************************************************************************************************
  *@ 函数功能:删除一个已经被创建成功的软件定时器
  *@ 函数参数:xTimer:软件定时器句柄
              xBlockTime:用户指定的超时时间, 单位为系统节拍周期(即 tick), 
              如果在 FreeRTOS调度器开启之前调用 xTimerStart(), 该形参将不起作用。
  *@ 返回值:如果删除命令在超时时间之前无法成功地发送到定时器命令队列则返回 pdFAILE, 成功发送则返回 pdPASS。
*******************************************************************************************************/
#define xTimerDelete( xTimer, xTicksToWait )    xTimerGenericCommand( ( xTimer ),tmrCOMMAND_DELETE,0U, NULL, ( xTicksToWait ) )

三、测试Demo

3.1 简单测试

在CubeMX中定时器配置:
在这里插入图片描述

添加软件定时器:
在这里插入图片描述

程序设计:

  1. 生成的代码中需要定义一下 ID(上图的Parameter是NULL的,后来我改成了no1 和 no2,需要对no1 和 no2定义一下);
  2. 不能在调度前使用xTimerStart() 函数,所以单独创建了一个任务启动定时器,然后删除;
  3. 回调函数中发送任务通知给温湿度读取任务;
  4. 温湿度读取任务接收任务通知执行任务;
/*1.定义一下 ID*/
	#define no1 1
	#define no2 2
	..
  /* Create the timer(s) */
  /* definition and creation of myTimer01 */
  osTimerDef(myTimer01, myTimeCallback);
  myTimer01Handle = osTimerCreate(osTimer(myTimer01), osTimerOnce, (void*) no1);

  /* definition and creation of myTimer02 */
  osTimerDef(myTimer02, myTimeCallback);
  myTimer02Handle = osTimerCreate(osTimer(myTimer02), osTimerPeriodic, (void*) no2);

...

/*2.创建了一个任务启动定时器*/
/* USER CODE END Header_StartTimerTask */
void StartTimerTask(void const * argument)
{
  /* USER CODE BEGIN StartTimerTask */
  /* Infinite loop */
  for(;;)
  {
    osTimerStart(myTimer01Handle,5000);
    osTimerStart(myTimer02Handle,3000);
    vTaskDelete(NULL);
    osDelay(1);
  }
  /* USER CODE END StartTimerTask */
}
...

/* 
myTimeCallback function 
3.回调函数中发送任务通知给温湿度读取任务
测试用,实际使用不能加printf在回调函数
*/
void myTimeCallback(void const * argument)
{
  /* USER CODE BEGIN myTimeCallback */
  uint8_t myTimerID;
  myTimerID = (uint8_t)pvTimerGetTimerID(argument);
  
  if (myTimerID == no1)
  {
    osSignalSet(THreadHandle,test_signal1);
    printf("ulTimerID = %d,send a Signal_1 to threadtask!\r\n",myTimerID);
  }
  else if(myTimerID == no2){
    osSignalSet(THreadHandle,test_signal2); 
    printf("ulTimerID = %d,send a Signal_2 to threadtask!\r\n",myTimerID);
  } 
  /* USER CODE END myTimeCallback */
}
	
/*4、温湿度读取函数,还是老样子,和第FreeRTOS记录(5、任务通知)中的函数一样*/	
...

3.1.1 再遇溢出问题

本来是个简单的测试,测试结束完结散花,没想到又遇到了溢出问题:
在这里插入图片描述
遇到这个问题那可就不能不管了,为了项目中能够更加合理的分配RAM空间,问题必须深究到底!!!
问题一点一点剥开来测试!!!

我们看一下溢出情况下 定时器控制任务的 情况:
在这里插入图片描述
在CubeMX中能看到2个定时器需要的内存大小(目前的设置的configTIMER_TASK_STACK_DEPTH 的大小为 128 字,512Bytes)这样子看的话足够用的啊?:
在这里插入图片描述
接下来测试,把 configTIMER_TASK_STACK_DEPTH 改成 256 字后,运行起来是正常的:
在这里插入图片描述
此时再来看一下任务栈剩余情况(开始剩余2字,多了128字,剩余130,这点OK!):
在这里插入图片描述

那我始终觉得128字,应该是足够了,我把 configTIMER_TASK_STACK_DEPTH 改回128字,把myTimeCallback函数中的 printf 语句去掉,因为正常使用肯定不能带的(快进快出):
在这里插入图片描述
测试是能够正常工作的(128字去掉printf的情况下)看任务栈剩余结果:
在这里插入图片描述

还有测试Demo中我们创建了2个定时器,定时器创建完了就占用了内存空间,其中有一个单次的定时器,虽然只运行一次,但是他只是出于休眠状态,随时可以启动运行(虽然每次都是运行一次),如果我们只想他开机运行一次,那么我们可以在回调函数中删除此定时器,那么其所占用的内存就会释放:
在这里插入图片描述
测试结果:
在这里插入图片描述
通过上面我们也可以算出,定时器1占用了 78-26=52 字的空间。

3.1.2 定时器数量问题

可创建的软件定时器的数量是由什么决定的呢?

这个问题推测是和定义的队列长度有关,因为一个队列可以控制一个定时器。

我们做如下测试,把队列的长度,configTIMER_QUEUE_LENGTH 改为1,然后再运行上述代码:

在这里插入图片描述

测试结果如下(下图中红色部分的疑问暂时未解决):

在这里插入图片描述
上面测试看上去好像是 configTIMER_QUEUE_LENGTH 为1的话只能有一个任务了,为了确定确实是这样,继续测试,configTIMER_QUEUE_LENGTH 改为2,添加第三个任务:

在这里插入图片描述
在这里插入图片描述
在回调函数中测试一下(下图定时器3的回调函数,printf忘了在后面跟打印的变量了,这里不影响结果,后面的测试我添加上去了):
在这里插入图片描述

测试结果如下:
在这里插入图片描述
那最后的测试就是,把 configTIMER_QUEUE_LENGTH 改成3,不出意外,3个定时器就能正常运行了:
在这里插入图片描述

测试结果如下:

在这里插入图片描述

问题:为什么3个定时器开启了,和2个定时器占用的栈空间一样?(未解决)

3.2 做一个时钟(待更新…)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS记录(八、用软件定时器?还是硬件定时器?) 的相关文章

  • 【FreeRTOS开发问题】FreeRTOS内存溢出

    FreeRTOS内存溢出 如下图所示 FreeRTOS编译完成后可以看到 系统提示无法分配内存到堆 Objects Template axf Error L6406E No space in execution regions with A
  • FreeRTOS系列

    1 RTOS简介 RTOS全称为 Real Time Operation System 即实时操作系统 RTOS强调的是实时性 又分为硬实时和软实时 硬实时要求在规定的时间内必须完成操作 不允许超时 而软实时里对处理过程超时的要求则没有很严
  • STM32移植FreeRTOS的Tips

    转自 http bbs armfly com read php tid 7140 1 在FreeRTOS的demo文件夹中拷贝对应的FreeRTOSConfig h文件后 需要加入一行 define configUSE MUTEXES 1
  • freeRTOS手册 第六章 . 中断管理

    如果我对本翻译内容享有所有权 允许任何人复制使用本文章 不会收取任何费用 如有平台向你收取费用与本人无任何关系 第六章 中断管理 章节介绍和范围 事件 嵌入式实时系统必需对环境中的事件做出响应 比如 外部网络设备收到一个发送给TCP IP栈
  • FreeRTOS_中断

    传送门 博客汇总帖 传送门 Cortex M3 中断 异常 传送门 Cortex M3笔记 基础 笔记内容参考 正点原子的FreeRTOS开发手册 cortex m3权威指南 Cortex M3和Cortex M4权威指南等 文中stm32
  • freertos————互斥锁

    线程安全 多线程程序处于一个多变的环境 可访问的全局变量和堆数据随时可能被其他的线程改变 多个线程同时访问一个共享数据 可能造成严重的后果 出现问题的是之前移植了一个freemodbus的从站 多个任务访问全局变量保持寄存器区 导致最后读出
  • 基于51单片机的时钟设计

    今天小刚做了一个基于51单片机的时钟 本来想把数码管显示动态扫描放到定时器1的中断里到但是 一按按键 就卡住了 效果不是很理想 所以就放弃了这种方案 不过最后也实现了功能 以下是程序代码 4个按键功能 1 切换 2 时间 3 时间 4 清零
  • FreeRTOS学习(三)开关中断

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 背景知识 Cotex M3的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽 NMI 1个Systick 滴答定时器 Cortex M处理
  • 啊哈C的简单使用

    打开啊哈C 新建一个程序输出hello world include
  • Arduino IDE将FreeRTOS用于STM32

    介绍 适用于STM32F103C8的FreeRTOS STM32F103C是一种能够使用FreeRTOS的ARM Cortex M3处理器 我们直接在Arduino IDE中开始使用STM32F103C8的FreeRTOS 我们也可以使用K
  • FreeRTOS死机原因

    1 中断回调函数中没有使用中断级API xxFromISR 函数 xSemaphoreGiveFromISR uart busy HighterTask 正确 xSemaphoreGive uart busy 错误 2 比configMAX
  • STM32定时器----TIMx->SR寄存器

    在研究stm32定时器时发现 当进入定时器的中断时 定时器计数器以及中断接收时正常运行的 并没有因为进入中断而停止 具体看以下分析 定时器初始化代码 TIM捕获通道开启宏定义 1 开启 0 关闭 define TIM ICCH1 1 def
  • FreeRTOS轻量级同步--任务通知

    1 简介 在FreeRTOS的配置参数中的configUSE TASK NOTIFICATIONS宏打开 一般RTOS会默认打开 如图1所示 图1 notify宏开关 RTOS在创建任务时 会创建一个32位的通知值ulNotifiedVal
  • 单片机通信数据延迟问题排查

    1 问题说明 笔者在最近的项目中 发现系统的响应延迟较高 经过排查 排除了单片机运行卡死的问题 2 原因分析 具体排查过程这里就不细致说明了 直接给出排查后原因 任务执行周期规划不合理 导致freertos队列发送接收到的命令有延迟 为了便
  • STM32 高级定时器周期、频率、占空比、对外输出电压详解

    STM32 高级定时器 最近在研究电机 对TIM定时器研究了一些 将一些存在疑惑的问题 通过试验和示波器分析 得到以下结论 供大家学习参考 1 介绍输出电压高低判断 输出比较时 OC1对外输出电压为示波器可以读取的电压 也是我们最终使用的电
  • C51单片机数码管动态显示

    数码管作为最廉价的输出设备 在各种自动化设备中有很大的应用 最简单普通的显示方式为动态刷新显示 称为假动态显示 即通过分时扫描每一位 利于人眼的视觉停留现象 造成一种静态显示的效果 如下图所示 C51单片机由于运行速度很慢 在高刷新频率下
  • FreeRTOSConfig.h 配置优化及深入

    本篇目标 基于上一篇的移植freertos stm32f4 freertos 上 修改 FreeRTOSConfig h 文件的相关配置来优化辅助 FreeRtos 的使用 并且建立一些基本功能 信号量 消息地列等 的简单应用位于 stm3
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • 如何更改 FreeRTOS 中任务的最大可用堆大小?

    我通过以下方式在任务中创建元素列表 l dllist pvPortMalloc sizeof dllist dlllist 有 32 字节大 我的嵌入式系统有 60kB SRAM 所以我希望系统可以轻松处理我的 200 个元素列表 我发现在
  • 如何将 void* 转换为函数指针?

    我在 FreeRTOS 中使用 xTaskCreate 其第四个参数 void const 是传递给新线程调用的函数的参数 void connect to foo void const task params void on connect

随机推荐

  • 1. 两数之和 C++

    给定一个整数数组 nums 和一个整数目标值 target 请你在该数组中找出 和为目标值 target 的那 两个 整数 并返回它们的数组下标 你可以假设每种输入只会对应一个答案 但是 数组中同一个元素在答案里不能重复出现 你可以按任意顺
  • 一文搞懂OC门、OD门及其作用

    我们先给出OC门 OD门的定义 然后从原理出发 介绍OC门 OD门的作用 1 什么是OC门 OD门 OC门 Open Collector Gate 集电极开路门 如图1所示 当N1导通时 输出低电平 当N1截止时 输出高阻态 电路的一种输出
  • 火狐安装网页视频下载插件(Video DownloadHelper)

    Video DownloadHelper是一款以最简单的方式下载网页视频的chrome插件 基本上火狐浏览器能够加载出视频流并正常播放的视频该插件都能够抓取 可以说该插件对于网页视频下载还是十分快捷并且使用场景广泛的 本地安装后的版本 Vi
  • 字节数组的妙用

    在计算机高级语言中 字节属于最小单位 例如在Java中 int占用4个字节 long占用8个字节等 基本上所有基本类型 包括String 都可以转换成字节 那么这到底有何作用 本篇博客主要是记录了我使用字节数组的经验 希望可以给大家提供一些
  • volatile详解(任何人都能懂的那种)

    volatile 看了好多篇博客终于明白这个关键字到底是干嘛的 让我综合所有的博客写一篇大家都能理解它的博客 要点赞呦 volatile是一个类型修饰符 作用是作为指令关键字 一般都是和const对应 确保本条指令不会被编译器的优化而忽略
  • 怎么将将 Python 的安装目录添加到了系统的环境变量路径中

    要在 Windows 系统中将 Python 的安装目录添加到环境变量路径中 请按照以下步骤操作 1 打开 控制面板 2 选择 系统和安全 3 选择 系统 4 在 系统属性 中 选择 高级系统设置 5 在 高级 选项卡中 选择 环境变量 6
  • 【微信小程序】微信小程序支付功能实现

    1 前言 微信小程序支付 开启新一代便捷支付新时代 随着互联网技术的不断发展 微信小程序支付已经成为了人们日常生活中不可或缺的一部分 微信小程序是一种无需下载安装即可使用的应用 用户可以通过微信扫描或搜索关键词来打开并使用 而微信小程序支付
  • javascript面试题--持续更新

    前端HTML篇 前端CSS篇 Vue篇 TypeScript篇 React篇 微信小程序篇 前端面试题汇总大全 含答案超详细 HTML JS CSS汇总篇 持续更新 前端面试题汇总大全二 含答案超详细 Vue TypeScript Reac
  • pytorch量化库使用(2)

    FX Graph Mode量化模式 训练后量化有多种量化类型 仅权重 动态和静态 配置通过qconfig mapping prepare fx函数的参数 完成 FXPTQ API 示例 import torch from torch ao
  • 高可用系统的设计与维护

    author skate time 2011 02 11 高可用系统的设计与维护 对于一个高可用的系统评价 主要体现在架构 功能 性能 安全 维护 兼容性等方面 如何设计维护这样一个高可用系统的 1 一个提供7 24服务的网站架构系统 要避
  • mysql主从 读写_mysql主从-读写分离

    一个完整的MySQL读写分离环境包括以下几个部分 应用程序client database proxy database集群 在本次实战中 应用程序client基于c3p0连接后端的database proxy database proxy负
  • 最新RAD Studio 11.3亚历山大版本上市

    By Marco Cantu February 27 2023 Embarcadero很高兴地宣布RAD Studio 11 Alexandria Release 3的发布 也被称为RAD Studio 11 3 同时发布的还有Delphi
  • k8s集群PHP环境使用

    一 环境介绍 k8s版本 1 15 2 存储 阿里云NAS 测试代码 wordpress 二 下载wordpress和创建好数据库等 1 下载wordpress wget https cn wordpress org latest zh C
  • 异步的AsyncHttpClient使用详解

    背景 前面的一篇文章 同步的HttpClient使用详解 中 提到了服务端通进行网络请求的方式 也讲述了在并发量大的情况下使用HttpClient的连接池来提高性能 此方法虽然很有效果 但是当访问量极大或网络不好的情况下也会出现某些网络请求
  • HyperLPR车牌识别技术算法之车牌粗定位与训练

    关于HyperLPR HyperLPR是一个使用深度学习针对对中文车牌识别的实现 与较为流行的开源的EasyPR相比 它的检测速度和鲁棒性和多场景的适应性都要好于目前开源的EasyPR HyperLPR可以识别多种中文车牌包括白牌 新能源车
  • js分享功能

    需求 页面需要添加分享到 微博 QQ空间 等功能 具体 div class jz blog a class jiathis button qzone QQ空间 a a class jiathis button tsina 新浪微博 a a
  • Cocos Creator性能调优优化集锦

    前言 一 为什么要做性能优化 性能 是一种优秀的能力 唤醒快 运行持久 稳定 这种能力在游戏上能让你的用户感觉很爽 表征表现为加载快 手机不发热 运行流畅 不卡顿 所以 性能优化的终极目标是 让你的用户感觉很爽 当然这种爽你不能以牺牲自己为
  • Docker快速部署Hadoop环境

    Docker安装部署Hadoop环境 通过三个容器来模拟三个节点 最后只保留Master节点实现搭建 安装环境 Ubuntu 22 04 1 LTS 和Docker 23 0 1 安装过程 拉取镜像 docker pull registry
  • 计算机视觉初步认识

    计算机视觉是使用计算机及相关设备对生物视觉的一种模拟 它的主要任务就是通过对采集的图片或视频进行处理以获得相应场景的三维信息 就像人类和许多其他类生物每天所做的那样 从计算机视觉领域可以衍生出大量有用的应用程序 下面是计算机视觉应用程序的一
  • FreeRTOS记录(八、用软件定时器?还是硬件定时器?)

    FreeRTOS软件定时器 相对前面的内容来说 软件定时器还是比较简单的 我们简单测试一下 因为是简单介绍 所以原理和源码的分析不会那么详细 具体可以根据文中API查看源码 使用起来记住创建 启动 回调函数核心步骤即可 增加测试Demo 再