STM32工作笔记0087---UCOSIII消息传递_消息队列

技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152

STM32工作笔记0087---UCOSIII消息传递_消息队列_第1张图片

STM32工作笔记0087---UCOSIII消息传递_消息队列_第2张图片

STM32工作笔记0087---UCOSIII消息传递_消息队列_第3张图片

STM32工作笔记0087---UCOSIII消息传递_消息队列_第4张图片

这里任务间通信可以有两种方式,全局变量是一种,比如A,B,任务,占用资源C

那么,这里可以使用,关闭中断,信号量,互斥信号量,上锁的方式来保证资源的独占.

还可以使用消息队列

STM32工作笔记0087---UCOSIII消息传递_消息队列_第5张图片

这里数据的指针,就是比如把数据放到一个数组里,那么这里传的就是这个数组的指针.

然后这个可见性

STM32工作笔记0087---UCOSIII消息传递_消息队列_第6张图片

这个可见性指的是,比如这里的,

在A,B之间传递消息C,那么C这个数据,在,A,B传递过程中要保证C这个数据,一直都是有效的.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第7张图片

这里,我们消息队列,传递数据,用的是指针,要注意并不是copy数据,因为copy数据,还需要占用内存.

这里传递一个指针,不会占用内存.节省了内存.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第8张图片

然后这里采用动态内存分配的技术,给消息分配内存块用malooc,使用完内存再释放

然后要注意传递的消息,可以是全局变量,全局数据结构,全局数组,函数指针

STM32工作笔记0087---UCOSIII消息传递_消息队列_第9张图片

一定不要是局部的,因为局部的,脱离了函数,就无效了,那么

很可能导致传递过去的数据就无效了.

所以这里消息数据的定义,一定要使用全局的,或者使用static,来定义一下这个变量.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第10张图片

消息队列就是个结构体.

去看看代码

STM32工作笔记0087---UCOSIII消息传递_消息队列_第11张图片

STM32工作笔记0087---UCOSIII消息传递_消息队列_第12张图片

消息队列的函数,是这个文件os_q.c

STM32工作笔记0087---UCOSIII消息传递_消息队列_第13张图片

去看看这个OS_Q这个消息队列结构

STM32工作笔记0087---UCOSIII消息传递_消息队列_第14张图片

可以看到这个os_q的消息队列结构

STM32工作笔记0087---UCOSIII消息传递_消息队列_第15张图片

然后看看这个结构体中的OS_MSG_Q这个值.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第16张图片

可以看到这里

InPtr 这个是就是 in进入

OutPtr 这个就是 out出,都是个指针

这里就是消息队列的进和出

因为有个队列那么把数据插入到消息队列的什么位置,用这个in来设置,

然后读取的时候,这个消息数据就要OUT

然后NbrEntriesSize,这个是消息队列中,能插入的消息最大数

然后NbrEntries是,当前消息队列用了允许的最大数的多少.

然后NbrEntriesMax这个是,从开始到现在,历史上用到过的,消息队列最大值是多少.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第17张图片

举个例子,这里一个消息队列,有4个盒子,也就是说,

这个消息队列最大可以放四个数据块NbrEntriesSize

然后如果来了第5个数据块,那么就不能放了,就要等第一个数据块

获取了数据以后,才能用.

然后,咱们说还有一个时间戳,去看看

STM32工作笔记0087---UCOSIII消息传递_消息队列_第18张图片

STM32工作笔记0087---UCOSIII消息传递_消息队列_第19张图片

.STM32工作笔记0087---UCOSIII消息传递_消息队列_第20张图片

STM32工作笔记0087---UCOSIII消息传递_消息队列_第21张图片

可以看到跟上面说的一样,这个消息,第一个NextPtr这个是指向下一个消息的指针

然后MsgPtr这个是指向当前消息数据的指针

然后MsgSize这个是,消息的大小

然后MsgTs是时间错可以看到就是这三个都有了.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第22张图片

可以看到这个图就比较清楚了.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第23张图片

标红的是重点的三个

