搜索
bottom↓
回复: 135

教你在12864上打点(基于ST7920控制器)

[复制链接]

出0入0汤圆

发表于 2010-3-25 11:31:56 | 显示全部楼层 |阅读模式
基于ST7920控制的12864液晶用于字符显示很方便的,但网友说用它显示图形并不合适,原因就是它绘图时先要关闭显示,绘完后又要打开,速度会较慢。我没有用过别的液晶,手中只有这一款,摆弄了几天,掌握了一点东西,写出来共享。
        首先,我们知道,图形都是由像素点组成的,绘图的基础其实就是画点。只要我们能点亮液晶的任意一个像素点,那么绘图就不是什么难事了。万丈高楼平地起嘛,先要做的,当然是要打好基础。
        ST7920提供了用于绘图的GDRAM(graph display RAM)。共 64×32 个字节的空间(由扩充指令设定绘图 RAM 地址),最多可以控制 256×64点阵的二维绘图缓冲空间。在它的Datasheet给出了GDRAM的坐标地址对照表:

(原文件名:图片1.png)

        用坐标表示,就是这样:
       
(原文件名:图片2.png)

        它的横坐标每一个地址都是16 位的。共16个地址,256位。
        很明显,它能控制256*64像素的液晶屏,而我们的只是128*64像素液晶屏,显然只用到它的一部分。
我刚开始以为它对应屏幕的绘图RAM是这样分布的(如红色部分):

(原文件名:图片3.png)
结果栽了大根头,后来终于弄明白,原来它对应屏幕的GDRAM是这样分布的:

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2010-3-25 11:40:18 | 显示全部楼层
汗,发了一半不小心提交了,继续


