FreeRTOS系列|软件定时器

2023-05-16

软件定时器

MCU一般都自带定时器,属于硬件定时器,但是不同的MCU其硬件定时器数量不同,有时需要考虑成本的问题。在硬件定时器不够用的时候,FreeRTOS也提供了定时器功能,不过是属于软件定时器,其定时精度没有硬件定时器高,但是对于精度要求不高的周期性任务也足够了

1. 软件定时器介绍

软件定时器允许设置一段时间,当设置的时间到达之后就会执行回调函数。软件定时器的回调函数是在定时器服务任务中执行的,因此不能在回调函数中调用会阻塞任务的API函数

定时器是一个可选的、不属于FreeRTOS内核的功能,是由定时器服务任务来提供的。定时器相关API函数大多是使用定时器命令队列发送命令给定时器服务任务的,用户不能直接访问该命令队列

在这里插入图片描述
如上图示,定时器命令队列将用户应用任务和定时器服务任务连接在一起。用户应用程序调用了函数xTimerReset(),其结果是复位命令会被发送到定时器命令队列中,再由定时器服务任务来处理这个命令

软件定时器分为两种:单次定时器和周期定时器。单次定时器在定时时间到了后执行一次回调函数就会停止运行;周期定时器一旦启动就会周期性的执行回调函数

在这里插入图片描述

定时器的相关配置

  • configUSE_TIMERS 宏置1:自动创建定时器服务任务
  • configTIMER_TASK_PRIORITY:软件定时器服务任务的任务优先级
  • configTIMER_QUEUE_LENGTH:设置定时器命令队列的队列长度
  • configTIMER_TASK_STACK_DEPTH:设置定时器服务任务的任务堆栈大小

FreeRTOS启动调度器的时候会自动创建定时器服务任务,其源码如下所示:

BaseType_t xTimerCreateTimerTask( void ){
  BaseType_t xReturn = pdFAIL;
  /* 检查软件定时器列表和队列,若没有创建内存空间则新建	*/
  prvCheckForValidListAndQueue();
  if( xTimerQueue != NULL ){
	#if( configSUPPORT_STATIC_ALLOCATION == 1 )
	{
	  /*****此处省略静态创建代码*****/
	}
	#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;
	  /* 开始创建消息队列 */
	  #if( configSUPPORT_STATIC_ALLOCATION == 1 )
	  {
		/*****************************/
		/*****此处省略静态创建代码*****/
		/*****************************/
	  }
	  #else
	  {
		xTimerQueue = xQueueCreate((UBaseType_t)configTIMER_QUEUE_LENGTH, sizeof(DaemonTaskMessage_t));
	  }
	  #endif
	  /*****************************/
	  /*****此处省略部分其他代码*****/
	  /*****************************/
	}
	else
	{
	  mtCOVERAGE_TEST_MARKER();
	}
  }
  taskEXIT_CRITICAL();
}

2. 软件定时器API函数

2.1 复位软件定时器

复位软件定时器,若软件定时器已经启动,则重新计算超时时间;若软件定时器没有启动,则启动软件定时器

/********************复位软件定时器,用在任务中************************************/
BaseType_t xTimerReset(TimerHandle_t xTimer,	//要复位的软件定时器句柄
					TickType_t xTicksToWait)	//阻塞时间
/********************复位软件定时器,用在中断服务函数中*****************************/
BaseType_t xTimerResetFromISR(TimerHandle_t xTimer, //要复位的软件定时器句柄
			BaseType_t * pxHigherPriorityTaskWoken) //退出后是否进行任务切换
/********************************************************************************/
返回值:定时器复位成功返回pdPASS;失败返回pdFAIL

复位定时器函数是一个宏,最终调用xTimerGenericCommand()函数

#define xTimerReset(xTimer, xTicksToWait) 			\
		xTimerGenericCommand((xTimer), 				\
							 tmrCOMMAND_RESET, 		\
							 (xTaskGetTickCount()), \
							 NULL, 					\
							 (xTicksToWait))		\
//参数:1、软件定时器句柄;2、定义Reset编号;3、当前的系统的Tick值;4、null;5、阻塞时间
2.2 创建软件定时器

创建一个软件定时器,并返回一个软件定时器句柄。创建软件定时器后,软件定时器并没有启动

/********************动态创建软件定时器*******************************************/
TimerHandle_t xTimerCreate(char * const pcTimerName,//软件定时器名字
					 TickType_t xTimerPeriodInTicks,//定时器周期(单位是时钟节拍数)
						   UBaseType_t uxAutoReload,//定时器模式(单次还是周期)
					         void * const pvTimerID,//定时器ID号
		 TimerCallbackFunction_t pxCallbackFunction)//定时器回调函数
