rtthread-nano增加自己的低功耗管理模块

前言

在低功耗项目中因为单片机资源不是很丰富,选择了rtthread-nano,rtthread有一个低功耗PM组件,但是这个组件是在标准版,看了一下PM实现的过程和代码,打算模仿实现一个自己的PM组件,下面分三步来介绍:
1.实现思路
2.API使用
3.注意事项

1.实现思路

首先了解一下官方PM组件的实现方法 https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/pm/pm?id=api-%e4%bb%8b%e7%bb%8d
我的理解就是有三个注意的地方,1.注册设备为低功耗设备–>也就是调用他们的API,参数为自己在进入低功耗模式前后的回调,2.在执行一些需要等待时的操作,需要调用他们的API,实现对电源的锁定,完事之后需要释放这个锁,也就是调用释放电源的API
所以模仿了他们的实现方式,过程为
1.创建一个低功耗线程,优先级比其他线程都高,的过程为,每1000ms进入此线程,判断电源是否上锁,没有的话则倒计时,当倒计时结束先执行进入之前的计划,然后进入,当有中断被唤醒,则执行退出之后的计划,线程设为最高优先级的目的就是,在执行中断之后第一时间转回这里执行退出之后的操作
低功耗线程流程
2.创建一个表,用于存储进出低功耗模式的回调,提供一个注册低功耗设备的函数,给其他模块调用,参数就是进出低功耗模式的回调
3.提供两个函数,一个电源上锁函数,一个电源解锁函数,当需要执行时间较长的操作时,就需要调用这个函数,一定要成对出现

2.API使用

我在网上找像这种资料时,希望的是直接给我一个.c和.h文件,然后告诉我怎么用就行了,下面就根据怎么用来说一下
1.就是创建一个低功耗线程了,线程入口函数,创建时记得优先级设置为最高

/*
	电源控制线程入口函数
*/
void  power_control_entry(void *param)
{	
	while(1)
	{
		rt_thread_mdelay(1000);
		if(power_param.lock) continue;
		if(power_param.mdelay_cnt-- <= 0)
		{
			rt_kprintf("进入低功耗\n");
			power_param.mdelay_cnt = power_param.mdelay_cnt_max;
			enter_stop1_model();
			rt_kprintf("退出低功耗\n");
		}
		rt_kprintf("倒计时-->%d\n",power_param.mdelay_cnt);
	}
}

还有执行进入和退出低功耗的函数

/*
	执行进入低功耗前的计划
*/
static void execute_plan_before_enter(void)
{
	for(uint8_t i = 0;i < SUPPORT_LP_DEV_MAX;i++)
	{
		if( lp_dev_table[i].plan_before_entering != NULL)
			lp_dev_table[i].plan_before_entering();
	}
}

/*
	执行退出低功耗之后的计划
*/
static void execute_plan_after_exit(void)
{
	for(uint8_t i = 0;i < SUPPORT_LP_DEV_MAX;i++)
	{
		if( lp_dev_table[i].plan_after_exit != NULL)
			lp_dev_table[i].plan_after_exit();
	}
}

进入低功耗模式函数

/*
	进入低功耗模式
*/
void enter_stop1_model(void)
{
	__HAL_RCC_PWR_CLK_ENABLE();
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF);
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUFI);
	
	execute_plan_before_enter();
	
	HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // 停止1,等待中断
	
	extern void SystemClock_Config(void);	
	SystemClock_Config();
	
	execute_plan_after_exit();
}

2.提供注册成低功耗设备的函数

/*
	低功耗设备注册
*/
void lowpower_dev_register(void (*plan_before_entering)(void),void (*plan_after_exit)(void))
{
	for(uint8_t i = 0;i < SUPPORT_LP_DEV_MAX;i++)
	{
		if(lp_dev_table[i].plan_before_entering == NULL)
		{
			lp_dev_table[i].plan_before_entering = plan_before_entering;
			lp_dev_table[i].plan_after_exit = plan_after_exit;
			break;
		}
	}
}

在.h文件创建两个结构体,一个是用于描述进出低功耗模式的回调函数,一个用于保存电源锁的一些状态

#define	MDELAY_CNT_MAX	1	/*进入延迟最大值*/

/*
	电源管理的一些数据
*/
typedef  struct
{
	int mdelay_cnt;			/*延迟进入计数值*/
	int mdelay_cnt_max;		/*延时进入最大值*/
	int32_t lock;			/*电源锁*/
}PowerStruct;


/*
	低功耗设备管理
*/
typedef struct
{
	void (*plan_before_entering)(void);		/*进入之前的准备*/
	void (*plan_after_exit)(void);			/*退出之后的计划*/
}lowPowerDEVStruct;

在.c就创建一个表,这里直接用数组实现了,缺点是需要自己确定有几个需要注册的低功耗设备,用链表能解决这个问题,但是麻烦点

#define	SUPPORT_LP_DEV_MAX	4	/*支持的低功耗设备数量*/
lowPowerDEVStruct lp_dev_table[SUPPORT_LP_DEV_MAX] = {0};


PowerStruct power_param = 
{
	.mdelay_cnt = MDELAY_CNT_MAX,		/*初始值*/
	.mdelay_cnt_max = MDELAY_CNT_MAX,	/*初始最大值*/
};

3.提供电源上锁和解锁接口函数

/*
	电源上锁
	参数:钥匙,最大31
	返回值:1上锁成功 ,0上锁失败
*/
uint8_t  power_lock_with_key(uint32_t key)
{
	if(!((power_param.lock >> key ) & 1)) 
	{
		power_param.mdelay_cnt = power_param.mdelay_cnt_max;
		power_param.lock |= 1 << key;
		return 1;
	}
	
	return 0;
}

/*
	电源解锁
	参数:钥匙
	返回值: 1成功解锁,0解锁失败
*/
uint8_t  power_unlock_with_key(uint32_t key)
{
	if((power_param.lock >> key ) & 1) 
	{
		power_param.lock ^= 1 << key;
		return 1;
	}
	
	return 0;
}

总的来说,使用过程就是,其他文件开机的时候调用注册函数,然后在需要等待的地方使用上锁和解锁函数就行了

3.注意事项

1.这个只实现了一个模式,就是单片机的停止1模式,因为待机模式会把ram清空
2.属于延时等待而不是立即进入,延时等待进入时间也是可以设置的,就多 写一个函数修改实例化的最大值成员就行了

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值