(原文件名:图片4.png)

        只要我们清楚了它的GDRAM和屏幕上像素点的映射(对应)关系,点亮对应的像素点就容易多了。要点亮某一个像素点,就是将这个像素点在GDRAM中对应的位置1,这个相信没人会不知道吧?
        我们先讨论一下思路,再一步步写代码。我觉得,思路要比代码重要的多,只要你的思路通了,正确了,那么写出代码肯定会很容易。
        首先,给你x,y的坐标,要你点亮一个点,要怎么做呢?从上面的图我们知道,它是分为两个半屏的,首先,我们要确定这个点是在上半屏还是下半屏,然后确定它是在那一行(纵坐标Y),再确定它是在哪一个字节的哪一个位(也就是确定它在那一列,即横坐标X)。这些都确定后我们就定位到某一个具体的位上了,只就将这个位置1,就OK了。
        下面我们边写代码边讨论。
        因为这里仅仅是讨论如何在12864上打点的,而不是给12864写一个驱动,所以对于基本的数据读写函数,我们不做讨论,这里假设已经有了如下基本函数:
        void lcd_write_cmd(unsigned char);   //lcd 命令写
        void lcd_write_data(unsigned char);  //lcd 数据写
        unsigend char lcd_read_data(void);   //lcd 数据读
        好了,就这些了。
        为了方便,我们定义如下宏:
        #define  BASIC_SET   0x00          //基本指令集,后面的数字查数据手册,下同。
        #define  EXTEND_SET  0x00           //扩展指令集
        #define  DRAW_ON     0x00           //绘图显示开
        #define  DRAW_OFF    0x00           //绘图显示关
       
        我们现在开始写点亮某一个点的函数:
        void lcd_set_dot(unsigned char x, unsigned char y)
        {
            unsigned char x_byet, x_bit;        //在横坐标的哪一个字节,哪一个位
            unsigned char y_byte, y_bit;
            
            x_byte = x / 16;                    //算出它在哪一个字节(地址)
                                                //注意一个地址是16位的
            x_bit = x % 16;                     //算出它在哪一个位
            y_byte = y /32;                     //y是没在哪个字节这个说法
                                                //这里只是确定它在上半屏还是下半屏
                                                //0:上半屏 1:下半屏
            y_bit = y % 32;                     //y_bit确定它是在第几行
            
            lcd_write_cmd(EXTEND_SET);          //扩展指令集
            lcd_write_cmd(DRAW_OFF);            //绘图显示关闭
            
            lcd_write_cmd(0x80 + y_bit);        //先写垂直地址
                                                //具体参照数据手册
            lcd_write_cmd(0x80 + x_byte + 8 * y_byte);   //水平坐标
                                                         //下半屏的水平坐标起始地址为0x88
                                                         //(+8*y_byte)就是用来确定在上半屏还是下半屏
            
            if (x_bit < 8)                               //如果x_bit位数小于8
            {
                lcd_write_data(0x01 << (7 - x_bit));     //写高字节。因为坐标是从左向右的
                                                         //而GDRAM高位在左,底位在右
                lcd_write_data(0x00);                    //低字节全部填0
            }
            else
            {
                lcd_write_data(0x00);                    //高字节全部填0
                lcd_write_data(0x01 << (15 - x_bit));
            }
            
            lcd_write_cmd(DRAW_ON);                     //打开绘图显示
            lcd_write_cmd(BASIC_SET);                   //回到基本指令集,毕竟ST7920是以字符为主的
       
            return ;
        }
       
        基本画点函数算是完成了,但是我们如果使用这个函数,就会发现问题。你且用它沿横坐标画几个连续的点试试,肯定不是你想要的结果。
        出现问题的原因是因为我们画点时对其余的位全部填0处理了,造成对原来的信息的破坏。所以我们要读出要写的那个地址原来的数据,再进行加工,写回去就可以解决问题了。
        改进后的代码:
        void lcd_set_dot(unsigned char x, unsigned char y)
        {
            unsigned char x_byet, x_bit;        //在横坐标的哪一个字节,哪一个位
            unsigned char y_byte, y_bit;
            unsigned char tmph, tmpl;           //定义两个临时变量,用于存放读出来的数据
            
        x &= 0x7F;
        y &= 0x3F;
            x_byte = x / 16;                    //算出它在哪一个字节(地址)
                                                //注意一个地址是16位的
            x_bit = x&0x0F;                     //算出它在哪一个位
            y_byte = y /32;                     //y是没在哪个字节这个说法
                                                //这里只是确定它在上半屏还是下半屏
                                                //0:上半屏 1:下半屏
            y_bit = y&0x3F;                     //y_bit确定它是在第几行
            
            lcd_write_cmd(EXTEND_SET);          //扩展指令集
            lcd_write_cmd(DRAW_OFF);            //绘图显示关闭
            
            lcd_write_cmd(0x80 + y_bit);        //先写垂直地址(最高位必须为1)
                                                //具体参照数据手册
            lcd_write_cmd(0x80 + x_byte + 8 * y_byte);   //水平坐标
                                                         //下半屏的水平坐标起始地址为0x88
                                                         //(+8*y_byte)就是用来确定
                                                         //在上半屏还是下半屏
        lcd_read_data();                  //先空读一次
        tmph = lcd_read_data();           //读高位
        tmpl = lcd_read_data();
       
        lcd_write_cmd(0x80 + y_bit);       //读操作会改变AC,所以重新设置一次
        lcd_write_cmd(0x80 + x_byte + 8 * y_byte);
       
            if (x_bit < 8)                             //如果x_bit位数小于8
            {
               lcd_write_data(tmph | (0x01 << (7 - x_bit)));  //写高字节。因为坐标是从左向右的
                                                              //而GDRAM高位在左,底位在右
                lcd_write_data(tmpl);                         //原数据送回
            }
            else
            {
                lcd_write_data(tmph);                         //原数据送回
                lcd_write_data(tmpl | (0x01 << (15 - x_bit)));
            }
            lcd_write_cmd(DRAW_ON);       //打开绘图显示
            lcd_write_cmd(BASIC_SET);     //回到基本指令集,毕竟ST7920是以字符为主的
        return ;
        }
       
        画点函数到此就完成了,剩下的事情就是对函数的优化了。例如对入口参数的检查,对乘除法的优化等等。

出0入0汤圆

发表于 2010-3-25 12:14:48 | 显示全部楼层
mark!!!

出0入0汤圆

发表于 2010-3-25 12:40:16 | 显示全部楼层
支持下。

出0入0汤圆

发表于 2010-3-25 12:52:59 | 显示全部楼层
谢谢
!!

出0入0汤圆

发表于 2010-3-25 13:06:43 | 显示全部楼层
谢谢

出0入0汤圆

发表于 2010-4-9 10:16:38 | 显示全部楼层
这么好的资料,对新手来说太好了。谢谢!

出0入0汤圆

