硬汉嵌入式论坛

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

[FreeRTOS] 关于 xQueueSend 函数   发送结构体指针数据的疑问。

[复制链接]

1

主题

6

回帖

9

积分

新手上路

积分
9
发表于 2016-8-29 10:59:43 | 显示全部楼层 |阅读模式
问题如下:
发送函数:

/* 初始化数组 */
ptMsg->ucMessageID = 0;
ptMsg->ulData[0] = 0;
ptMsg->usData[0] = 0;
    while(1)
    {
  /* 使用消息队列实现指针变量的传递 */
  if(xQueueSend(xQueue2,     /* 消息队列句柄 */
      (void *) &ptMsg,   /* 发送结构体指针变量ptMsg的地址 */
      (TickType_t)1) != pdPASS )
  {
   /* 发送失败,即使等待了10个时钟节拍 */
   printf("向xQueue2发送数据失败,即使等待了10个时钟节拍\r\n");
  }
  else
  {
   /* 发送成功 */
   ptMsg->ucMessageID++;
   ptMsg->ulData[0]++;
   ptMsg->usData[0]++;
   printf("向xQueue2发送数据成功\r\n");      
  }
        vTaskDelay(1000);
    }

接受函数:
  xResult = xQueueReceive(xQueue2,                   // 消息队列句柄
                          (void *)&ptMsg,       // 这里获取的是结构体的地址
                          (TickType_t)xMaxBlockTime);// 设置阻塞时间
  if(xResult == pdPASS)
  {
   // 成功接收,并通过串口将数据打印出来
   printf("接收到消息队列数据ptMsg->ucMessageID = %d\r\n", ptMsg->ucMessageID);
   printf("接收到消息队列数据ptMsg->ulData[0] = %d\r\n", ptMsg->ulData[0]);
   printf("接收到消息队列数据ptMsg->usData[0] = %d\r\n", ptMsg->usData[0]);
  }
  else
  {
   // 超时
   //bsp_LedToggle(2);
   //bsp_LedToggle(3);
  }

  vTaskDelay(100);
结果应该是     printf("接收到消息队列数据ptMsg->ucMessageID = %d\r\n", ptMsg->ucMessageID);
   printf("接收到消息队列数据ptMsg->ulData[0] = %d\r\n", ptMsg->ulData[0]);
   printf("接收到消息队列数据ptMsg->usData[0] = %d\r\n", ptMsg->usData[0]);
  这几个函数应该会从“0”开始打印,然后打印一次加“1”。
  但是实际上“0“没有打印出来,第一次打印的是“1”。

实际串口结果如下:
向xQueue2发送数据成功
接收到消息队列数据ptMsg->ucMessageID = 1
接收到消息队列数据ptMsg->ulData[0] = 1
接收到消息队列数据ptMsg->usData[0] = 1
向xQueue2发送数据成功
接收到消息队列数据ptMsg->ucMessageID = 2
接收到消息队列数据ptMsg->ulData[0] = 2
接收到消息队列数据ptMsg->usData[0] = 2
向xQueue2发送数据成功
接收到消息队列数据ptMsg->ucMessageID = 3
接收到消息队列数据ptMsg->ulData[0] = 3
接收到消息队列数据ptMsg->usData[0] = 3

请问各位大侠们,这是什么原因??我百思不得其解。。。
回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2016-8-29 11:02:16 | 显示全部楼层
补充:发送任务优先级为3,接受任务的优先级为4
            如果消息队列发送的不是结构体,而是uint8_t ucQueueMsgValue;这个数据,那么跑出来的结果就是从0开始打印。这才是对的。。。纳闷了。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
发表于 2016-8-29 11:26:07 | 显示全部楼层
是不是你的程序有问题,这个是我测试的:
1.jpg
回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2016-8-29 11:42:54 | 显示全部楼层
应该没啥问题啊,就发完之后自加1,然后延迟1s,如果没有自+1的话是会发0的。


        /* 使用消息队列实现指针变量的传递 */
        if(xQueueSend(xQueue2,                    /* 消息队列句柄 */
                     (void *) &ptMsg,            /* 发送结构体指针变量ptMsg的地址 */
                     (TickType_t)1) != pdPASS )
        {
            /* 发送失败,即使等待了10个时钟节拍 */
            printf("向xQueue2发送数据失败,即使等待了10个时钟节拍\\r\\n");
        }
        else
        {   
            /* 发送成功 */
            ptMsg->ucMessageID++;
            ptMsg->ulData[0]++;
            ptMsg->usData[0]++;
            
            printf("向xQueue2发送数据成功\\r\\n");                        
        }
        
        vTaskDelay(1000);
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
发表于 2016-8-29 11:51:21 | 显示全部楼层