去代码看看这三个函数

STM32工作笔记0087---UCOSIII消息传递_消息队列_第24张图片

OSQCreate()这个是创建消息队列

p_q是消息队列

然后p_name是消息名称

然后max_qty是 消息队列最大容纳多少个消息

p_err 是错误码

STM32工作笔记0087---UCOSIII消息传递_消息队列_第25张图片

这里,是请求消息队列

OSQPend()

p_q是要请求哪个消息队列

timeout是超时 ,0就是一直等待消息队列

opt是选项,去看看选项.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第26张图片

这个

OS_OPT_PEND_BLOCKING 是阻塞等待和

OS_OPT_PEND_NON_BLOCKING是不阻塞等待.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第27张图片

这个是接收到的消息的大小是多少

p_ts是时间错

p_err是错误码

STM32工作笔记0087---UCOSIII消息传递_消息队列_第28张图片

这个是消息发送,第一个p_q是

要向哪个消息队列发送消息

p_void是真正的消息,这里是指针,就是要发送什么样的消息.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第29张图片

这个是msg_size这个是要发送的消息的大小,这里要注意,这里是字节.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第30张图片

这里

选项的话

OS_OPT_POST_ALL这个,是向所有等待这个消息的任务发送消息

然后

OS_OPT_POST_FIFO 是,消息的进出方式,FIFO,先进先出

OS_OPT_POST_LIFO 是,消息的进出方式,LIFO,后进先出

OS_OPT_POST_NO_SCHED这个是 不做任务切换.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第31张图片

选项还可以做一些组合使用,具体的组合方法已经列出来了.

去看看案例去:

STM32工作笔记0087---UCOSIII消息传递_消息队列_第32张图片

这里,开始任务start_task然后

STM32工作笔记0087---UCOSIII消息传递_消息队列_第33张图片

main任务

STM32工作笔记0087---UCOSIII消息传递_消息队列_第34张图片

然后按键处理任务

STM32工作笔记0087---UCOSIII消息传递_消息队列_第35张图片

消息显示任务

然后后面代码:

STM32工作笔记0087---UCOSIII消息传递_消息队列_第36张图片

可以看到,这里

KEYMSG_Q_NUM 1这个是定义了,消息队列的数量,按键消息队列的数量,这里按键消息队列只能存储一个消息

然后

DATAMSG_Q_NUM 4这个是 发送数据的消息队列的数量,可以发送4个消息

然后这里定义了

OS_Q KEY_msg 按键消息的消息队列,用来模拟消息邮箱,咱们知道

再UCOII中是由消息邮箱概念的,在UCOSIII中没有消息邮箱概念了

消息邮箱和普通的消息队列的区别就是,消息邮箱,只能存放一条消息数据.

 

OS_Q DATA_Msg 定义一个数据消息队列用来发送消息的

STM32工作笔记0087---UCOSIII消息传递_消息队列_第37张图片

后面声明了一个定时器.,可以看到定时器的回调函数

STM32工作笔记0087---UCOSIII消息传递_消息队列_第38张图片

然后main函数中,创建消息队列

然后去创建定时器1

STM32工作笔记0087---UCOSIII消息传递_消息队列_第39张图片

然后再去创建三个任务

STM32工作笔记0087---UCOSIII消息传递_消息队列_第40张图片

然后去看看,定时器1的,回调函数做了啥.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第41张图片

可以看到,首先去申请一段内存,然后

STM32工作笔记0087---UCOSIII消息传递_消息队列_第42张图片

然后这里,往申请的内存中去放一个字符串,pbuf中放入字符,然后

执行的次数msg_num++,也就是发送消息的次数,也放到申请的内存pbuf中去.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第43张图片

然后再去发送消息,就把这个pbuf发送出去,可以看到

定了10个消息长度,然后

选项,先进先出

STM32工作笔记0087---UCOSIII消息传递_消息队列_第44张图片

然后再判断发送消息成功,发生错误的时候,就释放内存,停止定时器,

然后定时器的运行状态更新为停止运行

