基于uCOSII的LCD驱动实验

  • 实验目的
  1. 掌握在 UCOsH操作系统下编写应用程序 的基本方法
  • 实验内容
  1. 在移植好的UCOsII项 目中添加串口、LCD、 键盘的驱动程序
  2. 学习在UCOSII下 ,多应用任务的简单编程实例
  • 实验设备
  1. EL-RAM-860教 学 实验 箱 ,PentiumII以上 的 PC机 ,仿 真 调试 电缆 ,串 口直 连 电 缆 。
  2. PC操 作 系统 WIN98或 WIN⒛00或 WINXP, ADs1.2集 成 开发环 坑 , 仿真 调试 驱动程 序 。
  •  实验步骤

       实验题目1:

  1. 在界面显示一个半径为20的红色圆圈,且该圆圈随着上、下、左、右键的按下往该方向平移6个单位。
  2. 当捕获回车按键后串口输出当前激活按键的值如"Left Button Pressed!"等

       实验代码:

           代码说明:

            Main:此函数创建并启动了任务一,利用“邮箱”来进行多任务间的通信。

           Task1:创建并启动了任务2,3,4,也是利用“邮箱” 来进行多任务间的通信。通过设置任务的优先级来控制任务的调度。

           Task2:主要是控制LED灯的交替闪烁效果

           Task3:主要是向超级终端中输出键盘上的按键值,代码只变动了输出内容。   

           Task4:是进行GUI任务,代码变动主要是改写此函数,函数编写代码已经进行了相关的注释。

void Task_4(void *pdata)
{	
    I32 number;
	INT8U Loop;
  	for(;;) 
	{	
		number = GUI_WaitKey();
		Loop = TRUE;
		do
		{
			switch (number)
			{
				case  GUI_KEY_START:					// 得到开始命令	
					Set_Color(GUI_BLUE);
  					Fill_Rect(0,0,639,479);             //画窗口的边框
  					Set_Color(GUI_WHITE);
  					Set_BkColor (GUI_BLUE);           //设置窗口的背景颜色
  	              Fill_Rect(0,0,639,2);       
    			    Fill_Rect(0,0,2,479);
    			    Fill_Rect(0,477,639,479);
    			    Fill_Rect(637,0,639,479);	
    				Set_Color(GUI_YELLOW);
    				Set_Font    (&CHINESE_FONT16);
					Disp_String (CN_start"这是一个多任务显示的例程"CN_end,50,30);		
					Set_Color(GUI_RED);     //画红色的圆,
    				Fill_Circle (320, 240, 20);   //圆心坐标、半径为20
					Loop = FALSE;
					number = 0;
					break;
		    	default:								// 等待主任务发送的键值命令
					number = GUI_WaitKey();       
					Loop = TRUE;
					break;
			}
		}while(Loop==TRUE);
		
		do
		{
			
			switch (number)        
			{
				case GUI_KEY_UP:						//选择上移
				
				Set_Color(GUI_BLUE);                //将原先的圆消失掉
  				Fill_Rect(0,0,639,479);                //重新绘制窗口
  				Set_Color(GUI_WHITE);
  				Set_BkColor (GUI_BLUE);
  	            Fill_Rect(0,0,639,2);            //窗口的四条边框的绘制

    			Fill_Rect(0,0,2,479);
    			Fill_Rect(0,477,639,479);
    			Fill_Rect(637,0,639,479);
				Set_Color(GUI_RED);
				if(y-20<=1){
					y=240;           //如果圆要超过上边界,将圆设置到中心
				}else{
					y=y-6;
				}
       			Fill_Circle(x, y, 20);
				Loop = TRUE;
				number = 0;
				break;          								
				case GUI_KEY_DOWN:						//选择下移
				Set_Color(GUI_BLUE);                   //将原先的圆消失掉
  				Fill_Rect(0,0,639,479);                     //重新绘制窗口

  	 
  				Set_Color(GUI_WHITE);
  				Set_BkColor (GUI_BLUE);         
  	            Fill_Rect(0,0,639,2);              //窗口的四条边框的绘制

    			Fill_Rect(0,0,2,479);
    			Fill_Rect(0,477,639,479);
    			Fill_Rect(637,0,639,479);
				Set_Color(GUI_RED);
       			if(y+20>=479){   //如果圆要超过下边界,将圆设置到中心
					y=240;
				}else{
					y=y+6;
				}
       			Fill_Circle(x, y, 20);			
				
				Loop = TRUE;
				number = 0;
				break;
				case GUI_KEY_RIGHT:						//选择右移
				Set_Color(GUI_BLUE);            //将原先的圆消失掉
  				Fill_Rect(0,0,639,479);            //重新绘制窗口
  				Set_Color(GUI_WHITE);           
  				Set_BkColor (GUI_BLUE);
  	           Fill_Rect(0,0,639,2);             //窗口的四条边框的绘制
    			Fill_Rect(0,0,2,479);
    			Fill_Rect(0,477,639,479);
    			Fill_Rect(637,0,639,479);
				Set_Color(GUI_RED);            //x为全局变量
       			if(x+20>=639){             //如果圆要超过右边界
					x=320;                   //将圆心重新设置到中间
				}else{                        
					x=x+6;                    //每一次右移,x值加6
				}
       			Fill_Circle(x, y, 20);         
				Loop = TRUE;
				number = 0;                  
				break;              								
				case GUI_KEY_LEFT:						//选择左移		
				Set_Color(GUI_BLUE);            //将原先的圆消失掉

  				Fill_Rect(0,0,639,479);          //重新绘制窗口

  	
  				Set_Color(GUI_WHITE);
  				Set_BkColor (GUI_BLUE);
  	            Fill_Rect(0,0,639,2);            //窗口的四条边框的绘制

    			Fill_Rect(0,0,2,479);
    			Fill_Rect(0,477,639,479);    
    			Fill_Rect(637,0,639,479);
				Set_Color(GUI_RED);
       			if(x-20<=1){               //如果圆要超过左边界
 
					x=320;                    //将圆心重新设置到中间

				}else{                 
					x=x-6;
				}
       		Fill_Circle(x, y, 20);
				Loop = TRUE;
				number = 0;
				break;
				case  GUI_KEY_ESCAPE:				// 得到退出命令
				Set_Color(GUI_BLUE);
  				Fill_Rect(0,0,639,479);
  				Set_Color(GUI_WHITE);
   				Fill_Rect(0,0,639,2);
    			Fill_Rect(0,0,2,479);
    			Fill_Rect(0,477,639,479);
    			Fill_Rect(637,0,639,479);
				Loop = FALSE;
				number = 0;
				break;			
		    	default:								// 等待主任务发送的键值命令
				number = GUI_WaitKey();
				Loop = TRUE;
				break;
			}
		}while(Loop == TRUE);
	}
}
void Task_3(void *pdata)
{
    
    for(;;)
    {
    	if(key_number!=0xff)
    	{  
			Uart_Printf("key_number=%x Button Pressed!\n",key_number); //任务的干得活儿就是向超级终端发送内容
    		key_number=0xff;
    		OSTimeDly(30);                                                //延时100个节拍
    	}
    }
}

