四极管:3D图像 之 AVR 12864实现

来源:互联网 发布:2016零售业数据分析 编辑:程序博客网 时间:2024/06/09 03:01

转载请注明出处。作者:四极管。广西师范大学 电子工程学院大学生科技创新基地 邮箱: 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 intuchar   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,反白OFFwritecomm_12864(0x02);//地址归位}//*************函数部分***************************************************// 名字:dispstr_12864()             // 功能:移动显示汉字字组                // 局部变量:x,y12,*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};   // zconst 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};         // startconst 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};   // zconst int ff[13]={1,3,1,2,3,6,7,10,12,10,9,12,12};         // startconst 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};   // zconst int ff[12]={1,2,4,3,6,8,8,11,11,12,13,14};         // startconst 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};   // zconst int ff[13]={1,2,4,4,6,5,8,9,11,13,11,13,15};         // startconst 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 subroutinesfloat rotx=0.00;                     // starting amount of x rotationfloat roty=0.00;                     // starting amount of y rotationfloat 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 centeredrotx=rotx+0.00;                 // rotate the cube on X axisroty=roty+0.15;                 // and on its y axisrotz=rotz+0.00;                 // dont bother with z or it gets confusingsinax=sin(rotx);               // precalculate the sin and cos valuescosax=cos(rotx);             // for the rotation as this saves a sinay=sin(roty);             // little time when running as wecosay=cos(roty);             // call sin and cos less oftensinaz=sin(rotz);             // they are slow routinescosaz=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 iy=bb[i];                   // get y for vertex iz=cc[i];                   // get z for vertex iyt = y * cosax - z * sinax;         // rotate around the x axiszt = y * sinax + z * cosax;       // using the Y and Z for the rotationy = yt;z = zt;yt = y * cosax - z * sinax;         // rotate around the x axiszt = y * sinax + z * cosax;       // using the Y and Z for the rotationy = yt;z = zt;xt = x * cosay - z * sinay;       // rotate around the Y axiszt = x * sinay + z * cosay;       // using X and Zx = xt;z = zt;xt = x * cosaz - y * sinaz;         // finaly rotate around the Z axisyt = x * sinaz + y * cosaz;       // using X and Yx = xt;y = yt;x=x+xpos;                         // add the object position offsety=y+ypos;                         // for both x and yz=z+OFFSETZ-zpos;           // as well as Znewx[i]=(x*64/z)+OFFSETX;       // translate 3d to 2d coordinates for screennewy[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 linesx=newx[vertex];           // set line start x to vertex[i] x positionsy=newy[vertex];           // set line start y to vertex[i] y positionvertex=gg[i]-1;             // temp = end vertex for this lineex=newx[vertex];           // set line end x to vertex[i+1] x positioney=newy[vertex];           // set line end y to vertex[i+1] y positionif((sx>255) | (sy>255) | (ex>255) |( ey>255)){sx=255;sy=255;ex=255;ey=255;}draw_line(sx,sy,ex,ey);}}}
 
	
				
		
原创粉丝点击