发表于 2010-4-9 11:23:30 | 显示全部楼层
谢谢

出0入0汤圆

发表于 2010-4-9 12:47:02 | 显示全部楼层
ding

出0入0汤圆

发表于 2010-4-9 12:55:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-9 13:36:16 | 显示全部楼层
看了很有启发,我以前做过画点函数,没有成功,有空按这个思路重新做下。

出0入0汤圆

发表于 2010-4-10 01:11:10 | 显示全部楼层
支持一下

出0入0汤圆

发表于 2010-4-10 07:32:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-4-18 12:49:32 | 显示全部楼层
顶起来

出0入0汤圆

发表于 2010-5-10 09:34:35 | 显示全部楼层
看了好大收获,一起研究的加我QQ 865115958

出0入0汤圆

发表于 2010-5-10 12:03:29 | 显示全部楼层
顶一下

出0入0汤圆

发表于 2010-5-10 12:22:49 | 显示全部楼层
mark

出0入8汤圆

发表于 2010-5-10 12:46:30 | 显示全部楼层
记号~

出0入0汤圆

发表于 2010-5-10 12:56:40 | 显示全部楼层
不错,多谢分享!

出0入0汤圆

发表于 2010-5-11 11:19:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-11 12:54:21 | 显示全部楼层

出0入0汤圆

发表于 2010-5-11 15:07:34 | 显示全部楼层
1

出0入0汤圆

发表于 2010-5-27 09:48:14 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-27 13:23:37 | 显示全部楼层
mark

出0入131汤圆

发表于 2010-5-28 17:28:56 | 显示全部楼层
楼主 我真是爱死你了 这几天我正在弄这个 不过我不会c语言 我准备把它翻译成汇编 艾悲剧

出0入0汤圆

发表于 2010-5-29 10:32:13 | 显示全部楼层
谢谢楼主~~~!

出0入0汤圆

 楼主| 发表于 2010-6-4 14:41:22 | 显示全部楼层
回复【24楼】asj1989  
-----------------------------------------------------------------------
其实只要知道了原理,C和汇编都一样的。

出0入0汤圆

发表于 2010-6-4 17:08:00 | 显示全部楼层
Good !

出0入0汤圆

发表于 2010-6-4 20:08:49 | 显示全部楼层

出0入0汤圆

发表于 2010-6-17 18:08:03 | 显示全部楼层
cool啊,介绍了很多细节上的东西,不像很多人介绍的那样,抄来抄去的,都是废话、没几句是有用的!

出0入0汤圆

发表于 2010-6-17 20:55:03 | 显示全部楼层
学习。好文章,我转载了。楼主哥,不要介意。

出0入0汤圆

 楼主| 发表于 2010-6-17 22:44:17 | 显示全部楼层
再贴两个函数。没经过优化,大家多指教。

/*********************************************************************
* 函数名: lcd_draw_bmp();                                           *
* 功  能: 在LCD指定坐标绘制一指定大小的BMP图像                      *
* 输  入: x(0 - 7)  y(0 -63) width(1 - 128) height(1 - 63)          *
* ******************************************************************/
extern void lcd_draw_bmp(uchar x, uchar y, uchar width, uchar height, char *bmp)
{
    uchar i, j;

    uchar y_byte = y / 32;
    uchar y_bit = y % 32;

    lcd_write_cmd(EXTEND_SET);                     //扩展指令集
    lcd_write_cmd(DRAW_OFF);                       //绘图显示关

    if (y >= 32 || (y < 32 && y + height <= 32))   //要绘制的图案全部在上半屏或下半屏
    {
        for (i = 0; i < height; i++)
        {
            for (j = 0; j < width / 16; j++)
            {
                lcd_write_cmd(0x80 + y_bit + i);
                lcd_write_cmd(0x80 + x + j + y_byte * 8); //通过y_byte * 8 来选定上半屏或下半屏
                lcd_write_data(*bmp++);
                lcd_write_data(*bmp++);
            }
        }
    }
    else if (y < 32 && y + height > 32)  //要绘制的图案一半在上半屏,一半在下半屏
    {
        for (i = 0; i < 32 - y; i++)     //上半屏部分
        {
            for (j = 0; j < width / 16; j++)
            {
                lcd_write_cmd(0x80 + y_bit + i);
                lcd_write_cmd(0x80 + x + j);
                lcd_write_data(*bmp++);
                lcd_write_data(*bmp++);
            }
        }
        for (i = 0; i < y + height - 32; i++) //下半屏部分
        {
            for (j = 0; j < width / 16; j++)
            {
                lcd_write_cmd(0x80 + i);
                lcd_write_cmd(0x88 + x + j);
                lcd_write_data(*bmp++);
                lcd_write_data(*bmp++);
            }
        }
    }
    lcd_write_cmd(DRAW_ON);                   //绘图显示开
    lcd_write_cmd(BASIC_SET);                 //基本指令集

    return ;
}


