FreeRTOS源码分析-12 低功耗管理

这篇具有很好参考价值的文章主要介绍了FreeRTOS源码分析-12 低功耗管理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1 STM32低功耗管理概念及应用

1.1睡眠模式      

1.2 停止模式

1.3 待机模式      

2 Tickless低功耗管理

2.1 Tickless低功耗模式介绍

2.2 FreeRTOS低功耗模式配置

2.3 FreeRTOS低功耗模式应用 

3 低功耗管理实际项目开发

3.1 低功耗设计必须要掌握的硬件知识

3.2 开发板电路低功耗分析

3.3 HAL库低功耗处理相关接口

4 低功耗实现原理

4.1 空闲任务详解

4.2 任务删除自身详解 

4.3 Tickless业务流程

4.4 休眠处理详解


1 STM32低功耗管理概念及应用

低功耗产品案例

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

ADC是模拟电路,调压电路时数字电路,模数分离所以ADC是单独电路。

核心功耗在调压供电电路,关闭外设时钟即能关闭外设。

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

1.1睡眠模式      

在睡眠模式中,仅关闭了内核时钟,内核停止运行,但其片上外设,CM4核心的外设全都还照常运行。      

有两种方式进入睡眠模式,它的进入方式决定了从睡眠唤醒的方式,分别是WFI(wait for interrupt)和WFE(wait for event,也可以由中断唤醒,但是不会去处理中断),即由等待“中断”唤醒和由“事件”唤醒。睡眠模式的各种特性见下表

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

1.2 停止模式

在停止模式中,进一步关闭了其它所有的时钟,于是所有的外设都停止了工作,但由于其1.2V区域的部分电源没有关闭,还保留了内核的寄存器、内存的信息。      

