立志最细,在FreeRtos中数据传输方式及应用!!!

                                前言:本文参考,B站韦东山,开发文档,连接放在最后

为什么需要数据传输

        在FreeRtos操作系统中,任务之间的数据传输是为了协调任务之间的协作同步,当Task_a和Task_b为同步执行,Task_b会判断Task_a的返回值,当返回值为真的时候,Task_b执行这样就实现了任务之间的同步。   

数据传输方式

        常见的数据传输方法有,全局变量传输环形缓冲区buffer传输,队列queue传输,三种方法各有不同。

数据个数 互斥措施 阻塞-唤醒
全局变量 1
环形缓冲区buffer 多个
队列 多个

全局变量传输数据

        使用全局变量在两个Task之间进行数据传输,每次只能传输一个数据,同时没有互斥措施,跟阻塞唤醒的措施,同时需要注意的是在声明的时候需要加volatile关键字。

        当Task_a和Task_b之间使用全局变量来传输数据完成同步,阻塞唤醒机制的缺失导致Task_b使用cpu资源判断Task_a是否执行结束,导致cpu利用率比较低。

static volatile int g_flag_date;

           同时这种放在在传输数据时,由于Task的相互切换可能会导致造成,访问得到的数据的值是一个错误的值。

volatile int Receive_Date_x;
volatile int Receive_Date_y;
typedef struct
{
    int x;
    int y;
}Date_flag;

Date_flag Date;

xTaskCreate(Task1, "Task1_function", 128, NULL, osPriorityNormal, &Task1_Handle);
xTaskCreate(Task2, "Task2_function", 128, NULL, osPriorityNormal, &Task2_Handle);

void Task1_function(void)
{
    Date->x = 1;
    Date->y = 2;
}
void Task2_function(void)
{
   Receive_Date_x = Date->x;
   Receive_Date_y = Date->y;   
}



        在运行操作系统执行Task的时候,会出现一种情况,当Task1调用函数执行到给x赋值完就被切换出去,Task2的执行调用函数执行如果执行完,这个时候y是没有值的,这个值就出错了。

数据缓冲区buffer传输数据

        这种方式能够在两个Task之间传输数据,环形缓冲区是一个数组,通过在数组中写数据,可以实现多种数据的传输。

int buffer[8];//传输数据数组
int r=0,w=0;//读写变量

        这里在一个buffer中,如果 r=w=0这个时候代表,这个buffer是空的,当w写到7的位置,这个时候已经写完了,而r还没有开始读,这个时候buffer是已经满的,同时通过r和w这两个变量就能通过对buffer数组的数据,进行写入读取

#define Buffer_Size 8

int next_w = (w+1)%Buffer_Size;//写满从0开始

if(next_w!=r)//这个时候还没有写满,可以继续写
{
    buffer[w] = value;
    w++;
    if(w==8)
    {
        w = w % 8//此时w从0开始
    }
}

        上面是写操作,同样的根据这段代码可以进行读操作

队列(Queue)传输数据

        队列传输数据的本质就是环形缓冲区buffer ,同时增加了互斥措施,阻塞-唤醒机制,如果队列不传输数据,只调整"数据个数"就是信号量Semaphore,如果限制"数据个数"最大为1就是互斥量Mutex

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
//创建成功返回句柄 失败NULL      queue长度               每个数据大小字节为单位                   

     队列的创建方法分为静态创建和动态创建,区别在于静态创建的内存要提前确定好,同时静态创建比动态创建多一个参数。

QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength,UBaseType_t uxItemSize,uint8_t*pucQueueStorageBuffer, StaticQueue_t *pxQueueBuffer );

        同时通过创建队列留下的句柄,还可以对队列进行复位删除队列,这里的复位是指将队列原本的数据丢弃,

BaseType_t xQueueReset( QueueHandle_t pxQueue);
void vQueueDelete( QueueHandle_t xQueue );

                                        希望对你,有所帮助!!!

猜你喜欢

转载自blog.csdn.net/weixin_62292999/article/details/142454354