/*******************************************************
* 函数名: lcd_put_var()                               *
* 功  能: 向指定坐标输出一个两位数变量                *
* 输  入: x坐标(1 - 14) y坐标(1 - 4)                  *
* ****************************************************/
void lcd_put_var(uchar x, uchar y, uchar var)
{
    uchar xx, addr, tmp, varh;

    x--;
    y--;

    varh = (var / 10 % 10) + '0';       //算出变量高位的ASCII码
    var = (var % 10) + '0';             //变量低位的ASCII码
   
    //xx = x % 2;
    xx = x & 0x01;                      //x是奇数还是偶数
    //x = x / 2;                        
    x >>=  1;                           //x右移一位, 相当于 x / 2

    //根据y的值算出对应的地址
    if (y == 0)
    {
        addr = 0x80 + x;
    }
    else if (y == 1)
    {
        addr = 0x90 + x;
    }
    else if (y == 2)
    {
        addr = 0x88 + x;
    }
    else if (y == 3)
    {
        addr = 0x98 + x;
    }

    if (xx)                     //如果x % 2不为零, 说明数据在某一地址的低八位上
    {   
        lcd_write_cmd(addr);    //先写地址
        lcd_read_data();        //空读一次
        tmp = lcd_read_data();  //读出高八位数据
        lcd_write_cmd(addr);    //设置地址
        lcd_write_data(tmp);    //写原来高八位的数据
        lcd_write_data(varh);   //写变量的高位
        lcd_write_data(var);    //写变量的低位
    }
    else                        //数据在某地址上, 高八位一个数字, 低八位一个数字, 直接写入
    {
        lcd_write_cmd(addr);
        lcd_putc(varh);
        lcd_putc(var);
    }

    return ;
}

我试着贴了一下软件生成的Html代码,给果出来效果不理想,还是贴文本吧。

出0入0汤圆

 楼主| 发表于 2010-6-17 22:55:43 | 显示全部楼层
回复【29楼】wenpeijun  
-----------------------------------------------------------------------
谢谢。

回复【30楼】tear086  .COM 缺氧
-----------------------------------------------------------------------
很乐意看到有人转载:)

出0入264汤圆

发表于 2010-6-17 23:37:04 | 显示全部楼层
lcd_draw_bmp 有缺陷,只能做到宽度是16的倍数。 否则会覆盖掉原来图案。x坐标无法任意位置。
不过这个函数用于一般场合足矣。对于ST7920,如果没有开辟RAM 缓冲映射,图形输出函数做到,x ,y 坐标任意位置,widht 和 height任意,是很复杂的一件事情,要做大量的移位处理,同时涉及到读-修改-写,因此效率很低。

出0入264汤圆

发表于 2010-6-17 23:48:28 | 显示全部楼层
兼顾内存,效率等等因素,比较容易实现的是,任意坐标,任意高度,长度为8 的倍数。
譬如在坐标 17,17 处输出一幅 24*37的图片
//位图信息定义
typedef struct tagBitmap
{
        uint8 m_u8Width ;         //宽度(必须为8的整数倍,取图片数据时注意!)
        uint8 m_u8Height ;        //高度
        prog_uchar* m_pBitmapCode ;
}BITMAP,*PBITMAP ;

//显示位图
void ST7920ShowBitmap(uint8 u8X, uint8 u8Y,PBITMAP pBitmap)
{
        uint8 i,j;
        for(i = 0 ; i < pBitmap->m_u8Height; i++)
        {
                for(j = 0 ; j < pBitmap->m_u8Width/8; j++)
                {
                         
                        ST7920WriteByte(u8X+j*8,i+u8Y,pgm_read_byte(pBitmap->m_pBitmapCode+(i*(pBitmap->m_u8Width/8))+j));
                }
        }
}

