uc/os -Ⅱ操作系统实验

1.基础实验

1.1 跑马灯
两个任务,分别是按键和灯,按键控制跑马灯任务开始运行和停止挂起,跑马灯任务重4个LED灯轮流亮起熄灭。
1.2夜间自动照明系统
采集光敏传感器信号,将光照度大小显示在 LCD 显示屏上,并判断光照是
否小于预先设置的阈值,若小于,则高亮 LED 灯亮且维持 5 秒,并在 LCD 显示屏上提示“光照不足,开启照明”,若大于设置的阈值,关闭高亮 LED 灯,在LCD 显示屏上提示“光照充足,关闭照明”。通过按键 1、2 调节阈值光照强度。

2. 系统设计

2.1 模块图
在这里插入图片描述
实验一有三个任务,系统初始化任务,LED显示任务以及键盘扫描任务。
在这里插入图片描述
实验二有四个任务,分别为:光敏传感器监听任务,键盘扫描任务,系统初始化任务,LED显示任务。
2.2 流程图
在这里插入图片描述
该内容是实现LED灯的跑马灯,每一个DX_off()函数后面的延时可以取消。
在这里插入图片描述
该内容是实验一的键盘扫描函数,键盘输入“1”可挂起LED任务,键盘输入“2”可恢复LED任务。
在这里插入图片描述
光敏传感器监听任务与LED显示任务通过GtoLbox邮箱通信,键盘扫描任务与光敏传感器监听任务通过msg_key邮箱进行通信。
在这里插入图片描述
该任务是根据接收来自光敏任务的信息,来对LED进行控制,LED灯亮后,会持续五秒。
在这里插入图片描述
该任务作用是通过对键盘输入值的判断,来改变预先设定的光敏任务的阈值。
在这里插入图片描述
该任务,根据键盘扫描任务发送的消息来改变预定的阈值,并时刻读取传感器的值,进而判断是否对LED显示任务发送LED高亮任务,以及是否在LCD屏幕上显示提醒文字的作用。
2.3 开发环境
windows10

3.系统实现

3.1实验一 LED显示任务
算法描述:
1.D5_on(),睡眠0.25秒
2.D5_off(),睡眠0.25秒
3.D6_on(),睡眠0.25秒
4.D6_off(),睡眠0.25秒
5.D7_on(),睡眠0.25秒
6.D7_off(),睡眠0.25秒
7.D8_on(),睡眠0.25秒
8.D8_off(),睡眠0.25秒
9.回到步骤1
代码:

void TaskMy(void *p_arg)
{
	
    (void)p_arg;
    while (1)
    {
      //  OS_ENTER_CRITICAL();	//进入临界段(关中断)
     //   USART1Write("hello\n", sizeof("hello\n"));
      //  OS_EXIT_CRITICAL();		//退出临界段(开中断)
        D5_on();
        OSTimeDlyHMSM(0, 0, 0, 250);
        D5_off();
        OSTimeDlyHMSM(0, 0, 0, 250);
        D6_on();
        OSTimeDlyHMSM(0, 0, 0, 250);
        D6_off();
        OSTimeDlyHMSM(0, 0, 0, 250);
        D7_on();
        OSTimeDlyHMSM(0, 0, 0, 250);
        D7_off();
        OSTimeDlyHMSM(0, 0, 0, 250);
        D8_on();
        OSTimeDlyHMSM(0, 0, 0, 250);
        D8_off();
        OSTimeDlyHMSM(0, 0, 0, 250);
    }
}

3.2实验一 键盘扫描任务
算法描述:
1.使用key=key_board_scan();获取键盘输入值
2.判断key的值
2.1如果key等于1,挂起LED显示任务
2.2如果key等于2,复苏LED显示任务
3.回到步骤1
代码:

void TaskYou(void *p_arg)
{
    (void)p_arg;
    u8 key;	
    INT8U err;
    while (1)
    {
    key=key_board_scan();
    if(key == 8){
      err = OSTaskSuspend(1);
    }
    if(key == 12)
    {
      err = OSTaskResume(1);
    }}
}

3.3实验二 LED显示任务系统实现
初始设置:
//LED任务
//设置任务优先级
#define LED_TASK_PRIO 8
//设置任务堆栈大小
#define LED_STK_SIZE 512
//创建任务堆栈空间
OS_STK LED_TASK_STK[LED_STK_SIZE];
//任务函数接口
void led_task(void pdata);
算法描述:
1.使用OSMboxPend函数接收GtoLbox邮箱的值,并赋值给指针Led
2.判断Led指针指向的内容
2.1如果
Led 为1,调用D5_on(),持续五秒
3.睡眠1一秒
4.回到步骤1
代码:

