FreeRtos入门-2队列和队列集

本文讲述了在多任务环境中,如何通过队列管理和互斥量避免资源竞争,以及如何使用队列集实现灵活的数据接收。文章介绍了队列的工作原理、创建和使用步骤,以及在实际编程中的注意事项,如初始化队列和避免阻塞其他任务。
摘要由CSDN通过智能技术生成

队列

不同生产者A,B往队列里面写数据

不同消费者C,D往队列里面读数据

如果不用队列,A,B在写数据时候,A不能被B打断。那么需要用个标志位做互斥量,B进任务时,查看标志位在使用中,那么主动等待标志位为0时候再使用。

taskfunction()

{

if(flag ==0)

{

flag = 1;

A();

flag = 0;

}

}

这样代码存在问题

1,A任务执行时,轮询到B任务,虽然B任务无法被执行,但B任务占用了CPU使用率。

2,如果A任务运行到flag = 1,被B任务切换。那么B也可以继续往下执行,直到最后执行完成flag = 0,这样A再切回来时,又要从头执行。

因此使用队列替代全局变量flag判断。

队列的使用步骤

1,创建队列

2,初始化写入一次队列

3,任务中读队列,读到继续往下执行,读不到,阻塞在这里。

.

int main( void )
{
        
    #ifdef DEBUG
      debug();
    #endif
    qHandle_f = xQueueCreate(10,sizeof(int));
    xQueueSend(qHandle_f, &value, portMAX_DELAY);
    xTaskCreate(TaskGenericFunction, "Task4", 100, (void *)4, 1, NULL);
    xTaskCreate(TaskGenericFunction, "Task5", 100, (void *)5, 1, NULL);
    vTaskStartScheduler();
);

void TaskGenericFunction(void * param)
{
    int val = (int )param;

    while (1)
    {
        xQueueReceive(qHandle_f,  &value, portMAX_DELAY);
        printf("%d", val);
        xQueueSend(qHandle_f, &value, portMAX_DELAY);
        vTaskDelay(1);
    }
}

注意上面两处注意事项

1,创建完成队列后,需要写入一次,否则没有数据的队列,读队列时会发生阻塞

qHandle_f = xQueueCreate(10,sizeof(int));

xQueueSend(qHandle_f, &value, portMAX_DELAY);

2,不同任务调用同一个函数时,在使用队列时,需要加vTaskDelay,给其他任务预留运行时间,否则会一直运行这个任务

队列集

队列集的本质仍然是队列,但其特殊之处在于它内部存放的是“队列句柄”而不是直接的数据项。

当其中有队列有数据到达时,队列集的接口会返回可读的队列句柄。用户获得句柄后,就可以从相应的队列中读取数据。

与普通队列的区别

队列是一种基本的数据结构,它遵循FIFO(先进先出)的原则,即最早进入队列的数据项将首先被取出。队列通常用于任务之间的通信和数据传递,每个任务可以往队列中写入数据,也可以从队列中读取数据。队列有一定的容量限制,当队列满时,试图向其添加更多数据项的操作将被阻塞,直到有空间可用。

队列集实际上是保存了一组队列句柄的队列。它允许任务等待多个队列中的任何一个,当其中任何一个队列有数据到达时,队列集就会唤醒等待的任务。这样,任务就可以更灵活地响应来自不同输入设备的事件和数据。

总结:

功能:实现从不同设备中获取数据,数据长度 = 队列A+B。。

main:

  1. 创建队列A,B
  2. 创建队列集
  3. 将队列添加到队列集

生产者

写入队列

消费者

1)从队列集读出队列

2)处理数据

int main( void )
{
        static char str2[20];

    //1.创建队列
    qHandle_f1 = xQueueCreate(20,sizeof(int));
    qHandle_f2 = xQueueCreate(20,sizeof(str2));
    //2.创建队列集
     xQueueSet = xQueueCreateSet(40);
    //3.添加队列至队列集
    xQueueAddToSet(qHandle_f1,xQueueSet);
    xQueueAddToSet(qHandle_f2,xQueueSet);
    prvSetupHardware();
    printf("Hello, world!\r\n");
    xTaskCreate(Task1Function, "Task1", 100, NULL, 1, &xHandleTask1);
    xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);
    xTaskCreate(Task3Function, "Task3", 100, NULL, 1, NULL);
    /* Start the scheduler. */
    vTaskStartScheduler();
    return 0;
}
void Task1Function(void * param)
{
    int i = 0;

    while (1)
    {
        for(i = 0;i < 100;i++)
        xQueueSend(qHandle_f1, &i, portMAX_DELAY);
 
    }
}
void Task2Function(void * param)
{
    int i;
    char *str1 ="the number is:";
    char str2[20];
    char nchar;
    while (1)
    {
        for(i = 0;i<100;i++)
        {
            nchar = '0'+i;
            strcpy(str2,str1);
            strcat(str2,&nchar);
            xQueueSend(qHandle_f2, str2, portMAX_DELAY); 
        }
        
    }
}
void Task2Function(void * param)
{
    int i;
    char *str1 ="the number is:";
    char str2[20];
    char nchar;
    while (1)
    {
        for(i = 0;i<100;i++)
        {
            nchar = '0'+i;
            strcpy(str2,str1);
            strcat(str2,&nchar);
            xQueueSend(qHandle_f2, str2, portMAX_DELAY); 
        }
        
    }
}

程序中,

在main函数中,创建队列集,创建队列,将队列添加至队列集

其中队列长度都是20,存放数据的size不同,一个是int型,一个是指针类型

队列集的总长度是20+20。

👋

问题:如果这里的数据第一个20个char,第二个是20个指针。队列集总长度是多少?

1,队列的长度20,如果超过20发生阻塞,其他任务可以运行。

2,队列集的长度20+20,实际上是可以比20+20更大,可以存放的数据更多,如果队列集数据过小,比如也为20,那会出现队列集一直存放第一个任务的数据。而第二个得不到存储空间。

正确的做法应该是大于等于20+20

在task1中,产生0~100的数据,并把数据存入20个空间的队列1,当队列满了,会进入阻塞

在task2中,产生0~100的数据,合并字符串后,并把数据存入20个空间的队列2,当队列满了,会进入阻塞

在task3中,从队列集中取出队列,从队列中取出数据打印出来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值