×
单片机 > 单片机程序设计 > 详情

STM32 uCOS_II 实践 之 消息邮箱

发布时间:2020-06-19 发布时间:
|
所谓的消息邮箱并不是把数据进行传输,而是在合适的时间告诉任务去使用哪些变量或者当一些特殊的变量变化后可以及时并准确的使用变量,消息邮箱传递的是这些变量的指针,而这些变量本身就已经存在与内存中了,他们多以全局变量或者静态变量的形式存在。

首先介绍消息邮箱的一种使用方式,就是只传递一个非空指针,告诉等待消息的任务他等待的时间到了,但是这个指针里并没有有用的数据,而任务中也不应该对这个地址指向的变量进行任何的读取和写入操作,读写操作都是无意义的,从另外一个角度来看,虽然借用了别人的地址但是本身并没有对地址里的数据进行操作,所以地址里的数据也是安全的,说白了就是消息邮箱版信号量(非计数)。它的好处就是可以在系统里把信号量有关的代码给裁剪掉,但缺点是他并无法达到信号量的全部功能,这种用法无法进行计数,只是单纯的传递一次状态。如果把消息队列改造成计数信号量,个人觉得很没必要,除非你选的MCU非常的尴尬。权且就让这种方式作为初步了解消息邮箱的一个引子吧。

使用消息邮箱可以分为4个步骤:

步骤1:声明一个指针变量,这个指针变量在初始化消息邮箱的时候会把这个消息邮箱对应的事件控制块的指针存放进去。


void *Mbox_Task_LED1;

步骤2:对消息邮箱进行初始化,也就是初始化对应的事件控制块,并且会把这个事件控制块的指针作为返回值赋值给第一步声明的指针变量。消息邮箱初始化函数有一个参数,应该设置为空指针,表示消息邮箱为空。


Mbox_Task_LED1 = OSMboxCreate((void *)0);

 
步骤3:在任务里设置等待消息函数,当这个任务执行到这句话的时候,系统会把这个任务挂起,等待有消息的发送。这个函数里有3个变量,第一个参数是指等待的是哪个消息邮箱,第二个参数是指等待时间单位为系统心跳,0指无时间期限的等待,第三个参数为返回的错误类型。


OSMboxPend(Mbox_Task_LED1,0,&err);

步骤4:在其他的任务里或者中断服务程序里设置发送消息函数,需要注意的是,这个函数并不会引起系统调度,所以如果把它放在中断服务函数里的话就要去中断里的内容尽量简短,以保证消息发送出去后,能进来快的进行系统调度让消息接受函数相应。在这个函数里有2个参数,第一个参数为要发送给哪个消息邮箱,第二个参数为发送的数据的地址。在这里其实并没有真实的数据,只是把发送的地址用了一个非空地址,这个地址及其指向的数据都没有任何意义,也不需要进行任何的读写操作,只是传递一个消息到相应的等待函数,以解除对应任务的挂起状态。


OSMboxPost(Mbox_Task_LED1,(void *)1);

下面看下具体的代码:
步骤2和步骤3:


void Task_LED1(void* p_arg)
{
(void) p_arg ;

Mbox_Task_LED1 = OSMboxCreate((void *)0); // 创建消息邮箱,初值为空指针
while(1)
{
OSMboxPend(Mbox_Task_LED1,0,&err); // 等待邮箱的消息

LED1_HIGH;
OSTimeDlyHMSM(0,0,1,0);
LED1_LOW;
OSTimeDlyHMSM(0,0,1,0); // 延时,用来给其他任务留有运行的时间
}
}

步骤4:


void Interrupt_Handle_KEY3(void)
{
OSIntEnter();

// 在中断服务函数里如果调用ucos系统函数的话就必须加上进中断系统函数出去的时候要加上出中断系统函数

OSMboxPost(Mbox_Task_LED1,(void *)1);

// 发送邮箱消息,这个函数并不会引起系统调度,所以中断服务函数一定要简洁。
EXTI_ClearITPendingBit(EXTI_Line3); // 清除标志位

OSIntExit();
}


=======================================================================================================
下面说下传递一个真实的变量,步骤和上面是一样的,只不过在步骤3和步骤4的地方会有对变量的转换。代码如下:
步骤2和步骤3:


void Task_LED1(void* p_arg)
{
unsigned char num ;
unsigned char pp;
(void) p_arg ;

Mbox_Task_LED1 = OSMboxCreate((void *)0); // 创建消息邮箱,初值为空指针
while(1)
{
num = *(unsigned char *)OSMboxPend(Mbox_Task_LED1,0,&err); // 等待邮箱的消息
pp = num; // 这个变量用于仿真时数据监测
while(pp--)
{
LED1_HIGH;
OSTimeDlyHMSM(0,0,0,200);
LED1_LOW;
OSTimeDlyHMSM(0,0,0,200);
}
}
}

步骤4:


void Interrupt_Handle_KEY3(void)
{
OSIntEnter();

// 在中断服务函数里如果调用ucos系统函数的话就必须加上进中断系统函数出去的时候要加上出中断系统函数

OSMboxPost(Mbox_Task_LED1,(void *)&Num);

// 发送邮箱消息,这个函数并不会引起系统调度,所以中断服务函数一定要简洁。
EXTI_ClearITPendingBit(EXTI_Line3); // 清除标志位

OSIntExit();
}


如步骤4红色注释部分,在发送的时候把一个具体的变量取地址,并且强制转换为一个无定义变量的指针;在步骤3红色注释部分,在等待函数外部首先进行的时候变量类型的转换,转换成一个无符号字符型变量的指针,然后在进行间指操作,把地址里的数据取出来,最后赋值给函数的临时变量进行使用。					
					
					
关键字:STM32  uCOS  II  消息邮箱

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM 汇编的必知必会