/********************静态创建软件定时器*******************************************/
TimerHandle_t xTimerCreateStatic(char * const pcTimerName,//软件定时器名字
					 TickType_t xTimerPeriodInTicks,//定时器周期(单位是时钟节拍数)
						   UBaseType_t uxAutoReload,//定时器模式(单次还是周期)
					         void * const pvTimerID,//定时器ID号
		 TimerCallbackFunction_t pxCallbackFunction,//定时器回调函数
		              StaticTimer_t * pxTimerBuffer)//保存定时器结构体
/********************************************************************************/
返回值:创建成功返回软件定时器句柄;失败返回NULL

创建软件定时器函数xTimerCreate()的源码分析如下示:

TimerHandle_t xTimerCreate(	const char * const pcTimerName,
							const TickType_t xTimerPeriodInTicks,
							const UBaseType_t uxAutoReload,
							void * const pvTimerID,
							TimerCallbackFunction_t pxCallbackFunction){
  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){
  /* 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 );
  }
}
2.3 开启软件定时器
/****************开启软件定时器,用在任务中***********************************/
BaseType_t xTimerStart(TimerHandle_t xTimer,	//要复位的软件定时器句柄
					TickType_t xTicksToWait)	//阻塞时间
/****************开启软件定时器,用在中断服务函数中****************************/
BaseType_t xTimerStartFromISR(TimerHandle_t xTimer, //要复位的软件定时器句柄
			BaseType_t * pxHigherPriorityTaskWoken) //退出后是否进行任务切换
/********************************************************************************/
返回值:定时器开启成功返回pdPASS;失败返回pdFAIL

开始软件定时器函数是一个宏,最终调用xTimerGenericCommand()函数

#define xTimerStart(xTimer, xTicksToWait)           \
		xTimerGenericCommand((xTimer),              \
							 tmrCOMMAND_START, 		\
					         (xTaskGetTickCount()), \
							 NULL, 					\
							 (xTicksToWait))        \
//参数:1、软件定时器句柄;2、定义Start编号;3、当前的系统的Tick值;4、null;5、阻塞时间
2.4 停止软件定时器
/****************停止软件定时器,用在任务中***********************************/
BaseType_t xTimerStop(TimerHandle_t xTimer,		//要复位的软件定时器句柄
					TickType_t xTicksToWait)	//阻塞时间
/****************停止软件定时器,用在中断服务函数中****************************/
BaseType_t xTimerStopFromISR(TimerHandle_t xTimer,  //要复位的软件定时器句柄
			BaseType_t * pxHigherPriorityTaskWoken) //退出后是否进行任务切换
/********************************************************************************/
返回值:定时器停止成功返回pdPASS;失败返回pdFAIL

停止软件定时器函数是一个宏,最终也是调用xTimerGenericCommand()函数

#define xTimerStop(xTimer, xTicksToWait)            \
		xTimerGenericCommand((xTimer),              \
							 tmrCOMMAND_STOP, 		\
					         0U, 					\
							 NULL, 					\
							 (xTicksToWait))        \
//参数:1、软件定时器句柄;2、定义Stop编号;3、不需要传入消息;4、null;5、阻塞时间

函数xTimerGenericCommand()的源码如下:

BaseType_t xTimerGenericCommand(TimerHandle_t xTimer, 
						 const BaseType_t xCommandID,//标识触发的类型
					 const TickType_t xOptionalValue,//xTaskGetTickCount
 		BaseType_t * const pxHigherPriorityTaskWoken,
  					  const TickType_t xTicksToWait){
  BaseType_t xReturn = pdFAIL;
  DaemonTaskMessage_t xMessage;
  if( xTimerQueue != NULL ){
	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;
}

3. 软件定时器应用实例

本实例介绍FreeRTOS软件定时的的创建、开启和停止函数的操作与使用

使用STM32CubeMX将FreeRTOS移植到工程中,创建一个任务、两个软件定时器(单次和周期定时器)

  • TimerControl_Task:控制两个软件定时器的开启和停止
  • PeriodicTimer:周期定时器,定时周期为1000ms
  • OnceTimer:单次定时器,定时周期为2000ms
3.1 STM32CubeMX设置
  • RCC设置外接HSE,时钟设置为72M

  • PC0/PC1设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

  • PA0设置为GPIO输入模式、下拉模式;PE2/PE3/PE4设置为GPIO输入模式、上拉模式

  • USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位;

  • 激活FreeRTOS,添加任务,设置任务名称、优先级、堆栈大小、函数名称等参数

在这里插入图片描述

  • 使能软件定时器,设置优先级等参数

在这里插入图片描述

  • 添加单次定时器和周期定时器

在这里插入图片描述

  • 使用FreeRTOS操作系统,需要将HAL库的Timebase Source从SysTick改为其他定时器,选好定时器后,系统会自动配置TIM
  • 输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码
3.2 MDK-ARM软件编程
  • 创建按键驱动文件key.c和key.h,参考按键输入例程
  • 添加TimerControl_Task任务函数代码
void TimerControl_Task(void const * argument){
  uint8_t key;
  for(;;){	
	if((PeriodicTimerHandle != NULL)&&(OnceTimerHandle != NULL)){
	  key = KEY_Scan(0);
	  switch(key){
		case KEY_UP_PRES :
		  /* 设置软件定时器周期值 */
		  xTimerChangePeriod(PeriodicTimerHandle,1000,0);
		  xTimerStart(PeriodicTimerHandle,0);
		  printf("PeriodicTimer Start......!\r\n");
		  break;
		case KEY_DOWN_PRES :
		  xTimerStop(PeriodicTimerHandle,0);
		  printf("PeriodicTimer Stop******!\r\n");
		  break;
		case KEY_LEFT_PRES :
		  /* 设置软件定时器周期值 */
		  xTimerChangePeriod(OnceTimerHandle,2000,0);
		  xTimerStart(OnceTimerHandle,0);
		  printf("OnceTimer Start......!\r\n");
		  break;
		case KEY_RIGHT_PRES :
		  xTimerStop(OnceTimerHandle,0);
		  printf("OnceTimer Stop******!\r\n");
		  break;
	  }
	}
    osDelay(10);
  }
}
  • 添加周期定时器和单次定时器的回调函数
void OnceTimer_Callback(void const * argument){
  HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);
  printf("OnceTimer Finished!\r\n");
}

void PeriodicTimer_Callback(void const * argument){
  HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1); 
}
3.3 下载验证

