12864液晶屏不能像战舰上的液晶一样直接指定画点,它需要按16倍数指定X轴坐标,一次写入8位,所以每次写入的时候需要把前后的点读出来,再写上数据,如果一幅菜单图片靠画点画出来的需要执行很多次读点,这样很耗时,所以我换了一种思维,我想将12864的图形显示函数修改为可以指定任意长度宽度的图片显示在任意坐标上,下面是我写的逐行显示函数,但有朱多不足和漏洞,求大神给点意见。
void photodisplay0(u8 x,u8 y,u8 size,u8 csize,u8 *bmp)
{
unsigned char i, j ;
u16 ln,hn,n;
u8 l=x/16,lm=x%16;
u8 h=(x+size)/16,hm=(x+size)%8;
u8 km=0x80+y;//k=0x80+x,
u8 m=size/8+((size%8)?1:0);
u8 sh,xi;
u8 bmp0;
uchar GDRAM_hbit,GDRAM_lbit;
u16 GDRAM_Ebit0;
u16 GDRAM_bit;
if(csize+y>32){sh=32;xi=csize+y-32;}//大于液晶长度一半,分两次显示
else {sh=csize;xi=0;}
lcd_wcmd(0x34); //写数据时,关闭图形显示
if(lm!=0&&lm%8)m--;//坐标起始非8整数倍,最后一次写入需要处理,下同
if(hm!=0) m--;
for (i = 0; i < sh-y; i++)
//32行(上半屏)
{
if(hm!=0) //终点坐标非8的倍数,读出行末后面的点
{
lcd_wcmd(km + i); //光标指向Y坐标值
lcd_wcmd(0x80+h); //光标指向X坐标值
ReadData();//预读取数据
GDRAM_Ebit0=ReadData();//读取当前显示高八位数据
GDRAM_Ebit0<<=8;
GDRAM_Ebit0|=ReadData();//读取当前显示第八位数据
n=8-hm;
hn=pow(2,n)-1; //hn是最后一次写入的后面加上GDRAM_Ebit0的位数
}
lcd_wcmd(km + i); //光标指向Y坐标值
lcd_wcmd(0x80+l); //光标指向X坐标值
if(lm!=0) //起始坐标非16的倍数,读出第行开头的点
{
ReadData(); //预读取数据
GDRAM_bit=ReadData(); //读取当前显示高八位数据
GDRAM_bit<<=8;
GDRAM_bit|=ReadData(); //读取当前显示第八位数据
if(lm<8) n=8-lm; //lm<8,读出第行开头0到8的状态
else n=16-lm; //lm<8,读出第行开头8到16的状态
ln=pow(2,n)-1;
if(lm>8){ //lm>8
GDRAM_bit&=~ln; //将数据后n位去掉,方便后面接上图片的的前n个位
GDRAM_hbit=GDRAM_bit>>8;
GDRAM_lbit=GDRAM_bit;}
else if(lm%8==0) GDRAM_hbit=GDRAM_bit>>8;//lm=8
else GDRAM_hbit=((GDRAM_bit>>8)&(~ln)); //lm<8
lcd_wcmd(km + i); //光标指向起始位置 ,开始写入数据
lcd_wcmd(0x80+l);
if(lm%8==0) { lcd_wdat(GDRAM_hbit);}
else if(lm>8) {lcd_wdat(GDRAM_hbit);GDRAM_lbit|=((*bmp++)>>(8-n));lcd_wdat(GDRAM_lbit);}
else {GDRAM_hbit|=((*bmp++)>>(8-n));lcd_wdat(GDRAM_hbit);}//lcd_wdat(*bmp++);}
}
for (j = 0; j < m; j++){
//16*8列
if(lm!=0 && lm%8){bmp0=*bmp--;bmp0=(*bmp++<<n);bmp0|=((*bmp++)>>(8-n));lcd_wdat(bmp0);}
else lcd_wdat(*bmp++);
}
if(lm!=8&&lm!=0){ //最后一次写入处理
if(hm>4) //起始坐标加图片长度8>hm>4
{
bmp0=*bmp--;
bmp0=(*bmp++<<n);
bmp0|=((*bmp++)>>(8-n));
if(size%8==0) //图片长度为8整数倍
{
lcd_wdat(bmp0);
bmp0=*bmp--;
bmp0=(*bmp++<<n);
if(lm>8)bmp0|=(GDRAM_Ebit0&(hn));
else bmp0|=((GDRAM_Ebit0>>8)&(hn));
lcd_wdat(bmp0);
}else{
// bmp0&=~hn;
if(lm<8)bmp0|=(GDRAM_Ebit0&(hn));
else bmp0|=((GDRAM_Ebit0>>8)&(hn));
lcd_wdat(bmp0);
}
}else if(hm!=0) //起始坐标加图片长度4>=hm>0
{
bmp0=*bmp--;
bmp0=(*bmp++<<n);
bmp0|=((*bmp)>>(8-n));
if(size%8==0) //图片长度为8整数倍
{
lcd_wdat(bmp0);
bmp0=(*bmp++<<n);
if(lm>8)bmp0|=(GDRAM_Ebit0&(hn));
else bmp0|=((GDRAM_Ebit0>>8)&(hn));
lcd_wdat(bmp0);
}else{
lcd_wdat(bmp0);
bmp0=(*bmp++<<n);
if((lm%8>4)&&(((x+size)%16)>8))bmp0|=(GDRAM_Ebit0&hn);
else bmp0|=((GDRAM_Ebit0>>8)&hn);
lcd_wdat(bmp0);
}
}
}
else {
if(size%8){ //起始为8整数,终点坐标非8整数倍
bmp0=*bmp++;
if(lm==0)bmp0|=(GDRAM_Ebit0&hn);
else bmp0|=((GDRAM_Ebit0>>8)&hn);
lcd_wdat(bmp0);
}
}
delay_us(100);
}
/******************下半屏显示*****************************/
for (i = 0; i < xi; i++)
//32行(下半屏)
{
if(hm!=0)
{
lcd_wcmd(0x80 + i); //光标指向Y坐标值
lcd_wcmd(0x88+h); //光标指向X坐标值
ReadData();//预读取数据
GDRAM_Ebit0=ReadData();//读取当前显示高八位数据
GDRAM_Ebit0<<=8;
GDRAM_Ebit0|=ReadData();//读取当前显示第八位数据
n=8-hm;
hn=pow(2,n)-1;
}
lcd_wcmd(0x80 + i); //光标指向Y坐标值
lcd_wcmd(0x88+l); //光标指向X坐标值
if(lm!=0)
{
ReadData();//预读取数据
GDRAM_bit=ReadData();//读取当前显示高八位数据
GDRAM_bit<<=8;
GDRAM_bit|=ReadData();//读取当前显示第八位数据
// GDRAM_bit=~((~GDRAM_bit)|(2^lm-1));
if(lm<8) n=8-lm;
else n=16-lm;
ln=pow(2,n)-1;
if(lm>8){ GDRAM_bit&=~ln;
GDRAM_hbit=GDRAM_bit>>8;
GDRAM_lbit=GDRAM_bit;}
else if(lm%8==0) GDRAM_hbit=GDRAM_bit>>8;
else GDRAM_hbit=((GDRAM_bit>>8)&(~ln));
lcd_wcmd(0x80 + i); //先写入Y坐标值
lcd_wcmd(0x88+l);
if(lm%8==0) { lcd_wdat(GDRAM_hbit);}
else if(lm>8) {lcd_wdat(GDRAM_hbit);GDRAM_lbit|=((*bmp++)>>(8-n));lcd_wdat(GDRAM_lbit);}
else {GDRAM_hbit|=((*bmp++)>>(8-n));lcd_wdat(GDRAM_hbit);}//lcd_wdat(*bmp++);}
}
for (j = 0; j < m; j++){
//16*8列
if(lm!=0 && lm%8){bmp0=*bmp--;bmp0=(*bmp++<<n);bmp0|=((*bmp++)>>(8-n));lcd_wdat(bmp0);}
else lcd_wdat(*bmp++);}
if(lm!=8&&lm!=0){
if(hm>4)
{
bmp0=*bmp--;
bmp0=(*bmp++<<n);
bmp0|=((*bmp++)>>(8-n));
if(size%8==0)
{
lcd_wdat(bmp0);
bmp0=*bmp--;
bmp0=(*bmp++<<n);
if(lm>8)bmp0|=(GDRAM_Ebit0&(hn));
else bmp0|=((GDRAM_Ebit0>>8)&(hn));
lcd_wdat(bmp0);
}else{
if(lm<8)bmp0|=(GDRAM_Ebit0&(hn));
else bmp0|=((GDRAM_Ebit0>>8)&(hn));
lcd_wdat(bmp0);
}
}else if(hm!=0)
{
bmp0=*bmp--;
bmp0=(*bmp++<<n);
bmp0|=((*bmp)>>(8-n));
if(size%8==0)
{
lcd_wdat(bmp0);
bmp0=(*bmp++<<n);
if(lm>8)bmp0|=(GDRAM_Ebit0&(hn));
else bmp0|=((GDRAM_Ebit0>>8)&(hn));
lcd_wdat(bmp0);
}else{
lcd_wdat(bmp0);
bmp0=(*bmp++<<n);
if((lm%8>4)&&(((x+size)%16)>8))bmp0|=(GDRAM_Ebit0&hn);
else bmp0|=((GDRAM_Ebit0>>8)&hn);
lcd_wdat(bmp0);
}
}
}
else {//bmp0=*bmp--;
if(size%8){
bmp0=*bmp++;
if(lm==0)bmp0|=(GDRAM_Ebit0&hn);
else bmp0|=((GDRAM_Ebit0>>8)&hn);
lcd_wdat(bmp0);
}
}
delay_us(100);
}
lcd_wcmd(0x36); //写完数据,开图形显示
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
2、需要写入液晶的数据全部在内存操作完成
3、写入完毕后,将整个缓冲区写入显示屏即可
4、以上只有往硬件里写,不存在读取的问题,读取都在单片机内部的RAM中完成了,节省不少时间
一周热门 更多>