基于uC/OSII多任务的STM32报警模块

小作品简介

  这个小作品是uCOSII多任务系统的简单应用,使MCU(STM32F103)可以“同时”执行多个任务。并使用邮箱在多任务系统中通信。如果需要可以在文字末尾下载到完整的工程,其中System文件夹中3个文件由原子提供,提供了一些函数,便于编程和debug,具体可参看原子官方的教程。
  基于uC/OSII多任务的STM32报警模块_第1张图片
(本作品由于没有电机驱动,所以用三个三极管将就,这是不规范操作,效果也一般)
本工程中创建了5个任务,并设置最多为12个任务。分别是:
1. led0_task:控制LED灯的亮灭
2. MQ2_task : 检测烟雾传感器的值
3. FC_task : 检测是否有火焰
4. Alter_task : 接受邮箱信息,决定是否分通过蜂鸣器报警,启动电风扇。
5. LIGHT_task : 控制一个三色LED
由于是该模块与其他模块有通讯,工程中添加了无线模块驱动和初始化程序。假设不需要无线模块,注释初始化代码即可。硬件模块是一些常用模块,可以在网络上查看其简介

  • 元件清单
    • MQ2烟雾传感器
    • NRF24L01无线模块
    • 火焰传感器(2个)
    • 蜂鸣器
    • 直流电机
    • 三色LED灯
    • L298N电机驱动模块
    • STM32F103c8t6最小系统
  • 硬件连线
    • 电机信号线 -> PB0
    • MQ2数字接口 -> GPIOA.1 (模数转化)
    • 火焰传感器
      • A:DO -> GPIOB.5
      • B : DO -> GPIOB.6
    • 无线模块:
      • 1号引脚 -> GND
      • 2号引脚 -> VCC
      • 3号引脚 -> PA4
      • 4号引脚 -> PB9
      • 5号引脚 -> PA5
      • 6号引脚 -> PA7
      • 7号引脚 -> PA6
      • 8号引脚 -> PA10

主要程序

#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

你可能感兴趣的:(电子制作)