回 liuzjie 的帖子

liuzjie:应该没啥问题啊,就发完之后自加1,然后延迟1s,如果没有自+1的话是会发0的。


        /* 使用消息队列实现指针变量的传递 */
        if(xQueueSend(xQueue2,      .. (2016-08-29 11:42)
你的程序有点问题,如果你在高优先级的启动任务里面创建的发送任务和接收任务。

你的发送任务优先级是3,而你的接收任务优先级是4,正确的执行情况是,发送任务发送消息队列后,就会立即去执行高优先级的接收任务,也就是先执行消息
接收到消息队列数据ptMsg->ucMessageID = 1
接收到消息队列数据ptMsg->ulData[0] = 1
接收到消息队列数据ptMsg->usData[0] = 1
然后才是
向xQueue2发送数据成功

你的正好反了。
回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2016-8-29 12:01:05 | 显示全部楼层
那就更有疑问了,“正确的执行情况是,发送任务发送消息队列后,就会立即去执行高优先级的接收任务”
就算是低优先级,那也得发送完成之后,接收那边才能收到数据啊,对不对。
可是我都发送完成了才自+1的
如果没发送完成,就算跑接收程序也不会接受成功啊。。。

       /* 发送成功 */
            ptMsg->ucMessageID++;
            ptMsg->ulData[0]++;
            ptMsg->usData[0]++;
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
发表于 2016-8-29 12:05:14 | 显示全部楼层

回 liuzjie 的帖子

liuzjie:那就更有疑问了,“正确的执行情况是,发送任务发送消息队列后,就会立即去执行高优先级的接收任务”
就算是低优先级,那也得发送完成之后,接收那边才能收到数据啊,对不对。
可是我都发送完成了才自+1的
如果没发送完成,就算跑接收程序也不会接受成功啊。。。

....... (2016-08-29 12:01) 
充分论证了你的程序有bug。
回复

使用道具 举报

1

主题

6

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2016-8-29 15:02:45 | 显示全部楼层
感谢eric2013 的提醒,问题已找到,应该是程序设置的问题。
  xResult = xQueueReceive(xQueue2,                   // 消息队列句柄
           (void *)&ptMsg,             // 这里获取的是结构体的地址
           (TickType_t)xMaxBlockTime);// 设置阻塞时间
上面这个函数中的xMaxBlockTime参数不能设置过小,用原代码的300是可以的。
我因为考虑程序里面可能接受多个消息队列,所以就把xMaxBlockTime设为0,想尽快跳出,不作超时等待。理由如下
http://www.freertos.org/a00118.html        Setting xTicksToWait to 0 will cause the function to return immediately if the queue is empty
xTicksToWait为0的时候如果队列为空会立即跳出
但是实际上会丢一些数据,

顺便问一下eric2013 兄弟,
1.如果我在一个任务里面要接收2个以上的消息队列,该怎么处理好点??要是每个等待300ms超时总感觉处理不过来,毕竟别的任务还是要运行的。
2.在消息队列等待300ms超时这个过程里面会不会释放CPU使用权给更低级的任务运行??
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
发表于 2016-8-29 21:58:37 | 显示全部楼层

回 liuzjie 的帖子

liuzjie:感谢eric2013 的提醒,问题已找到,应该是程序设置的问题。
  xResult = xQueueReceive(xQueue2,                   // 消息队列句柄
     &nbs .. (2016-08-29 15:02) 
要充分理解消息队列里面这个延迟的作用。
这个延迟的作用是表示,此任务从消息队列里面获取数据,如果有数据,就立即获取,如果没有数据就就此任务挂起,并将挂起时间设置为300ms。如果300ms期间受到了消息,此任务立即就从挂起状态恢复到就绪态了,如果300ms内没有收到,300ms后也从挂起状态恢复到就绪态,就是这么个意思,不会丢失任何消息的。除非你发送的比较快,导致消息队列满了,不能再发送了。
======================================
另外你设置为0,是表示立即读取。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-15 00:51 , Processed in 0.268137 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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