其中最关键的一个函数是ST7920WriteByte()
它的功能是在屏幕上面任意位置写一个字节数据,譬如在 坐标19,20 处写一个字节 0xa5
ST7920WriteByte(19,20,0xa5) 即可。

出0入264汤圆

发表于 2010-6-17 23:54:22 | 显示全部楼层
之前也是对12864的液晶感兴趣,玩了很长一段时间,后来发现其实没有多大必要。找块内存大点的单片机,开辟一个RAM,想实现啥功能都容易的很。

出0入0汤圆

发表于 2010-6-18 00:14:48 | 显示全部楼层
学习 谢谢楼主分享

出0入0汤圆

 楼主| 发表于 2010-6-18 03:49:13 | 显示全部楼层
回复【33楼】mcu_lover  
-----------------------------------------------------------------------
是的。只不过现在刚开始学51不久,我用的51芯片开显示缓存不太现实。呵呵。只不过这个函数对我目前够用了。

出0入0汤圆

发表于 2010-6-18 09:11:37 | 显示全部楼层
学习 谢谢楼主分享

出0入0汤圆

发表于 2010-6-18 10:52:27 | 显示全部楼层
学习中……

出0入0汤圆

发表于 2010-6-22 20:00:37 | 显示全部楼层
顶~

出0入0汤圆

发表于 2010-6-23 10:16:25 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-6-26 21:40:06 | 显示全部楼层
好资料啊

出0入0汤圆

发表于 2010-7-25 23:39:14 | 显示全部楼层
顶下

出0入0汤圆

发表于 2010-7-26 08:41:19 | 显示全部楼层
好啊.多谢.

出0入0汤圆

发表于 2010-7-26 09:26:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-7-26 09:33:32 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-7-27 16:58:30 | 显示全部楼层
MARK 正要用12864

出0入0汤圆

发表于 2010-7-27 18:47:20 | 显示全部楼层
好东西呀!!谢谢楼主哟!

出0入0汤圆

发表于 2010-7-29 14:09:27 | 显示全部楼层
7920的用起来怎么都感觉不方便似的。

出0入0汤圆

发表于 2010-8-17 11:44:48 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-8 11:11:13 | 显示全部楼层
楼主的程序是串口的还是 并口的啊

出0入0汤圆

发表于 2010-9-9 16:37:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-9 23:49:15 | 显示全部楼层
mark~

出0入0汤圆

发表于 2010-9-14 20:46:17 | 显示全部楼层
楼主呀 我的怎么不能显示点呢 只是一趟线呀  画波形也是

出0入0汤圆

发表于 2010-9-14 21:33:05 | 显示全部楼层
//************打点***********************
#include <reg51.h>
#include<intrins.h>
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs=P2^2;
sbit lcdrw=P2^3;
sbit lcden=P2^4;
sbit lcdpsb=P2^5;
uchar code aa[]={"逝者如斯夫,"};
uchar code bb[]={"不舍昼夜"};



