这个小作品是uCOSII多任务系统的简单应用,使MCU(STM32F103)可以“同时”执行多个任务。并使用邮箱在多任务系统中通信。如果需要可以在文字末尾下载到完整的工程,其中System文件夹中3个文件由原子提供,提供了一些函数,便于编程和debug,具体可参看原子官方的教程。
(本作品由于没有电机驱动,所以用三个三极管将就,这是不规范操作,效果也一般)
本工程中创建了5个任务,并设置最多为12个任务。分别是:
1. led0_task:控制LED灯的亮灭
2. MQ2_task : 检测烟雾传感器的值
3. FC_task : 检测是否有火焰
4. Alter_task : 接受邮箱信息,决定是否分通过蜂鸣器报警,启动电风扇。
5. LIGHT_task : 控制一个三色LED
由于是该模块与其他模块有通讯,工程中添加了无线模块驱动和初始化程序。假设不需要无线模块,注释初始化代码即可。硬件模块是一些常用模块,可以在网络上查看其简介
#define START_TASK_PRIO 10
#define START_STK_SIZE 64
OS_STK START_TASK_STK[START_STK_SIZE];
void start_task(void *pdata);
这部分定义了开始任务的堆栈大小和任务函数,其他任务同理。
OS_EVENT *msg_mq2;
OS_EVENT *msg_fire;
OS_EVENT *msg_light;
OS_EVENT *msg_Wcolor;
这里定义了OS_EVENT类型的指针,用来创建邮箱。
int main(void)
{
Sys_Init(); //ÍâÉè³õʼ»¯
OSInit(); //ϵͳ³õʼ»¯
OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO);
OSStart(); //ucosIIÔËÐÐ
}
主函数非常简单,首先对外设进行初始化,比如配置IO口模式,初始化无线模块等,然后初始化ucos系统,创建开始任务,最后开始多任务操作系统,注意OSStart()函数必须有一个以上任务后,才可以调用。
void start_task(void *pdata)
{
OS_CPU_SR cpu_sr = 0;
pdata = pdata;
msg_mq2 = OSMboxCreate((void*)0); //´´½¨ÓÊÏä
msg_fire = OSMboxCreate((void*)0);
msg_light = OSMboxCreate((void*)0);
msg_Wcolor = OSMboxCreate((void*)0);
OS_ENTER_CRITICAL();
OSTaskCreate(led0_task, (void *)0,(OS_STK *)&LED0_TASK_STK[LED0_STK_SIZE-1], LED0_TASK_PRIO);
OSTaskCreate(MQ2_task, (void *)0,(OS_STK *)&MQ2_TASK_STK[MQ2_STK_SIZE-1], MQ2_TASK_PRIO);
OSTaskCreate(FC_task, (void *)0,(OS_STK *)&FC_TASK_STK[FC_STK_SIZE-1], FC_TASK_PRIO);
OSTaskCreate(Alter_task,(void *)0,(OS_STK *)&Alter_TASK_STK[ALTER_STK_SIZE-1],Alter_TASK_PRIO);
OSTaskCreate(LIGHT_task,(void *)0,(OS_STK *)&LIGHT_TASK_STK[LIGHT_STK_SIZE-1],LIGHT_TASK_PRIO);
OSTaskSuspend(START_TASK_PRIO);
OS_EXIT_CRITICAL();
}
开始函数一个OS_CPU_SR类型的变量,用来存放中断时候任务的状态,然后使用一次pdata,避免因为该指针不被使用,编译器报错或警告。然后创建4个邮箱,任务可以通过向邮箱投递信息或读取信息,来完成任务就的信息交流。接着使用宏关闭中断,确保任务正确的创建,最后开启中断。
void FC_task(void *pdata)
{
bool fire_alter = false;
enum color_list test;
// test = blue;
for(;;)
{
if(FIRE1&&FIRE2) //判断火源
fire_alter = false; //没有火源
else
fire_alter = true;
OSMboxPost(msg_fire,(void *)&fire_alter);
// OSMboxPost(msg_Wcolor,(void *)&test);
printf("%d\t",fire_alter);
delay_ms(1000);
}
}
这一部分是发送邮箱的应用,火焰传感模块一旦检测到火焰,就会输出高电平,这个时候通过读取IO口(FIRE1通过一些宏操作,值1表示读取IO为高电平,反之为低电平)的值,判断是否有火焰,并将值赋给bool变量fire_alter。最后通过函数,将fire_alter的值发送给msq_fire邮箱。
void Alter_task(void *pdata)
{
bool alter = false;
bool *fire = false;
bool *mq2 = false;
for(;;)
{
INT8U err;
fire = (bool *)OSMboxPend(msg_fire,200,&err); //¶ÁÈ¡ÓÊÏäµÄÖµ
mq2 = (bool *)OSMboxPend(msg_mq2, 200,&err);
alter = *fire || *mq2;
if(alter)
{
printf("Warning!\r\n");
BEE = 1;
MOTOR = 1;
}
else
{
printf("OK\r\n");
BEE = 0;
MOTOR = 0;
}
delay_ms(800);
}
}
这部分对环境异常做出处理。首先定义bool*来读取邮箱的值(读取邮箱返回值的类型是指针变量的)
fire = (bool *)OSMboxPend(msg_fire,200,&err);
这段表示读取msg_fire邮箱的值,并将返回值强制转化为bool 指针,并赋值给fire。
alter = *fire || *mq2;
fire或mq2指向的值有异常,alter就为真。最后延时800ms。
点击下载
密码: w847