void led_task(void *pdata)
{   
    (void)pdata;
    INT8U *Led;
    INT8U err;
	while(1)
	{ 
          Led = (INT8U *)OSMboxPend( ,0,&err);
          printf("Led %d",*Led);
          if(*Led == 1){
            D5_on();
            OSTimeDlyHMSM(0, 0, 5, 0);
            D5_off();
            
          }
            OSTimeDlyHMSM(0, 0, 1, 0);
	}									 
}	

3.4 实验二 光敏传感器监听系统任务实现
初始设置:
//光照任务
//设置任务优先级
#define Gmin_TASK_PRIO 9
//设置任务堆栈大小
#define Gmin_STK_SIZE 512
//创建任务堆栈空间
OS_STK Gmin_TASK_STK[BEEP_STK_SIZE];
//任务函数接口
void Gmin_task(void *pdata);
OS_EVENT GtoLbox;
算法描述:
1.使用OSMboxAccept接收邮箱msg_key的值并赋值给指针Limit
2.使用read_ADC()函数读取光敏传感器的值,fPhotoRes/ 4096.0 * 3.3并赋值给fPhotoRes
3.判断 Limit的值
3.1如果
Limit的值是1,阈值减小0.1
3.2如果
Limit的值是2,阈值增加0.1
4.如果fPhotoRes的值大于阈值
4.1LCD屏幕显示“光照不足,开启照明”,使用OSMboxPost(GtoLbox,(INT8U *)&Gmin)向LED任务,传递消息。
4.2LCD屏幕显示“光照充足,关闭照明”,使用OSMboxPost(GtoLbox,(INT8U *)&Gmin)向LED任务,传递消息。
5.睡眠1秒。
6.回到步骤1
代码:

void gmin_task(void *pdata) 
{
   (void)pdata;  
   float fPhotoRes;
   INT8U err;
   INT8U Gmin;
   INT8U *Limit;
   float doit = 2;
    while(1)
    {    
      Limit = (INT8U *)OSMboxAccept(msg_key); 
      fPhotoRes = read_ADC();
      fPhotoRes = fPhotoRes/ 4096.0 * 3.3;
      if(*Limit == 1)
      {
        doit += 0.1;
        //printf("%.lf  xianzhi %.2f \n\r", fPhotoRes, doit);
      }
      if(*Limit == 2)
      {
        doit -= 0.1;
      }
      if(fPhotoRes >= doit)
      {
        lcd_var_write(TEXT_TITLE, msg1, strlen(msg1));
        Gmin = 1;
        OSMboxPost(GtoLbox,(INT8U *)&Gmin);
      }
      else
      {
        lcd_var_write(TEXT_TITLE, msg2, strlen(msg2));
        Gmin = 0;
        OSMboxPost(GtoLbox,(INT8U *)&Gmin);
      }
      printf("doit = %.2f fPhotoRes = %.2f",doit,fPhotoRes);
      OSTimeDlyHMSM(0, 0, 1, 0);
    }
}

3.5实验二 键盘扫描系统任务实现
初始设置:
//按键扫描任务
//设置任务优先级
#define KEY_TASK_PRIO 10
//设置任务堆栈大小
#define KEY_STK_SIZE 512
//创建任务堆栈空间
OS_STK KEY_TASK_STK[KEY_STK_SIZE];
//任务函数接口
void key_task(void *pdata);
OS_EVENT *msg_key; //按键邮箱事件块指针
算法描述:
1.调用key_board_scan()获取键盘输入值
2.判断输入值
2.1如果输入值是1就向光敏传感器监听任务发送消息 1
2.2如果输入值是2就向光敏传感器监听任务发送消息2
3.回到步骤1
代码:

void key_task(void *pdata)
{	
  (void)pdata;
  u8 key;
  INT8U Keys;
  while(1)
  {
    key=key_board_scan();
    if(key == 8)
    {
      Keys = 1;
      OSMboxPost(msg_key,(INT8U *)&Keys);
    }
    if(key == 12)
    {
      Keys = 2;
      OSMboxPost(msg_key,(INT8U *)&Keys);
    }
  }
}

3.6 实验二 开始任务
初始设置:
//START 任务
//设置任务优先级
#define START_TASK_PRIO 18 //开始任务的优先级设置为最低
//设置任务堆栈大小
#define START_STK_SIZE 512
//创建任务堆栈空间
OS_STK START_TASK_STK[START_STK_SIZE];
//任务函数接口
void start_task(void pdata);
算法描述:
1.创建两个邮箱GtoLbox ,msg_key 使用函数OSMboxCreate((void
)0);
2.创建三个任务,分别为led_task,key_task,gmin_task。
代码:

