立志最细,在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 );
希望对你,有所帮助!!!