全部源代碼下載:http://www.zg4o1577.cn/f/128yhj.rar
#include"reg51.h" sbit cd = P2^0; unsigned char pdata *addr; #define uchar unsigned char #define uint unsigned short void lcd_writecom_two(uchar onedat,uchar twodat,uchar com); void lcd_writedat_onebyte(uchar onedat,uchar com); uchar lcd_readdat_onebyte(uchar com); void lcd_writedat_nbyte(uchar *dat,uchar len); void lcd_readdat_nbyte(uchar *dat ,uchar len); void clear_point(uchar x,uchar y); void sel_point(uchar x,uchar y); void sel_rmiddling(uchar x,uchar y); void clr_rmiddling(uchar x,uchar y); void sel_rbig(uchar x,uchar y); void clr_rbig(uchar x,uchar y); void graph_mode_writeword(uchar x,uchar y,uchar *dat); void graph_mode_write_letter(uchar x,uchar y,uchar *dat); void rhorizontal(uchar x0,uchar x1,uchar y); void erect(uchar y0,uchar y1,uchar x); void Draw_line(uchar x0,uchar y0,uchar x1,uchar y1); void draw_circle(int x, int y, int r); void lcd_init(); /********************************** 讀取lcd狀態 **********************************/ uchar lcd_readcom() { uchar temp; cd=1; addr = 0xff; temp = *addr; return temp; } /********************************* 判斷指令/數據讀寫忙碌狀態 *********************************/ void check_busy() { uchar temp; do{ temp=lcd_readcom(); }while((temp&0x03)!=0x03); } /********************************* 判斷數據自動寫忙碌狀態 *********************************/ void check_auto_write_busy() { uchar temp; do{ temp=lcd_readcom(); }while((temp&0x08)!=0x08); } /********************************* 判斷數據自動讀忙碌狀態 *********************************/ void check_auto_read_busy() { uchar temp; do{ temp=lcd_readcom(); }while((temp&0x04)!=0x04); } /********************************* 向lcd寫命令 *********************************/ void lcd_writecom(uchar dat) { check_busy(); cd=1; *addr = dat; } /************************************ 向lcd寫數據 ************************************/ void lcd_writedat(uchar dat) { check_busy(); cd=0; *addr = dat; } /******************************** 從lcd讀數據 *********************************/ uchar lcd_readdat() { uchar temp; cd=0; addr = 0xff; temp = *addr; return temp; } /************************************************ 發出命令控制 參數 低onedat 高twodat 命令com *************************************************/ void lcd_writecom_two(uchar onedat,uchar twodat,uchar com) { lcd_writedat(onedat); lcd_writedat(twodat); lcd_writecom(com); } /********************************************** 一次寫一個數據 對應地址指針位置 **********************************************/ void lcd_writedat_onebyte(uchar onedat,uchar com) { lcd_writedat(onedat); lcd_writecom(com); } /********************************************** 一次讀一個數據 對應地址指針位置 **********************************************/ uchar lcd_readdat_onebyte(uchar com) { uchar dat; lcd_writecom(com); dat=lcd_readdat(); return dat; } /**************************************** 一次寫n個數據 對應地址指針位置 ****************************************/ void lcd_writedat_nbyte(uchar *dat,uchar len) { lcd_writecom(0xb0); check_auto_write_busy(); while(len) { lcd_writedat(*dat); dat++; len--; } lcd_writecom(0xb2); } /**************************************** 一次讀n個數據 對應地址指針位置 ****************************************/ void lcd_readdat_nbyte(uchar *dat ,uchar len) { lcd_writecom(0xb1); check_auto_read_busy(); while(len) { *dat=lcd_readdat(); dat++; len--; } lcd_writecom(0xb2); } /************************************************ 清除一個點坐標 X,Y 左上角第一個點為0,0 ************************************************/ void clear_point(uchar x,uchar y) { uint addr; uchar temp1,temp2; addr=(y<<5)+(y<<3)+(x>>3);//32+8 temp1=addr;//&0x00ff; temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); lcd_writecom(0xf7-(x&0x07)); } /************************************************ 點亮一個點 坐標 X,Y 左上角第一個點為0,0 ************************************************/ void sel_point(uchar x,uchar y) { uint addr; uchar temp1,temp2; addr=(y<<5)+(y<<3)+(x>>3);//32+8 temp1=addr;//&0x00ff; temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); lcd_writecom(0xff-(x&0x07)); } /************************************************* 畫中等大小的點 4*4(用畫點方法 效率低) *************************************************/ /*sel_middling(uchar x,uchar y) { uint addr; uchar temp1,temp2,n; addr=y*160+(x>>1);//x/8*4; for(n=0;n<4;n++) { temp1=addr%6; temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); if(x%2) { lcd_writecom(0xfb); lcd_writecom(0xfa); lcd_writecom(0xf9); lcd_writecom(0xf8); } else { lcd_writecom(0xff); lcd_writecom(0xfe); lcd_writecom(0xfd); lcd_writecom(0xfc); } addr+=40; } }*/ /************************************************* 畫中等大小的點 4*4(用讀修改寫 效率高) *************************************************/ void sel_rmiddling(uchar x,uchar y) { uint addr; uchar temp1,temp2,n,dat; addr=(y<<7)+(y<<5)+(x>>1);//x/8*4;//128+32 for(n=0;n<4;n++) { temp1=addr;//&0x0ff; temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); if(x&0x01)//x%2 { dat=(lcd_readdat_onebyte(0xc5))|0x0f; lcd_writedat_onebyte(dat,0xc4); } else { dat=(lcd_readdat_onebyte(0xc5))|0xf0; lcd_writedat_onebyte(dat,0xc4); } addr+=40; } } /************************************************* 清楚中等大小的點 4*4(用清點方式 效率底) *************************************************/ /*clr_middling(uchar x,uchar y) { uint addr; uchar temp1,temp2,n; addr=y*160+(x>>1);//x/8*4; for(n=0;n<4;n++) { temp1=addr%6; temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); if(x%2) { lcd_writecom(0xf3); lcd_writecom(0xf2); lcd_writecom(0xf1); lcd_writecom(0xf0); } else { lcd_writecom(0xf7); lcd_writecom(0xf6); lcd_writecom(0xf5); lcd_writecom(0xf4); } addr+=40; } }*/ /************************************************* 清楚中等大小的點 4*4(用讀修改寫 效率高) *************************************************/ void clr_rmiddling(uchar x,uchar y) { uint addr; uchar temp1,temp2,n,dat; addr=(y<<7)+(y<<5)+(x>>1);//x/8*4;//128+32 for(n=0;n<4;n++) { temp1=addr;//&0xff; temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); if(x&0x01) { dat=(lcd_readdat_onebyte(0xc5))&0xf0; lcd_writedat_onebyte(dat,0xc4); } else { dat=(lcd_readdat_onebyte(0xc5))&0x0f; lcd_writedat_onebyte(dat,0xc4); } addr+=40; } } /********************************************************* 畫8*8的大點(用畫點方式 速度慢) *********************************************************/ /*void sel_big(uchar x,uchar y) { uint addr; uchar temp1,temp2,n; addr=(y<<8)+(y<<6)+(x);//x/8*4;y*320=y*(256+64)=(y<<8)+(y<<6) for(n=0;n<8;n++) { temp1=addr&0x00ff;//addr%6 temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); lcd_writecom(0xfb); lcd_writecom(0xfa); lcd_writecom(0xf9); lcd_writecom(0xf8); lcd_writecom(0xff); lcd_writecom(0xfe); lcd_writecom(0xfd); lcd_writecom(0xfc); addr+=40; } } */ /********************************************************* 畫8*8的大點(用讀改寫方式 速度快) *********************************************************/ void sel_rbig(uchar x,uchar y) { uint addr; uchar temp1,temp2,n,dat; addr=(y<<8)+(y<<6)+(x);//x/8*4;y*320=y*(256+64)=(y<<8)+(y<<6) for(n=0;n<8;n++) { temp1=addr;//&0x00ff;//addr%6 temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); //dat=(lcd_readdat_onebyte(0xc5))|0xff; dat=0xff; lcd_writedat_onebyte(dat,0xc4); addr+=40; } } /********************************************************* 清楚8*8的大點(用畫點方式 速度慢) *********************************************************/ /*void clr_big(uchar x,uchar y) { uint addr; uchar temp1,temp2,n; addr=(y<<8)+(y<<6)+(x);//x/8*4;y*320=y*(256+64)=(y<<8)+(y<<6) for(n=0;n<8;n++) { temp1=addr&0x00ff;//addr%6 temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); lcd_writecom(0xf3); lcd_writecom(0xf2); lcd_writecom(0xf1); lcd_writecom(0xf0); lcd_writecom(0xf7); lcd_writecom(0xf6); lcd_writecom(0xf5); lcd_writecom(0xf4); addr+=40; } } */ /********************************************************* 清除8*8的大點(用讀修改寫方式 速度快) *********************************************************/ void clr_rbig(uchar x,uchar y) { uint addr; uchar temp1,temp2,n,dat; addr=(y<<8)+(y<<6)+(x);//x/8*4;y*320=y*(256+64)=(y<<8)+(y<<6) for(n=0;n<8;n++) { temp1=addr;//&0x00ff;//addr%6 temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); //dat=(lcd_readdat_onebyte(0xc5))|0x00; dat=0x00; lcd_writedat_onebyte(dat,0xc4); addr+=40; } } /************************************************************* 圖形方式 屏上寫漢字 16*16 ************************************************************/ void graph_mode_writeword(uchar x,uchar y,uchar *dat) { uint addr; uint temp1; uchar n; temp1=y;temp1=(temp1<<9)+(temp1<<7);//512+128 addr=temp1+(x<<1); for(n=0;n<16;n++) { lcd_writecom_two((addr&0x00ff),(addr>>8),0x24); lcd_writedat_onebyte(*dat,0xc0); dat++; lcd_writedat_onebyte(*dat,0xc4); dat++; addr=addr+40; } } /************************************************************* 圖形方式 屏上寫字母,數字 8*16 ************************************************************/ void graph_mode_write_letter(uchar x,uchar y,uchar *dat) { uint addr; uint temp1; uchar n; temp1=y;temp1=(temp1<<9)+(temp1<<7);//512+128 addr=temp1+(x<<1); for(n=0;n<16;n++) { lcd_writecom_two((addr&0x00ff),(addr>>8),0x24); lcd_writedat_onebyte(*dat,0xc0); dat++; addr=addr+40; } } /****************************************************** 用畫點的方式劃橫線 (可以用讀改寫的方式) ******************************************************/ /*void horizontal(uchar x0,uchar x1,uchar y) { uchar temp,n; if(x0>x1) { temp=x0; x0=x1; x1=temp; } n=x1-x0; for(;n>0;n--) { sel_point(x0+n,y); } }*/ /************************************* 劃橫線 (用讀改寫的方式) ***************************************/ uchar get_num(uchar x0) { uchar dat; switch(x0) { case 0: dat=0xff;break; case 1: dat=0x7f;break; case 2: dat=0x3f;break; case 3: dat=0x1f;break; case 4: dat=0x0f;break; case 5: dat=0x07;break; case 6: dat=0x03;break; case 7: dat=0x01;break; } return dat; } uchar get_num_n(uchar x1) { uchar dat; switch(x1) { case 0: dat=0x80;break; case 1: dat=0xc0;break; case 2: dat=0xe0;break; case 3: dat=0xf0;break; case 4: dat=0xf8;break; case 5: dat=0xfc;break; case 6: dat=0xfe;break; case 7: dat=0xff;break; } return dat; } void rhorizontal(uchar x0,uchar x1,uchar y) { uint addr; uchar temp,n,temp1,temp2,dat,dat1; if(x0>x1) { temp=x0; x0=x1; x1=temp; } addr=(y<<5)+(y<<3)+(x0>>3); temp1=addr;//&0xff; temp2=addr>>8; lcd_writecom_two(temp1,temp2,0x24); lcd_writecom_two(temp1,temp2,0x24); n=x1-x0; dat1=lcd_readdat_onebyte(0xc5); if((x0>>3)!=(x1>>3)) { lcd_writedat_onebyte((get_num(x0&0x3)|dat1),0xc0); temp1=x0>>3; temp2=x1>>3; temp=temp2-temp1-1; lcd_writecom(0xb0); check_auto_write_busy(); while(temp) { lcd_writedat(0xff); temp--; } lcd_writecom(0xb2); dat1=lcd_readdat_onebyte(0xc5); lcd_writedat_onebyte((get_num_n(x1&0x03)|dat1),0xc4); } else { x0=x0&0x07; x1=x1%0x07; dat =~(get_num(x0)^get_num_n(x1)); lcd_writedat_onebyte((dat|dat1),0xc4); } } /***************************************** 用畫點的方式畫豎線 *****************************************/ void erect(uchar y0,uchar y1,uchar x) { uchar temp,n; if(y0>y1) { temp=y0; y0=y1; y1=temp; } n=y1-y0; for(;n>0;n--) { sel_point(x,y0+n); } } /******************************************************* 布蘭森漢姆(Bresenham)算法畫線 兩端點(x0,y0) (x1,y1) *******************************************************/ void Draw_line(uchar x0,uchar y0,uchar x1,uchar y1) { int dx,dy; //定義X.Y軸上增加的變量值 int sub; int temp; //起點、終點大小比較,交換數據時的中間變量 uchar flag; if(x0>x1) //X軸上,起點大于終點,交換數據 { temp=x1; x1=x0; x0=temp; temp=y1; y1=y0; y0=temp; } dx=x1-x0; //X軸方向上的增量 dy=y1-y0; //Y軸方向上的增量 if(dx==0) erect(y0,y1,x0); if(dy==0) rhorizontal(x0,x1,y0); if(dy>0) flag=1; else flag=0; if((dx!=0)&&(dy!=0)) { // 布蘭森漢姆(Bresenham)算法畫線 / if(flag==1) { if(dx>=dy) //*近X軸 { sub=2*dy-dx; //計算下個點的位置 while(x0!=x1) { sel_point(x0,y0); //畫起點 x0++; // X軸上加1 if(sub>0) // 判斷下下個點的位置 { y0++; // 為右上相鄰點,即(x0+1,y0+1) sub+=2*dy-2*dx; } else sub+=2*dy; // 判斷下下個點的位置 } sel_point(x0,y0); } else { sub=2*dy-dx; //*近Y軸 while(y0!=y1) { sel_point(x0,y0); //畫起點 y0++; if(sub>0) //判斷下下個點的位置 { x0++; sub+=2*dx-2*dy; } else sub+=2*dx; } sel_point(x0,y0); } } else { dy=y0-y1; if(dx>=dy) //*近X軸 { sub=2*dy-dx; //計算下個點的位置 while(x0!=x1) { sel_point(x0,y0); //畫起點 x0++; // X軸上加1 if(sub>0) // 判斷下下個點的位置 { y0--; // 為右上相鄰點,即(x0+1,y0+1) sub+=2*dy-2*dx; } else sub+=2*dy; // 判斷下下個點的位置 } sel_point(x0,y0); } else { sub=2*dx-dy; //*近Y軸 while(y0!=y1) { sel_point(x0,y0); //畫起點 y0--; if(sub>0) //判斷下下個點的位置 { x0++; sub+=2*dx-2*dy; } else sub+=2*dx; } sel_point(x0,y0); } } } } /**************************************************** 畫圓 圓點(x,y) 半徑 r ****************************************************/ void draw_circle(int x, int y, int r) { int a, b, num; a = 0; b = r; while(2 * b * b >= r * r) // 1/8圓即可 { sel_point(x + a, y - b); // 0~1 sel_point(x - a, y - b); // 0~7 sel_point(x - a, y + b); // 4~5 sel_point(x + a, y + b); // 4~3 sel_point(x + b, y + a); // 2~3 sel_point(x + b, y - a); // 2~1 sel_point(x - b, y - a); // 6~7 sel_point(x - b, y + a); // 6~5 a++; num = (a * a + b * b) - r*r; if(num > 0) { b--; a--; } } } void lcd_init() { lcd_writecom_two(0x00,0x00,0x24); lcd_writecom_two(0x00,0x00,0x21); lcd_writecom_two(0x00,0x00,0x42); lcd_writecom_two(0x28,0x00,0x43);//28 lcd_writecom_two(0x00,0x00,0x40); lcd_writecom_two(0x01e,0x00,0x41);//1e lcd_writecom(0xa0); lcd_writecom(0x98); lcd_writecom(0x80); } main() { unsigned char i; lcd_init(); Draw_line(0,0,239,127); Draw_line(0,127,239,0); Draw_line(0,0,239,0); Draw_line(0,127,239,127); Draw_line(0,0,0,127); Draw_line(239,0,239,127); while(1) { for(i=60;i<150;i++) draw_circle(i,64, 60); } }