实验三UCOSII信号量和邮箱管理.docx
- 文档编号:28398872
- 上传时间:2023-07-13
- 格式:DOCX
- 页数:16
- 大小:112.45KB
实验三UCOSII信号量和邮箱管理.docx
《实验三UCOSII信号量和邮箱管理.docx》由会员分享,可在线阅读,更多相关《实验三UCOSII信号量和邮箱管理.docx(16页珍藏版)》请在冰豆网上搜索。
实验三UCOSII信号量和邮箱管理
实验三-UCOS-II信号量和邮箱管理
班级学号姓名同组人
实验日期室温大气压成绩
实验三UCOS-II信号量和邮箱管理
一、实验目的
1、掌握UCOS-II中信号量的原理和函数的应用;
2、掌握UCOS-II在邮箱管理的原理和含义;
3、掌握开发UCOS-II的信号量和邮箱的应用的程序结构。
二、实验步骤
1、UCOSII信号量和邮箱简介
系统中的多个任务在运行时,经常需要互相无冲突地访问同一个共享资源,或者需要互相支持和依赖,甚至有时还要互相加以必要的限制和制约,才保证任务的顺利运行。
因此,操作系统必须具有对任务的运行进行协调的能力,从而使任务之间可以无冲突、流畅地同步运行,而不致导致灾难性的后果。
在UCOSII中,是使用信号量、邮箱和消
息队列这些被称作事件的中间环节来实现任务之间的通信的。
两个任务通过事件进行通讯的示意图如图所示:
在图中任务1是发信方,任务2是收信方。
发信方负责把信息发送到时间上,这项
操作叫做发送事件。
收信方通过读取事件操作对事件进行查询:
如果有信息则读取,否则等待。
读事件操作叫做请求事件。
为把描述事件的数据结构统一起来,UCOSII使用叫做事件控制块(ECB)的数据结构来描述诸如信号量、邮箱和消息队列这些事件。
事件控制块中包含包括等待任务表在内的所有有关事件的数据,事件控制块结构体定义如下:
typedefstruct
{
INT8UOSEventType;//事件的类型
INT16UOSEventCnt;//信号量计数器
void*OSEventPtr;//消息或消息队列的指针
INT8UOSEventGrp;//等待事件的任务组
INT8UOSEventTbl[OS_EVENT_TBL_SIZE];//任务等待表
#ifOS_EVENT_NAME_EN>0u
INT8U*OSEventName;//事件名
#endif
}OS_EVENT;
1)信号量
信号量是一类事件。
使用信号量的最初目的,是为了给共享资源设立一个标志,该标志表示该共享资源的占用情况。
这样,当一个任务在访问共享资源之前,就可以先对这个标志进行查询,从而在了解资源被占用的情况之后,再来决定自己的行为。
信号量可以分为两种:
一种是二值型信号量,另外一种是N值信号量。
UCOSII将二值型信号量称之为也叫互斥型信号量,将N值信号量称之为计数型信号量,也就是普通的信号量。
本次实验中主要学习互斥型信号量。
在UCOSII中,与信号量相关的几个函数。
①创建信号量函数
在使用信号量之前,我们必须用函数OSSemCreate来创建一个信号量,该函数的原
①创建邮箱函数
创建邮箱通过函数OSMboxCreate实现,该函数原型为:
OS_EVENT*OSMboxCreate(void*msg)函数中的参数msg为消息的指针,函数的返回值为消息邮箱的指针。
调用函数OSMboxCreate需先定义msg的初始值。
在一般的情况下,这个初始值为NULL;但也可以事先定义一个邮箱,然后把这个邮箱的指针作为参数传递到函数OSMboxCreate中,
使之一开始就指向一个邮箱。
②任务可以通过调用函数OSMboxPost向消息邮箱发送消息,这个函数的原型为:
INT8UOSMboxPost(OS_EVENT*pevent,void*msg)其中pevent为消息邮箱的指针,msg为消息指针。
③请求邮箱函数
当一个任务请求邮箱时需要调用函数OSMboxPend,这个函数的主要作用就是查看邮箱指针OSEventPtr是否为NULL,如果不是NULL就把邮箱中的消息指针返回给调用函数的
任务,同时用OS_NO_ERR通过函数的参数err通知任务获取消息成功;如果邮箱指针OSEventPtr是NULL,则使任务进入等待状态,并引发一次任务调度。
函数OSMboxPend的原型为:
void*OSMboxPend(OS_EVENT*pevent,INT16Utimeout,INT8U*err),其中pevent为请求邮箱指针,timeout为等待时限,err为错误信息。
④查询邮箱状态函数
任务可以通过调用函数OSMboxQuery查询邮箱的当前状态。
该函数原型为:
INT8UOSMboxQuery(OS_EVENT*pevent,OS_MBOX_DATA*pdata)其中pevent为消息邮箱指针,pdata为存放邮箱信息的结构。
向邮箱发送消息函数。
⑤删除邮箱函数
在邮箱不再使用的时候,我们可以通过调用函数OSMboxDel来删除一个邮箱,该函数原型为:
OS_EVENT*OSMboxDel(OS_EVENT*pevent,INT8Uopt,INT8U*err),其中pevent为消息邮箱指针,opt为删除选项,err为错误信息。
三、实验内容
本次实验在UCOSII里面创建6个任务:
开始任务、LED任务、触摸屏任务、蜂鸣器任务、按键扫描任务和主任务,开始任务用于创建信号量、创建邮箱、初始化统计任务以及其他任务的创建,之后挂起;LED任务用于DS0控制,提示程序运行状况;蜂鸣器任务用于测试信号量,是请求信号量函数,每得到一个信号量,蜂鸣器就叫一次;触摸屏任务用于在屏幕上画图,可以用于测试CPU使用率;按键扫描任务用于按键扫描,优先级最高,将得到的键值通过消息邮箱发送出去;主任务则通过查询消息邮箱获得键值,
并根据键值执行DS1控制、信号量发送(蜂鸣器控制)、触摸区域清屏和触摸屏校准等控制。
1、所要用到的硬件资源如下:
1)指示灯DS0、DS1
2)4个按键(KEY0/KEY1/KEY2/WK_UP)
3)蜂鸣器
4)TFTLCD模块
2、软件参数设置
OS_TICKS_PER_SEC=500,即UCOSII的时钟节拍为2ms。
在加入UCOSII代码后,我们只需要修改test.c函数了,打开test.c,输入如下代码:
#include"sys.h"
#include"usart.h"
#include"delay.h"
#include"led.h"
#include"beep.h"
#include"key.h"
#include"exti.h"
#include"wdg.h"
#include"timer.h"
#include"tpad.h"
#include"oled.h"
#include"lcd.h"
#include"usmart.h"
#include"rtc.h"
#include"wkup.h"
#include"adc.h"
#include"dac.h"
#include"dma.h"
#include"24cxx.h"
#include"flash.h"
#include"rs485.h"
#include"can.h"
#include"touch.h"
#include"includes.h"
/////////////////////////////////////UCOSII任务设置/////////////////////////////////
//START任务
//设置任务优先级
#defineSTART_TASK_PRIO10//开始任务的优先级设置为最低
//设置任务堆栈大小
#defineSTART_STK_SIZE64
//任务堆栈
OS_STKSTART_TASK_STK[START_STK_SIZE];
//任务函数
voidstart_task(void*pdata);
//LED任务
//设置任务优先级
#defineLED_TASK_PRIO7
//设置任务堆栈大小
#defineLED_STK_SIZE64
//任务堆栈
OS_STKLED_TASK_STK[LED_STK_SIZE];
//任务函数
voidled_task(void*pdata);
//触摸屏任务
//设置任务优先级
#defineTOUCH_TASK_PRIO6
//设置任务堆栈大小
#defineTOUCH_STK_SIZE64
//任务堆栈
OS_STKTOUCH_TASK_STK[TOUCH_STK_SIZE];
//任务函数
voidtouch_task(void*pdata);
//蜂鸣器任务
//设置任务优先级
#defineBEEP_TASK_PRIO5
#defineBEEP_STK_SIZE64
//任务堆栈
OS_STKBEEP_TASK_STK[BEEP_STK_SIZE];
//任务函数
voidbeep_task(void*pdata);
//主任务
//设置任务优先级
#defineMAIN_TASK_PRIO4
//设置任务堆栈大小
#defineMAIN_STK_SIZE128
//任务堆栈
OS_STKMAIN_TASK_STK[MAIN_STK_SIZE];
//任务函数
voidmain_task(void*pdata);
//按键扫描任务
//设置任务优先级
#defineKEY_TASK_PRIO3
//设置任务堆栈大小
#defineKEY_STK_SIZE64
//任务堆栈
OS_STKMAIN_TASK_STK[MAIN_STK_SIZE]
//任务函数
Voidkey_task(void*pdata);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
OS_EVENT*msg_key;//按键邮箱事件块指针
OS_EVENT*sem_beep;//蜂鸣器信号量指针
//加载主界面
voiducos_load_main_ui(void)
{
LCD_Clear(WHITE);//清屏
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(30,10,200,16,16,"WarShipSTM32");
LCD_ShowString(30,30,200,16,16,"UCOSIITEST2");
LCD_ShowString(30,50,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,75,200,16,16,"KEY0:
DS0KEY_UP:
ADJUST");
LCD_ShowString(30,95,200,16,16,"KEY1:
BEEPKEY2:
CLEAR");
LCD_ShowString(80,210,200,16,16,"TouchArea");
LCD_DrawLine(0,120,lcddev.width,120);
LCD_DrawLine(0,70,lcddev.width,70);
LCD_DrawLine(150,0,150,70);
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(160,30,200,16,16,"CPU:
%");
LCD_ShowString(160,50,200,16,16,"SEM:
000");
}
intmain(void)
{
Stm32_Clock_Init(9);//系统时钟设置
uart_init(72,9600);//串口初始化为9600
delay_init(72);//延时初始化
LED_Init();//初始化与LED连接的硬件接口
LCD_Init();//初始化LCD
usmart_dev.init(72);//初始化USMART
BEEP_Init();//蜂鸣器初始化
KEY_Init();//按键初始化
tp_dev.init();//触摸屏初始化
ucos_load_main_ui();//加载主界面
OSInit();//初始化UCOSII
OSTaskCreate(start_task,
(void*)0,
(OS_STK*)&START_TASK_STK[START_STK_SIZE-1],
START_TASK_PRIO);//创建起始任务
OSStart();
}
//开始任务
voidstart_task(void*pdata)
{
OS_CPU_SRcpu_sr=0;
pdata=pdata;
msg_key=OSMboxCreate((void*)0);//创建消息邮箱
sem_beep=OSSemCreate(0);//创建信号量
OSStatInit();//初始化统计任务.这里会延时1秒钟左右
OS_ENTER_CRITICAL();//进入临界区(无法被中断打断)
OSTaskCreate(led_task,
(void*)0,
(OS_STK*)&LED_TASK_STK[LED_STK_SIZE-1],
LED_TASK_PRIO);
OSTaskCreate(touch_task,
(void*)0,
(OS_STK*)&TOUCH_TASK_STK[TOUCH_STK_SIZE-1],
TOUCH_TASK_PRIO);
OSTaskCreate(beep_task,
(void*)0,
(OS_STK*)&BEEP_TASK_STK[BEEP_STK_SIZE-1],
BEEP_TASK_PRIO);
OSTaskCreate(main_task,
(void*)0,
(OS_STK*)&MAIN_TASK_STK[MAIN_STK_SIZE-1],
MAIN_TASK_PRIO);
OSTaskCreate(key_task,
(void*)0,
(OS_STK*)&KEY_TASK_STK[KEY_STK_SIZE-1],
KEY_TASK_PRIO);
OSTaskSuspend(START_TASK_PRIO);//挂起起始任务.
OS_EXIT_CRITICAL();//退出临界区(可以被中断打断)
}
//LED任务
voidled_task(void*pdata)
{
u8t;
while
(1)
{
t++;
delay_ms(10);
if(t==8)LED0=1;//LED0灭
if(t==100)//LED0亮
{
t=0;
LED0=0;
}
}
}
//蜂鸣器任务
voidbeep_task(void*pdata)
{
u8err;
while
(1)
{
OSSemPend(sem_beep,0,&err);
BEEP=1;
delay_ms(60);
BEEP=0;
delay_ms(940);
}
}
//触摸屏任务
voidtouch_task(void*pdata)
{
while
(1)
{
tp_dev.scan(0);
if(tp_dev.sta&TP_PRES_DOWN)//触摸屏被按下
{
if(tp_dev.x
{
TP_Draw_Big_Point(tp_dev.x,tp_dev.y,RED);//画图
delay_ms
(2);
}
}elsedelay_ms(10);//没有按键按下的时候
}
}
//主任务
voidmain_task(void*pdata)
{
u32key=0;
u8err;
u8semmask=0;
u8tcnt=0;
while
(1)
{
key=(u32)OSMboxPend(msg_key,10,&err);
switch(key)
{
case1:
//控制DS1
LED1=!
LED1;
break;
case2:
//发送信号量
semmask=1;
OSSemPost(sem_beep);
break;
case3:
//清除
LCD_Fill(0,121,lcddev.width,lcddev.height,WHITE);
break;
case4:
//校准
OSTaskSuspend(TOUCH_TASK_PRIO);//挂起触摸屏任务
TP_Adjust();
OSTaskResume(TOUCH_TASK_PRIO);//解挂
ucos_load_main_ui();//重新加载主界面
break;
}
if(semmask||sem_beep->OSEventCnt)//需要显示sem
{
POINT_COLOR=BLUE;
LCD_ShowxNum(192,50,sem_beep->OSEventCnt,3,16,0X80);//显示信号量的值
if(sem_beep->OSEventCnt==0)semmask=0;//停止更新
}
if(tcnt==50)//0.5秒更新一次CPU使用率
{
tcnt=0;
POINT_COLOR=BLUE;
LCD_ShowxNum(192,30,OSCPUUsage,3,16,0);//显示CPU使用率
}
tcnt++;
delay_ms(10);
}
}
//按键扫描任务
voidkey_task(void*pdata)
{
u8key;
while
(1)
{
key=KEY_Scan(0);
if(key)OSMboxPost(msg_key,(void*)key);//发送消息
delay_ms(10);
}
}
该部分代码我们创建了6个任务:
start_task、led_task、beep_task、touch_task、main_task和key_task,优先级分别是10和7~3,堆栈大小除了main_task是128,其他都是64。
该程序的运行流程就比上一章复杂了一些,我们创建了消息邮箱msg_key,用于按键任务和主任务之间的数据传输(传递键值),另外创建了信号量sem_beep,用于蜂鸣器任务和主任务之间的通信。
本代码中,使用了UCOSII提供的CPU统计任务,通过OSStatInit初始化CPU统计任
务,然后在主任务中显示CPU使用率。
另外,在主任务中用到了任务的挂起和恢复函数,在执行触摸屏校准的时候,必须先将触摸屏任务挂起,待校准完成之后,再恢复触摸屏任务。
这是因为触摸屏校准和触摸屏任务都用到了触摸屏和TFTLCD,而这两个东西是不支持多个任务占用的,所以必须采用独占的方式使用,否则可能导致数据错乱。
四、实验结果
下载验证,在代码编译成功之后,我们通过下载代码到战舰STM32开发板上,可以看到LCD显示界面如图所示
从图中可以看出,默认状态下,CPU使用率仅为1%。
此时通过在触摸区域画图,可以看到CPU使用率飙升(42%),说明触摸屏任务是一个很占CPU的任务;通过按KEY0,可以控制DS1的亮灭;通过按KEY1则可以控制蜂鸣器的发声,同时,可以在LCD上面看到信号量的当前值;通过按KEY2,可以清除触摸屏的输入;通过按WK_UP可以进入校准程序,进行触摸屏校准。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 UCOSII 信号量 邮箱 管理