集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 1844|回复: 4

LCD12864学习总结

[复制链接]
fpga_feixiang 发表于 2019-4-7 15:10:33 | 显示全部楼层 |阅读模式
/* 简单理解即是
*  CGRAM是留给自己造字的地方,CGROM是字库所在地方
*  DDRAM是显示数据地方
*  地址计数器用来存CGRAM以及DDRAM的地址值
*
*  对DDRAM的操作基本单位是字(16*16的倍数),写地址只需写入一个起始地址即可
*  对CGRAM的操作x(列)的基本单位是字,y(行)的基本单位是行,写地址需要分别写入起始的y和x
*   
*/

#define _LCD_12864_C
#include "config.h"
#include "Lcd12864.h"


/* 等待液晶准备好 */
void LcdWaitReady()
{
    uint8 sta;

    LCD12864_DB = 0xFF;
    LCD12864_RS = 0;
    LCD12864_RW = 1;
    do {
        LCD12864_E = 1;
        sta = LCD12864_DB;
        LCD12864_E = 0;
    } while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(uint8 cmd)
{
    LcdWaitReady();
    LCD12864_RS = 0;
    LCD12864_RW = 0;
    LCD12864_DB = cmd;
    LCD12864_E  = 1;
    LCD12864_E  = 0;
}
/* 向液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(uint8 dat)
{
    LcdWaitReady();
    LCD12864_RS = 1;
    LCD12864_RW = 0;
    LCD12864_DB = dat;
    LCD12864_E  = 1;
    LCD12864_E  = 0;
}
/*
* 函数名:LcdShowString
* 描  述:在显示屏上显示一串字符串
* 输  入:str - 待显示字符串指针
*         x - 屏幕显示横坐标(以像素为单位)
*         y - 屏幕显示纵坐标(以像素为单位)
* 输  出:无
* 备  注:输入的字符串必须符合C语言规范,即以'\0'-NULL为结束标识;
*         x、y坐标必须是16的整数倍,因DDRAM地址以全角字符(16*16pixel)为单位。
*         x、y坐标同样从0开始数  
*/
void LcdShowString(uint8 x, uint8 y, uint8 *str)
{
    uint8 addr;

    //由输入的显示坐标计算DDRAM的地址
    x >>= 4;    //对应的字   
    y >>= 4;    //对应的字
    //这个计算666的,,,其实带入坐标就立刻理解其含义了eg (16,32)
    if (y >= 2)  //到了下半屏
    {              
        y -= 2;
        x += 8;    //eg(1,2)
    }
    addr = y*16 + x;     //eg(9,0) 666的公式
    //由起始DDRAM地址连续写入字符串
    LcdWriteCmd(0x30); //启动DDRAM操作  基本指令集
    LcdWriteCmd(0x80|addr);      //eg 89H
    while (*str != '\0')
    {
        LcdWriteDat(*str);
        str++;
    }
}
/*
* 函数名:LcdShowImage
* 描  述:在显示屏上显示一幅图像
* 输  入:img - 待显示图像指针
*         x - 屏幕显示横坐标(以像素为单位)
*         y - 屏幕显示纵坐标(以像素为单位)
*         w - 图像宽度(以像素为单位)
*         h - 图像高度(以像素为单位)
* 输  出:无
* 备  注:x与w必须是16的整数倍,因CGRAM最小寻址单位为2字节;y与h可为0-63的任意值。
*/
void LcdShowImage(uint8 x, uint8 y, uint8 w, uint8 h, uint8 *img)
{                      //eg(16,0,96,32,welcome)
    int16 i;
    uint8 xi,yi;
    uint8 xt,yt;

    x >>= 4;       //换算成字,还用于判断上屏还是下屏
    w >>= 3;       //换算成字节
    i = 0;
    LcdWriteCmd(0x36); //启动CGRAM操作    启动绘图指令
    for (yi=0; yi<h; yi++)//行的循环
    {
        yt = y+yi;
        xt = x;
        if (yt >= 32)  //超出上屏
        {
            yt -= 32;  //对应下屏坐标(行,列)=>单位(行,字)
            xt += 8;
        }
        LcdWriteCmd(0x80|yt);  //行,第几行
        LcdWriteCmd(0x80|xt);  //列,第几字
        for (xi=0; xi<w; xi++) //上面一个循环已经定位到所在行,
        {//字是分开高低写入的,所以此处一字节为单位。一个字节完了之后指针自动+1。
            LcdWriteDat(img[i++]);
        }
    }
}

/*
* 函数名:LcdClearArea
* 描  述:清除屏幕上的一块图形显示区域
* 输  入:x - 区域起始横坐标(以像素为单位)
*         y - 区域起始纵坐标(以像素为单位)
*         w - 区域宽度(以像素为单位)
*         h - 区域高度(以像素为单位)
* 输  出:无
* 备  注:x与w必须是16的整数倍,因CGRAM最小寻址单位为2字节;y与h可为0-63的任意值。
*/
void LcdClearArea(uint8 x, uint8 y, uint8 w, uint8 h)
{
    uint8 xi,yi;
    uint8 xt,yt;

    x >>= 4;  //右移四位相当于除以2^4即是16
    w >>= 3;  //右移三位相当于除以2^3即是8
    LcdWriteCmd(0x36); //启动CGRAM操作
    for (yi=0; yi<h; yi++)
    {
        yt = y+yi;
        xt = x;
        if (yt >= 32)
        {
            yt -= 32;
            xt += 8;
        }
        LcdWriteCmd(0x80|yt); //注意这里要写入两个地址分别是位地址
        LcdWriteCmd(0x80|xt); //和字地址
        for (xi=0; xi<w; xi++)
        {
            LcdWriteDat(0x00); //写入0x00以清除显示
        }
    }
}

/* 12864液晶初始化函数 */
void InitLcd12864()
{
    uint8 x, y;

    //字符模式初始化
    LcdWriteCmd(0x30);  //基本指令集
    LcdWriteCmd(0x01);  //清零字符显示
    LcdWriteCmd(0x02);  //地址归位
    LcdWriteCmd(0x0C);  //开显示

    //图形模式初始化
    LcdWriteCmd(0x34);    //启动扩展指令,关闭图形显示
    for (y=0; y<32; y++)  //清零图形显示缓冲区 GDRAM
    {
        LcdWriteCmd(0x80|y);//写Y坐标,也就是行地址
        LcdWriteCmd(0x80|0);//写X坐标,也就是列地址
        for (x=0; x<32; x++)//这一行进行写0,写完一个字节地址会自动加1,这里表示写完一行32个字节
        {                   //写完之后跳出循环,到下一行。
            LcdWriteDat(0x00);
        }
    }
    LcdWriteCmd(0x36);  //开启图形模式显示
}   

//GDRAM是32行×16字。写数据之前必须先送行地址(垂直地址Y),然后送列地址(水平地址X)。
//读写的基本操作单元是字(2个字节)。
//读写完一个字节后地址指针在本行自动加一,到达行末则返回行首地址(地址循环)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
DDRAM:(Data Display Ram),数据显示RAM,往里面写啥,屏幕就会显示啥。
CGROM:(Character Generation ROM),字符发生ROM。里面存储了中文汉字的字模,也称作中文字库,编码方式有GB2312(中文简体)和BIG5(中文繁体)。笔者使用的是育松电子的QC12864B,讲解以此为例。
CGRAM:(Character Generation RAM),字符发生RAM,,12864内部提供了64×2B的CGRAM,可用于用户自定义4个16×16字符,每个字符占用32个字节。
GDRAM:(Graphic Display RAM):图形显示RAM,这一块区域用于绘图,往里面写啥,屏幕就会显示啥,它与DDRAM的区别在于,往DDRAM中写的数据是字符的编码,字符的显示先是在CGROM中找到字模,然后映射到屏幕上,而往GDRAM中写的数据时图形的点阵信息,每个点用1bit来保存其显示与否。
HCGROM:(Half height Character Generation ROM):半宽字符发生器,就是字母与数字,也就是ASCII码。
---------------------
zxopenhl 发表于 2019-4-7 15:47:04 | 显示全部楼层
LCD12864学习总结
zhangyukun 发表于 2019-4-8 09:32:03 | 显示全部楼层
LCD12864学习总结
大鹏 发表于 2022-4-14 12:46:31 | 显示全部楼层
LCD12864学习总结
durongze 发表于 2023-6-18 20:06:56 | 显示全部楼层
本帖最后由 durongze 于 2023-6-18 21:53 编辑

这个如何使用呢?


另外这里有个verilog的代码,这个管脚如何配置呢?
module  LCD12864 (
clk,
rs, rw, en,
dat
);  
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2024-11-27 10:32 , Processed in 0.060582 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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