OSStatInit();				//初始化统计任务.这里会延时1秒钟左右	
OS_ENTER_CRITICAL();			//进入临界区(无法被中断打断)    
GtoLbox = OSMboxCreate((void*)0); // 创建邮箱
msg_key = OSMboxCreate((void*)0);
OSTaskCreate(led_task,(void*)0,(OS_STK*)&LED_TASK_STK[LED_STK_SIZE-1],LED_TASK_PRIO);	
OSTaskCreate(key_task,(void*)0,(OS_STK*)&KEY_TASK_STK[KEY_STK_SIZE-1],KEY_TASK_PRIO);	
OSTaskCreate(gmin_task,(void*)0,(OS_STK*)&Gmin_TASK_STK[Gmin_STK_SIZE-1],Gmin_TASK_PRIO);
OS_EXIT_CRITICAL();				//退出临界区(可以被中断打断)

4.调试分析

4.1原理分析
实验一:
在实验一中,LED显示任务的优先级高于键盘扫描任务,键盘扫描任务在LED显示任务睡眠后,运行。
实验二:
整个项目从main函数开始运行,然后在main函数中创建了开始任务,以及所用设备的初始化,开始任务创建后开始执行开始任务,开始任务的内容是创建了两个邮箱,以及三个新任务,三个新任务的优先级都是高于开始任务的,此时任务队列中有四个函数,优先级关系为:LED显示任务>光敏传感器扫描任务>键盘扫描任务>开始任务。
因为LED显示任务执行了OSMboxPend()函数,但此时没有任务向其传递消息,所以LED任务被挂起,然后执行了光敏传感器扫描任务,执行完成后睡眠一秒,并向LED任务传递了消息,然后执行了LED任务,然后LED任务睡眠,然后在上述两个任务苏醒之前,执行键盘扫描任务。
4.2分析
实验一:
实验一调试过程十分流畅,任务挂起函数为OSTaskSuspend(),任务复苏函数为OSTaskResume().
实验二:
光敏传感器的使用样例在《STM32+ucosii试验箱光盘内容》中,该样例能正常运行,直接使用可移植模板会报错,需要将样例中的abc.c文件覆盖模板中的该文件,这样就可以正常运行,但是出现了任务一直处于睡眠的情况,原因是堆栈空间过小,增加空间后就可规避该问题。再后来就是OSMboxPend()函数和OSMboxAccept()函数的使用区别,OSMboxPend()函数如果没有收到消息会让任务挂起,但是OSMboxAccept()函数不会,实验要求是可以通过键盘来改变设定的阈值大小,如果光敏传感器监听任务使用OSMboxPend()函数来接收键盘扫描任务的消息,会变成只有键盘扫描任务向光敏任务发送消息,光敏任务才能执行。通过实践,这种方式带来的用户体验很差,使用OSMboxAccept()函数就可规避这个问题,并且光敏任务优先级高于键盘任务,并且执行完成后睡眠1秒,光敏任务的实际执行时间很短,光敏任务睡眠和LED任务睡眠的时间占了很大一部分比例,这也就说明键盘扫描函数的执行时间远远高于其余任务,这样可以让用户感觉不到输入时延,提高用户体验。最终持续在这样的逻辑下能够正常运行。

关于UCOSII实时操作系统 第一讲 初识uCOSII 4 1、uCOSII单任务实验: 4 2、uCOSII多任务实验: 6 3、任务状态之间的转换: 9 4、空闲任务和统计任务简介: 9 5、任务的三要件: 9 程序代码、私有堆栈、任务控制块 9 6、任务控制块TCB(P80) 9 7、创建任务 9 8、任务的栈空间 10 9、栈的增长方向: 10 第二讲 调度运行机制 11 1、任务挂起和恢复 11 2、任务挂起、恢复的状态转换 13 3、时钟节拍ISR 15 4、时钟节拍函数OSTimtick() 16 5、延时系统调用 16 第三讲 任务管理uCOSII 17 1、任务删除 17 2、任务请求删除实验 19 3、在源码中增加打印信息一般步骤 24 4、OSTaskDelReq()函数理解流程图 25 第四讲 互斥性信号量管理 26 1、优先级反转 26 2、信号量SEM使用 26 3、互斥信号量Mutux使用 29 4、关于信号量程序分析 32 5、关于互斥信号量分析 32 6、OSMutexPend()函数流程图 33 7、OSMutexPost()函数流程图 33 第五讲 消息邮箱 34 1、基本概念 34 2、对于OSMboxPend()理解 34 3、对于OSMboxPost()理解 34 4、消息邮箱管理一般程序 35 5、使用OSMboxQuery() 38 6、OSMboxPend()函数Timeout等待超时程序 38 7、OSMboxPost()函数邮箱状态为FUll程序 40 8、关于OSTimeTickHook(void)使用 41 第六讲 信号量集 43 1、信号量集案例 43 2、OSFlagPend()源码 46 3、OSFlagPost()源码 51 第七讲 动态内存 54 1、内存管理基本概念 54 2、内存管理基本概念 54 3、内存管理案例 54 4、案例分析 69 5、教学案例: 71
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dearzcs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值