实 现:在屏幕上画点功能。(能够很快显示)
综合实例(使用480*320显示)
已 改 进:画点更快,刷新频率可以控制
编 者:张永辉 2012年11月17日 三文件
/***************************************************************************************************
* INCLUDE FILES
*app.c
****************************************************************************************************/
#include <includes.h>
#include "OpenglLcd.h"
OS_STK AppStartTaskStk[APP_OS_CFG_START_TASK_STK_SIZE];
static void App_TaskStart (void);
/***************************************************************************************************
* INCLUDE FILES
***************************************************************************************************/
int main (void)
{
INT8U err;
OSInit();
GlInit(); //openGL初始化,必须放在此位置。
OSTaskCreate((void (*)(void *)) App_TaskStart,
(void *) 0,
(OS_STK *)&AppStartTaskStk[APP_OS_CFG_START_TASK_STK_SIZE-1],
(INT16U )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR)
);
#if (OS_TASK_NAME_SIZE >= 5) //Give a name to tasks
OSTaskNameSet(OS_TASK_IDLE_PRIO,"Idle",&err); //默认的Idle任务
#endif
OSStart(); // Start OS
}
/***************************************************************************************************
* 第一个任务 App_TaskStart()
***************************************************************************************************/
void App_TaskStart (void)
{
#if OS_TASK_STAT_EN > 0
OSStatInit(); // Determine CPU capacity
#endif
while (1)
{
printf("Delay 2 second and print\n");
OSTimeDlyHMSM(0, 0, 1, 0); //需要任务GL_TaskStart申请空间完成后才能DisTset。
GlDisTset();
OSTimeDlyHMSM(0, 0, 1, 0);
GlDisClear();
}
}
/***************************************************************************************************
OpenGL模拟显示屏
文 件 名: OpenglLcd.h
模块功能:模拟显示器
颜色模式:固定为565模式
编译环境:VS2008
系统环境:ucOS2.86
改 进: 画点函数很快。画面刷新频率可以控制了,可以让出很多CPU。
编 者: 张永辉 2012-11-19
***************************************************************************************************/
#ifndef __OPENGLLCD__H
#define __OPENGLLCD__H
/**************************************************************************************************/
#define u16 unsigned short //数据长度。
#define u32 unsigned int
#define GL_TASK_STK_SIZE 256 //两任务的堆栈
#define GL_TASK_DISBUFFCOPY_STK_SIZE 256
#define GL_TASK_STK_PRIO 10 //两任务的优先级
#define GL_TASK_DISBUFFCOPY_STK_PRIO 9
#define X_SIZE 800 //定义屏幕尺寸
#define Y_SIZE 600
#define GL_FREASH_TIME() OSTimeDly(7) //屏幕刷新时间间隔 500/7=72Hz
extern u16 GlDisBuff[Y_SIZE][X_SIZE]; //显存区。向此写入数据即可改变颜色.与显示屏的接口。
/***************************************************************************************************
颜色定义
***************************************************************************************************/
#define COLOUR_CLEAR 0X0000 //调用GlInit() GlDisClear()后的显示屏颜色
/***************************************************************************************************
功能函数
***************************************************************************************************/
void GlInit(void); //在OSInit()之后,OSStart()之前调用。
void GlDisTset(void); //测试,将显示屏画RBG三个色后返回
void GlDisPoint(u32 x,u32 y, u16 Color); //描点函数
void GlDisClear(void); //清屏
/**************************************************************************************************/
#endif
/***************************************************************************************************
OpenGL模拟显示屏
文 件 名: OpenglLcd.c
***************************************************************************************************/
#include <GL/glut.h>
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glut32.lib")
#include <includes.h>
#include "OpenglLcd.h"
/**************************************************************************************************/
//静态变量
static u32 FreshFlg = 0;
static const GLint ImageWidth =X_SIZE; //使用OpenGL的GLint类型,它是32位的。
static const GLint ImageHeight=Y_SIZE;
static GLint ImagelLength; //图像缓冲占的字节长度
static GLubyte* ImageDataP; //图像缓冲区指针更改该区域的值即可改变图像
static OS_STK GLTaskStk[GL_TASK_STK_SIZE]; //两个任务的堆栈
static OS_STK GlTaskDisBuffCopyStk[GL_TASK_DISBUFFCOPY_STK_SIZE];
u16 GlDisBuff[Y_SIZE][X_SIZE]; //显存区
/**************************************************************************************************/
//两个任务
void static GlTaskStart (void);
void static GlTaskDisBuffCopy(void);
/***************************************************************************************************
初始化函数
在OSInit()之后,OSStart()之前调用
***************************************************************************************************/
void GlInit(void)
{
u32 x , y;
//给背景色
for(y = 0; y < Y_SIZE ; y++)
{
for(x = 0; x < X_SIZE ; x++)
{
GlDisBuff[y][x] = COLOUR_CLEAR;
}
}
//任务:GL将显存的颜色显示到显示屏
OSTaskCreate((void (*)(void *)) GlTaskStart,
(void *) 0,
(OS_STK *)&GLTaskStk[GL_TASK_STK_SIZE-1],
(INT16U )GL_TASK_STK_PRIO);
//任务:将GlDisBuff的颜色刷新到显存
OSTaskCreate((void (*)(void *)) GlTaskDisBuffCopy,
(void *) 0,
(OS_STK *)&GlTaskDisBuffCopyStk[GL_TASK_DISBUFFCOPY_STK_SIZE-1],
(INT16U )GL_TASK_DISBUFFCOPY_STK_PRIO);
}
/***************************************************************************************************
功能函数集
***************************************************************************************************/
//--------------------------------------------------------------------------------------------------
//函数功能:性能测试 功能测试函数
void GlDisTset(void)
{
int x = 0;
int y = 0;
//绘制红色区域块
for(x = 0;x < X_SIZE/3; x++)
{
for(y = 0;y <= Y_SIZE;y++)
{
GlDisPoint(x,y,0x1f<<11);
}
}
//绘制绿色区域块
for(x = X_SIZE/3; x < 2*X_SIZE/3; x++)
{
for(y = 0;y <= Y_SIZE;y++)
{
GlDisPoint(x,y,0x3f<<5);
}
}
//绘制蓝色区域块
for(x = 2*X_SIZE/3; x <= X_SIZE; x++)
{
for(y = 0;y <= Y_SIZE;y++)
{
GlDisPoint(x,y,0x1f);
}
}
}
//--------------------------------------------------------------------------------------------------
//函数功能:清屏
void GlDisClear(void)
{
u32 x , y;
for(y = 0; y < Y_SIZE ; y++)
{
for(x = 0; x < X_SIZE ; x++)
{
GlDisBuff[y][x] = COLOUR_CLEAR;
}
}
}
//--------------------------------------------------------------------------------------------------
//函数功能:在屏幕上画点
// x : x坐标位置 0... X_SIZE-1
// y : y坐标位置 0... Y_SIZE-1
// C : 点的颜色 0... 65535 RGB565模式
//坐 标 系:左上角(0,0) 右下角(X_SIZE,Y_SIZE)
void GlDisPoint(u32 x,u32 y, u16 Color)
{
if(x >= X_SIZE || y >= Y_SIZE)
{
return;
}
GlDisBuff[y][x] = Color;
}
/***************************************************************************************************
任务函数:GlTaskDisBuffCopy
任务:将GlDisBuff的颜色刷新到显存
***************************************************************************************************/
void static GlTaskDisBuffCopy(void)
{
GLint post,ypost;
GLubyte fr,fg,fb;
u32 x , y;
u16 Color;
//等待 GlTaskStart() 给ImageDataP分配储存空间后才能对ImageDataP操作。
GL_FREASH_TIME();
GL_FREASH_TIME();
while(1)
{
//决定刷新频率
GL_FREASH_TIME();
//把颜色从GlDisBuff复制到ImageDataP
for(y = 0; y < Y_SIZE ; y++)
{
ypost = (Y_SIZE-1-y)*X_SIZE; //计算y坐标
for(x = 0; x < X_SIZE ; x++)
{
//颜色变换 将565变成24位模式
Color = GlDisBuff[y][x];
fr = (GLubyte)((Color >> 8)|(0x07));
fg = (GLubyte)((Color >> 3)|(0x03));
fb = (GLubyte)((Color << 3));
//坐标变换 ImageDataP坐标是:按笛卡尔坐标系的第一象限,x=[0 ... X_SIZE-1] y=[0 ... Y_SIZE-1]
post = (ypost + x)*3;
//向缓冲区写入一个点的颜色
ImageDataP[post] = fb; //B
ImageDataP[post+1] = fg; //G
ImageDataP[post+2] = fr; //R
}
}
FreshFlg = 1; //与GlTaskStart()任务保持同步
}
}
/***************************************************************************************************
任务函数:GlTaskStart
任务:GL将内存的颜色显示到显示屏
***************************************************************************************************/
void static GL_Display(void); //显示处理回调函数
void static GL_Idle(void); //CPU空闲时自动回调用的函数
//--------------------------------------------------------------------------------------------------
//函数功能:GL任务
void static GlTaskStart (void)
{
#if OS_TASK_STAT_EN > 0
OSStatInit(); // Determine CPU capacity
#endif
//计算图像大小
ImagelLength = ImageWidth * 3; //每个像素3字节
while( ImagelLength % 4 != 0 ) //修正LineLength使其为4的倍数
{
++ImagelLength; //每一行像素数据的长度若不是4的倍数则填充数据使它是4的倍数
}
ImagelLength *= ImageHeight; //PixelLength = ImageWidth*3*ImageHeight
//申请图像缓冲区
ImageDataP = (GLubyte*)malloc(ImagelLength);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); //修改了参数为GLUT_DOUBLE
glutInitWindowPosition(100, 100);
glutInitWindowSize(X_SIZE, Y_SIZE);
glutCreateWindow("华丽的显示屏"); //窗口标题
glutDisplayFunc(&GL_Display);
glutIdleFunc(&GL_Idle); //新加入了这句
FreshFlg = 1;
glutMainLoop();
free(ImageDataP);
while (1)
{
printf("err : GL_TaskStart is backup");
OSTimeDlyHMSM(0, 0, 2, 0);
}
}
void static GL_Display(void)
{
//glClear(GL_COLOR_BUFFER_BIT);//可以不要清屏,因为每次绘制时,画面都覆盖整个屏幕
//绘制像素
glDrawPixels(ImageWidth, ImageHeight,GL_BGR_EXT,GL_UNSIGNED_BYTE,ImageDataP);
//完成绘制
glutSwapBuffers();
}
void static GL_Idle(void)
{
//在CPU空闲时调用. 在这里可以添加程序,使扫描速度降低。
if(FreshFlg == 0)
{
return;
}
FreshFlg = 0; //同步
GL_Display();
}