然后屏幕打出,定时器停止的字样.

这里为什么要,出现错误的时候要,停止定时器呢?

因为咱们知道,这个定时器,一直执行,所以会一直申请内存,那么

也没释放内存,所以这里一直申请内存就会

导致内存溢出,溢出以后,再发送消息除了错误,这里就要关闭定时器,不让他再去申请内存了.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第45张图片

malloc这个文件,定义了这个函数

再看看main函数

STM32工作笔记0087---UCOSIII消息传递_消息队列_第46张图片

这里,当按下key0的时候

去发送消息然后,检测一下消息队列的容量是多少.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第47张图片

可以看到这里的key就是个值

那么可以看到,这里就是把key的值取出来,放到消息里面,发送出去了

STM32工作笔记0087---UCOSIII消息传递_消息队列_第48张图片

然后再去看看

这个按键消息处理任务

STM32工作笔记0087---UCOSIII消息传递_消息队列_第49张图片

STM32工作笔记0087---UCOSIII消息传递_消息队列_第50张图片

可以看到,这个按键消息处理任务重针对,不同的按键做了不同的操作.

然后消息显示任务

STM32工作笔记0087---UCOSIII消息传递_消息队列_第51张图片

可以看到,消息显示任务,这里

msgdis_task就是,先去请求消息

然后,然后把请求到的消息,显示出来,

然后再释放消息内存,这个

释放消息内存,就对应

STM32工作笔记0087---UCOSIII消息传递_消息队列_第52张图片

前面,定时器的回调函数中消息申请内存

然后下载到开发版上看一下

STM32工作笔记0087---UCOSIII消息传递_消息队列_第53张图片

 启动可以看到这类定时器1,首先是停止的,

然后,再去看看,检查消息队列大小

STM32工作笔记0087---UCOSIII消息传递_消息队列_第54张图片

这里可以看到,这里用消息队列的大小,减去当前使用了的,消息的大小,

从而,获取到,消息队列剩余的大小

msgq_remain_size

STM32工作笔记0087---UCOSIII消息传递_消息队列_第55张图片

可以看到,数据消息发送队列,是4,剩余也是4.

 STM32工作笔记0087---UCOSIII消息传递_消息队列_第56张图片

然后按下不同按键就有对应的反应.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第57张图片

可以看到,按键以后,就可以看到,DATA_MSG去显示消息,同时剩余的DATA_Msg_rema

就增加了

STM32工作笔记0087---UCOSIII消息传递_消息队列_第58张图片

任务内建消息,用于,多个任务等待统一消息队列.

看看代码如何使用:

STM32工作笔记0087---UCOSIII消息传递_消息队列_第59张图片

STM32工作笔记0087---UCOSIII消息传递_消息队列_第60张图片

有三个任务,start开始任务,main任务,然后

消息任务

STM32工作笔记0087---UCOSIII消息传递_消息队列_第61张图片

然后,声明,任务内建消息长度

定时器1.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第62张图片

main函数中,可以看到,这里并没有创建消息队列,只是创建了定时器1.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第63张图片

而且又去创建了各个任务

msgdis_TaskTcb这个是消息显示任务

STM32工作笔记0087---UCOSIII消息传递_消息队列_第64张图片

这个是定时器的回调函数,可以看到这里

OSTaskQPost

这个是发送消息的话,就是给哪个任务去发送消息OS_TCB

然后这里按键

STM32工作笔记0087---UCOSIII消息传递_消息队列_第65张图片

STM32工作笔记0087---UCOSIII消息传递_消息队列_第66张图片

按键没有做消息发送,仅仅做了按键扫描然后,开启,和停止定时器就可以了.

STM32工作笔记0087---UCOSIII消息传递_消息队列_第67张图片

这显示的话,就是请求的时候,没有,请求哪个消息队列,默认就是请求自己任务的消息队列.

去下载到开发版看看效果

STM32工作笔记0087---UCOSIII消息传递_消息队列_第68张图片

 

 

 

 

 

你可能感兴趣的:(硬件嵌入式)