硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3470|回复: 4
收起左侧

[FreeRTOS] FreeRTOS测试实验

[复制链接]

3

主题

5

回帖

14

积分

新手上路

积分
14
发表于 2018-9-8 10:22:34 | 显示全部楼层 |阅读模式

一、队列
1.创建三个任务一个队列:
```
/*声明一个类型为xQueueHandle的变量,其用于保存队列句柄,以便三个任务都可以引用此队列*/
xQueueHandle xQueue;
static void AppTaskCreate (void)
{
/*创建的队列用于保存最多5个值,每个数据单元都有足够的空间来存储一个long型变量*/
  xQueue=xQueueCreate(5,sizeof(long));
  if(xQueue != NULL)
  {
    /*创建连个写队列任务实例,任务入口参数用于传递发送到队列的值。所以一个实例
    不停的发送100,而另一个任务实例不停的往队列发送200.两个任务的优先级都设为1.*/
    xTaskCreate(vSenderTask,"Sender1",1000,(void*)100,1,NULL);
    xTaskCreate(vSenderTask,"Sender2",1000,(void*)200,1,NULL);
    /*创建一个读队列任务实例。其优先级设为2,高于写任务优先级*/
    xTaskCreate(vReceiverTask,"Receiver",1000,NULL,2,NULL);

  }
}
```
2.发送任务(有两个实列):
```
static void vSenderTask(void *pvParameters)
{
  long ValueToSend;
  portBASE_TYPE xStatus;
  /*该任务会被创建两个实例,所以写入队列的值通过任务入口参数传递;
  这种方式使得每个实例使用不同的值。队列创建时指定其数据单元为long型,
  所以把入口参数强制转换为数据单元要求的类型*/
  ValueToSend = (long) pvParameters;
  for(;;)
  {
    /*往队列发送数据
    第一个参数是要写入的队列。队列在调度器启动之前就被创建了,所以先于此任务执行;
    第二个参数是被发送数据的地址,本例中即变量ValueToSend的地址;
    第三个参数是阻塞超时时间-当队列满时,任务转入阻塞状态以等待队列空间有效。本例
    中没有设定超时时间,因为此独列绝不会保持超过一个数据单元的的机会(因为读数据的
    任务优先级更高),所以也绝不会满,这正是我们要测试的特性*/
    xStatus = xQueueSendToBack(xQueue,&ValueToSend,0);
    if(xStatus != pdPASS)
    {
      /*发送操作由于队列满而无法完成-这是不可能发生的,本例中队列不可能满*/
      printf("Could not send to the queue.\r\n");   
    }
    /*允许其它发送任务执行。taskYIELD()通知调度器现在就切换到其它任务,而不必等到
    本任务的时间片耗尽,这个非常有必要否则无法立即转而执行实例2*/
    taskYIELD();
  }
}
```
3.接收队列数据任务:
```
static void vReceiverTask(void *pvParameters)
{
  /*声明变量,用于保存从队列中接收的值*/
  long ReceivedValue;
  portBASE_TYPE xStatus;
  const portTickType xTicksToWait = 100/portTICK_RATE_MS;
  for(;;)
  {
    /*此调用会发现队列一直为空,因为本任务将立即删除刚写入的数据单元(首先因为
    任务优先级高,第一次会发现队列为空,因为写任务优先级低,而当写任务写入了数
    据后又被该任务立即读取了,也就是删除了,所以永远为空)*/
    if(uxQueueMessagesWaiting(xQueue)!=0)
    {
      printf("Queue should have been empty\r\n");
    }
    /*往队列接收数据
    第一个参数是要被读取的队列。队列在调度器启动之前就被创建了,所于优先于此任务
    执行;
    第二个参数是保存接收到数据的缓冲区地址。此变量类型与队列数据单元类型相同,
    所以有足够的大小来存储接收到的数据;
    第三个参数是阻塞超时时间-当队列为空时,任务转入阻塞状态以等待队列数据有效。
    本例中常量portTICK_RATE_MS用来将100ms绝对时间转换为系统心跳为单位的时间值*/
    xStatus = xQueueSendToBack(xQueue,&ReceivedValue,xTicksToWait);
    if(xStatus == pdPASS)
    {
      /*成功读出数据,打印出来*/
      printf("Received= %ld\r\n",ReceivedValue);
    }
    else
    {
      /*等待100ms也没有收到任何数据
      必然存在错误,因为发送任务在不停的往队列中写入数据*/
      printf("Could not receive from the queue.\r\n");
    }

  }
}
4.串口截图:

按理应该交叉打印100和200的
这个是为什么呢?
5.分析:
首先执行读取任务,读取任务进入100ms阻塞,写入任务实例1得以运行,当任务1写入数据100后,读取任务
立刻返回读取,数据被删除了,读取任务重新进入阻塞状态,程序返回到taskYIELD()立即切换到实例2,
写入数据200,立刻又被读取任务读取,数据被删除,循环往复,所以串口应该交叉打印100和200.

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2018-9-8 10:30:11 | 显示全部楼层

回帖奖励 +3 个金币

为什么接收任务里面也是调用的xQueueSendToBack
回复

使用道具 举报

3

主题

5

回帖

14

积分

新手上路

积分
14
 楼主| 发表于 2018-9-8 10:47:44 | 显示全部楼层
唉,自己太不认真了
回复

使用道具 举报

3

主题

5

回帖

14

积分

新手上路

积分
14
 楼主| 发表于 2018-9-8 10:49:51 | 显示全部楼层
eric2013 发表于 2018-9-8 10:30
为什么接收任务里面也是调用的xQueueSendToBack

带了操作系统后我就一直不太会调试了,每次总是跑到莫名的地方
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106978
QQ
发表于 2018-9-8 14:29:53 | 显示全部楼层
zidone 发表于 2018-9-8 10:49
带了操作系统后我就一直不太会调试了,每次总是跑到莫名的地方

慢慢习惯了就好了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-13 05:21 , Processed in 0.157304 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表