void delayus()
{
        _nop_();
                _nop_();
                        _nop_();
                                _nop_();
}
void delayms(uchar ms)
{
        uchar i;
        while(ms--)
        for(i=0;i<110;i++);
}
void checkbusy()
{
        uchar busy;
       
        do{
                lcdrs=0;
                lcden=0;
                lcdrw=1;
                delayus();
                lcden=1;
                busy=P0;
                delayus();
                lcden=0;       
          }
          while(busy&0x80);                  //判断最高位是否为0,为0则处于空闲状态
}
void write_cmd(uchar cmd)
{
    checkbusy();
        lcdrs=0;
        lcdrw=0;
        lcden=0;
        delayus();
        P0=cmd;
        lcden=1;
        delayus();
        lcden=0;
}
void write_dat(uchar dat)
{
        checkbusy();
        lcdrs=1;
        lcdrw=0;
        lcden=0;
        delayus();
        P0=dat;
        lcden=1;
        delayus();
        lcden=0;

}
uchar Read_byte(void)          //读数据
{
        uchar cc;
        checkbusy();
        P1=0xff;
        lcdrs=1;
        lcdrw=1;
        lcden=0;
        delayus();
        lcden=1;
        cc=P1;
        delayus();
        lcden=0;
        return(cc);

}
void lcd_set_dot(unsigned char x, unsigned char y)
{
    unsigned char x_byte, x_bit;        //在横坐标的哪一个字节,哪一个位
    unsigned char y_byte, y_bit;
    unsigned char tmph, tmpl;           //定义两个临时变量,用于存放读出来的数据
     
    x &= 0x7F;
    y &= 0x3F;
    x_byte = x / 16;                    //算出它在哪一个字节(地址)
                                        //注意一个地址是16位的
    x_bit = x&0x0F;                     //算出它在哪一个位
    y_byte = y /32;                     //y是没在哪个字节这个说法
                                        //这里只是确定它在上半屏还是下半屏
                                        //0:上半屏 1:下半屏
    y_bit = y&0x3F;                     //y_bit确定它是在第几行
     
    write_cmd(0x34);          //扩展指令集
   // write_cmd(DRAW_OFF);            //绘图显示关闭
     
    write_cmd(0x80 + y_bit);        //先写垂直地址(最高位必须为1)
                                        //具体参照数据手册
    write_cmd(0x80 + x_byte + 8 * y_byte);   //水平坐标
                                                 //下半屏的水平坐标起始地址为0x88
                                                 //(+8*y_byte)就是用来确定
                                                 //在上半屏还是下半屏
Read_byte();                  //先空读一次
tmph = Read_byte();           //读高位
tmpl = Read_byte();
write_cmd(0x80 + y_bit);       //读操作会改变AC,所以重新设置一次
write_cmd(0x80 + x_byte + 8 * y_byte);

    if (x_bit < 8)                             //如果x_bit位数小于8
    {
       write_dat(tmph | (0x01 << (7 - x_bit)));  //写高字节。因为坐标是从左向右的
                                                      //而GDRAM高位在左,底位在右
        write_dat(tmpl);                         //原数据送回
    }
    else
    {
        write_dat(tmph);                         //原数据送回
        write_dat(tmpl | (0x01 << (15 - x_bit)));
    }  
    write_cmd(0x36);       //打开绘图显示
    write_cmd(0x30);     //回到基本指令集,毕竟ST7920是以字符为主的
return ;
}


void clear_GDRAM()
{
       
        uchar i,j;
        write_cmd(0x34);
        for(i=0;i<32;i++)
        {
                write_cmd(0x80+i);
                write_cmd(0x80);
                for(j=0;j<16;j++)
                write_dat(0x00);
        }
        for(i=0;i<32;i++)
        {
                write_cmd(0x80+i);
                write_cmd(0x88);
                for(j=0;j<16;j++)
                write_dat(0x00);
        }

        write_cmd(0x30);
}
void init()
{
        lcdpsb=1;
        write_cmd(0x30);
        delayms(5);
        write_cmd(0x0c);
        delayms(5);
        write_cmd(0x01);
        delayms(5);
}
void main()
{
    uchar i;
        init();
        write_cmd(0x90);
        while(aa!='\0')
        {
                write_dat(aa);
                i++;
                delayms(50);
        }
        delayms(300);
        write_cmd(0x88);
        i=0;
        while(bb!='\0')
        {
                write_dat(bb);
                i++;
                delayms(50);
        }
        init();
        clear_GDRAM();
        lcd_set_dot(31, 31) ;
    while(1);
   
       
}

出0入0汤圆

发表于 2010-9-14 21:33:51 | 显示全部楼层
b帮忙看看吧

出0入0汤圆

发表于 2010-9-21 21:40:43 | 显示全部楼层
mark 正在学习LCD

出0入0汤圆

发表于 2010-9-21 22:45:53 | 显示全部楼层
to 【55楼】 xuanxuanno1

看程序是并行模式,感觉对7920来说并行模式没有任何优势可言,无论是使用还是价钱,

出0入0汤圆

发表于 2010-9-22 21:29:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-10 22:43:03 | 显示全部楼层
不错,谢谢分享。

收益匪浅~~

出0入0汤圆

发表于 2010-11-10 22:46:38 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-11-12 18:52:43 | 显示全部楼层
make

出100入2764汤圆

发表于 2010-11-12 21:43:19 | 显示全部楼层
顶!
楼主不错 继续关注

出0入0汤圆

