转载请注明出处。作者:四极管。广西师范大学 电子工程学院大学生科技创新基地 邮箱: yangxingbo-0311@163.com。
原文地址:http://blog.csdn.net/yangxingbo0311/article/details/7201097
这个代码是参考基地当时一牛人来做的··后面还有在C++builder上的实现··很炫的哦··很值得借鉴
------------------------------------------------------------------------------------------------
程序说明:程序由12864的串行模式修改为并行模式,主要是为了提高12864的速度。在原有的
汉字、字符显示功能,绘图功能的基础上,增加了多个功能函数,以完善12864显示各种图象数据的
功能
------------------------------------------------------------------------------------------------
1.汉字字幕的左移动功能,函数名称为:
dispstr_12864_move(uchar x,uchar y1,uchar y2,uchar *pstr1,uint word_number,uint speed)
使用说明:x为文字在屏幕上地址定位横坐标;y1为第(1~4)行文字定位地址坐标;y2为第(1~4)行文字定位地
址坐标;*pstr1为第一行文字组;*pstr2为第二行文字组 ;word_number 移动显示的文字数目;speed 为字幕移
动的速度。该函数的功能大家可以根据自己的需要修改和完善,本函数中只提供基本的移动算法。
--------------------------------------------------------------------------------------------------
2.12864全屏区域单点描点函数,函数名称为:
plot_12864(uchar x,uchar y,uchar *buf),给定一个坐标(x,y),即可在屏幕上对应的坐标显示出一个点
其中,x取值范围为:1~128 y的取值范围为:1~64 !!!注意!!!不可超出规定的取值范围,否则屏幕
有可能不能正常显示,原因是数据溢出缓冲区。
--------------------------------------------------------------------------------------------------
3.12864全屏区域多点镜像描点函数,函数名称为:
mirror_point_12864(uchar center,uchar x,uchar h,uchar *buf)center为对称轴的坐标,即屏幕上对应
的y坐标x为要镜像描点的横坐标,h为镜像描点的高度,buf为数据存放的目标缓存区。此函数主要是用在音乐频
谱的显示上。
----------------------------------------------------------------------------------------------------
4.任意两点间画直线的函数,函数名为:
draw_Line(uchar x0,uchar y0,uchar x1,uchar y1),采用布兰森汉姆(Bresenham)算法画线,给定两个点的
坐标(x0,y0),(x1,y1)就能实现在这两点间画出直线。辅助实现该函数功能的附属函数有:
①求两个数的绝对值|a-b|的函数abs(uchar a,uchar b)
②画垂直线的函数subsection_point_12864(uchar x,uchar center,uchar h,uchar *buf)
③画横线的函数line_piont(uchar x0,uchar y0,uchar x1,uchar *buf)
----------------------------------------------------------------------------------------------------
5.画圆函数,函数名为:
draw_circle(uchar x0,uchar y0,uchar r),采用布兰森汉姆(Bresenham)算法画圆,先画1/8个圆,然后用对称
方法画出剩下的部分。(x0,y0)为圆心的坐标,x0:1~128 y0:1~64 r为圆的半径:1~31。
-----------------------------------------------------------------------------------------------------
**************************************************************************************************
*************************************************************************************************/
//*******头文件部分********//
#include "avr/io.h"
#include <util/delay.h>
#include "math.h"
#define data_port PORTB
#define RS_1() {DDRC |= (1<<7);nop();PORTC |= (1<<7);}
#define RW_1() {DDRC |= (1<<6);nop();PORTC |= (1<<6);}
#define EN_1() {DDRC |= (1<<5);nop();PORTC |= (1<<5);}
#define RS_0() {DDRC |= (1<<7);nop();PORTC &= ~(1<<7);}
#define RW_0() {DDRC |= (1<<6);nop();PORTC &= ~(1<<6);}
#define EN_0() {DDRC |= (1<<5);nop();PORTC &= ~(1<<5);}
#define set_output() DDRB = 0XFF
#define set_input() DDRB = 0X00
#define port_lcd PINB
#define nop() asm("nop")
#define uchar unsigned char
#define uint unsigned int
uchar music[1024]={};
uchar magic[16]={};
//**********************************************************************
void delay_100ms(uint i)
{
uint k;
for (k=0;k<i;k++)
{
_delay_ms(10);
_delay_ms(10);
_delay_ms(10);
_delay_ms(10);
_delay_ms(10);
_delay_ms(10);
_delay_ms(10);
_delay_ms(10);
_delay_ms(10);
_delay_ms(10);
}
}
//**********************************************************************
//*************函数部分***************/
/* 名字:busywait_12864() */
/* 功能:检测RT12864M是否忙 */
/* 局部变量:无 */
/* 全局变量:无 */
/* 返回值: 无 */
//************************************/
void busywait_12864(void)
{
uchar bf=0;
loop:RS_0();
RW_1();
EN_1();
set_input();
_delay_us(6);
bf = port_lcd;
EN_0();
if(bf&0x80)goto loop;
set_output();
}
//*************函数部分***************/
/* 名字:writecomm_12864() */
/* 功能:写命令进RT12864M */
/* 局部变量:command */
/* 全局变量:无 */
/* 返回值: 无 */
//************************************/
void writecomm_12864(uchar command)
{
busywait_12864();
set_output();
RS_0();
RW_0();
data_port = command;
EN_1();
EN_0();
}
//*************函数部分***************/
/* 名字:writedata_12864() */
/* 功能:写数据写进RT12864M */
/* 局部变量:wrdata */
/* 全局变量:无 */
/* 返回值: 无 */
//************************************/
void writedata_12864(uchar wrdata)
{
busywait_12864();
set_output();
RS_1();
RW_0();
data_port = wrdata;
EN_1();
EN_0();
}
//*************函数部分***************/
/* 名字:Init_12864() */
/* 功能:初始化RT12864M */
/* 局部变量:无 */
/* 全局变量:无 */
/* 返回值: 无 */
//************************************/
void Init_12864(void)
{
writecomm_12864(0x30);//功能设置 8位数据,基本指令
_delay_ms(1);
writecomm_12864(0x0c);//显示状态 ON,游标OFF,反白OFF
_delay_ms(1);
writecomm_12864(0x01);//清除显示
_delay_ms(1);
writecomm_12864(0x02);//地址归位
}
//*************函数部分***************/
/* 名字:locatexy_12864() */
/* 功能:定位显示地址 */
/* 局部变量:x,y */
/* 全局变量:无 */
/* 返回值: 无 */
//************************************/
void locatexy_12864(uchar x,uchar y)
{
uchar addr=0;
switch(y)
{
case 0:addr=0x80+x;break;
case 1:addr=0x90+x;break;
case 2:addr=0x88+x;break;
case 3:addr=0x98+x;break;
default:break;
}
writecomm_12864(addr);
}
//*************函数部分***************/
/* 名字:distwochar_12864() */
/* 功能:显示两个字符即一个汉字 */
/* 局部变量:x,y,char1,char2 */
/* 全局变量:无 */
/* 返回值: 无 */
//************************************/
void distwochar_12864(uchar x,uchar y,uchar char1,uchar char2)
{
locatexy_12864(x,y);
writedata_12864(char1);
writedata_12864(char2);
}
//*************函数部分***************/
/* 名字:dispstr_12864() */
/* 功能:显示汉字字组 */
/* 局部变量:x,y,*pstr */
/* 全局变量:无 */
/* 返回值: 无 */
//************************************/
void dispstr_12864(uchar x,uchar y,uchar *pstr)
{
uint i,t=0;
while(pstr[t]!='\0')t++;
for(i=0;i<t;i++)
{
distwochar_12864(x,y,pstr[i],pstr[i+1]);
i+=1;
x+=1;
if(x==8)
{
x=0;
y++;
if(y==4)y=0;
}
}
}
/*=========================================*/
/* 函数:drawpic(uchar *pdraw); */
/* 功能描述:画图形 */
/* 参数接口:pdraw,是存放图形数据的表 */
/*=========================================*/
void drawpic_12864(uchar *pdraw)
{
uint x,y;
long uint k=0;
uchar yaddr=0x80;
//writecomm_12864(0x30);//功能设置---8BIT控制界面,绘图显示OFF
writecomm_12864(0x34);//功能设置---8BIT控制界面,扩充指令集
for(y=0;y<32;y++)
{
writecomm_12864(yaddr++);//设置绘图区的Y地址坐标
writecomm_12864(0x80); //设置绘图区的X地址坐标
for(x=0;x<8;x++)
{
writedata_12864(pdraw[k++]);
writedata_12864(pdraw[k++]);
}
}
yaddr=0x80;
for(y=0;y<32;y++)
{
writecomm_12864(yaddr++);//设置绘图区的Y地址坐标
writecomm_12864(0x88); //设置绘图区的X地址坐标
for(x=0;x<8;x++)
{
writedata_12864(pdraw[k++]);
writedata_12864(pdraw[k++]);
}
}
// writecomm_12864(0x32);//功能设置---8BIT控制界面,绘图显示ON
writecomm_12864(0x36);//功能设置---8BIT控制界面,绘图显示OFF
//返回基本设置
writecomm_12864(0x30);//功能设置 8位数据,基本指令
writecomm_12864(0x0c);//显示状态 ON,游标OFF,反白OFF
writecomm_12864(0x02);//地址归位
}
//*************函数部分***************************************************
// 名字:dispstr_12864()
// 功能:移动显示汉字字组
// 局部变量:x,y12,*pstr1,*pstr2,word_number,speed
// 使用说明:x为文字定位地址横坐标?
// y1为第(1~4)行文字定位地址坐标
// y2为第(1~4)行文字定位地址坐标
// *pstr1为第一行文字组
// *pstr2为第二行文字组
// word_number 移动显示的文字数目
// speed 移动的速度
// 全局变量:无
// 返回值: 无
//***********************************************************************
void dispstr_12864_move(uchar x,uchar y1,uchar y2,
uchar *pstr1,
uint word_number,uint speed)
{
uchar i,t;
uint move;
for (move=0;move<word_number;move++)
{
for (t=0;t<16;t++)
{
for(i=0;i<t;i++)
{
distwochar_12864(x,y1,pstr1[i+move*2],pstr1[i+move*2+1]);
//distwochar_12864(x,y2,pstr2[i+move*2],pstr2[i+move*2+1]);
i+=1;
x+=1;
if(x==8)
{
x=0;
}
}
}
delay_100ms(speed);
}
}
//******************************************************
//*************函数部分********************************/
/* 名字:abs(x1-x0) */
/* 功能:计算两个数相减的绝对值 */
/* 局部变量:取值范围 */
/* */
/* 全局变量:无 */
/* 返回值: 无 */
/* 注意 */
//*****************************************************/
int abs(int a,int b)
{
uint fabs = 0;
if ((a-b)>0) fabs = a-b;
else fabs = b-a;
return (fabs);
}
//****************************************************
//*************函数部分****************************/
/* 名字:plot1_12864() */
/* 功能:图象单点描点函数 */
/* 局部变量:取值范围 x:[-64,64] y:[-32,31] */
/* 全局变量:无 */
/* 返回值: 无 */
//*************************************************/
void plot1_12864(int x,int y,uchar *buf)
{
uchar a=0;
if ((x>0)|(x==0))
{
if (!((x+64)%8))
{
a|=(1<<0);
buf[(31-y)*16+((x+64)/8)-1]|=a;
}
else
{
a|=(1<<(8-(x+63)%8));
buf[(31-y)*16+((x+64)/8)]|=a;
}
}
else
{
if (!((64+x)%8))
{
a|=(1<<0);
buf[(31-y)*16+((64+x)/8)-1]|=a;
}
else
{
a|=(1<<(8-(x+64)%8));
buf[(31-y)*16+(64+x)/8]|=a;
}
}
}
//*************函数部分****************************/
/* 名字:plot1_12864() */
/* 功能:图象单点描点函数 */
/* 局部变量:取值范围 x:[-64,64] y:[-32,31] */
/* 全局变量:无 */
/* 返回值: 无 */
//*************************************************/
void plot_12864(int x,int y,uchar *buf)
{
uchar a=0;
if (!(x%8))
{
a|=(1<<0);
buf[(64-y)*16+(x/8)-1]|=a;
}
else
{
a|=(1<<(8-x%8));
buf[(64-y)*16+(x/8)]|=a;
}
}
//******************************************************
//*************函数部分********************************/
/* 名字:mirror_point_12864() */
/* 功能:图象多点镜像描点函数 */
/* 局部变量:取值范围 :y:[1,128] */
/* 像距为:h:[1,63] 中心线:center:[1,64] */
/* 全局变量:无 */
/* 返回值: 无 */
/* 注意!!:两点之间的距离不得超过64(12864只有64行)*/
//*****************************************************/
void mirror_point_12864(uchar center,uchar x,uchar h,uchar *buf)
{
uchar a=0,i,high=0;
if (h>31) high = 31;
else high = h;
if (!(x%8))
{
a|=(1<<0);
for (i=0;i<high;i++)
{
buf[(64-center+i)*16+(x/8)-1]|=a;
buf[(64-center-i)*16+(x/8)-1]|=a;
}
}
else
{
a|=(1<<(8-x%8));
for (i=0;i<high;i++)
{
buf[(64-center+i)*16+(x/8)]|=a;
buf[(64-center-i)*16+(x/8)]|=a;
}
}
}
//******************************************************
//*************函数部分********************************/
/* 名字:clear_print_12864() */
/* 功能:清除图象数据存储区 */
/* 局部变量:取值范围 :y:[1,128] */
/* */
/* 全局变量:无 */
/* 返回值: 无 */
/* 注意 */
//*****************************************************/
void clear_print_12864(uchar *buffer)
{
int i;
for (i=0;i<1024;i++)
{
buffer[i] = 0x00;
}
drawpic_12864(buffer);
}
//******************************************************
//*************函数部分********************************/
/* 名字:subsection_point_12864() */
/* 功能:分段描点函数 */
/* 局部变量: */
/* */
/* 全局变量:无 */
/* 返回值: 无 */
/* 注意!!:两点之间的距离不得超过64(12864只有64行)*/
//*****************************************************/
void subsection_point_12864(uchar x,uchar center,uchar h,uchar *buf)
{
uchar a=0,i,high=0;
if (h>63) high = 63;
else high = h;
if (!(x%8))
{
a|=(1<<0);
for (i=0;i<high;i++)
{
buf[(64-center-i)*16+(x/8)-1]|=a;
}
}
else
{
a|=(1<<(8-x%8));
for (i=0;i<high;i++)
{
buf[(64-center-i)*16+(x/8)]|=a;
}
}
}
//*************函数部分********************************/
/* 名字:line_piont() */
/* 功能:画横线函数 */
/* 局部变量: */
/* */
/* 全局变量:无 */
/* 返回值: 无 */
/* 注意!!:两点之间的距离不得超过128(12864只有128宽*/
//*****************************************************/
void line_piont(int x0,int y0,int x1,uchar *buf)
{
uchar i;
for (i=x0;i<x1;i++)
{
plot_12864(i,y0,buf);
}
}
//*************函数部分********************************/
/* 名字:load_magic_12864() */
/* 功能:加载频谱魔幻花样 */
/* 局部变量:取值范围 :y:[1,128] */
/* */
/* 全局变量:无 */
/* 返回值: 无 */
/* 注意 */
//*****************************************************/
void load_magic_12864(uchar *buffer)
{
uchar i,h;
for (i=0;i<16;i++)
{
h= buffer[i];
line_piont(i*8+1,h+1,i*8+8,music);
line_piont(i*8+1,h+2,i*8+8,music);
}
}
/********************************************************
* 名称:draw_Line()
采用布兰森汉姆(Bresenham)算法画线
* 功能:任意两点间的直线。根据硬件特点,实现加速。
* 入口参数:x0 直线起点所在行的位置
* y0 直线起点所在列的位置
* x1 直线终点所在行的位置
‘ y1 直线终点所在列的位置
* 出口参数: 无
* 说明:操作失败原因是指定地址超出缓冲区范围。
*********************************************************/
void draw_line(int x0,int y0,int x1,int y1)
{
int temp;
int dx,dy; //定义起点到终点的横、纵坐标增加值
int s1,s2,status,i;
int Dx,Dy,sub;
dx=x1-x0;
if(dx>=0) //X的方向是增加的
s1=1;
else //X的方向是降低的
s1=-1;
dy=y1-y0; //判断Y的方向是增加还是降到的
if(dy>=0) s2=1;
else s2=-1;
Dx=abs(x1,x0); //计算横、纵标志增加值的绝对值
Dy=abs(y1,y0);
if(Dy>Dx) //
{ //以45度角为分界线,靠进Y轴是status=1,靠近X轴是status=0
temp=Dx;
Dx=Dy;
Dy=temp;
status=1;
}
else status=0;
//********判断垂直线和水平线*******************************************
//if(dx==0) //横向上没有增量,画一条水平线
//line_piont(x0,y0,x1,music);
//if(dy==0) //纵向上没有增量,画一条垂直线
// subsection_point_12864(x0,y0,y1,music);
//*********Bresenham算法画任意两点间的直线*****************************
sub=2*Dy-Dx; //第1次判断下个点的位置
for(i=0;i<Dx+1;i++)
{
plot_12864(x0,y0,music); //画点
if(sub>=0)
{
if(status==1) //在靠近Y轴区,x值加1
x0+=s1;
else //在靠近X轴区,y值加1
y0+=s2;
sub-=2*Dx; //判断下下个点的位置
}
if(status==1)
y0+=s2;
else
x0+=s1;
sub+=2*Dy;
}
}
/***************************************************************
名称:Draw_circle (在任意位置画圆)
说明:使用Bresenham法画1/8个圆,在用对称性画出其他的7/8个圆
按下图把圆分为8份
0
7 1
6 2
5 3
4
*****************************************************************/
void draw_circle(uchar x0,uchar y0,uchar r)
{
int a,b;
int di;
a=0;
b=r;
di=3-2*r; //判断下个点位置的标志
while(a<=b)
{ //plot_12864(uchar x,uchar y,uchar *buf)
plot_12864(x0-b,y0-a,music); //3
plot_12864(x0+b,y0-a,music); //0
plot_12864(x0-a,y0+b,music); //1
plot_12864(x0-b,y0-a,music); //7
plot_12864(x0-a,y0-b,music); //2
plot_12864(x0+b,y0+a,music); //4
plot_12864(x0+a,y0-b,music); //5
plot_12864(x0+a,y0+b,music); //6
plot_12864(x0-b,y0+a,music);
a++;
/***使用Bresenham算法画圆**/
if(di<0)
di +=4*a+6;
else
{
di +=10+4*(a-b);
b--;
}
plot_12864(x0+a,y0+b,music);
}
}
//*************函数部分********************************/
/* 名字:cube_3D() */
/* 功能:3D图象变换算法变换立方体 */
/* 局部变量: */
/* */
/* 全局变量:无 */
/* 返回值: 无 */
/* 注意!!:两点之间的距离不得超过64(12864只有64行)*/
//*****************************************************/
/* 定义显示位置 */
//#define OFFSETX 30
uchar OFFSETX = 64;
#define OFFSETY 38
#define OFFSETZ 60
/立方体加文字/
/*const signed int aa[23]={8,-8,-8,8,8,-8,-8,8,8,8,8,8,8,0,4,-4,-8,-8,-8,-8,-8,-8,-8}; // x
const signed int bb[23]={8,8,-8,-8,8,8,-8,-8,0,-4,4,-2,2,8,8,8,4,4,4,-4,-4,-4,0}; // y
const signed int cc[23]={-8,-8,-8,-8,8,8,8,8,6,-6,-6,0,0,-6,6,6,-6,0,6,6,0,-6,0}; // z
const int ff[22]={1,2,3,4,5,6,7,8,1,2,3,4,9,9,12,14,14,17,19,20,21,22}; // start
const int gg[22]={2,3,4,1,6,7,8,5,5,6,7,8,10,11,13,15,16,19,20,21,18,23}; // end*/
/
const signed int aa[14]={-16,-14,-18,-12,-20,8,-8,0,20,12,20,12,20,12}; // x
const signed int bb[14]={16,10,10,0,0,16,16,0,16,16,10,10,0,0}; // y
const signed int cc[14]={0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // z
const int ff[13]={1,3,1,2,3,6,7,10,12,10,9,12,12}; // start
const int gg[13]={3,5,2,4,2,8,8,12,14,9,11,11,13}; // end
/
/*const signed int aa[16]={-11,-3,-7,11,-3,-13,-1,-7,-13,-1,0,8,4,8,0,0}; // x
const signed int bb[16]={20,20,12,16,16,12,12,12,0,0,20,20,16,12,12,0}; // y
const signed int cc[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // z
const int ff[12]={1,2,4,3,6,8,8,11,11,12,13,14}; // start
const int gg[12]={3,3,5,8,7,9,10,16,12,13,14,15}; // end*/
/
/*const signed int aa[16]={-26,-26,-16,-12,-12,-3,-3,2,10,18,22,30,22,30,22,30}; // x
const signed int bb[16]={16,0,0,16,0,16,0,16,0,16,16,16,8,8,0,0}; // y
const signed int cc[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // z
const int ff[13]={1,2,4,4,6,5,8,9,11,13,11,13,15}; // start
const int gg[13]={2,3,5,6,7,7,9,10,13,15,12,14,16}; // end*/
/
int sx,sy,ex,ey; // define global vars for calling graphics subroutines
float rotx=0.00; // starting amount of x rotation
float roty=0.00; // starting amount of y rotation
float rotz=0.00; // starting amount of z rotation
/**************************************************************************
* 3D显示主程序
***************************************************************************/
void Disply3D(float xpos,float ypos,float zpos)
{
int newx[23]; // translated screen x co-ordinates for vertex
int newy[23]; // translated screen y co-ordinates for vertex
int i,loop; // temp variable for loops
int vertex;
float xt,yt,zt,x,y,z,sinax,cosax,sinay,cosay,sinaz,cosaz; // lots of work variables
for (loop=0;loop<1;loop++)
{
xpos=xpos+0.00; // move the object
ypos=ypos+0.00; // it would wander off screen
zpos=zpos+0.00; // really quick, so leave it centered
rotx=rotx+0.00; // rotate the cube on X axis
roty=roty+0.15; // and on its y axis
rotz=rotz+0.00; // dont bother with z or it gets confusing
sinax=sin(rotx); // precalculate the sin and cos values
cosax=cos(rotx); // for the rotation as this saves a
sinay=sin(roty); // little time when running as we
cosay=cos(roty); // call sin and cos less often
sinaz=sin(rotz); // they are slow routines
cosaz=cos(rotz); // and we dont want slow!
for (i=0; i<14; i++) // translate 3d vertex position to 2d screen position
{
x=aa[i]; // get x for vertex i
y=bb[i]; // get y for vertex i
z=cc[i]; // get z for vertex i
yt = y * cosax - z * sinax; // rotate around the x axis
zt = y * sinax + z * cosax; // using the Y and Z for the rotation
y = yt;
z = zt;
yt = y * cosax - z * sinax; // rotate around the x axis
zt = y * sinax + z * cosax; // using the Y and Z for the rotation
y = yt;
z = zt;
xt = x * cosay - z * sinay; // rotate around the Y axis
zt = x * sinay + z * cosay; // using X and Z
x = xt;
z = zt;
xt = x * cosaz - y * sinaz; // finaly rotate around the Z axis
yt = x * sinaz + y * cosaz; // using X and Y
x = xt;
y = yt;
x=x+xpos; // add the object position offset
y=y+ypos; // for both x and y
z=z+OFFSETZ-zpos; // as well as Z
newx[i]=(x*64/z)+OFFSETX; // translate 3d to 2d coordinates for screen
newy[i]=(y*64/z)+OFFSETY; // drawing so we can see the cube
}
for (i=0; i<13; i++) // draw the lines that make up the object
{
vertex=ff[i]-1; // temp = start vertex for this line
sx=newx[vertex]; // set line start x to vertex[i] x position
sy=newy[vertex]; // set line start y to vertex[i] y position
vertex=gg[i]-1; // temp = end vertex for this line
ex=newx[vertex]; // set line end x to vertex[i+1] x position
ey=newy[vertex]; // set line end y to vertex[i+1] y position
if((sx>255) | (sy>255) | (ex>255) |( ey>255))
{
sx=255;
sy=255;
ex=255;
ey=255;
}
draw_line(sx,sy,ex,ey);
}
}
}