编译无误下载到开发板后,打开串口调试助手

  • 按下KEY_UP按键,开启周期定时器,此时LED2指示灯每隔1s闪烁一次
  • 按下KEY_DOWN按键,关闭周期定时器,LED2停止闪烁
  • 按下KEY_LEFT按键,开启单次定时器,2s后LED1状态翻转,停止运行
  • 按下KEY_RIGHT按键,关闭单次定时器

在这里插入图片描述

关注我的公众号,在公众号里发如下消息,即可获取相应的工程源代码:

FreeRTOS软件定时器实例

在这里插入图片描述

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

FreeRTOS系列|软件定时器 的相关文章

  • FreeRTOS-内核控制函数

    FreeRTOS 内核控制函数 FreeRTOS中有一些内核函数 一般来说这些内核函数在应用层不会使用 但是内核控制函数是理解FreeRTOS中断的基础 接下来我们逐一分析这些内核函数 taskYIELD 该函数的作用是进行任务切换 这是一
  • 解决错误“ #error “include FreeRTOS.h“ must appear in source files before “include event_groups.““例子分享

    今天来给大家分享一下 关于之前自己在学习FreeRTOS过程中遇到的一个错误提示 话不多说 我们直接来看 错误分析 首先 我们看一下错误的提示 error 35 error directive include FreeRTOS h must
  • FreeRTOS学习(八) 延时函数

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 FreeRTOS延时函数有两个 分别是 vTaskDelay vTaskDelayUntil 1 vTaskDelay 任务相对延时 函数原型
  • 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学习笔记<中断>

    中断概念 Cortex M的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽中断 NMI 1个Systick 滴答定时器 定时器中断和多个系统异常 Cortex M处理器有多个用于管中断和异常的可编程寄存器 这些寄存器大多数都在 NV
  • FreeRTOS ------- 任务(task)

    在学习RTOS的时候 个人觉得带着问题去学习 会了解到更多 1 什么是任务 在FreeRTOS中 每个执行线程都被称为 任务 每个任务都是在自己权限范围内的一个小程序 其具有程序入口每个任务都是在自己权限范围内的一个小程序 其具有程序入口通
  • FreeRTOS临界区

    FreeRTOS临界区是指那些必须完整运行 不能被打断的代码段 比如有的外设的初始化需要严格的时序 初始化过程中不能被打断 FreeRTOS 在进入临界区代码的时候需要关闭中断 当处理完临界区代码以后再打开中断 FreeRTOS 系统本身就
  • 【FreeRTOS(三)】任务状态

    文章目录 任务状态 任务挂起 vTaskSuspend 取消任务挂起 vTaskResume 挂起任务调度器 vTaskSuspendAll 取消挂起任务调度器 xTaskResumeAll 代码示例 任务挂起 取消任务挂起 代码示例 挂起
  • freeRTOS使用uxTaskGetStackHighWaterMark函数查看任务堆栈空间的使用情况

    摘要 每个任务都有自己的堆栈 堆栈的总大小在创建任务的时候就确定了 此函数用于检查任务从创建好到现在的历史剩余最小值 这个值越小说明任务堆栈溢出的可能性就越大 FreeRTOS 把这个历史剩余最小值叫做 高水位线 此函数相对来说会多耗费一点
  • FreeRTOS:中断配置

    目录 一 Cortex M 中断 1 1中断简介 1 2中断管理简介 1 3优先级分组定义 1 4优先级设置 1 5用于中断屏蔽的特殊寄存器 1 5 1PRIMASK 和 FAULTMASK 寄存器 1 5 2BASEPRI 寄存器 二 F
  • FreeRTOS之软件定时器

    FreeRTOS之软件定时器 声明 本人按照正点原子的FreeRTOS例程进行学习的 欢迎各位大佬指责和批评 谢谢 include sys h include delay h include usart h include led h in
  • FreeRTOS死机原因

    1 中断回调函数中没有使用中断级API xxFromISR 函数 xSemaphoreGiveFromISR uart busy HighterTask 正确 xSemaphoreGive uart busy 错误 2 比configMAX
  • FreeRTOS学习---“定时器”篇

    总目录 FreeRTOS学习 任务 篇 FreeRTOS学习 消息队列 篇 FreeRTOS学习 信号量 篇 FreeRTOS学习 事件组 篇 FreeRTOS学习 定时器 篇 FreeRTOS提供了一种软件定时器 用来快速实现一些周期性的
  • 单片机通信数据延迟问题排查

    1 问题说明 笔者在最近的项目中 发现系统的响应延迟较高 经过排查 排除了单片机运行卡死的问题 2 原因分析 具体排查过程这里就不细致说明了 直接给出排查后原因 任务执行周期规划不合理 导致freertos队列发送接收到的命令有延迟 为了便
  • STM32 Freertos 添加 外部sram heap_5.c

    1 添加外部SRAM 初始化 2 添加heap 5 c 3 初始化heap 5 c 外部堆栈 Define the start address and size of the two RAM regions not used by the
  • 再论FreeRTOS中的configTOTAL_HEAP_SIZE

    关于任务栈和系统栈的基础知识 可以参考之前的随笔 FreeRTOS 任务栈大小确定及其溢出检测 这里再次说明 define configTOTAL HEAP SIZE size t 17 1024 这个宏 官方文档解释 configTOTA
  • FreeRTOS 配置TICK_RATE_HZ

    我使用的是带有 5 4 版 FreeRTOS 的 MSP430f5438 我有一个有趣的问题 我无法弄清楚 基本上 当我将 configTICK RATE HZ 设置为不同的值时 LED 闪烁得更快或更慢 它应该保持相同的速率 我将 con
  • FreeRTOS 匈牙利表示法 [重复]

    这个问题在这里已经有答案了 我是 RTOS 和 C 编程的新手 而且我仍在习惯 C 的良好实践 因此 我打开了一个使用 FreeRTOS 的项目 我注意到操作系统文件使用匈牙利表示法 我知道一点符号 但面临一些新的 标准 FreeRTOS
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d