发表于 2010-12-8 16:40:31 | 显示全部楼层
我参考了楼主的程序,但是调试的时候发现不能画水平的线,也不能画挨着很近的竖线,怀疑画点那段程序有bug
我用的是ST7920和12864液晶并行方式,各位高手能指点一下吗?很急啊,拜托了各位
void Draw_Point(unsigned char x,unsigned char y)
{
        unsigned char x_byte, x_bit,str[16];                //在横坐标的哪一个字节,哪一个位
          unsigned char y_byte, y_bit;
          unsigned char tmph, tmpl,test;                   //定义两个临时变量,用于存放读出来的数据
          x &= 0x7F;
          y &= 0x3F;
          x_byte = x / 16;                                          //算出它在哪一个字节(地址)
                                                                                  //注意一个地址是16位的
          x_bit = x&0x0F;                                          //算出它在哪一个位
          y_byte = y / 32;                                          //y是没在哪个字节这个说法
                                                                                  //这里只是确定它在上半屏还是下半屏
                                                                                  //0:上半屏 1:下半屏
          y_bit = y&0x1F;                                          //y_bit确定它是在第几行
//          WriteCmd12864(0x36);                  //扩展指令集
//          delay(1);       
          WriteCmd12864(0x34);
          delay(1);

          WriteCmd12864(0x80 + y_bit);                 //读操作会改变AC,所以重新设置一次
          delay(1);
          WriteCmd12864(0x80 + x_byte + 8 * y_byte);
          delay(1);
          
          LCD12864_Read();                                        //先空读一次
          tmph = LCD12864_Read();                        //读高位
          tmpl = LCD12864_Read();
          delay(1);
          WriteCmd12864(0x80 + y_bit);                 //读操作会改变AC,所以重新设置一次
          delay(5);
          WriteCmd12864(0x80 + x_byte + 8 * y_byte);
          delay(5);       
          if (x_bit < 8)                                                         //如果x_bit位数小于8
          {
                 WriteData12864(tmph | (0x01 << (7 - x_bit)));        //写高字节。因为坐标是从左向右的
                                                                                                                                                                                  //而GDRAM高位在左,底位在右
                 delay(1);       
                 WriteData12864(tmpl);                                                 //原数据送回
                   delay(1);       
/*                  WriteCmd12864(0x30);
          delay(1);
          LcdClear();
          sprintf(str,"%x",tmph);
          DisplayCgrom(0x80, str);
          test=tmph | (0x01 << (7 - x_bit));
          sprintf(str,"%x",test);
          DisplayCgrom(0x88, str);
          delayTT(1000);*//这一段我在屏幕上打印调试信息,当我写(0,0)(1,0)两个点时,返回的tmph是0x80和0x40
                          //这个第二次返回应该是0xc0才对啊!
         }
          else
          {
                  WriteData12864(tmph);                                                 //原数据送回
                  delay(1);       
                  WriteData12864(tmpl | (0x01 << (15 - x_bit)));
                  delay(1);       
          }
    WriteCmd12864(0x36);                  //扩展指令集
          delay(1);
         WriteCmd12864(0x30);                  //扩展指令集
          delay(1);
}

出0入0汤圆

发表于 2011-3-15 20:08:57 | 显示全部楼层
mark!!!

出0入0汤圆

发表于 2011-3-16 08:57:44 | 显示全部楼层
我也在这里分享一下自己写的12232打点函数,也是ST7920主控

void ST7920AdvancedMode(){
        ST7920WriteCommand(ST7920_8BIT_MODE | ST7920_ADVANCED_MODE);                                //扩展指令集
        ST7920WriteCommand(ST7920_8BIT_MODE | ST7920_ADVANCED_MODE | ST7920_GD_ENABLE);
}
   
void ST7920BaseMode(){
    ST7920WriteCommand(ST7920_8BIT_MODE);                                                                                //8位数据端口 基本指令集
    ST7920WriteCommand(ST7920_8BIT_MODE);                                                                                //8位数据端口 基本指令集
}

void ST7920PrintDot(BYTE x, BYTE y){
        BYTE Byte0 = 0,Byte1 = 0;
        ST7920WriteCommand(ST7920_GDRAM_ADDRESS | y);
        ST7920WriteCommand(ST7920_GDRAM_ADDRESS | (x>>4));
        ST7920ReadData();                                                                                                                        //Dummy Read
        Byte1 = ST7920ReadData();
        Byte0 = ST7920ReadData();
        ST7920WriteCommand(ST7920_GDRAM_ADDRESS | y);
        ST7920WriteCommand(ST7920_GDRAM_ADDRESS | (x>>4));
        x&=0x0F;
        if(x >= 8){
                x &= 0x07;
                ST7920WriteData(Byte1);
                ST7920WriteData(Byte0 | (0x80>>x));
        }else{
                ST7920WriteData(Byte1 | (0x80>>x));
                ST7920WriteData(Byte0);
        }
}

