12864 显示画圆多种图形

/*******************************************************************************************************/

//程序说明:本程序为12864(st7920)驱动程序,只实现了最简单的显示功能

/*******************************************************************************************************/

#include<reg52.h>

#include<intrins.h> //内含-NOP-函数

#include<stdlib.h> //内含rand()函数

#define uchar unsigned char

#define uint unsigned int

//**********宏定义所需指令

#define BASIC_SET  0x30

#define EXTEND_SET 0x34

#define DRAW_ON    0x36

#define DRAW_OFF   0x34

//*************端口定义

sbit LCD_RS = P3^5;

sbit LCD_RW = P3^6;

sbit LCD_EN = P3^4;

sbit wela = P2^6;

sbit dula = P2^7;

//************变量定义

//****************短延时

void delay(uint k)

{

uint i;

uchar j;

for(i = 0; i < k ;i ++)

for(j = 0; j < 10 ;j ++);

}

//***********12864写指令函数

void write_com(uchar cmd)

{

LCD_RS = 0;

LCD_RW = 0;

LCD_EN = 0;

P0 = cmd;

delay(5);

LCD_EN = 1;

delay(5);

LCD_EN = 0;

}

//********12864写数据函数

void write_dat(uchar dat)

{

LCD_RS = 1;

LCD_RW = 0;

LCD_EN = 0;

P0 = dat;

delay(5);

LCD_EN = 1;

delay(5);

LCD_EN = 0;

}

//****************从LCD中读数据

uchar read_dat(void)

{

uchar temp;

P0 = 0XFF; //释放数据线

LCD_RS = 1;   //数据

LCD_RW = 1;  //读模式

LCD_EN = 1;  //为高电平进行读数据或指令

delay(1);

temp = P0;

LCD_EN = 0;

return temp;

}

//********************************************************

//设置光标(地址)函数

//参数说明:x---为行号,y为列号

//********************************************************

void set_cursor(unsigned char x, unsigned char y)

{

unsigned char i;

switch(x)    //确定行号

{

case 0x00: i=0x80; break; //第一行

case 0x01: i=0x90; break;  //第二行

case 0x02: i=0x88; break;  //第三行

case 0x03: i=0x98; break;  //第四行

default : break;

}

i = y+i;  //确定列号

write_com(i);

}

//********************************************************

//显示字符函数

//********************************************************

void display_char(unsigned char Alphabet)

{

write_dat(Alphabet); //写入需要显示字符的显示码

}

//********************************************************

//指定位置显示字符串函数

//参数说明:x为行号,y为列号

//********************************************************

void display_string(unsigned char x,unsigned char y,unsigned char *Alphabet)

{

unsigned char i=0;

set_cursor(x,y); //设置显示的起始地址

while(Alphabet[i]!=‘\0‘)

{

write_dat(Alphabet[i]); //写入需要显示字符的显示码

i++;

}

}

//***************************************************************************以下为GDRAM绘图部分************************************************************************//

//*********************绘图显示的清屏函数(因清屏指令在画图时不能用)------------------------------------------------------------------------------注意!!!!!!!

void gui_clear()

{

uchar i , j , k;

write_com(EXTEND_SET);//扩展指令集,8位数据传输

write_com(DRAW_OFF);//绘图显示关闭

for(i = 0; i < 2; i ++)//分上下两屏写

{

for(j = 0; j < 32; j ++)

{

write_com(0x80 + j);//写y坐标

delay(1);

if(i == 0) //写x坐标

{

write_com(0x80);

delay(1);

}

else      //写下半屏

{

write_com(0x88);

delay(1);

}

for(k = 0; k < 16; k ++)//写一整行数据

{

write_dat(0x00);//写高字节

write_dat(0x00);//写低字节

delay(1);

}

}

}

write_com(DRAW_ON);//打开绘图显示

write_com(BASIC_SET);//打开基本指令集

}

//*************************************************************************************************

//***************有反白显示功能的打点函数**********************************************************

//参数:color=1,该点填充1;color=0,该点填充白色0;

//*************************************************************************************************

void GUI_Point(unsigned char x,unsigned char y,unsigned char color)