实验题目2:

  在编写一个任务5,此任务中完成,设置其优先级为60,绘制一个圆,此圆的初始半径为2,然后扩大到50之后缩小为半径为2的圆。扩大的频率为LED灯闪烁的频率的1/2.

  代码的实现:

 在task1中创建并启动任务task5,在task2中设置让task2闪烁完一回,线程睡眠OSTimeDly(30); ,让低优先级的task5得到执行,task2中创建一个信号量,让task2运行两次,往信号量中扔一把钥匙,达到灯闪烁频率的1/2是圆扩大的频率,task5负责接受取出钥匙得到运行。

void Task_5(void *pdata)
{	
    I32 number;
	INT8U Loop;
  	for(;;) 
	{	Key_P = OSMboxPend(Key_Mbox1, 0, &err); //取钥匙获取执行机会
		number = GUI_WaitKey();
								              // 得到开始命令	
					Set_Color(GUI_BLUE);
  					Fill_Rect(0,0,639,479);             //画窗口的边框
  					Set_Color(GUI_WHITE);
  					Set_BkColor (GUI_BLUE);           //设置窗口的背景颜色
  	              Fill_Rect(0,0,639,2);       
    			    Fill_Rect(0,0,2,479);
    			    Fill_Rect(0,477,639,479);
    			    Fill_Rect(637,0,639,479);	
    				Set_Color(GUI_YELLOW);
    				Set_Font    (&CHINESE_FONT16);
					Disp_String (CN_start"这是一个多任务显示的例程"CN_end,50,30);		
                 R+=2;               //此处R是全局变量
                If(R>50){
                 R=2;             //当圆半径到达了50时,圆半径回到2
                }
					Set_Color(GUI_RED);     //画红色的圆,
    				Fill_Circle (320, 240, R);   //圆心坐标、半径为20
					Loop = FALSE;
					number = 0;
Loop = TRUE;
      
					
					number = GUI_WaitKey();       
					Loop = TRUE;
								}
				
		
}
void Task_2(void *pdata)
{
    INT32U i,flag=0;
    K=1;                     //k是全局变量,控制代码执行两次往信号量里//面扔一把钥匙
    Key_Mbox1 = OSMboxCreate((void *)0);//创建信号量Key_Mbox1
    for(;;)
    {
       k++;
If(k%2==0)
OSMboxPost(Key_Mbox1,&key_number);//往信号量Key_Mbox1仍钥匙
    	OSTimeDly(30);  
     	if(flag==0)
     	{
     		for(i=0;i<100000;i++);
    		rGPGDAT = rGPGDAT&~(0x3<<8)|(0x1<<8);
    		for(i=0;i<100000;i++);
    		flag = 1;
    	}
    	else
    	{
    		for(i=0;i<100000;i++);
			rGPGDAT = rGPGDAT&~(0x3<<8)|(0x2<<8);
			for(i=0;i<100000;i++);
			flag = 0;
        		}
  OSTimeDly(30);  
    	                                              //延时30个节拍
    }
}

实验结果截图:

问题以及总结:

         本次实验过程中绘制红心圆的时候往上移,左移、右移发现之前的圆不会消失,于是就造成了圆移动的过程中绘画成一条线,于是我就想到每次点击上下移动之前把原先这个圆给删除掉,但是GUI中又没有提供相关的函数,于是借鉴了一下别人的做法,每一移动触发之前,先把面板上的组件清空,把原先的窗口设置成白色,然后重新绘制窗口,这样之前的圆就消失了。

        在任务二中,task5老是得不到机会运行,因为task5的优先级太低,而task2中总是在运行,导致低优先级的task5得不到机会运行,后来在老师的帮助下,将task任务线程睡眠,也就是延迟30个节拍,让task5得到机会能够运行。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值