出0入0汤圆

发表于 2011-3-16 22:17:52 | 显示全部楼层
这个帖子真不错,我学习了,谢谢各位。

出0入0汤圆

发表于 2011-3-17 09:12:18 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-17 11:31:00 | 显示全部楼层
这帖子真不错,受益匪浅,顶

出0入0汤圆

发表于 2011-3-17 13:24:21 | 显示全部楼层
好帖!顶!

出50入4汤圆

发表于 2011-3-17 13:29:30 | 显示全部楼层
印象中好像在哪看过?

出0入0汤圆

发表于 2011-3-17 14:45:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-18 10:32:14 | 显示全部楼层
引用图片【楼主位】AIHHLI 咚冬
-----------------------------------------------------------------------

(原文件名:图片1.png)

出0入0汤圆

发表于 2011-3-18 10:36:19 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-18 10:39:34 | 显示全部楼层
mark

出0入4汤圆

发表于 2011-3-18 10:51:39 | 显示全部楼层
建立一个显存也比这个要舒服呀

出0入0汤圆

发表于 2011-3-18 11:07:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-18 12:33:26 | 显示全部楼层
好文件!

出0入0汤圆

发表于 2011-3-18 13:42:18 | 显示全部楼层
很是不错

出0入0汤圆

发表于 2011-3-28 21:35:16 | 显示全部楼层
回复【34楼】mcu_lover
-----------------------------------------------------------------------

厉害!

出0入0汤圆

发表于 2011-3-28 22:46:25 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-3-28 23:13:18 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-1 15:41:21 | 显示全部楼层
对楼主膜拜!!强帖昂……

出0入0汤圆

发表于 2011-4-3 20:36:13 | 显示全部楼层
学习了

出0入0汤圆

发表于 2011-5-5 11:47:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-5 12:59:08 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-5-6 09:14:50 | 显示全部楼层
lcd_write_data(tmph | (0x01 << (7 - x_bit)));  //写高字节。因为坐标是从左向右的

出0入0汤圆

发表于 2011-5-6 09:16:03 | 显示全部楼层
lcd_write_data(tmph | (0x01 << (7 - x_bit)));  什么意思啊,如果x_bit=3时,结果是什么。

出500入0汤圆

发表于 2011-6-11 09:03:30 | 显示全部楼层
#define  BASIC_SET   0x00          //基本指令集,后面的数字查数据手册,下同。
#define  EXTEND_SET  0x00           //扩展指令集
#define  DRAW_ON     0x00           //绘图显示开
#define  DRAW_OFF    0x00           //绘图显示关

都是0x00?

出0入0汤圆

发表于 2011-6-11 10:39:49 | 显示全部楼层
mark鸟

出0入0汤圆

发表于 2011-6-11 15:14:56 | 显示全部楼层
cool

出0入0汤圆

发表于 2011-6-11 15:31:30 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-6-11 16:27:37 | 显示全部楼层
MARK下

出0入0汤圆

发表于 2011-6-12 14:01:29 | 显示全部楼层
学习..学习...

出0入0汤圆

发表于 2011-6-24 11:29:09 | 显示全部楼层
感谢lz给分析的这么详细,看了之后,对ST7920又有了进一步的了解。

出0入0汤圆

发表于 2011-6-24 11:37:24 | 显示全部楼层
好好····最近正在玩这个额啊····

出0入0汤圆

发表于 2011-7-19 16:24:21 | 显示全部楼层
xiexie l a

出0入0汤圆

发表于 2011-8-11 00:31:36 | 显示全部楼层
12864学习中,楼主的的解释让俺是受益非浅啊!顶,顶,我顶!我用你的打点函数,出现乱码现象,可以有人帮忙不?

出0入0汤圆

发表于 2011-8-17 15:18:21 | 显示全部楼层
回复【98楼】lihp1603
-----------------------------------------------------------------------

主程序中有开绘图显示吗
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 18:21

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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