一、 關于12864的畫圖功能。
我們知道在紙上畫出一個點,我們要知道這個點在張紙上面的位置,也就是這個點在這張紙上面的坐標。而在12864上面畫點也是一樣,我們要先知道這個點在液晶屏上面的坐標,然后我們該坐標點黑或是點白可以了。而在這之前,我們要首先理解12864圖形顯示坐標。
12864的繪圖顯示坐標如圖所示:
3668744846546777487.jpg (85.8 KB, 下載次數: 80)
下載附件
2017-3-16 00:33 上傳
需要注意的是它的水平位址并不是一個點有一個位址的,它是16個格才有一個位址。它的垂直位址也分為上下兩半部分。當我們給出位址是X是0,Y是0的時候,其實里面包含了16個點,也就是說我們一次要操作16個點。所有當我們要點亮一個點的時候,我們不僅要知道的位址,還要知道它在這個位址中是第幾個位,也就是第幾個點。
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit RS=P2^6; //這個是LCD的數據命令選擇端
sbit RW=P2^5; //這個是LCD的寫入或是讀出選擇端
sbit PSB=P3^2; //這個是LCD串行還是并行選擇端
sbit RST=P3^4; //這個是LCD的復位端口
sbit LCDE=P2^7; // 這個是LCD的使能端
/*
延時子函數
*/
void delay(uint x)
{
uint y;
for(;x>0;x--)
for(y=110;y>0;y--);
}
/*
忙碌檢查
*/
void lcd_busy()
{
RS=0;
RW=1;
P0=0XFF;
LCDE=1;
delay(2);
while((P0&0x80)==0x80);
/*如下圖1,當LCD忙碌的時候BF位是為1,而我們只需要想知道這位,所有與上0x80,當它是1的時候得到0X80,當它是0的時候得到0.*/
LCDE=0;
}
/*
寫入命令
*/
void write_com(uchar com)
{
lcd_busy();
/*每次操作LCD之前都需要檢查一次LCD是否忙碌,不過一般LCD工作比單片機快,所有都不用檢查。*/
RS=0;
RW=0;
LCDE=0;
P0=com;
delay(1);
LCDE=1;
delay(3);
LCDE=0;
}
/*
寫入數據
*/
void write_num(uchar num)
{
lcd_busy();
RS=1;
RW=0;
LCDE=0;
P0=num;
delay(1);
LCDE=1;
delay(3);
LCDE=0;
}
/*
讀取數據
*/
uchar read_data()
{
uchar read;
lcd_busy();
RS=1;
RW=1;
LCDE=0;
delay(1);
LCDE=1;
delay(3);
read=P0;
LCDE=0;
delay(5);;
return read;
}
/*
畫圖清屏,由于LCD的清屏指令0X01不能作用在繪圖中,所有只能自己寫清屏子程序
*/
void clear_lcd()
{
uchar i,j;
write_com(0x34);
for(i=0;i<32;i++) //因為LCD有縱坐標32格所以寫三十二次
{
write_com(0x80+i); //先寫入縱坐標Y的值
write_com(0x80); //再寫入橫坐標X的值
for(j=0;j<32;j++) //橫坐標有16位,每位寫入兩個字節的的數據,也就寫入32次
{ //因為當寫入兩個字節之后橫坐標會自動加1,所以就不用再次寫入地址了。
write_num(0x00);
}
}
write_com(0x36);
write_com(0x30);
}
/*
寫入一個點的子程序。具體步驟是:計算出X軸、Y軸的地址、X軸中的第幾位,然后讀出該地址現在的值,因為一般寫入新的點的時候,會覆蓋掉16個點中其他點,當你要同時顯示16個點中的兩個點的時候就會沖突,所以先將顯示中的點讀出來,然后在或上要點亮的點,這樣就可以同時點亮。注意讀取數據的時候讀取的第一個數據不要,從第二數據開始取,也就是說要讀取三次,只取后面兩次的值。還有就是讀取數據之前要先寫入你要讀取數據的地址,讀取數據之后的寫入數據還要從新寫入地址。最后就是輸入數據地址,先輸入Y軸,再輸入X軸,輸入數據。
*/
void put_point(uchar x,uchar y)
{
uint bt=0,read=0;
uchar x_adr,y_adr,h_bit,l_bit;
y_adr=0x80+y%32; //計算Y軸的地址,應為縱坐標有64個,所有對32求余,當Y大于31時,Y的坐標是下半屏的。
if(y>31) //計算X軸的地址當Y大于31時X的地址在下半屏,從0X88開始,小于31時X的地址是在上半屏,從0X80開始
x_adr=0x88+x/16;
else
x_adr=0x80+x/16;
bt=0x8000>>(x%16); //求這個點到底是在哪個點
write_com(0x34);
write_com(0x34);
write_com(y_adr); //讀取數據的時候要先寫入所取數據的地址
write_com(x_adr);
read_data(); //讀取的第一個字節不要,
read=read_data(); //從第二個字節開始接收。
read<<=8;
read|=read_data();
bt=bt|read;
h_bit=bt>>8;
l_bit=bt;
write_com(y_adr); //寫入點的時候,重新寫入地址,因為地址已經改變。
write_com(x_adr);
write_num(h_bit);
write_num(l_bit);
write_com(0x36); //開顯示
write_com(0x30); //轉回基本指令集
}
/*
液晶初始化
*/
void lcd_init()
{
PSB=1;
RST=1;
write_com(0x30); //基本指令操作
write_com(0x0c); //開顯示
write_com(0x01); //清除LCD顯示
}
void main()
{
float i;
uchar x,y;
lcd_init();
clear_lcd();
while(1)
{
write_com(0x34);
write_com(0x34);
write_com(0x80);
write_com(0x88);
for(i=16;i>0;i--) //畫出X軸
{
write_num(0xff);
}
for(i=0;i<64;i++) //畫出Y軸
{
put_point(0,i);
}
for(i=0;i<128;i++)
{
x=i;
y=32-x%32;
put_point(x,y);
}
write_com(0x36);
write_com(0x30);
while(1);
}
}
|