所以从停止模式唤醒,并重新开启时钟后,还可以从上次停止处继续执行代码。停止模式可以由任意一个外部中断(EXTI)唤醒。在停止模式中可以选择电压调节器为开模式或低功耗模式,可选择内部FLASH工作在正常模式或掉电模式。(唤醒后,要重新初始化外设时钟

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

一般都把FLASH掉电模式和、FLASH掉电模式都设置为处于关闭状态。唤醒后会有延迟,需要产品对延迟容忍度的考虑。

1.3 待机模式      

待机模式,它除了关闭所有的时钟,还把1.2V区域的电源也完全关闭了,也就是说,从待机模式唤醒后,由于没有之前代码的运行记录,只能对芯片复位,重新检测boot条件,从头开始执行程序。它有四种唤醒方式,分别是WKUP(PA0)引脚的上升沿,RTC闹钟事件,NRST引脚的复位和IWDG(独立看门狗)复位。

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

内存掉电了,程序是错乱的,所以只有上述几种复位

2 Tickless低功耗管理

2.1 Tickless低功耗模式介绍

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

Idle task 任务中会调用tickless,当休眠时间>10ms那么会进入低功耗模式,可选择3种休眠模式 

再分析多任务调度源码的时候,有个UnblockTime,我们可以把这个值传给tickless,来计算下个任务需要调度的时间。

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

2.2 FreeRTOS低功耗模式配置

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

问:为什么要大于2个tick值?

进入休眠模式,需要进行很多判断处理一些外设等。

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

2.3 FreeRTOS低功耗模式应用 

CubeMX

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

生成代码后Freertos.c中会多两个代码

#if configUSE_TICKLESS_IDLE == 1 
#define configPRE_SLEEP_PROCESSING                        PreSleepProcessing
#define configPOST_SLEEP_PROCESSING                       PostSleepProcessing
#endif /* configUSE_TICKLESS_IDLE == 1 */




void PreSleepProcessing(uint32_t *ulExpectedIdleTime);
void PostSleepProcessing(uint32_t *ulExpectedIdleTime);

自写休眠函数

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32




__weak void PreSleepProcessing(uint32_t *ulExpectedIdleTime)
{
	/* place for user code */ 
	printf("input sleep mode!\r\n,ulExpectedIdleTime = %u\r\n",*ulExpectedIdleTime);//休眠时间tick值打印
	HAL_SuspendTick();   //先挂起Systick
	HAL_PWREx_EnableFlashPowerDown();
	__HAL_RCC_GPIOA_CLK_DISABLE(); 
	__HAL_RCC_GPIOB_CLK_DISABLE();  
	__HAL_RCC_GPIOC_CLK_DISABLE();  
	__HAL_RCC_GPIOH_CLK_DISABLE();  
	__HAL_RCC_GPIOI_CLK_DISABLE();
	__HAL_RCC_GPIOF_CLK_DISABLE();
}

__weak void PostSleepProcessing(uint32_t *ulExpectedIdleTime)
{
	/* place for user code */
	HAL_PWREx_DisableFlashPowerDown();
	printf("output sleep mode!\r\n");
	
	__HAL_RCC_GPIOA_CLK_ENABLE(); 
	__HAL_RCC_GPIOB_CLK_ENABLE(); 
	__HAL_RCC_GPIOC_CLK_ENABLE(); 
	__HAL_RCC_GPIOI_CLK_ENABLE();
	__HAL_RCC_GPIOF_CLK_ENABLE();
	__HAL_RCC_GPIOH_CLK_ENABLE(); 
	//HAL_ResumeTick();   //不能再这恢复tick值,否则会不断唤醒
}

如果不挂起Systick和不注释TIM6,会不断触发中断唤醒,还需要查看每个任务中osDelay,不能设太小。

3 低功耗管理实际项目开发

不启用Tickless,烧写程序,直接接电流表测试功耗

启用后在测试电流

程序               TimerTask     Tickless    L去除LCD  关闭GPIO外设时钟&Flash DOWN
工作电流        441mA        395mA       193mA       192mA
休眠程序减少               46mA 

3.1 低功耗设计必须要掌握的硬件知识

主要从四个方面控制功耗:

  • 主控芯片
  • 电源管理
  • 外设模块
  • 外设接口 

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

 FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32 FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

3.2 开发板电路低功耗分析

根据原理图找芯片手册www.alldatasheet.com

电源芯片手册,静态电流5ma 

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

3.3 HAL库低功耗处理相关接口

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

4 低功耗实现原理

4.1 空闲任务详解

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

idleTack

void vTaskStartScheduler( void )
        //空闲任务创建
		xReturn = xTaskCreate(	prvIdleTask,
								"IDLE", configMINIMAL_STACK_SIZE,
								( void * ) NULL,
								( tskIDLE_PRIORITY | portPRIVILEGE_BIT ),
								&xIdleTaskHandle ); 

/*
    全局搜索IDLE,发现portTASK_FUNCTION,再次搜索这个宏是方便用户开发,其他语言也能实        
    现,相当于
*/
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
	

/*
	空闲任务,宏定义实际相当于void prvIdleTask( void *pvParameters );

*/
static portTASK_FUNCTION( prvIdleTask, pvParameters )
{
	/* Stop warnings. */
	( void ) pvParameters;

	/** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
	SCHEDULER IS STARTED. **/

	for( ;; )
	{
		/*检查任务删除自身处理 */
		prvCheckTasksWaitingTermination();
		/*判断调度器工作模式是否开启了优先级抢占模式*/
		#if ( configUSE_PREEMPTION == 0 )
		{ 
			/* 
				1、触发了上下文切换
				2、让调度器判断是否有其他任务,处于了就绪态,然后进行调度
			*/
			taskYIELD();
		}
		#endif /* configUSE_PREEMPTION */
		//调度器使能抢占式
		#if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
		{
			/*
                列表项检查:
				1、和空闲任务处于同一优先级的任务,处于就绪态
				2、进行上下文切换
				3、高于空闲任务优先级的任务,有调度器进行处理

			*/
			if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
			{
				taskYIELD();
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */
		/*
			钩子函数,主要让用户自己填充代码
		*/
		#if ( configUSE_IDLE_HOOK == 1 )
		{
			extern void vApplicationIdleHook( void );

			/* 用户自己实现,比如检测外部信息 */
			vApplicationIdleHook();
		}
		#endif /* configUSE_IDLE_HOOK */

		/* 低功耗处理功能 */
		#if ( configUSE_TICKLESS_IDLE != 0 )
		{
		TickType_t xExpectedIdleTime;

			/* 获取系统的最小时间片 */
			xExpectedIdleTime = prvGetExpectedIdleTime();
			//判断是否大于休眠空闲处理的最小间隔=2tick
			if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
			{
				//挂起调度器
				vTaskSuspendAll();
				{
					/* 又一次获取获取系统的最小时间片,防止挂起调度器期间又有任务更新*/
					xExpectedIdleTime = prvGetExpectedIdleTime();
					//再次判断
					if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
					{
						//进入了休眠处理,传入系统的最小时间片
						portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
					}
					else
					{
						mtCOVERAGE_TEST_MARKER();
					}
				}
				//恢复调度器
				( void ) xTaskResumeAll();
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		#endif /* configUSE_TICKLESS_IDLE */
	}
}






低功耗处理慢点分析,先查看一下任务删除自身的源码分析。

4.2 任务删除自身详解 

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

 结合之前任务删除分析,uxDeletedTasksWaitingCleanUp 在vTaskDelete进行加1处理

/*任务删除自身*/
static void prvCheckTasksWaitingTermination( void )
{

	/** THIS FUNCTION IS CALLED FROM THE RTOS IDLE TASK **/

	#if ( INCLUDE_vTaskDelete == 1 )
	{
		BaseType_t xListIsEmpty;

		/* 
			遍历将要删除的任务
			uxDeletedTasksWaitingCleanUp 在vTaskDelete进行加1处理
		*/
		while( uxDeletedTasksWaitingCleanUp > ( UBaseType_t ) 0U )
		{
			//挂起了调度器
			vTaskSuspendAll();
			{
				//读取删除任务自身列表里任务状态是否为空
				xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
			}
			//开启调度器
			( void ) xTaskResumeAll();
			
			if( xListIsEmpty == pdFALSE )
			{
				//删除任务
				TCB_t *pxTCB;
				//进入临界段
				taskENTER_CRITICAL();
				{
					/*
						1、获取任务控制块
						2、从任务列表项移除任务
						3、任务总计数减一
						4、等待删除计数减一
					*/
					pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
					( void ) uxListRemove( &( pxTCB->xStateListItem ) );
					--uxCurrentNumberOfTasks;
					--uxDeletedTasksWaitingCleanUp;
				}
				//退出临界段
				taskEXIT_CRITICAL();
				//释放了任务控制块
				prvDeleteTCB( pxTCB );
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
	}
	#endif /* INCLUDE_vTaskDelete */
}
	

问:为什么挂起调度器?

不需要别的任务调度,以免影响读取删除任务列表状态。 

4.3 Tickless业务流程

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

大于2个TICK才有意义去处理休眠

先跳转在4.1中低功耗处理分析代码,将要获取的空闲时间xExpectedIdleTime = prvGetExpectedIdleTime()。

最后进入portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )

4.4 休眠处理详解

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

计算systick装载值

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

Systick最大值为24bit

/*
		获取最小系统时间片
	*/
	static TickType_t prvGetExpectedIdleTime( void )
	{
	TickType_t xReturn;
	UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;

		/* */
		#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
		{
			//就绪态的任务优先级高于空闲
			if( uxTopReadyPriority > tskIDLE_PRIORITY )
			{
				uxHigherPriorityReadyTasks = pdTRUE;
			}
		}
		#else
		{
			const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;

			/* 就绪态的任务优先级高于空闲 */
			if( uxTopReadyPriority > uxLeastSignificantBit )
			{
				uxHigherPriorityReadyTasks = pdTRUE;
			}
		}
		#endif
		//当前任务优先级高于空闲任务
		if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
		{
			xReturn = 0;
		}
		//与空闲任务优先级相同的其他任务处于就绪态
		else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
		{
			xReturn = 0;
		}
		//高优先级任务处于就绪态
		else if( uxHigherPriorityReadyTasks != pdFALSE )
		{
			/* There are tasks in the Ready state that have a priority above the
			idle priority.  This path can only be reached if
			configUSE_PREEMPTION is 0. */
			xReturn = 0;
		}
		else //空闲任务优先级最高,才计算
		{
			//系统解锁时间-系统tick计数值== 就是当前系统的最小时间片
			xReturn = xNextTaskUnblockTime - xTickCount;
		}

		return xReturn;
	}

进入低功耗模式

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

 恢复systick

FreeRTOS源码分析-12 低功耗管理,FreeRTOS源码分析,单片机,嵌入式硬件,stm32

portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
//这个函数,是需要用户自己实现,但是STM32FreeRTOS已经帮我们实现
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
	#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif
/*
	低功耗实际处理函数
	1、传入系统的最小时间片

*/
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
	{
	uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
	TickType_t xModifiableIdleTime;

		/* 判断
			系统最小时间片是否大于systick的最大装载周期  单位都tick
		*/
		if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
		{
			//系统最小时间片=systick最大装载周期
			//如果获取系统最小时间片很大,但是systick休眠周期的最大值就是最大装载值
			//为什么这样设计????  
				1、systick定时器受限制(定时周期)
				2、保证systick精度问题
			xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
		}

		/* 关闭systick定时器 */
		portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;

		/*
			systick重载值= 当前的systick计数值+单次系统tick装载值*(系统最小时间片-1)
			
		*/
		ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
		//装载值是否大于补偿周期 之后减去补偿周期
		//最终计算出,systick重载值
		if( ulReloadValue > ulStoppedTimerCompensation )
		{
			ulReloadValue -= ulStoppedTimerCompensation;
		}

		/* 关闭中断 
		
			关闭所有中断 和 进入临界段不一样 
			虽然关闭了中断,但是可以唤醒CPU,不进行中断处理
		
		*/
		__disable_irq();
		__dsb( portSY_FULL_READ_WRITE );
		__isb( portSY_FULL_READ_WRITE );

		/* 是否有其他任务,进入了就绪态 */
		if( eTaskConfirmSleepModeStatus() == eAbortSleep )
		{
			//终止休眠
			/* 当前的systick计数值,放到systick装载寄存器中 */
			portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;

			/* 启动systick */
			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;

			/* 重新赋值装载寄存器值为一个系统的tick周期. */
			portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;

			/* 开启中断 */
			__enable_irq();
		}
		else
		{
			/* 装载休眠systick装载值 */
			portNVIC_SYSTICK_LOAD_REG = ulReloadValue;

			/* 清除systick当前计数值 */
			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;

			/* 启动systick定时器*/
			portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;

			/*  */
			xModifiableIdleTime = xExpectedIdleTime;
			//这个就是给我用户提供的接口,让我自己实现休眠处理,其实就是进一步降低功耗
			configPRE_SLEEP_PROCESSING( &xModifiableIdleTime );
			if( xModifiableIdleTime > 0 )
			{
				//让CPU休眠
				__dsb( portSY_FULL_READ_WRITE );
				__wfi();
				__isb( portSY_FULL_READ_WRITE );
			}
			//退出处理
			configPOST_SLEEP_PROCESSING( &xExpectedIdleTime );

			/* 停止systick定时器 */
			ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
			portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );

			/* 使能中断 */
			__enable_irq();
			//判断是否为systick唤醒的
			if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
			{
				uint32_t ulCalculatedLoadValue;

				/*systick恢复值= 单个tick周期值- (休眠装载值-当前systick计数值)*/
				ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );

				/* 
					这是一个保护处理
					1、装载值很小,就赋值为1个tick周期
					2、装载很大,也赋值为1个tick周期
					
				*/
				if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
				{
					ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
				}
				//装载恢复systick装载值
				portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;

				/* 休眠周期的补偿值,单位为tick  也就是1ms单位  */
				ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
			}
			else
			{
				/* 休眠运行装载值= 休眠装载值-当前systick计数值)*/
				ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;

				/* 休眠运行周期,单位为tick值 */
				ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;

				//装载恢复systick装载值
				portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
			}

			/* 清除systick计数值*/
			portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
			portENTER_CRITICAL();
			{
				/*
					1、使能了systick
					2、补偿系统的tick周期值,也是说,tick运行了多长时间(tick值)
						为什么这样做?
						在调度器恢复的时候,会根据tick值,进行遍历的,保证实时性
					3、恢复systick周期为1个tick值
				*/
				portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
				vTaskStepTick( ulCompleteTickPeriods );
				portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
			}
			portEXIT_CRITICAL();
		}
	}

这些逻辑都是在调试中发现的,主要去理解先计算Systick装载值,在进入休眠,在恢复三个不住。文章来源地址https://www.toymoban.com/news/detail-646544.html

到了这里,关于FreeRTOS源码分析-12 低功耗管理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FreeRTOS_Stm32F103系列单片机标准库移植

    链接:FreeRTOS 下面的教程是基于从github下载压缩包进行的,最好下载这个或者直接看3.1,从我百度网盘下载。如果是别的下载源也问题不大,大同小异。 此时我们需要下载以下两个仓库, 点进去按下面的步骤下载就行了,另一个也是这样下。 链接: FreeRTOS官网 打开链接我们

    2024年01月22日
    浏览(49)
  • 【毕业设计】13-基于单片机的锂电池管理系统(原理图+源码+仿真工程+答辩论文+答辩PPT)

    包含此题目毕业设计全套资料: 原理图工程文件 源码工程 仿真工程 论文低重复率,字数:27821。 详情请私信! 研究基本内容: 1.了解在以单片机为基础上的动力锂电池管理系统的研究目的、意义及研究现状; 2.利用单片机实动力电池电压、电流、温度检测的功能,并完成电

    2024年02月19日
    浏览(50)
  • 【单片机学习笔记】Windows+Vscode+STM32F4+freeRTOS+FatFs gcc环境搭建

    为摒弃在接受keil邮件,研究了下gun编译,以STM32F407为例,简单记录 Git 选择对应版本直接安装即可https://git-scm.com/download/win make gcc ​ 1)将上述软件包放置于C盘根目录 2)添加环境变量 3)cmd命令行测试环境 分别输入 启动文件及LD文件 目录路径表示问题 字节对齐及指定位置存

    2024年02月07日
    浏览(54)
  • FreeRTOS学习之路,以STM32F103C8T6为实验MCU(序章——浅谈单片机以及FreeRTOS)

    学习之路主要为FreeRTOS操作系统在STM32F103(STM32F103C8T6)上的运用,采用的是标准库编程的方式,使用的IDE为KEIL5。 注意!!!本学习之路可以通过购买STM32最小系统板以及部分配件的方式进行学习,也可以通过Proteus仿真的方式进行学习。 后续文章会同时发表在个人博客(jaso

    2024年02月06日
    浏览(54)
  • 单片机学习12-串口通信

    目录 串口通信实验 通信的基本概念 串行通信与并行通信 异步通信与同步通信 单工、半双工与全双工通信 通信速率(比特率) 单片机串口介绍 串口通信简介 串口相关寄存器 串口工作方式 方式 0  方式 1 方式 2 和方式 3 串口的使用方法 硬件设计 软件编程         我们

    2024年02月11日
    浏览(50)
  • 交流220v转12v给单片机供电芯片

    客户的应用需求:AD220V转DC12V 体积要非常小,单片机使用,单片机设备12V 电流很小不会超过100mA? 【AD220V转DC12V体积小的问题】 问题:我需要将交流电(220V)转换为直流电(12V),并且需要一个非常小的体积。同时,我需要根据输出电流的不同,选择不同型号的单片机。 解

    2024年02月12日
    浏览(35)
  • 51单片机学习笔记-12LCD1602液晶屏

    [toc] 注:笔记主要参考B站江科大自化协教学视频“51单片机入门教程-2020版 程序全程纯手打 从零开始入门”。 注:工程及代码文件放在了本人的Github仓库。 LCD1602(Liquid Crystal Display)液晶显示屏是一种字符型液晶显示模块,可以显示ASCII码的标准字符和其它的一些内置特殊字

    2024年02月11日
    浏览(49)
  • Android Studio制作手机App:通过手机蓝牙(Bluetooth)与STM32上的低功耗蓝牙(HC-42)连接通信,实现手机端对单片机的控制。

    背景: 本文的内容是针对单片机蓝牙模块(HC-42)开发的手机App。在这之前,我想先声明一点,手机与手机间的蓝牙连接方式”与“手机与HC间的蓝牙连接方式”是不一样的。原因就是手机搭配的是“经典蓝牙”模块,HC等蓝牙属于“低功耗蓝牙”模块。(二者的区别想了解的

    2024年02月04日
    浏览(51)
  • 【期末不挂科-单片机考前速过系列P12】(第十二章:单片机的并行拓展例题)经典例题盘点(带图解析)

    前言 大家好吖,欢迎来到 YY 滴单片机系列 ,热烈欢迎! 本章主要内容面向接触过单片机的老铁 主要内容含: 欢迎订阅 YY 滴C++专栏!更多干货持续更新!以下是传送门! YY的《C++》专栏 YY的《C++11》专栏 YY的《Linux》专栏 YY的《数据结构》专栏 YY的《C语言基础》专栏 YY的《

    2024年01月19日
    浏览(90)
  • STC12C5A系列单片机内部 EEPROM 的应用

    参考范例程序。 eeprom.c eeprom.h STC12C5A60S2 只有两个扇区,每个扇区有 512 个字节。 测试读取功能: 测试写入功能: 测试擦除功能: 注意:如果擦除将擦除整个扇区。 运行结果如下:

    2024年02月15日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包