• ucosIII_消息队列


     1.消息队列的作用

     对比信号量和互斥信号量。信号量和互斥信号量是用来完成任务间同步或共享资源加锁的。也就是说这两种都是一种flag标志位作用。表示一种事件的发生,并不能传递数据。那比如说我想让任务A给任务B发送4个字节的数据,怎么办?所以引入了消息队列的概念。

    2.消息队列的API 文件os_q.c

    2.1创建消息队列

    void  OSQCreate (OS_Q        *p_q,
                     CPU_CHAR    *p_name,
                     OS_MSG_QTY   max_qty,
                     OS_ERR      *p_err)

     第一个参数是一个消息队列的结构体变量,需要先定义在:

    OS_Q DATA_Msg;                //定义一个消息队列,用于发送数据

    第二个参数是一个名字

    第三个参数是是需要传递的数据的长度,字节为单位

    第四个参数是保存返回值的变量

    2.2删除消息队列

    OS_OBJ_QTY  OSQDel (OS_Q    *p_q,
                        OS_OPT   opt,
                        OS_ERR  *p_err)

    2.3发送消息

    void  OSQPost (OS_Q         *p_q,
                   void         *p_void,
                   OS_MSG_SIZE   msg_size,
                   OS_OPT        opt,
                   OS_ERR       *p_err)

     第一个参数是一个消息结构体变量

    第二个参数是传递的数据的第一个字节的地址(如果是数组则传数组名,如果是malloc分配的内存需要传对应的指针即可)

    第三个参数是传递数据的大小,字节为单位

    第四个参数是 

      OS OPT POST ALL
      OS OPT POST FIFO
      OS OPT POST LIFO
      0S OPT POST NO SCHED

    2.4请求消息

    void  *OSQPend (OS_Q         *p_q,
                    OS_TICK       timeout,
                    OS_OPT        opt,
                    OS_MSG_SIZE  *p_msg_size,
                    CPU_TS       *p_ts,
                    OS_ERR       *p_err)

    第一个参数是消息结构体变量

    第二个参数是超时时间

    第三个参数是设置阻塞还是不阻塞

    第四个参数是传递的数据的大小(这个参数是一个输出型参数,是请求到数据后自动计算有多少字节的数据,我们需要读它)

    第五个参数是时间戳

    第六个参数是记录错误返回值的

    使用过程:

    1 任务A发送消息队列,包含数据多少字节

    2 任务B接收消息队列,自动计算消息队列有多少字节

     3.任务之间使用消息队列传递数据

    现在创建2个任务A和B,任务A发送数据,任务B接收数据。先使用消息队列发送字符串在发送4个字节的int数据。记录下遇到的问题。

    3.1传递字符串

    省略基础代码,只保留和消息队列相关的。

    定义数据大小和消息队列(全局)

    #define MyMsgSizeInByte    4    //发送数据的消息队列的大小
    OS_Q MyMsg;                //定义一个消息队列,用于发送数据

    创建消息队列(在第一个任务中,)

    //创建消息队列MyMsg
        OSQCreate ((OS_Q*        )&MyMsg,    
                    (CPU_CHAR*    )"MyMsg",    
                    (OS_MSG_QTY    )MyMsgSizeInByte,    
                    (OS_ERR*    )&err);    

    任务A:发送数据

    //任务A的任务函数
    void taskA(void *p_arg)
    {
        OS_ERR err;
        u8 *p;
        u8 *pbuf;
    char * TaskAData = "TaskADatatoPost";
    while(1) { printf("任务1 "); OSQPost(&MyMsg,TaskAData,sizeof(TaskAData),OS_OPT_POST_FIFO + OS_OPT_POST_ALL,&err);
         printf("任务1 post 数据:%s ",TaskAData);
            OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);   //延时10ms
        }
    }

    任务B:请求数据

    //任务B任务函数
    void taskB(void *p_arg)
    {    
        u8 num;
        u8 datas[4]= {0};
        OS_MSG_SIZE size = 10;
        OS_ERR err;
        u8 *TaskBData;
        
        while(1)
        {
            //printf("任务2
    ");
            TaskBData = OSQPend(&MyMsg,0,OS_OPT_PEND_BLOCKING,&size,0,&err);
           
            printf("任务2 pend 数据:%s
    ",TaskBData);
            printf("size大小%d
    ",size);
            OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);   //延时1s   
        }
    }

    结果

    发送字符串很顺利。

    3.2传递多个int类型数据

     在发送4个字节int数据时遇到了个问题,只能接收第一个字节的数据。

    定义了1个全局数组用来发送数据

    int datatopost[4] = {15,16,17,18}; //存放任务A发
    
    任务A:发送数据
    //任务A的任务函数
    void taskA(void *p_arg)
    {
        u8 key,num;
        OS_ERR err;
        u8 *p;
        u8 *pbuf;
    while(1)
        {
            
            printf("任务1
    ");
    
            OSQPost(&MyMsg,datatopost,4,OS_OPT_POST_FIFO + OS_OPT_POST_ALL,&err);
            printf("任务1 post 数据:%d%d%d%d
    ",datatopost[0],datatopost[1],datatopost[2],datatopost[3]);
    
            OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);   //延时1s
        }
    }

    任务B:接收数据

    //任务B任务函数
    void taskB(void *p_arg)
    {    
        u8 num;
        u8 datas[4]= {0};
        OS_MSG_SIZE size = 10;
        OS_ERR err;
        u8 *TaskBData;//接收数据的指针
    
        while(1)
        {
            //printf("任务2
    ");
            TaskBData = OSQPend(&MyMsg,0,OS_OPT_PEND_BLOCKING,&size,0,&err);
            printf("任务2 pend 数据:%d%d%d%d
    ",TaskBData[0],TaskBData[1],TaskBData[2],TaskBData[3]);
    
            printf("size大小%d
    ",size);
            OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);   //延时1s
    
             
        }
    }

    结果:

     我在任务B中定义了一个u8指针用来接收这4个字节的数据。但是从运行结果中看到任务B确实接收到了4个字节,但是只能接收到第一个字节的数据。经过查找资料,最后发现要使用malloc给消息队列分配内存才行,改进代码后,任务A发送的数据不再使用全局变量,在任务A中使用malloc函数分配内存,经过测试只要发送的时候使用malloc,任务B接收的时候直接定义一个指针还是使用malloc分配内存,都可以接收到。关于详细的介绍在最后面的博客地址中有介绍。下面使用的mymalloc是原子封装的ucos系统下的malloc函数。

    任务 A

    //任务A的任务函数
    void taskA(void *p_arg)
    {
        u8 key,num;
        OS_ERR err;
        u8 *p;
        u8 *pbuf;
       
        pbuf = mymalloc(SRAMIN,10);    //申请10个字节
        pbuf[0]=15;pbuf[1]=16;pbuf[2]=17;pbuf[3]=18;
        
        while(1)
        {
            
            printf("任务1
    ");
    
            OSQPost(&MyMsg,pbuf,4,OS_OPT_POST_FIFO + OS_OPT_POST_ALL,&err);
            printf("任务1 post 数据:%d%d%d%d
    ",pbuf[0],pbuf[1],pbuf[2],pbuf[3]);
    
            OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);   //延时1s
        }
    }

    任务B

    //任务B任务函数
    void taskB(void *p_arg)
    {    
        u8 num;
        u8 datas[4]= {0};
        OS_MSG_SIZE size = 10;
        OS_ERR err;
        u8 *TaskBData;
        //TaskBData = mymalloc(SRAMIN,10);    //申请10个字节 无论这里是否分配内存都可以接到4个字节完整的数据
    
        while(1)
        {
            //printf("任务2
    ");
            TaskBData = OSQPend(&MyMsg,0,OS_OPT_PEND_BLOCKING,&size,0,&err);
            printf("任务2 pend 数据:%d%d%d%d
    ",TaskBData[0],TaskBData[1],TaskBData[2],TaskBData[3]);
    
            printf("size大小%d
    ",size);
            OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);   //延时1s
         
        }
    }

    结果:

      参考资料:

    1.消息队列接收数据覆盖问题https://blog.csdn.net/u012252959/article/details/53115024

    2.原子的mymalloc

  • 相关阅读:
    java-version
    Centos7使用google-Chrome浏览器
    sign_and_send_pubkey: signing failed: agent refused operation
    删除带中划线的数据库
    yum update报错RPM数据库问题
    Centos的timedatectl
    /var/lib/docker/overlay2/db72dadf047395c178feb0eaedd932b48e283abcaa5a870c0c746bab8ee6f76a: no such file or directory
    /bin/bash^M: 坏的解释器: 没有那个文件或目录
    repeat()函数
    (Problem 47)Distinct primes factors
  • 原文地址:https://www.cnblogs.com/1024E/p/13416955.html
Copyright © 2020-2023  润新知