随机推荐

  • 斐波那契数列 Java实现

    关于斐波那契数列在百度百科上的定义如下 xff1a 斐波那契数列 xff0c 又称黄金分割数列 xff0c 指的是这样一个数列 xff1a 0 1 1 2 3 5 8 13 21 34 在数学上 xff0c 斐波纳契数列以如下被以递归的方法
  • Maven+Jetty运行项目无法热修改html处理

    一直以来都在做后端工程的开发 xff0c 很少做前端设计 xff0c 最近工作需要开始做前端开发 xff0c 感觉 辛辛苦苦几十年 xff0c 一朝回到解放前 的节奏啊 xff0c 遇到不少问题 xff0c 记录下来以备后查 今天在使用Ma
  • Spring4.3.0 Junit4.11 initializationError(org.junit.runner.manipulation.Filter)

    Spring4 3 0 Junit4 11 initializationError org junit runner manipulation Filter 昨天手欠 xff0c 在项目中把Spring3 2 14版本升级到4 3 0版本
  • zookeeper入门(一)——ZooKeeper伪集群安装

    zookeeper入门 xff08 一 xff09 ZooKeeper伪集群安装 在进行本篇文章之前 xff0c 先请大家了解一下zookeeper xff08 后面的文章为了省事有可能直接使用zk缩写来替代 xff09 xff0c 关于z
  • zookeeper入门(二)——zk客户端脚本使用

    zookeeper入门 xff08 二 xff09 zk客户端脚本使用 在上一篇文章zookeeper入门 xff08 一 xff09 ZooKeeper伪集群安装我们讲了在单机进行zk伪集群安装 xff0c 本篇文章我们来讲一下zk提供的
  • 事务基础知识

    数据库事务 数据库事务定义 xff0c 满足4个特性 xff1a 原子性 xff08 Atomic xff09 一致性 xff08 Consistency xff09 隔离性 xff08 Isolation xff09 和持久性 xff08
  • MySQL事务隔离级别

    1 MySQL所支持的事务隔离级别 MySQL所支持的事务隔离级别 xff1a READ UNCOMMITTED READ COMMITTED REPEATABLE READ SERIALIZABLE 其中 REPEATABLE READ是
  • Thrift第一个示例

    第一步 xff1a 引入thrift依赖包 compile span class hljs keyword group span span class hljs string 39 org apache thrift 39 span nam
  • FreeRTOS系列|计数信号量

    计数信号量 1 计数信号量简介 计数型信号量有以下两种典型用法 事件计数 xff1a 每次事件发生 xff0c 事件处理函数将释放信号量 xff08 信号量计数值加1 xff09 xff0c 其他处理任务会获取信号量 xff08 信号量计数
  • Redis学习——01.redis安装

    下载 tar xzvf redis span class hljs number 3 2 span span class hljs number 10 span span class hljs preprocessor tar span s
  • IDEA常用设置

    显示主题 建议使用Darcula Appearance gt Theme 编辑器字体 建议使用Courier New或者Consolas Editor gt Font gt Font 打开自动编译 Compiler gt Build pro
  • Windows下执行Linux命令

    常用的工具 Cygwin xff08 http www cygwin com xff09 Cygwin是一个在windows平台上运行的类UNIX模拟环境 xff0c 详细参见百度百科 xff1a https baike baidu com
  • Linux网络编程 - 多线程服务器端的实现(1)

    引言 本来 xff0c 线程在 Windows 中的应用比在 Linux 平台中的应用更广泛 但 Web 服务的发展迫使 UNIX 系列的操作系统开始重视线程 由于 Web 服务器端协议本身具有的特点 xff0c 经常需要同时向多个客户端提
  • 访问带有用户名、密码保护的 URL

    一 URL xff0c 统一资源定位器 指向互联网上的 资源 xff0c 可协议名 主机 端口和资源组成 如 http username password 64 host 8080 directory file query ref Comp
  • 【RT-Thread】STM32F1片内Flash实现Bootloader

    目录 前言1 开发环境搭建2 Bootloader制作3 APP程序制作4 OTA固件打包5 Ymodem升级小结 前言 RT Thread官网对于Bootloader的实现方案有非常详细的描述 xff0c 目前支持F1 F4 L4系列单片
  • SDVOE和传统矩阵的区别

    SDVOE最显著的特点 xff1a 分辨率高 xff0c 最高支持4KP60 4 4 4 图像质量好 xff0c 完全可以达到无压缩效果延时小 xff0c Genlock模式下4K30延时只有不到0 1ms xff0c 链路上嵌入千兆网络
  • GD32的DMA配置

    参考 GD32F4xx 用户手册 DMA 控制器由 4 部分组成 xff1a AHB 从接口配置 DMA xff1b 两个 AHB 主接口进行数据传输 xff1b 两个仲裁器进行 DMA 请求的优先级管理 xff1b 数据处理和计数 DMA
  • nuttx杂记

    1 设置自启动应用 修改deconfig文件下的 CONFIG INIT ENTRYPOINT 参数即可 2 消息队列使用 以下是Nuttx系统中使用queue create函数创建队列的示例代码 xff1a include lt stdi
  • linux下使用jlink 调试 stm32的破事

    安装libusb sudo apt get install libusb 安装readline wget c ftp ftp gnu org gnu readline readline 6 2 tar gz tar zxvf readlin
  • FreeRTOS系列|软件定时器

    软件定时器 MCU一般都自带定时器 xff0c 属于硬件定时器 xff0c 但是不同的MCU其硬件定时器数量不同 xff0c 有时需要考虑成本的问题 在硬件定时器不够用的时候 xff0c FreeRTOS也提供了定时器功能 xff0c 不过