{

unsigned char x_Dyte,x_byte; //定义列地址的字节位,及在字节中的哪1位

unsigned char y_Dyte,y_byte; //定义为上下两个屏(取值为0,1),行地址(取值为0~31)

unsigned char GDRAM_hbit,GDRAM_lbit;

write_com(0x36); //扩展指令命令

/***X,Y坐标互换,即普通的X,Y坐标***/

x_Dyte=x/16; //计算在16个字节中的哪一个

x_byte=x&0x0f; //计算在该字节中的哪一位

y_Dyte=y/32; //0为上半屏,1为下半屏

y_byte=y&0x1f; //计算在0~31当中的哪一行

write_com(0x80+y_byte); //设定行地址(y坐标),即是垂直地址

write_com(0x80+x_Dyte+8*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏,即是水平地址

read_dat(); //预读取数据

GDRAM_hbit= read_dat(); //读取当前显示高8位数据

GDRAM_lbit= read_dat(); //读取当前显示低8位数据

delay(1);

write_com(0x80+y_byte); //设定行地址(y坐标)

write_com(0x80+x_Dyte+8*y_Dyte); //设定列地址(x坐标),并通过8*y_Dyte选定上下屏

delay(1);

if(x_byte<8) //判断其在高8位,还是在低8位

{

if(color==1)

{

write_dat(GDRAM_hbit|(0x01<<(7-x_byte))); //置位GDRAM区高8位数据中相应的点

}

else

write_dat(GDRAM_hbit&(~(0x01<<(7-x_byte)))); //清除GDRAM区高8位数据中相应的点

write_dat(GDRAM_lbit); //显示GDRAM区低8位数据

}

else

{

write_dat(GDRAM_hbit);

if(color==1)

write_dat(GDRAM_lbit|(0x01<<(15-x_byte))); //置位GDRAM区高8位数据中相应的点

else

write_dat(GDRAM_lbit&(~(0x01<<(15-x_byte))));//清除GDRAM区高8位数据中相应的点

}

write_com(0x30); //恢复到基本指令集

}

//***********(给定坐标并打点的)任意位置打点函数

void lcd_set_dot(uchar x,uchar y)

{

uchar x_byte,x_bit;//确定在坐标的那一字节哪一位

uchar y_ping , y_bit;//确定在坐标的哪一屏哪一行

uchar tmph , tmpl;//定义两个临时变量,用于存放读出来的数据

write_com(EXTEND_SET);//扩展指令集

write_com(DRAW_OFF);//绘图显示关闭

x_byte = x / 16;//算出在哪一字节,注意一个地址是16位的

x_bit = x % 16;//& 0x0f;//算出在哪一位

y_ping = y / 32;//确定在上半屏还是下半屏,0代表上半屏,1代表下半屏

y_bit = y % 32;//& 0x1f;//确定在第几行

write_com(0X80 + y_bit);//先写垂直地址(最高位必须)

write_com(0x80 + x_byte + 8 * y_ping);//水平坐标,下半屏坐标起始地址为0x88,(+8*y_ping)就是用来确定上半屏还是下半屏

read_dat();//预读取数据

tmph = read_dat();//读取当前显示高8位数据

tmpl = read_dat();//读取当前显示低8位数据

delay(1);

write_com(0x80 + y_bit);//读操作会改变AC,所以重新设置一下

write_com(0x80 + x_byte + 8 * y_ping);

delay(1);

if(x_bit < 8)

{

write_dat(tmph | (0x01 << (7 - x_bit)));//写高字节,因为坐标是从左向右的,GDRAM高位在昨,低位在右

write_dat(tmpl);//原低位数据送回

}

else

{

write_dat(tmph);//原高位数据送回

write_dat(tmpl | (0x01 << (15 - x_bit)));

}

write_com(DRAW_ON); //打开绘图显示

write_com(BASIC_SET);//回到基本指令集

}

//************画水平线函数**********************************//

//x0、x1为起始点和终点的水平坐标,y为垂直坐标***************//

//**********************************************************//

void gui_hline(uchar x0, uchar x1, uchar y)

{

uchar bak;//用于对两个数互换的中间变量,使x1为大值

if(x0 > x1)

{

bak = x1;

x1 = x0;

x0 = bak;

}

do

{

lcd_set_dot(x0 , y);//从左到右逐点显示

x0 ++;

}

while(x1 >= x0);

}

//***********画竖直线函数***********************************//

//x为起始点和终点的水平坐标,y0、y1为垂直坐标***************//

//**********************************************************//

void gui_rline(uchar x, uchar y0, uchar y1)

{

uchar bak;//用于对两个数互换的中间变量,使y1为大值

if(y0 > y1)

{

bak = y1;

y1 = y0;

y0 = bak;

}

do

{

lcd_set_dot(x , y0);//从上到下逐点显示

y0 ++;

}

while(y1 >= y0);

}

//*********任意两点间画直线*********************************//

//x0、y0为起始点坐标,x1、y1为终点坐标**********************//

//**********************************************************//

void gui_line(uchar x0 , uchar y0 , uchar x1 , uchar y1)

{

char dx;//直线x轴差值

char dy;//直线y轴差值

char dx_sym;//x轴增长方向,为-1时减值方向,为1时增值方向

char dy_sym;//y轴增长方向,为-1时减值方向,为1时增值方向

char dx_x2;//dx*2值变量,用于加快运算速度

char dy_x2;//dy*2值变量,用于加快运算速度

char di;   //决策变量

if(x0 == x1)//判断是否为垂直线

{

gui_rline(x0 , y0 , y1);//画垂直线

return;

}

if(y0 == y1)//判断是否为水平线

{

gui_hline(x0 , x1 , y0);//画水平线

return;

}

dx = x1 - x0;//求取两点之间的差值

dy = y1 - y0;

//****判断增长方向,或是否为水平线、垂直线、点*//

if(dx > 0)//判断x轴方向

dx_sym = 1;

else

{

if(dx < 0)

dx_sym = -1;

else

{

gui_rline(x0 , y0 , y1);

return;

}

}

if(dy > 0)//判断y轴方向

dy_sym = 1;

else

{

if(dy < 0)

dy_sym = -1;

else

{

gui_hline(x0 , x1 , y0);

return;

}

}

/*将dx、dy取绝对值***********/

dx = dx_sym * dx;

dy = dy_sym * dy;

/****计算2倍的dx、dy值*******/

dx_x2 = dx * 1;//我改为了一倍,这样才跟真实的两点对应

dy_x2 = dy * 1;

/***使用bresenham法进行画直线***/

if(dx >= dy)//对于dx>=dy,使用x轴为基准

{

di = dy_x2 - dx;

while(x0 != x1)

{

lcd_set_dot(x0,y0);

x0 +=dx_sym;

if(di < 0)

di += dy_x2;//计算出下一步的决策值

else

{

di += dy_x2 - dx_x2;

y0 += dy_sym;

}

}

lcd_set_dot(x0, y0);//显示最后一点

}

else  //对于dx<dy使用y轴为基准

{

di = dx_x2 - dy;

while(y0 != y1)

{

lcd_set_dot(x0, y0);

y0 += dy_sym;

if(di < 0)

di += dx_x2;

else

{

di += dx_x2 - dy_x2;

x0 += dx_sym;

}

}

lcd_set_dot(x0, y0);//显示最后一点

}

}

//***************************************************************************//

//*******************画指定宽度的任意两点之间的直线**************************//

//参数说明:x0、y0为起始点坐标,x1、y1为终点坐标,with为线宽*****************//

//***************************************************************************//

void gui_linewith(uchar x0 , uchar y0 , uchar x1 , uchar y1 , uchar with)

{

char dx; // 直线x轴差值变量

char dy;           // 直线y轴差值变量

char dx_sym; // x轴增长方向,为-1时减值方向,为1时增值方向

char dy_sym; // y轴增长方向,为-1时减值方向,为1时增值方向

char dx_x2; // dx*2值变量,用于加快运算速度

char dy_x2; // dy*2值变量,用于加快运算速度

char di; // 决策变量

char   wx, wy; // 线宽变量

char   draw_a, draw_b;

// 参数过滤

if(with==0) return;

if(with>50) with = 50;

dx = x1-x0; // 求取两点之间的差值

dy = y1-y0;

wx = with/2;

wy = with-wx-1;

//判断增长方向,或是否为水平线、垂直线、点

if(dx>0) // 判断x轴方向

{

dx_sym = 1; // dx>0,设置dx_sym=1

}

else

{

if(dx<0)

{

dx_sym = -1; // dx<0,设置dx_sym=-1

}

else

{

//dx==0,画垂直线,或一点

wx = x0-wx;

if(wx<0) wx = 0;

wy = x0+wy;

while(1)

{

x0 = wx;

gui_rline(x0, y0, y1);

if(wx>=wy) break;

wx++;

}

return;

}

}

if(dy>0) // 判断y轴方向

{

dy_sym = 1; // dy>0,设置dy_sym=1

}

else

{

if(dy<0)

{

dy_sym = -1; // dy<0,设置dy_sym=-1

}

else

{

//dy==0,画水平线,或一点

wx = y0-wx;

if(wx<0) wx = 0;

wy = y0+wy;

while(1)

{

y0 = wx;

gui_hline(x0, x1, y1);

if(wx>=wy) break;

wx++;

}

return;

}

}

// 将dx、dy取绝对值

dx = dx_sym * dx;

dy = dy_sym * dy;

//计算2倍的dx及dy值

dx_x2 = dx*2;

dy_x2 = dy*2;

//使用Bresenham法进行画直线

if(dx>=dy) // 对于dx>=dy,则使用x轴为基准

{

di = dy_x2 - dx;

while(x0!=x1)

{

//x轴向增长,则宽度在y方向,即画垂直线

draw_a = y0-wx;

if(draw_a<0) draw_a = 0;

draw_b = y0+wy;

gui_rline(x0, draw_a, draw_b);

x0 += dx_sym;

if(di<0)

{

di += dy_x2; // 计算出下一步的决策值

}

else

{

di += dy_x2 - dx_x2;

y0 += dy_sym;

}

}

draw_a = y0-wx;

if(draw_a<0) draw_a = 0;

draw_b = y0+wy;

gui_rline(x0, draw_a, draw_b);

}

else // 对于dx<dy,则使用y轴为基准

{

di = dx_x2 - dy;

while(y0!=y1)

{

//y轴向增长,则宽度在x方向,即画水平线

draw_a = x0-wx;

if(draw_a<0) draw_a = 0;

draw_b = x0+wy;

gui_hline(draw_a, y0, draw_b);

y0 += dy_sym;

if(di<0)

{

di += dx_x2;

}

else

{

di += dx_x2 - dy_x2;

x0 += dx_sym;

}

}

draw_a = x0-wx;

if(draw_a<0) draw_a = 0;

draw_b = x0+wy;

gui_hline(draw_a, y0, draw_b);

}

}

//***********画矩形函数*************************************//

//x0、y0为矩形左上角坐标值,x1、y1为矩形右下角坐标值********//

//**********************************************************//

void gui_rectangle(uchar x0 , uchar y0 , uchar x1 , uchar y1)

{

gui_hline(x0 , x1 , y0);

gui_rline(x0 , y0 , y1);

gui_rline(x1 , y0 , y1);

gui_hline(x0 , x1 , y1);

}

//****************画填充矩形函数****************************//

//x0、y0为矩形左上角坐标值,x1、y1为矩形右下角坐标值********//

//**********************************************************//

/*void gui_rectangle_fill(uchar x0 , uchar y0 , uchar x1 , uchar y1)

{

uchar i;//转换数据的中间变量,使x1、y1大

if(x0 > x1)

{

i = x0;

x0 = x1;

x1 = i;

}

if(y0 > y1)

{

i = y0;

y0 = y1;

y1 = i;

}

//***判断是否是直线***/

/* if(y0 == y1)//画水平线

{

gui_hline(x0 , x1 , y0);

return;

}

if(x0 == x1)//画竖直线

{

gui_rline(x0 , y0 , y1);

return;

}

while(y0 <= y1)//画填充矩形

{

gui_hline(x0 , x1 , y0);

y0 ++;

}

} */

//*******************画正方形函数*************************//

//x0、y0为正方形左上角坐标,with正方形边长****************//

//********************************************************//

/*void gui_square(uchar x0 , uchar y0 , uchar with)

{

if(with == 0)

return;

if((x0 + with) > 127)//横轴超出液晶边界

return;

if((y0 + with) > 63)

return;

gui_rectangle(x0 , y0 , x0 + with , y0 + with);

} */

//****************画填充正方形函数*************************//

//x0、y0为正方形左上角坐标,with正方形边长*****************//

//*********************************************************//

/*void gui_square_fill(uchar x0 , uchar y0 , uchar with)

{

if(with == 0)

return;

if((x0 + with) > 127)//横轴超出液晶边界

return;

if((y0 + with) > 63)

return;

gui_rectangle_fill(x0 , y0 , x0 + with , y0 + with);

} */

//****************画圆函数*********************************//

//x0、y0为圆心坐标,r为圆的半径****************************//

//*********************************************************//

void gui_circle(uchar x0 , uchar y0 , uchar r)

{

char a , b;

char di;

if(r > 31 || r == 0)//圆大于液晶屏或者没半径则返回

return;

a = 0;

b = r;

di = 3 - 2 * r;//判断下个点位置的标志

while(a <= b)

{

lcd_set_dot( x0 - b , y0 - a);//3

lcd_set_dot( x0 + b , y0 - a); //0

lcd_set_dot( x0 - a , y0 + b); //1

lcd_set_dot( x0 - b , y0 - a); //7

lcd_set_dot( x0 - a , y0 - b); //2

lcd_set_dot( x0 + b , y0 + a); //4

lcd_set_dot( x0 + a , y0 - b); //5

lcd_set_dot( x0 + a , y0 + b); //6

lcd_set_dot( x0 - b , y0 + a);

a ++;

//***使用bresenham算法画圆********/

if(di < 0)

di += 4 * a + 6;

else

{

di += 10 + 4 * (a - b);

b --;

}

lcd_set_dot( x0 + a , y0 + b);

}

}

//***************************************************************************//

//***************************画正椭圆函数************************************//

//说明:给定椭圆的四个点的参数,最左、最右点的x轴坐标值为x0、x1,最上、最下点

//      的y轴坐标为y0、y1.

//说明:----------------------------显示效果不好

//***************************************************************************//

void gui_ellipse(char x0, char x1, char y0, char y1)

{

char  draw_x0, draw_y0; // 刽图点坐标变量

char  draw_x1, draw_y1;

char  draw_x2, draw_y2;

char  draw_x3, draw_y3;

char  xx, yy; // 画图控制变量

char  center_x, center_y; // 椭圆中心点坐标变量

char  radius_x, radius_y; // 椭圆的半径,x轴半径和y轴半径

int  radius_xx, radius_yy; // 半径乘平方值

int  radius_xx2, radius_yy2; // 半径乘平方值的两倍

char  di; // 定义决策变量

/* 参数过滤 */

if( (x0==x1) || (y0==y1) ) return;

/* 计算出椭圆中心点坐标 */

center_x = (x0 + x1) >> 1;

center_y = (y0 + y1) >> 1;

/*计算出椭圆的半径,x轴半径和y轴半径 */

if(x0 > x1)

{

radius_x = (x0 - x1) >> 1;

}

else

{

radius_x = (x1 - x0) >> 1;

}

if(y0 > y1)

{

radius_y = (y0 - y1) >> 1;

}

else

{

radius_y = (y1 - y0) >> 1;

}

/* 计算半径平方值 */

radius_xx = radius_x * radius_x;

radius_yy = radius_y * radius_y;

/* 计算半径平方值乘2值 */

radius_xx2 = radius_xx<<1;

radius_yy2 = radius_yy<<1;

/* 初始化画图变量 */

xx = 0;

yy = radius_y;

di = radius_yy2 + radius_xx - radius_xx2*radius_y ; // 初始化决策变量

/* 计算出椭圆y轴上的两个端点坐标,作为作图起点 */

draw_x0 = draw_x1 = draw_x2 = draw_x3 = center_x;

draw_y0 = draw_y1 = center_y + radius_y;

draw_y2 = draw_y3 = center_y - radius_y;

lcd_set_dot(draw_x0, draw_y0); // 画y轴上的两个端点

lcd_set_dot(draw_x2, draw_y2);

while( (radius_yy*xx) < (radius_xx*yy))

{

if(di<0)

{

di+= radius_yy2*(2*xx+3);

}

else

{

di += radius_yy2*(2*xx+3) + 4*radius_xx - 4*radius_xx*yy;

yy--;

draw_y0--;

draw_y1--;

draw_y2++;

draw_y3++;

}

xx ++; // x轴加1

draw_x0++;

draw_x1--;

draw_x2++;

draw_x3--;

lcd_set_dot(draw_x0, draw_y0);

lcd_set_dot(draw_x1, draw_y1);

lcd_set_dot(draw_x2, draw_y2);

lcd_set_dot(draw_x3, draw_y3);

}

di = radius_xx2*(yy-1)*(yy-1) + radius_yy2*xx*xx + radius_yy + radius_yy2*xx - radius_xx2*radius_yy;

while(yy>=0)

{

if(di<0)

{

di+= radius_xx2*3 + 4*radius_yy*xx + 4*radius_yy - 2*radius_xx2*yy;

xx ++; // x轴加1

draw_x0++;

draw_x1--;

draw_x2++;

draw_x3--;

}

else

{

di += radius_xx2*3 - 2*radius_xx2*yy;

}

yy--;

draw_y0--;

draw_y1--;

draw_y2++;

draw_y3++;

lcd_set_dot(draw_x0, draw_y0);

lcd_set_dot(draw_x1, draw_y1);

lcd_set_dot(draw_x2, draw_y2);

lcd_set_dot(draw_x3, draw_y3);

}

}

//*******************************************************************

//*******画满屏图片-----本程序为逐行写,因此图片数据也应该是逐行取的

//参数:dat为填充的数据------用本程序时需要满屏图的数组

//*******************************************************************

void gui_draw_full_picture (unsigned char *dat)

{

unsigned char i;

unsigned char j;

unsigned char k;

unsigned char bGDRAMAddrX = 0x80; //GDRAM水平地址

unsigned char bGDRAMAddrY = 0x80; //GDRAM垂直地址

for(i = 0; i < 2; i++)

{

for(j = 0; j < 32; j++)

{

for(k = 0; k < 8; k++)

{

write_com(0x34); //设置为8位MPU接口,扩充指令集,关闭绘图显示

write_com(bGDRAMAddrY+j); //垂直地址Y

write_com(bGDRAMAddrX+k); //水平地址X

write_dat(*dat++); //写数据高字节

write_dat(*dat++); //写数据低字节

}

}

bGDRAMAddrX = 0x88; //写下半屏幕

}

write_com(0x36); //打开绘图模式

write_com(0x30); //恢复基本指令集,关闭绘图模式

}

unsigned char code  DCB2HEX_TAB[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};

//****************************输出一行数据函数,此行可任意长,不必非得是8的倍数**和下个函数合用画任意大小(矩形)的图形或汉字

//参数:flag反显标志,1为反显 ,x、y为指定显示位置的起始点,*dat要输出的点阵数组,no显示此行所需的点个数,即图形一行的点数

void gui_loadline(unsigned char x,unsigned char y,unsigned char *dat,unsigned char no,unsigned char flag)

{

unsigned char bit_dat;

unsigned char i;

/* 参数过滤,若指定显示位置超出液晶屏则返回 */

if(x>127) return;

if(y>63) return;

for(i=0; i<no; i++)//超出本行所规定的点数则本行显示完成

{

/* 判断是否要读取点阵数据,每字节的开始读取一次点阵数组即i为8的倍数时 */

if( (i%8)==0 ) bit_dat = *dat++;

/* 对相应的点打1或打0, i&0x07意思是对8求余*/

if( (bit_dat&DCB2HEX_TAB[i&0x07])==0 )//取出i对应的位,并判断是否为0

{

if(flag==0) //判断是否反显,该位取出的数据为0,反显要打为1,flag==0代表不反显

GUI_Point(x,y,0);  //正常显示0,GUI_Point(x,y,0)代表在x、y处打0

else

GUI_Point(x,y,1);  //将0反显

}

else

{

if(flag==0)

GUI_Point(x,y,1);

else

GUI_Point(x,y,0);

}

if( (++x)>127) return;//若显示超出了液晶屏则返回

}

}

//***************************************************************************

//*****************在自定义大小的区域内画图或画字函数****************************

//参数说明: x、y指定显示区域的起始点坐标

//          dat 要输出显示的图形或汉字点阵数组。

//          hno 要显示区域的长度

//          lno 要显示区域的高度

//          flag反显标志,1为反显

//****************************************************************************

void  GUI_Put_Area(unsigned char x,unsigned char y,unsigned char *dat,unsigned char hno,unsigned char lno,unsigned char flag)

{

unsigned char i;

for(i=0;i<lno;i++)//逐行打点,打点行数要小于区域高度

{

gui_loadline(x,y,dat,hno,flag); // 打一行数据

y++; //使指针指向下一行

dat += (hno>>3); //比如说上一行打了2字节,此处的意思是使数据向后推进2字节,(hno>>3)意思是算出上一行有几个字节数据

if((hno&0x07)!=0) //hno&0x07意思是对8求余,因一行不满整字节时,上一句的意思就是算出上一行的整字节数,但实际上在取模时不满一个

dat++;   //字节也按一个字节取,所以上一句少计算了一个字节,这里加上

}

}

//*********************************************************************************以上为GDRAM绘图部分************************************************************************//

//**********************************************************************************以下为CGRAM自定义字库部分******************************************************************//

//********************************************************

//设置CGRAM字库

//ST7920 CGRAM(用户自定义图标)空间分布

//空间1地址:40H~4FH共16个地址,一个地址对应两个字节数据;对应调用码:0000H

//空间2地址:50H~5FH共16个地址,一个地址对应两个字节数据;对应调用码:0002H

//空间3地址:60H~6FH共16个地址,一个地址对应两个字节数据;对应调用码:0004H

//空间4地址:70H~7FH共16个地址,一个地址对应两个字节数据;对应调用码:0006H

//参数说明:num为空间编号,取1、2、3、4,CGRAM_ZIKU为地址指针

void SET_CGRAM(unsigned char num,unsigned char *CGRAM_ZIKU)

{

unsigned char i,add;

write_com(0x34); //再次设置为8位并行口,扩展指令集

write_com(0x02); //SR=0,允许设置CGRAM地址

write_com(0x30); //恢复设置为8位并行口,基本指令集

add=(num<<4)|0x40; //计算CGRAM的首地址

for(i=0;i<16;i++)

{

write_com(add+i); //设置CGRAM的首地址

write_dat(CGRAM_ZIKU[i*2]); //写入高8位数据

write_dat(CGRAM_ZIKU[i*2+1]);//写入低8位数据

}

}

//********************************************************

//指定位置显示CGRAM自造字函数

//参数说明:x为行号,y为列号,num为编号

//********************************************************

void display_CGRAM(unsigned char x,unsigned char y,unsigned char num)

{

set_cursor(x,y); //设置显示的起始地址

write_dat(0x00); //写入需要显示汉字的高八位数据

write_dat(num*2); //写入需要显示字符的低八位数据

}

uchar code CGRAM_ZIKU[] = {0X03,0X80,0X00,0X80,0XF8,0X8E,0X23,0X91,0X22,0X21,0X22,0X20,0X23,0XA0,0X20,0X20,

0X20,0X20,0X20,0X20,0X20,0X20,0X20,0X21,0X20,0X11,0XF8,0X0E,0X00,0X00,0X00,0X00};//I2C

//**************设置CGRAM字库并显示函数

void set_and_display()

{

SET_CGRAM( 1,CGRAM_ZIKU);//把自定义字库写入CGRAM,且写入空间地址1

display_CGRAM(0 , 1 , 1);//在指定的位置显示空间地址1中自定义的字符

}

//***************************************************************************以上为自定义字库部分**************************************************************//

//****************12864初始化函数

void lcd_init()

{

write_com(0x30);//基本指令操作,8位并口

delay(1);

write_com(0x06);//设置为游标右移,DDRAM地址加一,画面不动

delay(1);

write_com(0x0c);//显示开,关光标

delay(1);

write_com(0x01);//清除lcd显示内容

delay(1);

}

//*****************************主函数

void main()

{

wela=0;

dula=0;

delay(1);

lcd_init();//12864初始化函数

gui_clear();//画图时清屏函数

delay(10);

set_and_display();//显示自定义字库

gui_circle( 86 , 32 , 30); //画圆

gui_linewith( 5 , 5 , 120 , 60 , 3);//画指定线宽直线

gui_ellipse(10 , 120 , 5 , 60);//画正椭圆

while(1);

}

时间: 2024-07-29 01:22:32

12864 显示画圆多种图形的相关文章

圆角背景实现,如实现圆角按钮;用xml文件画圆

项目中为了更好的视觉效果,然后又懒的去弄图片做背景时,往往就会通过xml布局文件来实现圆角的效果. 在drawable目录下新建一个shape类型的xml文件,设置<corners android:radius="5dp" />,然后在需要设为圆角的控件中,如按钮或LinearLayout,设置他们的background为drawable="@drawable/...".即可达到圆角的效果 // 用xml文件画圆 用竖线连接ListView的各个item

汇编画圆

汇编画圆-->效果如下图 代码如下: 1 dseg segment 2 center_x dw 150 ;原点坐标_x 3 center_y dw 90 ;原点坐标_y 4 radius dw 50 ;半径_r 5 label_x dw ? ;外接正方形右边界 6 label_y dw ? ;外接正方形下边界 7 distance dw ? 8 dseg ends 9 cseg segment 10 assume cs:cseg , ds:dseg 11 start: 12 mov ax , d

中点画线法画圆

中点画线法已经在画直线的时候详细讲过了,画圆时我们也可以用这种方法.画一个圆心为坐标原点的1/4圆,然后对其进行简单几何变换,平移对称,就可以得到任意圆. 类似的用中点画线法,从(0,r)点开始,每次要么向右走,要么向右下走,直到x==y,即到达四分之一圆处: (1)当d<0时,中点在圆内,则取正右方的点,(x+1,y+0.5),此时d=d+2*x+3; (2) 当d>=0时,中点在圆外,则取右下方的点,(x+1,y-1),此时d=d+2*(x-y)+5; (3) d0=1-r,即点(0,r)

根据周长计算不同形状图形的面积?计算多种图形的面积

/** *  根据周长计算不同形状图形的面积?计算多种图形的面积, *  并比较各种图形面积的最大值.正方形的面积公式为:0.0625*c*c. *  圆形的面积公式为:0.0796*c*c,其中,c表示图形的周长. */ /** * 根据周长计算不同形状图形的面积?计算多种图形的面积, * 并比较各种图形面积的最大值.正方形的面积公式为:0.0625*c*c. * 圆形的面积公式为:0.0796*c*c,其中,c表示图形的周长. */ public class AreaTest { publi

用Windjs画圆

无意中接触了jscex,也就是Wind.js的前身,深深被它和它的作者老赵吸引.该轻量级js库是为了实现异步编程所设计的,可能因为eval的种种不安全因素或者应用不是很广的原因至今也没很大程度上的推广,从github上来看代码也已经两年多没更新了,但是还是有必要写几个小的demo的,毕竟下份需要阅读的代码中有用到该类库. 先写个canvas上画圆的demo. 等等,画圆?开玩笑,arc简单搞定!那么,要是不用h5的api自己来写这个函数呢?动手画了下感觉还是蛮easy的: 1 <!DOCTYPE

《图形学》实验六:中点Bresenham算法画圆

开发环境: VC++6.0,OpenGL 实验内容: 使用中点Bresenham算法画圆. 实验结果: 代码: 1 #include <gl/glut.h> 2 3 #define WIDTH 500 4 #define HEIGHT 500 5 #define OFFSET 15 6 #define R 8 7 8 void Init() //其它初始化 9 { 10 glClearColor(1.0f,1.0f,1.0f,1.0f); //设置背景颜色,完全不透明 11 glColor3f

几何画板如何画圆内接正七边形

由正七边形的特征,我们知道,每一个点都相当于前面的点逆时针旋转360°/7,抓住这个规律,我们可以用几何画板迭代功能来解决.下面将详细介绍几何画板圆内接正七边形的绘制方法. 具体的操作步骤如下: 利用“圆工具”画圆O,在圆O上任取一点A. 双击圆心O作为旋转中心.选中A点,选择菜单“变换”——“旋转”,旋转参数选为选择固定角度,然后在框中输入360/7,然后点击“旋转”按钮,将旋转得到的点标签改为B.连接线段AB. 选择A点,选择“变换”——“迭代”,点击B点作为初像.此时屏幕上显示出迭代的像是

计算机图形学中的中点画线,中点画圆,Bresenham画线与画圆算法

#include<iostream>#include<graphics.h>  // 这样引用 EasyX 图形库#include<conio.h>#include<time.h>#include<math.h>#include<stdlib.h>using namespace std; //Bresenham画线void Bresenham_line(int x0,int y0,int x1,int y1){ int x,y,dx,

matlab画圆

首先介绍一下rectangle函数 1.rectangle函数实际上是一个画矩形的行数,语法调用为: rectangle('Position',[x,y,w,h]),表示的是下哦那个点(x,y)开始画一个宽w高h的矩形.默认情况下是从(0,0)开始画一个宽1高1的矩形.例如直接在命令窗口出入:rectangle,axis equal  画出的图形如下图所示.(axis equal的意思是保持横纵坐标等比例) 2. rectangle函数可以制定矩形边的曲率,这就为我们画圆提供了一个思路.改变曲率