OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2780|回复: 4

12864如何显示菜单

[复制链接]

8

主题

11

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-7-20
在线时间
5 小时
发表于 2017-9-9 13:35:50 | 显示全部楼层 |阅读模式
10金钱
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); //写完数据,开图形显示
}

12864液显程序.zip

363.87 KB, 下载次数: 95

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-9-9 16:59:46 | 显示全部楼层
1、单片机内存够大的话,直接开一个128*64的缓冲区,二维的
2、需要写入液晶的数据全部在内存操作完成
3、写入完毕后,将整个缓冲区写入显示屏即可
4、以上只有往硬件里写,不存在读取的问题,读取都在单片机内部的RAM中完成了,节省不少时间
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

8

主题

11

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2017-7-20
在线时间
5 小时
 楼主| 发表于 2017-9-10 07:53:44 来自手机 | 显示全部楼层
八度空间 发表于 2017-9-9 16:59
1、单片机内存够大的话,直接开一个128*64的缓冲区,二维的
2、需要写入液晶的数据全部在内存操作完成
3 ...

不是很懂,液晶写入的数据都是按16倍数指定地址,一次写入八位,但液晶上本来是有图片的,我是在原本图片上打上一幅较小的图片同时不影响原本图片的其他位置。大神说的开缓冲区是一个什么样的原理,有没有可供参考的程序代码?
回复

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2017-9-10 13:04:09 | 显示全部楼层
陈乔誉_学员 发表于 2017-9-10 07:53
不是很懂,液晶写入的数据都是按16倍数指定地址,一次写入八位,但液晶上本来是有图片的,我是在原本图片 ...

12864可以写入图片的,按这个来就可以了
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复

使用道具 举报

15

主题

513

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3180
金钱
3180
注册时间
2016-1-14
在线时间
370 小时
发表于 2019-5-9 20:12:47 | 显示全部楼层
谢谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-21 01:42

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表