FreeRTOS-队列

学习记录:
队列=环形缓存区+各类同步互斥操作(包括:发送者链表、接收者链表、各种状态切换操作)
发送者A(taskA):发送数据,如果流水线(环形buffer)没空间了,则等待(tickdelay,进入delay链表),如果有空间,则写入值并返回。
A发送完成后,会查看接收者链表,如果非空,则将第一个任务从delay链表拖出来,使其进入就绪状态,用于接收数据。

A和B(发送和接收任务)的工作状态相反:

发送者B(taskB):接收数据,如果流水线(环形buffer)没数据了,则等待(tickdelay,进入delay链表),如果有数据,则接收值并返回。

B接收完成后,会查看发送者链表,如果非空,则将第一个任务从delay链表拖出来,使其进入就绪状态,用于发送数据。

注:
只有当环形buffer满了,才会将发送任务放到发送者链表,放进去的意义表示该任务进入堵塞状态
只有当环形buffer空了,才会将接收任务放到接收者链表,放进去的意义表示该任务进入堵塞状态

这说明:刚创建好队列的时候,队列为空,此时接收任务处于堵塞状态,使其堵塞是同步操作。
这时接收任务只能等待发送任务将其从delay链表拖出,或者等待超时。(此时任务出错,这也是为什么不用暂停链表的原因,暂停链表等于小黑屋,自己无法主动脱身)
所以,接收任务B永远得等待发送任务A准备好数据,才能处理该数据,这是互斥操作。

故:数据传输靠环形Buffer,同步互斥靠链表、链表数组的不断调控

2025.9.20更新:

队列集:就是队列集合,其本质也是一个队列,只不过其数据是其他子队列的句柄。
发送者在发送的时候,除了上面说的工作,还会在发送成功后检测该队列是否在某个队列集里面,如果在,则顺便将该队列的句柄放到对应的队列集里面,如下图:每写一个数据,队列集就会增加一个句柄(是有序增加,后续读取也是有序读取)。


这样的话,我们只要创建一个input_Task任务,按序处理这个队列集数据,就能处理好下面所有硬件的数据,而不需要为每一个硬件创建一个单独的数据处理任务,减少内存调度开销。而input_Task可以向功能应用层的函数发送(也是队列)处理好的数据,如角度、计数值什么的

底层不同函数两两之间还是用单个的队列传输,底层到上面的应用函数层,则通过数据集传输,而input_Task可根据任务需求定制。

2025.9.21更新:
队列集设置步骤(hal):
①在freertosconfig.h里面增加#define ConfigUSE_QUEUE_SETS 1
②新建所有的队列\队列集
③把所有队列放到队列集里。,
一定要先把队列放进去再创建任务,因为队列集的时候要保证队列里面没有数据,有数据就会放放置失败,后续input_task就不会处理该队列的数据,表象上就是任务不更新了。
④之后再创建任务、开启调度器等其他初始化任务
顺序:
①初始化函数(内部会创建对应外设的队列)
②应用任务创建,主要是顶层应用输出
③在应用任务内部,创建各类队列\队列集,创建好后立刻加入队列集,之后再创建底层驱动任务(如果是中断驱动,则不用创建),最后再创建input_task任务。
如下代码:

void MX_FREERTOS_Init(void) {
.....
xTaskCreate(game1_task, "GameTask", 128, NULL, osPriorityNormal, NULL);
//game1_task是顶层应用函数
.....
}


void game1_task(void *params)
{...
    //创建队列
	g_xQueuePlatform = xQueueCreate(10, sizeof(struct input_data));

    //创建队列集
	g_xQueueSetInput = xQueueCreateSet(IR_QUEUE_LEN + ROTARY_QUEUE_LEN + MPU6050_QUEUE_LEN);

	//获取各类队列,然后加入队列集
	g_xQueueIR = GetQueueIR();
	g_xQueueRotary = GetQueueRotary();
	g_xQueueMPU6050 = GetQueueMPU6050();
	xQueueAddToSet(g_xQueueIR, g_xQueueSetInput);
	xQueueAddToSet(g_xQueueRotary, g_xQueueSetInput);
	xQueueAddToSet(g_xQueueMPU6050, g_xQueueSetInput);

	/创建底层驱动函数
    xTaskCreate(MPU6050_Task, "MPU6050Task", 128, NULL, osPriorityNormal, NULL);
    xTaskCreate(InputTask, "InputTask", 128, NULL, osPriorityNormal, NULL);

...
}

小技巧:
①static让函数只局限在该文件使用,可以通过函数输出:

ir.c文件:
static QueueHandle_t g_xQueueIR;

QueueHandle_t GetQueueIR(void)
{
	return g_xQueueIR;
}

game.c文件:
g_xQueueIR = GetQueueIR();

②任务不一定放在freertos.c里面,可以附属在其他文件,通过extern可以引用到。
③中断函数在外面可以随意放。

内容概要:本文介绍了一个基于Matlab的综合能源系统优化调度仿真资源,重点实现了含光热电站、有机朗肯循环(ORC)和电含光热电站、有机有机朗肯循环、P2G的综合能源优化调度(Matlab代码实现)转气(P2G)技术的冷、热、电多能互补系统的优化调度模型。该模型充分考虑多种能源形式的协同转换与利用,通过Matlab代码构建系统架构、设定约束条件并求解优化目标,旨在提升综合能源系统的运行效率与经济性,同时兼顾灵活性供需不确定性下的储能优化配置问题。文中还提到了相关仿真技术支持,如YALMIP工具包的应用,适用于复杂能源系统的建模与求解。; 适合人群:具备一定Matlab编程基础和能源系统背景知识的科研人员、研究生及工程技术人员,尤其适合从事综合能源系统、可再生能源利用、电力系统优化等方向的研究者。; 使用场景及目标:①研究含光热、ORC和P2G的多能系统协调调度机制;②开展考虑不确定性的储能优化配置与经济调度仿真;③学习Matlab在能源系统优化中的建模与求解方法,复现高水平论文(如EI期刊)中的算法案例。; 阅读建议:建议读者结合文档提供的网盘资源,下载完整代码和案例文件,按照目录顺序逐步学习,重点关注模型构建逻辑、约束设置与求解器调用方式,并通过修改参数进行仿真实验,加深对综合能源系统优化调度的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值